@pheem49/mint 1.14.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 +1258 -35
- package/Cargo.toml +5 -2
- package/LICENSE +21 -654
- package/README.md +93 -756
- package/Release_Note.md +53 -446
- 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 +9 -1
- package/crates/mint-cli/src/agent/approval_prompts.rs +16 -3
- package/crates/mint-cli/src/agent/live_status.rs +545 -148
- package/crates/mint-cli/src/agent/markdown_render.rs +601 -61
- package/crates/mint-cli/src/agent.rs +723 -258
- package/crates/mint-cli/src/commands/agent.rs +83 -74
- package/crates/mint-cli/src/commands/eval.rs +9 -5
- package/crates/mint-cli/src/commands/git.rs +204 -0
- package/crates/mint-cli/src/commands/integrations.rs +35 -0
- package/crates/mint-cli/src/commands/knowledge.rs +13 -32
- package/crates/mint-cli/src/commands/mod.rs +81 -2
- package/crates/mint-cli/src/commands/tailnet_web.rs +235 -0
- package/crates/mint-cli/src/image.rs +32 -11
- package/crates/mint-cli/src/interactive/chat_tui.rs +7853 -0
- package/crates/mint-cli/src/interactive/command_ui.rs +477 -0
- package/crates/mint-cli/src/interactive/format.rs +8 -0
- package/crates/mint-cli/src/interactive/input_box.rs +94 -8
- package/crates/mint-cli/src/interactive/picker.rs +180 -37
- package/crates/mint-cli/src/interactive/resume_picker.rs +686 -0
- package/crates/mint-cli/src/interactive/slash_commands.rs +1071 -501
- package/crates/mint-cli/src/interactive/thought_viewer.rs +286 -0
- package/crates/mint-cli/src/interactive/tool_activity.rs +328 -0
- package/crates/mint-cli/src/interactive.rs +454 -166
- package/crates/mint-cli/src/main.rs +93 -26
- package/crates/mint-cli/src/markdown.rs +12 -5
- 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 +37 -61
- package/crates/mint-cli/src/plugins_cli.rs +8 -5
- package/crates/mint-cli/src/setup.rs +10 -8
- package/crates/mint-cli/src/terminal_theme.rs +189 -0
- package/crates/mint-cli/src/updater.rs +112 -23
- 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/agent_loop.rs +1 -0
- package/crates/mint-core/src/agent/chat.rs +1003 -209
- package/crates/mint-core/src/agent/code_tools.rs +98 -2
- package/crates/mint-core/src/agent/memory/sources.rs +240 -0
- package/crates/mint-core/src/agent/memory.rs +805 -33
- 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 +233 -190
- 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/linked_folders.rs +118 -3
- package/crates/mint-core/src/api_server/routes/media_gen.rs +10 -57
- package/crates/mint-core/src/api_server/routes/misc.rs +114 -121
- 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 +85 -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 +140 -12
- package/crates/mint-core/src/avatar_bridge.rs +13 -2
- package/crates/mint-core/src/browser/cdp.rs +74 -83
- package/crates/mint-core/src/browser/evidence.rs +260 -0
- package/crates/mint-core/src/browser/input.rs +1 -1
- package/crates/mint-core/src/browser/interact.rs +98 -124
- package/crates/mint-core/src/browser/lifecycle.rs +75 -4
- package/crates/mint-core/src/browser/mod.rs +16 -2
- package/crates/mint-core/src/browser/navigate.rs +27 -19
- package/crates/mint-core/src/browser/observe.js +40 -0
- package/crates/mint-core/src/browser/session.rs +1610 -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/git/branches.rs +348 -0
- package/crates/mint-core/src/git/checkpoint.rs +40 -0
- package/crates/mint-core/src/git/diff.rs +206 -0
- package/crates/mint-core/src/git/mod.rs +10 -2
- package/crates/mint-core/src/integrations/channels.rs +88 -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 +107 -40
- package/crates/mint-core/src/live_sync.rs +28 -9
- package/crates/mint-core/src/media/auto_shorts.rs +1 -0
- package/crates/mint-core/src/media/gemini_live.rs +145 -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/mic_transcribe.rs +1 -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/subtitle.rs +1 -0
- 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 +105 -0
- package/crates/mint-core/src/orchestration/mcp_review.rs +153 -0
- package/crates/mint-core/src/orchestration/memory_skill.rs +110 -33
- package/crates/mint-core/src/orchestration/mod.rs +3129 -481
- 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/browser.rs +16 -139
- 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 +5 -3
- 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/tools/web.rs +1 -1
- package/crates/mint-core/src/orchestration/workspace_helpers.rs +4 -1
- package/crates/mint-core/src/prompts/agent.rs +75 -31
- package/crates/mint-core/src/prompts/chat.rs +1 -1
- package/crates/mint-core/src/prompts/persona.rs +1 -1
- package/crates/mint-core/src/prompts/tool_catalog.rs +121 -27
- package/crates/mint-core/src/search/knowledge.rs +7 -1
- package/crates/mint-core/src/search/linked_folders/index.rs +896 -0
- package/crates/mint-core/src/search/linked_folders.rs +473 -131
- package/crates/mint-core/src/slash/catalog.rs +1 -1
- package/crates/mint-core/src/slash/mod.rs +644 -33
- package/crates/mint-core/src/slash/model_fetcher.rs +12 -3
- package/crates/mint-core/src/slash/models.rs +66 -10
- 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 +235 -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 +292 -0
- package/crates/mint-core/src/system/workspace_history.rs +604 -0
- package/crates/mint-core/src/system.rs +5 -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/memory_persistence.rs +39 -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/ImageStudioPanel-D0lnhQV5.css +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-DOj7_WR3.css +1 -0
- package/out/web/assets/VeoStudioPanel-DiJs_Cg2.js +4 -0
- package/out/web/assets/WorkspacePanel-CbJ1PFoZ.js +1 -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-DAOBA7ZG.js → abnfDiagram-VCTEODGH-CD0CjoGl.js} +1 -1
- package/out/web/assets/{architecture-7GRP2DOG-CgSwQOPQ.js → architecture-7GRP2DOG-RKV83OeZ.js} +1 -1
- package/out/web/assets/{architectureDiagram-5GKGNRK7-CYp3yupP.js → architectureDiagram-5GKGNRK7-nN_HAFct.js} +1 -1
- package/out/web/assets/{blockDiagram-NRAW4CY4-CyWybDWr.js → blockDiagram-NRAW4CY4-BrrqzHW5.js} +1 -1
- package/out/web/assets/{c4Diagram-UCG6FXSJ-BvY3U709.js → c4Diagram-UCG6FXSJ-DTdV8_zE.js} +1 -1
- package/out/web/assets/{chunk-75Z2AOVW-TLXCoZYv.js → chunk-75Z2AOVW-_M0z5olV.js} +1 -1
- package/out/web/assets/chunk-CKBBP62Z-BpQEgeHF.js +2 -0
- package/out/web/assets/{chunk-CLGD4ZFX-xjsKtNS7.js → chunk-CLGD4ZFX-D54yGvGS.js} +1 -1
- package/out/web/assets/chunk-DSNCTWBM-C-gvT2ru.js +2 -0
- package/out/web/assets/chunk-DU6HZSFF-CnFngIhW.js +128 -0
- package/out/web/assets/{chunk-F27PBJKO-BFpgF55A.js → chunk-F27PBJKO-BqtWrnEO.js} +1 -1
- package/out/web/assets/{chunk-G27WJ6UU-DfF7qW-C.js → chunk-G27WJ6UU-Ckoq5mi2.js} +1 -1
- package/out/web/assets/{chunk-GMAD6QVW-C-558kh_.js → chunk-GMAD6QVW-BuhEcgHq.js} +1 -1
- package/out/web/assets/{chunk-JQ64N6SF-wJmeGKAw.js → chunk-JQ64N6SF-CF8T7GiZ.js} +1 -1
- package/out/web/assets/{chunk-LCL6LL3I-C1wHD8Ie.js → chunk-LCL6LL3I-BhXV9zyH.js} +1 -1
- package/out/web/assets/{chunk-OBVCFTLP-BsRTPBqs.js → chunk-OBVCFTLP-CRIkunUB.js} +1 -1
- package/out/web/assets/{chunk-P2QGCYS3-HZIiM7Ni.js → chunk-P2QGCYS3-UFEU6BxZ.js} +1 -1
- package/out/web/assets/{chunk-POPQ4Y6H-Dk9wvVb0.js → chunk-POPQ4Y6H-CQcrNbjr.js} +1 -1
- package/out/web/assets/{chunk-PWAF6VOD-BmjYLNbq.js → chunk-PWAF6VOD-Cc2uVDsG.js} +1 -1
- package/out/web/assets/{chunk-R7TYR2AO-CaHIf-lK.js → chunk-R7TYR2AO-DiCxzdAY.js} +1 -1
- package/out/web/assets/{chunk-RHFEMEQ7-_T561hOU.js → chunk-RHFEMEQ7-b7hnPmrR.js} +1 -1
- package/out/web/assets/{chunk-SVP7TREG-CM-GGYoY.js → chunk-SVP7TREG-Bu_yYb-V.js} +1 -1
- package/out/web/assets/{chunk-TEH6E4GO-K2A8Vg2C.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-ClzaB6cc.js → cynefin-OW5HDTMX-CnzQfOGp.js} +1 -1
- package/out/web/assets/{cynefinDiagram-5FMLGOSQ-D_JzZBzf.js → cynefinDiagram-5FMLGOSQ-DVtQnfpm.js} +1 -1
- package/out/web/assets/{dagre-3AP2YEHR-BDuUeMHj.js → dagre-3AP2YEHR-DG76_k5_.js} +1 -1
- package/out/web/assets/{diagram-S7CK7UJ4-DgtcfE8P.js → diagram-S7CK7UJ4-CaouUoze.js} +1 -1
- package/out/web/assets/{diagram-UQ7AKVKN-DTLoEYti.js → diagram-UQ7AKVKN-B4bEc26B.js} +1 -1
- package/out/web/assets/{diagram-VSXAHHWV-ChGl9pXz.js → diagram-VSXAHHWV-BJ86Ov2Y.js} +1 -1
- package/out/web/assets/{diagram-VX7I27RA-Be8DWz0S.js → diagram-VX7I27RA-7hH5IPYf.js} +1 -1
- package/out/web/assets/{diagram-Z3DM3KII-BMXjRTOF.js → diagram-Z3DM3KII-CCM4clo8.js} +1 -1
- package/out/web/assets/dist-js-BkYNznHX.js +1 -0
- package/out/web/assets/{ebnfDiagram-PWID7BFC-8Q9pl1CJ.js → ebnfDiagram-PWID7BFC-Da7WAM3k.js} +1 -1
- package/out/web/assets/{erDiagram-SSCWMZ5O-DjH8Lnkn.js → erDiagram-SSCWMZ5O-CzzmnZWT.js} +1 -1
- package/out/web/assets/event-Cdt7Byyj.js +1 -0
- package/out/web/assets/{eventmodeling-NTZA5JFV-BKUH_DOp.js → eventmodeling-NTZA5JFV-xcfsA0XD.js} +1 -1
- package/out/web/assets/fira-code-latin-600-normal-BmSSHshu.woff +0 -0
- package/out/web/assets/fira-code-latin-600-normal-CvYZpPHg.woff2 +0 -0
- package/out/web/assets/fira-code-symbols2-600-normal-Dvq6IQE5.woff +0 -0
- package/out/web/assets/flowDiagram-A5DVABFB-JdtH1673.js +1 -0
- package/out/web/assets/{ganttDiagram-EL5Y4UJY-D7fZKJNM.js → ganttDiagram-EL5Y4UJY-B3ClFGmL.js} +1 -1
- package/out/web/assets/{gitGraph-4MIJSDKK-BypWaaBU.js → gitGraph-4MIJSDKK-BZ_y_cDU.js} +1 -1
- package/out/web/assets/{gitGraphDiagram-WWUBYQGX-DWiw_3bq.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-KkAUxT4j.js → info-A6RAGUB7-B7I3K0F1.js} +1 -1
- package/out/web/assets/{infoDiagram-RXCK75RN-BNb6E48y.js → infoDiagram-RXCK75RN-deX_1MPh.js} +1 -1
- package/out/web/assets/{ishikawaDiagram-5VMMS53U-Caa-JoAK.js → ishikawaDiagram-5VMMS53U-s38yo28y.js} +1 -1
- package/out/web/assets/{journeyDiagram-EYS64GPL-DOrmFGz6.js → journeyDiagram-EYS64GPL-CZn2kB8b.js} +1 -1
- package/out/web/assets/jsx-runtime-DN4NhQUK.js +1 -0
- package/out/web/assets/{kanban-definition-3QL26DDD-BOWCYcK0.js → kanban-definition-3QL26DDD-DodjgySL.js} +1 -1
- package/out/web/assets/markdown-CMhYIcWB.js +39 -0
- package/out/web/assets/{mermaid-parser.core-BQqjCkS_.js → mermaid-parser.core-Whu2rlJC.js} +3 -3
- package/out/web/assets/mermaid.core-CKyPo8VH.js +11 -0
- package/out/web/assets/{mindmap-definition-FBJOCRG2-jTceWpr0.js → mindmap-definition-FBJOCRG2-260WBDxZ.js} +1 -1
- package/out/web/assets/modelManager-CUaGWMWu.js +2 -0
- package/out/web/assets/oauthManager-DlNhXJr6.js +1 -0
- package/out/web/assets/{packet-AYTQ26CC-CJ5RXgol.js → packet-AYTQ26CC-CEeIRKRG.js} +1 -1
- package/out/web/assets/{pegDiagram-XKGWAZYB-y8wMtd0y.js → pegDiagram-XKGWAZYB-BYadI-KO.js} +1 -1
- package/out/web/assets/{pie-WAS4IAKB-72fTBbl4.js → pie-WAS4IAKB-D8uf4dh5.js} +1 -1
- package/out/web/assets/{pieDiagram-E7YTZNPT-e0O02qWq.js → pieDiagram-E7YTZNPT-CjSDy4hO.js} +1 -1
- package/out/web/assets/{quadrantDiagram-AXDQQJYC-C9phYLom.js → quadrantDiagram-AXDQQJYC-B8D3gU5d.js} +1 -1
- package/out/web/assets/{radar-RG4KPBEZ-BAU2hzUT.js → radar-RG4KPBEZ-DZJxnokY.js} +1 -1
- package/out/web/assets/{railroad-74A4TZTK-B0bCAVHC.js → railroad-74A4TZTK-DBysUiUi.js} +1 -1
- package/out/web/assets/{railroad-abnf-HS5TGJTU-WhxO7ndE.js → railroad-abnf-HS5TGJTU-CHWxoJYg.js} +1 -1
- package/out/web/assets/{railroad-ebnf-LZEXJU2U-BkA0m7-F.js → railroad-ebnf-LZEXJU2U-DDv7X6bY.js} +1 -1
- package/out/web/assets/{railroad-peg-WCYAUIDC-BsVpHIaj.js → railroad-peg-WCYAUIDC-DpfcYYNJ.js} +1 -1
- package/out/web/assets/{railroadDiagram-O6MQD6OU-CyOLN65Q.js → railroadDiagram-O6MQD6OU-CYtyv0t3.js} +1 -1
- package/out/web/assets/{requirementDiagram-EFPCY7ZU-DQXJ7Dud.js → requirementDiagram-EFPCY7ZU-D2X-Ewik.js} +1 -1
- package/out/web/assets/{sankeyDiagram-P5KCCOFB-B2XLyIIc.js → sankeyDiagram-P5KCCOFB-Bn2x6C4Y.js} +1 -1
- package/out/web/assets/{sequenceDiagram-WJ2MYXX4-DGQY4wwm.js → sequenceDiagram-WJ2MYXX4-BvFLKtPd.js} +1 -1
- package/out/web/assets/{stateDiagram-HBIQ2CUA-DHZpDwNy.js → stateDiagram-HBIQ2CUA-Bx0GWeaY.js} +1 -1
- package/out/web/assets/stateDiagram-v2-4QOOHH4V--hol1yg_.js +1 -0
- package/out/web/assets/studio-B1mk40wD.js +1 -0
- package/out/web/assets/{swimlanes-XN3QIQJK-Bn_jcZz-.js → swimlanes-XN3QIQJK-CCma0T7L.js} +1 -1
- package/out/web/assets/swimlanesDiagram-VK2B7HYN-BkohoVsU.js +8 -0
- package/out/web/assets/{timeline-definition-24CTP7MA-CdTERuJZ.js → timeline-definition-24CTP7MA-iCRhhJ7C.js} +1 -1
- package/out/web/assets/{treeView-Q6P3EWNA-TKBKQG6R.js → treeView-Q6P3EWNA-DZ-y08qp.js} +1 -1
- package/out/web/assets/{treemap-WGGIJYW6-BP7gQoiC.js → treemap-WGGIJYW6-De0CxzMx.js} +1 -1
- package/out/web/assets/{vennDiagram-4TSXK5OY-BHUmxDuK.js → vennDiagram-4TSXK5OY-w_7aZ6xe.js} +1 -1
- package/out/web/assets/{wardley-WFR3VGLG-9bct5AAN.js → wardley-WFR3VGLG-DT0y0xJ4.js} +1 -1
- package/out/web/assets/{wardleyDiagram-VM6X3IG4-BfJwDDso.js → wardleyDiagram-VM6X3IG4-DAdXELbQ.js} +1 -1
- package/out/web/assets/window-BJCVtyET.js +1 -0
- package/out/web/assets/{xychartDiagram-S5SC5T6Z-Dqd9Mvpo.js → xychartDiagram-S5SC5T6Z-IZIXf3Vo.js} +1 -1
- package/out/web/index-web.html +4 -4
- package/out/web/index.html +4 -4
- package/package.json +80 -20
- package/shared-modules/.github/workflows/ci.yml +120 -0
- package/shared-modules/.github/workflows/update.yaml +28 -0
- package/slash-commands.json +16 -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-web.html +1 -0
- package/src/renderer/index.html +1 -2
- package/src/renderer/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/src/renderer/shared/agentProgress.ts +201 -3
- package/src/renderer/shared/components/AgentActivityDrawer.tsx +9 -8
- package/src/renderer/shared/components/AgentActivityTable.tsx +193 -133
- 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 +91 -40
- package/src/renderer/shared/components/AuthGate.tsx +79 -48
- package/src/renderer/shared/components/BackgroundTerminals.tsx +181 -0
- package/src/renderer/shared/components/CalculationCard.tsx +41 -15
- 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 +52 -33
- package/src/renderer/shared/components/ChatPanel.test.tsx +21 -0
- package/src/renderer/shared/components/ChatPanel.tsx +676 -415
- package/src/renderer/shared/components/ChunkErrorBoundary.tsx +115 -64
- package/src/renderer/shared/components/CliSessionsView.test.tsx +125 -0
- package/src/renderer/shared/components/CliSessionsView.tsx +543 -0
- package/src/renderer/shared/components/CodeReviewPage.tsx +668 -0
- package/src/renderer/shared/components/CollapsiblePasteInput.tsx +90 -0
- package/src/renderer/shared/components/CommandPalette.tsx +8 -8
- package/src/renderer/shared/components/ContextCompactionStatus.tsx +17 -0
- package/src/renderer/shared/components/DashboardSidebar.tsx +853 -229
- package/src/renderer/shared/components/DesktopTitlebar.tsx +371 -0
- package/src/renderer/shared/components/DiffReviewModal.tsx +3 -3
- 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/GitBranchSelector.tsx +442 -0
- 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/ImageGenCard.tsx +31 -12
- package/src/renderer/shared/components/ImageSearchCard.tsx +76 -65
- package/src/renderer/shared/components/ImageStudioPanel.tsx +49 -49
- package/src/renderer/shared/components/InlineThoughtNote.tsx +27 -0
- 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/LinkedFoldersView.tsx +365 -46
- package/src/renderer/shared/components/McpRegistryPicker.tsx +1 -1
- package/src/renderer/shared/components/McpServersView.tsx +51 -30
- package/src/renderer/shared/components/McpToolAllowlist.tsx +2 -4
- package/src/renderer/shared/components/McpToolResults.tsx +99 -0
- package/src/renderer/shared/components/MermaidCard.tsx +14 -8
- package/src/renderer/shared/components/MintDashboard.tsx +1002 -831
- 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 +547 -219
- package/src/renderer/shared/components/ModsPanel.tsx +156 -0
- package/src/renderer/shared/components/PlanChecklistWidget.tsx +1 -1
- package/src/renderer/shared/components/PluginsView.tsx +1 -1
- 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 +11 -18
- package/src/renderer/shared/components/RunSummaryDashboard.tsx +8 -14
- package/src/renderer/shared/components/ScheduledTasksView.tsx +11 -10
- package/src/renderer/shared/components/ScreenCaptureDialog.css +221 -0
- package/src/renderer/shared/components/ScreenCaptureDialog.tsx +199 -0
- 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 +41 -45
- package/src/renderer/shared/components/Settings/AudioTab.tsx +16 -15
- package/src/renderer/shared/components/Settings/AutomationTab.tsx +10 -60
- package/src/renderer/shared/components/Settings/AvatarCropModal.tsx +368 -0
- package/src/renderer/shared/components/Settings/GeneralTab.tsx +368 -113
- 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/PluginsTab.tsx +20 -12
- package/src/renderer/shared/components/Settings/ProfileTab.tsx +29 -5
- package/src/renderer/shared/components/Settings/SearchableModelCombobox.tsx +411 -0
- package/src/renderer/shared/components/Settings/ThemeTab.tsx +416 -165
- package/src/renderer/shared/components/SkillsView.tsx +41 -16
- 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 +41 -12
- package/src/renderer/shared/components/SourcesBlock.tsx +55 -51
- package/src/renderer/shared/components/StockCard.tsx +58 -24
- package/src/renderer/shared/components/SubagentDagView.tsx +4 -4
- package/src/renderer/shared/components/TerminalDock.tsx +241 -0
- package/src/renderer/shared/components/ThinkingBlock.tsx +14 -8
- package/src/renderer/shared/components/ToolSurfacePage.test.tsx +32 -0
- package/src/renderer/shared/components/ToolSurfacePage.tsx +568 -0
- package/src/renderer/shared/components/ToolsPanelToggle.tsx +13 -0
- package/src/renderer/shared/components/UiFeatureCard.tsx +267 -0
- package/src/renderer/shared/components/UiGridCard.tsx +188 -0
- package/src/renderer/shared/components/UiMockupWidget.tsx +149 -0
- package/src/renderer/shared/components/VeoStudioPanel.tsx +22 -37
- 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/WeatherCard.tsx +3 -3
- package/src/renderer/shared/components/WorkspaceContextPopover.tsx +138 -0
- 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 +154 -0
- 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 +57 -3
- package/src/renderer/shared/constants/models.ts +189 -2
- package/src/renderer/shared/constants/slashCommands.ts +1 -1
- package/src/renderer/shared/conversation/coordinator.test.ts +27 -0
- package/src/renderer/shared/conversation/coordinator.ts +82 -0
- 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 +13 -0
- package/src/renderer/shared/conversation/syncView.ts +6 -0
- 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 +64 -0
- package/src/renderer/shared/css/agent-observability.css +46 -15
- package/src/renderer/shared/css/auth-gate.css +114 -15
- package/src/renderer/shared/css/chat-ui-cards.css +495 -0
- package/src/renderer/shared/css/code-review.css +856 -0
- package/src/renderer/shared/css/code-sessions.css +479 -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/file-changes.css +132 -0
- package/src/renderer/shared/css/image-studio.css +16 -16
- package/src/renderer/shared/css/library.css +476 -0
- package/src/renderer/shared/css/management-views.css +415 -27
- package/src/renderer/shared/css/mcp-results.css +11 -0
- package/src/renderer/shared/css/model-selector.css +543 -85
- 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/agents.css +1 -1
- package/src/renderer/shared/css/settings/automation.css +13 -13
- package/src/renderer/shared/css/settings/general.css +526 -5
- 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/plugins.css +5 -5
- package/src/renderer/shared/css/settings/profile.css +331 -1
- package/src/renderer/shared/css/settings/theme.css +656 -3
- 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/veo-studio.css +16 -15
- package/src/renderer/shared/css/viewed-images.css +15 -0
- package/src/renderer/shared/fonts.css +46 -0
- package/src/renderer/shared/fonts.ts +10 -37
- 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 +90 -0
- package/src/renderer/shared/platform.ts +219 -7
- package/src/renderer/shared/theme/themeManager.test.ts +43 -0
- package/src/renderer/shared/theme/themeManager.ts +157 -0
- package/src/renderer/shared/theme/themes.ts +116 -0
- package/src/renderer/shared/theme/tokens.css +318 -0
- package/src/renderer/shared/types.ts +137 -2
- package/src/renderer/shared/utils/agentActivity.test.ts +75 -0
- package/src/renderer/shared/utils/agentActivity.ts +168 -8
- 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/cardJson.test.ts +35 -0
- package/src/renderer/shared/utils/cardJson.ts +30 -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/fileIcons.ts +1 -1
- package/src/renderer/shared/utils/markdown.tsx +330 -81
- package/src/renderer/shared/utils/markdown.webImages.test.tsx +40 -0
- 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/providers.ts +8 -3
- package/src/renderer/shared/utils/screenCapture.ts +43 -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 +5 -2
- 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/ui.ts +4 -64
- 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 +16 -1
- package/src/renderer/src/components/BrowserShell.tsx +108 -0
- package/src/renderer/src/components/BrowserSuggestionsPopup.tsx +91 -0
- package/src/renderer/src/components/LiveTranslateControls.tsx +65 -0
- package/src/renderer/src/components/MintDashboard.tsx +4 -2
- package/src/renderer/src/components/PicturesLibrary.tsx +2 -287
- package/src/renderer/src/components/ScreenPicker.css +227 -0
- package/src/renderer/src/components/ScreenPicker.tsx +312 -526
- package/src/renderer/src/components/SettingsWindow.tsx +48 -5
- package/src/renderer/src/components/SpotlightWindow.tsx +1 -0
- package/src/renderer/src/components/WidgetWindow.tsx +27 -3
- package/src/renderer/src/components/WorkspacePanel.tsx +269 -61
- package/src/renderer/src/components/browser-shell.css +185 -0
- package/src/renderer/src/components/browser-suggestions-popup.css +55 -0
- package/src/renderer/src/components/liveTranslateFrames.test.ts +44 -0
- package/src/renderer/src/components/liveTranslateFrames.ts +45 -0
- package/src/renderer/src/components/liveTranslateLanguage.ts +6 -0
- package/src/renderer/src/css/app-shell.css +400 -204
- package/src/renderer/src/css/chat.css +1666 -594
- package/src/renderer/src/css/dashboard.css +11 -0
- package/src/renderer/src/css/desktop-tools.css +928 -0
- package/src/renderer/src/css/misc.css +5 -60
- package/src/renderer/src/css/pictures.css +2 -407
- package/src/renderer/src/css/settings/base.css +394 -157
- package/src/renderer/src/css/sidebar-workspace.css +1072 -376
- package/src/renderer/src/css/spotlight.css +15 -26
- package/src/renderer/src/css/tool-surfaces.css +784 -0
- package/src/renderer/src/css/widget.css +36 -8
- package/src/renderer/src/env.d.ts +4 -9
- package/src/renderer/src/hooks/useProviderModels.ts +2 -9
- package/src/renderer/src/index.css +53 -46
- package/src/renderer/src/main.tsx +12 -0
- package/src/renderer/src/proactiveSuggestions.ts +29 -0
- package/src/renderer/src/tauri.ts +302 -339
- package/src/renderer/src/voiceInput.ts +2 -1
- package/src/renderer/src-web/App.tsx +40 -0
- package/src/renderer/src-web/components/MintDashboard.tsx +4 -2
- package/src/renderer/src-web/components/PicturesLibrary.tsx +2 -284
- package/src/renderer/src-web/components/PullToRefresh.tsx +107 -0
- package/src/renderer/src-web/components/SettingsWindow.tsx +36 -5
- package/src/renderer/src-web/css/app-shell.css +188 -207
- package/src/renderer/src-web/css/chat.css +1236 -507
- package/src/renderer/src-web/css/dashboard.css +11 -0
- package/src/renderer/src-web/css/misc.css +3 -55
- package/src/renderer/src-web/css/mobile.css +679 -0
- package/src/renderer/src-web/css/pictures.css +2 -415
- package/src/renderer/src-web/css/pull-to-refresh.css +54 -0
- package/src/renderer/src-web/css/settings/base.css +353 -134
- package/src/renderer/src-web/css/settings/mobile.css +320 -0
- package/src/renderer/src-web/css/sidebar-workspace.css +546 -187
- package/src/renderer/src-web/css/spotlight.css +9 -26
- package/src/renderer/src-web/css/widget.css +1 -6
- package/src/renderer/src-web/env.d.ts +4 -12
- package/src/renderer/src-web/hooks/useProviderModels.ts +2 -9
- package/src/renderer/src-web/index.css +53 -96
- package/src/renderer/src-web/main.tsx +12 -0
- package/src/renderer/src-web/proactiveSuggestions.ts +3 -0
- package/src/renderer/src-web/tauri.ts +309 -364
- 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 +5 -0
- package/.cargo/config.toml +0 -13
- package/.claude/settings.local.json +0 -182
- package/.codex +0 -0
- package/CLAUDE.md +0 -102
- package/out/web/Live2DCubismCore.js +0 -9
- package/out/web/assets/MintDashboard-DWSqucgb.js +0 -57
- package/out/web/assets/SettingsWindow-DFM2aj5B.js +0 -2
- package/out/web/assets/chunk-CKBBP62Z-nr1uKPj9.js +0 -2
- package/out/web/assets/chunk-DSNCTWBM-Dtj8Rqsd.js +0 -2
- package/out/web/assets/chunk-DU6HZSFF-2tv5K1wT.js +0 -128
- package/out/web/assets/classDiagram-DTDB5LWJ-BdSFArgw.js +0 -1
- package/out/web/assets/classDiagram-v2-JRS7N3AN-BdSFArgw.js +0 -1
- package/out/web/assets/core-DImejIUG.js +0 -1
- package/out/web/assets/dist-js-BxuKEVWM.js +0 -1
- package/out/web/assets/event-BNl8Zahw.js +0 -1
- package/out/web/assets/fira-code-cyrillic-400-normal-UC0NFL4U.woff2 +0 -0
- package/out/web/assets/fira-code-cyrillic-400-normal-dc1q3VD7.woff +0 -0
- package/out/web/assets/fira-code-cyrillic-500-normal-Bu7VCL72.woff +0 -0
- package/out/web/assets/fira-code-cyrillic-500-normal-CX35h3Mg.woff2 +0 -0
- package/out/web/assets/fira-code-cyrillic-ext-400-normal-Buh61xzB.woff +0 -0
- package/out/web/assets/fira-code-cyrillic-ext-400-normal-txZ9Fk_1.woff2 +0 -0
- package/out/web/assets/fira-code-cyrillic-ext-500-normal-CYRspHgm.woff2 +0 -0
- package/out/web/assets/fira-code-cyrillic-ext-500-normal-CwtLmSFD.woff +0 -0
- package/out/web/assets/fira-code-greek-400-normal-B2Gh_Y8s.woff2 +0 -0
- package/out/web/assets/fira-code-greek-400-normal-DobhaxvF.woff +0 -0
- package/out/web/assets/fira-code-greek-500-normal-CVO0IRNt.woff2 +0 -0
- package/out/web/assets/fira-code-greek-500-normal-DEXIWiey.woff +0 -0
- package/out/web/assets/fira-code-greek-ext-400-normal-DR7mBgIM.woff2 +0 -0
- package/out/web/assets/fira-code-greek-ext-400-normal-DSPUheWg.woff +0 -0
- package/out/web/assets/fira-code-greek-ext-500-normal-BO3iq16n.woff2 +0 -0
- package/out/web/assets/fira-code-greek-ext-500-normal-CMiNLXER.woff +0 -0
- package/out/web/assets/fira-code-latin-ext-400-normal-DG73JjOf.woff +0 -0
- package/out/web/assets/fira-code-latin-ext-400-normal-KSMg0QLl.woff2 +0 -0
- package/out/web/assets/fira-code-latin-ext-500-normal-CaANqXjI.woff +0 -0
- package/out/web/assets/fira-code-latin-ext-500-normal-Crd9e_oI.woff2 +0 -0
- package/out/web/assets/flowDiagram-A5DVABFB-BpnHUSU7.js +0 -1
- package/out/web/assets/index-CVRg270z.css +0 -1
- package/out/web/assets/index-DxZQr9yD.js +0 -10
- package/out/web/assets/inter-cyrillic-400-normal-HOLc17fK.woff +0 -0
- package/out/web/assets/inter-cyrillic-400-normal-obahsSVq.woff2 +0 -0
- package/out/web/assets/inter-cyrillic-500-normal-BasfLYem.woff2 +0 -0
- package/out/web/assets/inter-cyrillic-500-normal-CxZf_p3X.woff +0 -0
- package/out/web/assets/inter-cyrillic-600-normal-4D_pXhcN.woff +0 -0
- package/out/web/assets/inter-cyrillic-600-normal-CWCymEST.woff2 +0 -0
- package/out/web/assets/inter-cyrillic-ext-400-normal-BQZuk6qB.woff2 +0 -0
- package/out/web/assets/inter-cyrillic-ext-400-normal-DQukG94-.woff +0 -0
- package/out/web/assets/inter-cyrillic-ext-500-normal-B0yAr1jD.woff2 +0 -0
- package/out/web/assets/inter-cyrillic-ext-500-normal-BmqWE9Dz.woff +0 -0
- package/out/web/assets/inter-cyrillic-ext-600-normal-Bcila6Z-.woff +0 -0
- package/out/web/assets/inter-cyrillic-ext-600-normal-Dfes3d0z.woff2 +0 -0
- package/out/web/assets/inter-greek-400-normal-B4URO6DV.woff2 +0 -0
- package/out/web/assets/inter-greek-400-normal-q2sYcFCs.woff +0 -0
- package/out/web/assets/inter-greek-500-normal-BIZE56-Y.woff2 +0 -0
- package/out/web/assets/inter-greek-500-normal-Xzm54t5V.woff +0 -0
- package/out/web/assets/inter-greek-600-normal-BZpKdvQh.woff +0 -0
- package/out/web/assets/inter-greek-600-normal-plRanbMR.woff2 +0 -0
- package/out/web/assets/inter-greek-ext-400-normal-DGGRlc-M.woff2 +0 -0
- package/out/web/assets/inter-greek-ext-400-normal-KugGGMne.woff +0 -0
- package/out/web/assets/inter-greek-ext-500-normal-2j5mBUwD.woff +0 -0
- package/out/web/assets/inter-greek-ext-500-normal-C4iEst2y.woff2 +0 -0
- package/out/web/assets/inter-greek-ext-600-normal-B8X0CLgF.woff +0 -0
- package/out/web/assets/inter-greek-ext-600-normal-DRtmH8MT.woff2 +0 -0
- package/out/web/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
- package/out/web/assets/inter-latin-400-normal-CyCys3Eg.woff +0 -0
- package/out/web/assets/inter-latin-500-normal-BL9OpVg8.woff +0 -0
- package/out/web/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
- package/out/web/assets/inter-latin-600-normal-CiBQ2DWP.woff +0 -0
- package/out/web/assets/inter-latin-600-normal-LgqL8muc.woff2 +0 -0
- package/out/web/assets/inter-latin-ext-400-normal-77YHD8bZ.woff +0 -0
- package/out/web/assets/inter-latin-ext-400-normal-C1nco2VV.woff2 +0 -0
- package/out/web/assets/inter-latin-ext-500-normal-BxGbmqWO.woff +0 -0
- package/out/web/assets/inter-latin-ext-500-normal-CV4jyFjo.woff2 +0 -0
- package/out/web/assets/inter-latin-ext-600-normal-CIVaiw4L.woff +0 -0
- package/out/web/assets/inter-latin-ext-600-normal-D2bJ5OIk.woff2 +0 -0
- package/out/web/assets/inter-vietnamese-400-normal-Bbgyi5SW.woff +0 -0
- package/out/web/assets/inter-vietnamese-400-normal-DMkecbls.woff2 +0 -0
- package/out/web/assets/inter-vietnamese-500-normal-DOriooB6.woff2 +0 -0
- package/out/web/assets/inter-vietnamese-500-normal-mJboJaSs.woff +0 -0
- package/out/web/assets/inter-vietnamese-600-normal-BuLX-rYi.woff +0 -0
- package/out/web/assets/inter-vietnamese-600-normal-Cc8MFFhd.woff2 +0 -0
- package/out/web/assets/kanit-latin-400-normal-BUlsQXH3.woff2 +0 -0
- package/out/web/assets/kanit-latin-400-normal-HVZWrfev.woff +0 -0
- package/out/web/assets/kanit-latin-500-normal-CX_4XcKi.woff2 +0 -0
- package/out/web/assets/kanit-latin-500-normal-qBha86O4.woff +0 -0
- package/out/web/assets/kanit-latin-600-normal-0lS78yAd.woff2 +0 -0
- package/out/web/assets/kanit-latin-600-normal-DlacpeTg.woff +0 -0
- package/out/web/assets/kanit-latin-ext-400-normal-B2xPf58u.woff2 +0 -0
- package/out/web/assets/kanit-latin-ext-400-normal-CHvNKHHD.woff +0 -0
- package/out/web/assets/kanit-latin-ext-500-normal-BFdWrG22.woff +0 -0
- package/out/web/assets/kanit-latin-ext-500-normal-EHs3suD6.woff2 +0 -0
- package/out/web/assets/kanit-latin-ext-600-normal-BBDzoLaj.woff +0 -0
- package/out/web/assets/kanit-latin-ext-600-normal-DAX3wtuq.woff2 +0 -0
- package/out/web/assets/kanit-thai-400-normal-D2nliXKa.woff +0 -0
- package/out/web/assets/kanit-thai-400-normal-D80Pglro.woff2 +0 -0
- package/out/web/assets/kanit-thai-500-normal-BB8gri04.woff2 +0 -0
- package/out/web/assets/kanit-thai-500-normal-Iy_w0a80.woff +0 -0
- package/out/web/assets/kanit-thai-600-normal-Bj6oiaDc.woff2 +0 -0
- package/out/web/assets/kanit-thai-600-normal-wbTlPO7I.woff +0 -0
- package/out/web/assets/kanit-vietnamese-400-normal-DRI8YWyb.woff2 +0 -0
- package/out/web/assets/kanit-vietnamese-400-normal-dow6Bnto.woff +0 -0
- package/out/web/assets/kanit-vietnamese-500-normal-BzTrpCM3.woff2 +0 -0
- package/out/web/assets/kanit-vietnamese-500-normal-T1ndT7MF.woff +0 -0
- package/out/web/assets/kanit-vietnamese-600-normal-Bi7fw3I4.woff2 +0 -0
- package/out/web/assets/kanit-vietnamese-600-normal-DXCRAa_8.woff +0 -0
- package/out/web/assets/mali-latin-400-normal-ByPcZ8Gx.woff +0 -0
- package/out/web/assets/mali-latin-400-normal-Cuc6Ykl8.woff2 +0 -0
- package/out/web/assets/mali-latin-500-normal-B01M-LP6.woff2 +0 -0
- package/out/web/assets/mali-latin-500-normal-Thgqw_9f.woff +0 -0
- package/out/web/assets/mali-latin-600-normal-B9TiUNpT.woff2 +0 -0
- package/out/web/assets/mali-latin-600-normal-CycpQCwU.woff +0 -0
- package/out/web/assets/mali-latin-ext-400-normal-DUVdJQO4.woff +0 -0
- package/out/web/assets/mali-latin-ext-400-normal-iCG1ALuJ.woff2 +0 -0
- package/out/web/assets/mali-latin-ext-500-normal-BfJE4UMZ.woff2 +0 -0
- package/out/web/assets/mali-latin-ext-500-normal-FoLEyOKS.woff +0 -0
- package/out/web/assets/mali-latin-ext-600-normal-BTvIfiCp.woff2 +0 -0
- package/out/web/assets/mali-latin-ext-600-normal-DAQcLVmD.woff +0 -0
- package/out/web/assets/mali-thai-400-normal-BO7A3bLZ.woff2 +0 -0
- package/out/web/assets/mali-thai-400-normal-CX9VrjTn.woff +0 -0
- package/out/web/assets/mali-thai-500-normal-Cph2qha9.woff +0 -0
- package/out/web/assets/mali-thai-500-normal-D89rMT77.woff2 +0 -0
- package/out/web/assets/mali-thai-600-normal-DPgXT6rZ.woff +0 -0
- package/out/web/assets/mali-thai-600-normal-DlTx3OsB.woff2 +0 -0
- package/out/web/assets/mali-vietnamese-400-normal-DUKxzXaz.woff2 +0 -0
- package/out/web/assets/mali-vietnamese-400-normal-gFDLvsOK.woff +0 -0
- package/out/web/assets/mali-vietnamese-500-normal--OY07q2c.woff +0 -0
- package/out/web/assets/mali-vietnamese-500-normal-KDrNRwfW.woff2 +0 -0
- package/out/web/assets/mali-vietnamese-600-normal-CtTMUU7T.woff +0 -0
- package/out/web/assets/mali-vietnamese-600-normal-DFlJr66u.woff2 +0 -0
- package/out/web/assets/mermaid.core-DYGGlqOf.js +0 -11
- package/out/web/assets/mitr-latin-400-normal-Cb18vPmZ.woff +0 -0
- package/out/web/assets/mitr-latin-400-normal-CwbkLQ4a.woff2 +0 -0
- package/out/web/assets/mitr-latin-500-normal-B4JOhzAi.woff +0 -0
- package/out/web/assets/mitr-latin-500-normal-BmClOow2.woff2 +0 -0
- package/out/web/assets/mitr-latin-ext-400-normal-B3CPG7Yo.woff2 +0 -0
- package/out/web/assets/mitr-latin-ext-400-normal-DTx65hiC.woff +0 -0
- package/out/web/assets/mitr-latin-ext-500-normal-B_Diajz1.woff2 +0 -0
- package/out/web/assets/mitr-latin-ext-500-normal-DYOsVaVT.woff +0 -0
- package/out/web/assets/mitr-thai-400-normal-CS4Do6aM.woff +0 -0
- package/out/web/assets/mitr-thai-400-normal-CXWaAdVj.woff2 +0 -0
- package/out/web/assets/mitr-thai-500-normal-CVdBrEVH.woff2 +0 -0
- package/out/web/assets/mitr-thai-500-normal-CW_B5D-i.woff +0 -0
- package/out/web/assets/mitr-vietnamese-400-normal-CPMGWyoC.woff2 +0 -0
- package/out/web/assets/mitr-vietnamese-400-normal-Z6XhIpdY.woff +0 -0
- package/out/web/assets/mitr-vietnamese-500-normal-CDrv0585.woff2 +0 -0
- package/out/web/assets/mitr-vietnamese-500-normal-CMQWyq-Z.woff +0 -0
- package/out/web/assets/noto-sans-thai-latin-400-normal-BaWBrqFP.woff2 +0 -0
- package/out/web/assets/noto-sans-thai-latin-400-normal-Dh_FJjOB.woff +0 -0
- package/out/web/assets/noto-sans-thai-latin-500-normal-BC04jsmm.woff +0 -0
- package/out/web/assets/noto-sans-thai-latin-500-normal-fyBKClF1.woff2 +0 -0
- package/out/web/assets/noto-sans-thai-latin-600-normal-CemcjnVR.woff2 +0 -0
- package/out/web/assets/noto-sans-thai-latin-600-normal-Dbc-dNO6.woff +0 -0
- package/out/web/assets/noto-sans-thai-latin-ext-400-normal-B-1H0YkH.woff +0 -0
- package/out/web/assets/noto-sans-thai-latin-ext-400-normal-nBP59pVw.woff2 +0 -0
- package/out/web/assets/noto-sans-thai-latin-ext-500-normal-B-ZWb8SZ.woff2 +0 -0
- package/out/web/assets/noto-sans-thai-latin-ext-500-normal-CrEHO7C8.woff +0 -0
- package/out/web/assets/noto-sans-thai-latin-ext-600-normal-PkMZo0xa.woff +0 -0
- package/out/web/assets/noto-sans-thai-latin-ext-600-normal-maHHBsez.woff2 +0 -0
- package/out/web/assets/noto-sans-thai-thai-400-normal-BEOmKAI1.woff2 +0 -0
- package/out/web/assets/noto-sans-thai-thai-400-normal-Dxb_unuU.woff +0 -0
- package/out/web/assets/noto-sans-thai-thai-500-normal-BOGXO2tw.woff +0 -0
- package/out/web/assets/noto-sans-thai-thai-500-normal-CU_X86GQ.woff2 +0 -0
- package/out/web/assets/noto-sans-thai-thai-600-normal-CmgB8_JK.woff +0 -0
- package/out/web/assets/noto-sans-thai-thai-600-normal-Cs73sVjl.woff2 +0 -0
- package/out/web/assets/oauthManager-DNiwM8Rn.js +0 -2
- package/out/web/assets/oauthManager-DuamS1Av.css +0 -1
- package/out/web/assets/outfit-latin-300-normal-AWLfuCom.woff +0 -0
- package/out/web/assets/outfit-latin-300-normal-CRYTwY6m.woff2 +0 -0
- package/out/web/assets/outfit-latin-400-normal-BGsTXAXT.woff2 +0 -0
- package/out/web/assets/outfit-latin-400-normal-DMwTpYkH.woff +0 -0
- package/out/web/assets/outfit-latin-500-normal-ClnHRwRh.woff +0 -0
- package/out/web/assets/outfit-latin-500-normal-DKnIMDSk.woff2 +0 -0
- package/out/web/assets/outfit-latin-600-normal-B7SfZ07L.woff2 +0 -0
- package/out/web/assets/outfit-latin-600-normal-BEfTtDA7.woff +0 -0
- package/out/web/assets/outfit-latin-ext-300-normal-BYS6Dpvq.woff2 +0 -0
- package/out/web/assets/outfit-latin-ext-300-normal-CMIMshEd.woff +0 -0
- package/out/web/assets/outfit-latin-ext-400-normal-5tcqmc2S.woff2 +0 -0
- package/out/web/assets/outfit-latin-ext-400-normal-DHm7mdGe.woff +0 -0
- package/out/web/assets/outfit-latin-ext-500-normal-DrCvqoFD.woff +0 -0
- package/out/web/assets/outfit-latin-ext-500-normal-zeox_O30.woff2 +0 -0
- package/out/web/assets/outfit-latin-ext-600-normal-B85nYjL1.woff2 +0 -0
- package/out/web/assets/outfit-latin-ext-600-normal-CWJcPgd7.woff +0 -0
- package/out/web/assets/preload-helper-D0uHx7FM.js +0 -1
- 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-ext-400-normal-1pHbN9uy.woff +0 -0
- package/out/web/assets/prompt-latin-ext-400-normal-DdSafGZ9.woff2 +0 -0
- package/out/web/assets/prompt-latin-ext-500-normal--EZ1um7s.woff2 +0 -0
- package/out/web/assets/prompt-latin-ext-500-normal-D-lI1EVT.woff +0 -0
- package/out/web/assets/prompt-latin-ext-600-normal-C8b50x67.woff +0 -0
- package/out/web/assets/prompt-latin-ext-600-normal-Cg9L7iJU.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-vietnamese-400-normal-BCPzsgPT.woff2 +0 -0
- package/out/web/assets/prompt-vietnamese-400-normal-D4pLyeNK.woff +0 -0
- package/out/web/assets/prompt-vietnamese-500-normal-DmzxmPwa.woff2 +0 -0
- package/out/web/assets/prompt-vietnamese-500-normal-w_sS_j2F.woff +0 -0
- package/out/web/assets/prompt-vietnamese-600-normal-1dyohtNh.woff +0 -0
- package/out/web/assets/prompt-vietnamese-600-normal-7QWjJBsF.woff2 +0 -0
- package/out/web/assets/sarabun-latin-400-normal-DmguIS-7.woff +0 -0
- package/out/web/assets/sarabun-latin-400-normal-URPBxl-K.woff2 +0 -0
- package/out/web/assets/sarabun-latin-500-normal-BjUTcdxu.woff2 +0 -0
- package/out/web/assets/sarabun-latin-500-normal-CJexTAnl.woff +0 -0
- package/out/web/assets/sarabun-latin-600-normal-9FonlkKx.woff +0 -0
- package/out/web/assets/sarabun-latin-600-normal-DMD3TROr.woff2 +0 -0
- package/out/web/assets/sarabun-latin-ext-400-normal-BbP7GpLL.woff2 +0 -0
- package/out/web/assets/sarabun-latin-ext-400-normal-BsmTn0SS.woff +0 -0
- package/out/web/assets/sarabun-latin-ext-500-normal-Cot16Bd2.woff +0 -0
- package/out/web/assets/sarabun-latin-ext-500-normal-DE1LysqI.woff2 +0 -0
- package/out/web/assets/sarabun-latin-ext-600-normal-0tXu9x_i.woff +0 -0
- package/out/web/assets/sarabun-latin-ext-600-normal-BRxjKUQ6.woff2 +0 -0
- package/out/web/assets/sarabun-thai-400-normal-C2DaJlKK.woff2 +0 -0
- package/out/web/assets/sarabun-thai-400-normal-CH-UbWgg.woff +0 -0
- package/out/web/assets/sarabun-thai-500-normal-BVssjame.woff2 +0 -0
- package/out/web/assets/sarabun-thai-500-normal-C3iDLEzi.woff +0 -0
- package/out/web/assets/sarabun-thai-600-normal-3dIAQ-_s.woff2 +0 -0
- package/out/web/assets/sarabun-thai-600-normal-DWKeTe6a.woff +0 -0
- package/out/web/assets/sarabun-vietnamese-400-normal-DPfkSCMy.woff +0 -0
- package/out/web/assets/sarabun-vietnamese-400-normal-igdrzAGY.woff2 +0 -0
- package/out/web/assets/sarabun-vietnamese-500-normal-CpRVvGRU.woff +0 -0
- package/out/web/assets/sarabun-vietnamese-500-normal-Dpe7Br9m.woff2 +0 -0
- package/out/web/assets/sarabun-vietnamese-600-normal-BMbOgAW-.woff +0 -0
- package/out/web/assets/sarabun-vietnamese-600-normal-DkxrOlLB.woff2 +0 -0
- package/out/web/assets/stateDiagram-v2-4QOOHH4V-s6P9g2_b.js +0 -1
- package/out/web/assets/swimlanesDiagram-VK2B7HYN-CV9fOLrV.js +0 -8
- package/out/web/assets/tauri-CNrHQ2Gb.js +0 -3
- package/out/web/assets/window-DkIhgI7B.js +0 -1
- package/skills-lock.json +0 -41
- package/src/renderer/public/Live2DCubismCore.js +0 -9
- package/src/renderer/src/companionWidget.ts +0 -95
- package/src/renderer/src/components/Live2DStage.tsx +0 -389
- package/src/renderer/src/components/ModelPanel.tsx +0 -154
- package/src/renderer/src/css/model.css +0 -627
- 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,41 +1,35 @@
|
|
|
1
|
-
import {
|
|
2
|
-
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'
|
|
3
6
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
type PictureEntry,
|
|
27
|
-
type RuntimeStatus,
|
|
28
|
-
} from '@/tauri'
|
|
29
|
-
|
|
30
|
-
import ChatPanel from './ChatPanel'
|
|
7
|
+
mergeFileChanges,
|
|
8
|
+
parseFileChangesFromProgress,
|
|
9
|
+
} from '../agentProgress'
|
|
10
|
+
import { catalogPlatform, conversationPlatform, mediaPlatform, runtimePlatform, workspacePlatform, type SlashResponse } from '../platform'
|
|
11
|
+
import type { ChatSession, DocumentAttachment, RuntimeStatus } from '../types'
|
|
12
|
+
|
|
13
|
+
const {
|
|
14
|
+
clearChatHistory, deleteChatSession, renameChatSession,
|
|
15
|
+
saveSystemInteraction, updateChatSessionWorkspace,
|
|
16
|
+
listen, readClipboardImage,
|
|
17
|
+
} = conversationPlatform
|
|
18
|
+
const { getRuntimeStatus, setActiveModel, selectWorkspaceDirectory, selectLinkedFolderPath, isTauriRuntime } = runtimePlatform
|
|
19
|
+
const { convertFileSrc } = mediaPlatform
|
|
20
|
+
const {
|
|
21
|
+
listLearnedSkills, addLearnedSkill, deleteLearnedSkill, detectSystemTools, reauthMcpServer,
|
|
22
|
+
listMcpServerTools, setProfileValue, listCronJobs, addCronJob, removeCronJob,
|
|
23
|
+
setCronJobEnabled, listLinkedFolders, addLinkedFolder, removeLinkedFolder, runSlashCommand,
|
|
24
|
+
linkedFolderStatus, refreshLinkedFolder, listLinkedFolderNotes, readLinkedFolderNote, openLinkedFolderNote,
|
|
25
|
+
} = catalogPlatform
|
|
26
|
+
|
|
27
|
+
import ChatPanel, { type ConversationActions, type ConversationViewModel } from './ChatPanel'
|
|
28
|
+
import ScreenCaptureDialog from './ScreenCaptureDialog'
|
|
31
29
|
import DashboardSidebar, { type DashboardView } from './DashboardSidebar'
|
|
32
|
-
import
|
|
33
|
-
import
|
|
34
|
-
import
|
|
35
|
-
import type { ModelInteraction } from '@/components/ModelPanel'
|
|
36
|
-
import PicturesLibrary from '@/components/PicturesLibrary'
|
|
37
|
-
import WorkspacePanel from '@/components/WorkspacePanel'
|
|
38
|
-
import { CommandPalette } from './CommandPalette'
|
|
30
|
+
import DesktopTitlebar from './DesktopTitlebar'
|
|
31
|
+
import ErrorNotice from './ErrorNotice'
|
|
32
|
+
import type { ToolSurface } from './ToolSurfacePage'
|
|
39
33
|
import {
|
|
40
34
|
errorMessage,
|
|
41
35
|
readImage,
|
|
@@ -45,32 +39,37 @@ import {
|
|
|
45
39
|
applyThemeStyles,
|
|
46
40
|
parseUtcDate,
|
|
47
41
|
} from '../utils/ui'
|
|
42
|
+
import { workspacePaths } from '../utils/workspaces'
|
|
48
43
|
import { executeSlashCommand } from '../utils/slashCommandProcessor'
|
|
44
|
+
import { captureScreenForChat } from '../utils/screenCapture'
|
|
45
|
+
import { useConversationCoordinator } from '../conversation/useConversationCoordinator'
|
|
46
|
+
import { isPersistedConversation } from '../conversation/projectNavigation'
|
|
47
|
+
import type { PromptOptions } from '../conversation/lifecycle'
|
|
49
48
|
|
|
50
49
|
|
|
51
|
-
const EXPRESSIONS = [
|
|
52
|
-
"Default",
|
|
53
|
-
"Dumb Cat",
|
|
54
|
-
"Dumb Cat Eye Roll",
|
|
55
|
-
"Take Photo",
|
|
56
|
-
"Poke",
|
|
57
|
-
"Cat Filter",
|
|
58
|
-
]
|
|
59
50
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
"Apron",
|
|
63
|
-
"Glasses",
|
|
64
|
-
"Hold Pen",
|
|
65
|
-
]
|
|
66
|
-
|
|
67
|
-
import { DEFAULT_CONFIG } from '../constants/config'
|
|
51
|
+
import { DEFAULT_CONFIG, migrateFontFamily, migrateTypographyScale } from '../constants/config'
|
|
52
|
+
import { BackgroundTerminals } from './BackgroundTerminals'
|
|
68
53
|
|
|
69
54
|
const LAST_WORKSPACE_PATH_KEY = 'mint:last-workspace-path'
|
|
55
|
+
const RECENT_WORKSPACE_PATHS_KEY = 'mint:recent-workspace-paths'
|
|
56
|
+
const MAX_RECENT_WORKSPACES = 8
|
|
70
57
|
const ACTIVE_CONVERSATION_ID_KEY = 'mint:active-conversation-id'
|
|
71
58
|
const LAST_ACTIVE_TIME_KEY = 'mint:last-active-timestamp'
|
|
72
59
|
const DESKTOP_INACTIVITY_THRESHOLD_MS = 30 * 60 * 1000 // 30 minutes
|
|
73
60
|
|
|
61
|
+
function readRecentWorkspacePaths(): string[] {
|
|
62
|
+
if (typeof window === 'undefined') return []
|
|
63
|
+
try {
|
|
64
|
+
const parsed: unknown = JSON.parse(window.localStorage.getItem(RECENT_WORKSPACE_PATHS_KEY) || '[]')
|
|
65
|
+
return Array.isArray(parsed)
|
|
66
|
+
? [...new Set(parsed.filter((path): path is string => typeof path === 'string' && Boolean(path.trim())))].slice(0, MAX_RECENT_WORKSPACES)
|
|
67
|
+
: []
|
|
68
|
+
} catch {
|
|
69
|
+
return []
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
74
73
|
function touchActiveTimestamp() {
|
|
75
74
|
if (typeof window === 'undefined') return
|
|
76
75
|
try {
|
|
@@ -103,25 +102,14 @@ function isDesktopRecentlyActive(): boolean {
|
|
|
103
102
|
// Unsent composer text, stashed per conversation so switching chats or
|
|
104
103
|
// reloading the page doesn't lose an in-progress message.
|
|
105
104
|
const DRAFT_KEY_PREFIX = 'mint:draft:'
|
|
106
|
-
const draftStorageKey = (id: string) => `${DRAFT_KEY_PREFIX}${id}`
|
|
107
105
|
function readDraft(id: string | null | undefined): string {
|
|
108
106
|
if (!id) return ''
|
|
109
107
|
try {
|
|
110
|
-
return window.localStorage.getItem(
|
|
108
|
+
return window.localStorage.getItem(`${DRAFT_KEY_PREFIX}${id}`) || ''
|
|
111
109
|
} catch {
|
|
112
110
|
return ''
|
|
113
111
|
}
|
|
114
112
|
}
|
|
115
|
-
function writeDraft(id: string | null | undefined, value: string) {
|
|
116
|
-
if (!id) return
|
|
117
|
-
try {
|
|
118
|
-
if (value) window.localStorage.setItem(draftStorageKey(id), value)
|
|
119
|
-
else window.localStorage.removeItem(draftStorageKey(id))
|
|
120
|
-
} catch {
|
|
121
|
-
/* private mode / quota — draft persistence is best-effort */
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
113
|
const SIDEBAR_DEFAULT_WIDTH = 264
|
|
126
114
|
const SIDEBAR_MIN_WIDTH = 200
|
|
127
115
|
const SIDEBAR_MAX_WIDTH = 420
|
|
@@ -172,6 +160,10 @@ function isRootOrNewChatRoute(): boolean {
|
|
|
172
160
|
target.includes('imagine') ||
|
|
173
161
|
target.includes('veo-studio') ||
|
|
174
162
|
target.includes('veo') ||
|
|
163
|
+
target.includes('code') ||
|
|
164
|
+
target === '/cli' ||
|
|
165
|
+
target === 'cli' ||
|
|
166
|
+
target.includes('cli-sessions') ||
|
|
175
167
|
target.includes('settings')
|
|
176
168
|
) {
|
|
177
169
|
return false
|
|
@@ -200,7 +192,7 @@ function activeConversationId() {
|
|
|
200
192
|
}
|
|
201
193
|
}
|
|
202
194
|
|
|
203
|
-
// When visiting Root URL ('/' or '/chat' without specific ID), always start a fresh New
|
|
195
|
+
// When visiting Root URL ('/' or '/chat' without specific ID), always start a fresh New chat
|
|
204
196
|
// (matching ChatGPT / Claude / Gemini industry-standard UX).
|
|
205
197
|
// Applies to Web UI always, and Desktop App upon cold launch / inactivity / new day.
|
|
206
198
|
if (isRootOrNewChatRoute()) {
|
|
@@ -234,31 +226,25 @@ const MOCK_WELCOME_INTERACTION = {
|
|
|
234
226
|
}
|
|
235
227
|
|
|
236
228
|
|
|
237
|
-
import SkillsView from './SkillsView'
|
|
238
|
-
import ScheduledTasksView from './ScheduledTasksView'
|
|
239
|
-
import LinkedFoldersView from './LinkedFoldersView'
|
|
240
|
-
import McpServersView from './McpServersView'
|
|
241
|
-
import PluginsView from './PluginsView'
|
|
242
229
|
import { isSupportedDocument } from '../utils/documentTypes'
|
|
243
|
-
import {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
import type { SlashResponse } from '../platform'
|
|
230
|
+
import { useProactiveSuggestions } from '@/proactiveSuggestions'
|
|
231
|
+
|
|
232
|
+
const WorkspacePanel = lazy(() => import('@/components/WorkspacePanel'))
|
|
233
|
+
const ToolSurfacePage = lazy(() => import('./ToolSurfacePage'))
|
|
234
|
+
const SkillsView = lazy(() => import('./SkillsView'))
|
|
235
|
+
const ScheduledTasksView = lazy(() => import('./ScheduledTasksView'))
|
|
236
|
+
const LinkedFoldersView = lazy(() => import('./LinkedFoldersView'))
|
|
237
|
+
const McpServersView = lazy(() => import('./McpServersView'))
|
|
238
|
+
const PluginsView = lazy(() => import('./PluginsView'))
|
|
239
|
+
const CliSessionsView = lazy(() => import('./CliSessionsView'))
|
|
240
|
+
const LibraryPage = lazy(() => import('./LibraryPage'))
|
|
241
|
+
const ImageStudioPanel = lazy(() => import('./ImageStudioPanel'))
|
|
242
|
+
const VeoStudioPanel = lazy(() => import('./VeoStudioPanel'))
|
|
243
|
+
const CommandPalette = lazy(() => import('./CommandPalette').then(({ CommandPalette: Component }) => ({ default: Component })))
|
|
244
|
+
|
|
245
|
+
function LazyPanelFallback() {
|
|
246
|
+
return <div className="auth-gate-loading" style={{ minHeight: 160 }}>Loading panel…</div>
|
|
247
|
+
}
|
|
262
248
|
|
|
263
249
|
function getInitialViewFromUrl(): DashboardView {
|
|
264
250
|
if (typeof window === 'undefined') return 'chat'
|
|
@@ -269,9 +255,10 @@ function getInitialViewFromUrl(): DashboardView {
|
|
|
269
255
|
if (target.includes('skills')) return 'skills'
|
|
270
256
|
if (target.includes('mcp')) return 'mcp'
|
|
271
257
|
if (target.includes('plugins')) return 'plugins'
|
|
272
|
-
if (target.includes('picture')) return 'pictures'
|
|
258
|
+
if (target.includes('picture') || target.includes('library')) return 'pictures'
|
|
273
259
|
if (target.includes('image-studio') || target.includes('imagine')) return 'imagine'
|
|
274
260
|
if (target.includes('veo-studio') || target.includes('veo')) return 'veo'
|
|
261
|
+
if (target.includes('code') || target === '/cli' || target === 'cli' || target.includes('cli-sessions')) return 'code'
|
|
275
262
|
return 'chat'
|
|
276
263
|
}
|
|
277
264
|
|
|
@@ -279,9 +266,10 @@ function getCleanPathForView(v: string, activeId?: string): string {
|
|
|
279
266
|
if (v === 'skills') return '/skills'
|
|
280
267
|
if (v === 'mcp') return '/mcp'
|
|
281
268
|
if (v === 'plugins') return '/plugins'
|
|
282
|
-
if (v === 'pictures') return '/
|
|
269
|
+
if (v === 'pictures') return '/library'
|
|
283
270
|
if (v === 'imagine') return '/image-studio'
|
|
284
271
|
if (v === 'veo' || v === 'veo_studio') return '/veo-studio'
|
|
272
|
+
if (v === 'code') return '/code'
|
|
285
273
|
if (v === 'settings') return '/settings'
|
|
286
274
|
if (activeId) return `/chat/${encodeURIComponent(activeId)}`
|
|
287
275
|
return '/chat'
|
|
@@ -317,27 +305,93 @@ 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
|
-
// state) so the URL-change effect below can read it
|
|
335
|
-
|
|
336
|
-
|
|
313
|
+
// state) so the URL-change effect below can read it.
|
|
314
|
+
const { conversation, actions: conversationActions } = useConversationCoordinator(
|
|
315
|
+
{
|
|
316
|
+
workspacePath: window.localStorage.getItem(LAST_WORKSPACE_PATH_KEY) || '',
|
|
317
|
+
message: readDraft(initialConversationId),
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
conversationId: initialConversationId,
|
|
321
|
+
draftKeyPrefix: DRAFT_KEY_PREFIX,
|
|
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
|
+
},
|
|
347
|
+
},
|
|
348
|
+
)
|
|
349
|
+
const {
|
|
350
|
+
conversationId, workspacePath, message, imageAttachments, videoAttachments, documentAttachment,
|
|
351
|
+
sending, sendingMessage, sendingImageCount, sendingVideoCount, streamedReply,
|
|
352
|
+
streamedResponse, agentProgress, interactions, hasOlderInteractions,
|
|
353
|
+
streamingConversationId, activeTurnId, agentActivitySnapshots, pendingApprovals,
|
|
354
|
+
sessionAutoApproved, chatSessions,
|
|
355
|
+
} = conversation
|
|
356
|
+
const activateConversation = (id: string) => {
|
|
357
|
+
conversationActions.activate(id)
|
|
358
|
+
}
|
|
337
359
|
// Web only in practice (desktop's window has no mobile-width breakpoint,
|
|
338
360
|
// so nothing ever sets this true there) — declared unconditionally so
|
|
339
361
|
// `changeView` can close it on every navigation without branching.
|
|
340
362
|
const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false)
|
|
363
|
+
const [screenCaptureOpen, setScreenCaptureOpen] = useState(false)
|
|
364
|
+
|
|
365
|
+
useEffect(() => {
|
|
366
|
+
if (!mobileSidebarOpen) return
|
|
367
|
+
const closeOnEscape = (event: KeyboardEvent) => {
|
|
368
|
+
if (event.key === 'Escape') setMobileSidebarOpen(false)
|
|
369
|
+
}
|
|
370
|
+
window.addEventListener('keydown', closeOnEscape)
|
|
371
|
+
return () => window.removeEventListener('keydown', closeOnEscape)
|
|
372
|
+
}, [mobileSidebarOpen])
|
|
373
|
+
const [workspaceRefreshRevision, setWorkspaceRefreshRevision] = useState(0)
|
|
374
|
+
const [recentWorkspacePaths, setRecentWorkspacePaths] = useState<string[]>(readRecentWorkspacePaths)
|
|
375
|
+
|
|
376
|
+
function rememberWorkspace(path: string) {
|
|
377
|
+
const recent = workspacePaths([path, ...readRecentWorkspacePaths()]).slice(0, MAX_RECENT_WORKSPACES)
|
|
378
|
+
try {
|
|
379
|
+
window.localStorage.setItem(RECENT_WORKSPACE_PATHS_KEY, JSON.stringify(recent))
|
|
380
|
+
} catch {
|
|
381
|
+
/* Keep the in-memory recent list usable when storage is unavailable. */
|
|
382
|
+
}
|
|
383
|
+
setRecentWorkspacePaths(recent)
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
useEffect(() => {
|
|
387
|
+
if (workspacePath.trim()) rememberWorkspace(workspacePath)
|
|
388
|
+
}, [workspacePath])
|
|
389
|
+
|
|
390
|
+
async function selectCodeHubFolder() {
|
|
391
|
+
const selected = await selectLinkedFolderPath()
|
|
392
|
+
if (selected) rememberWorkspace(selected)
|
|
393
|
+
return selected
|
|
394
|
+
}
|
|
341
395
|
|
|
342
396
|
const changeView = (newView: any, targetConversationId?: string) => {
|
|
343
397
|
setMobileSidebarOpen(false)
|
|
@@ -353,7 +407,10 @@ export default function MintDashboard() {
|
|
|
353
407
|
}
|
|
354
408
|
return prev
|
|
355
409
|
}
|
|
356
|
-
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
|
|
357
414
|
const targetPath = getCleanPathForView(mappedView, targetConversationId || conversationId)
|
|
358
415
|
if (typeof window !== 'undefined' && window.location.pathname !== targetPath) {
|
|
359
416
|
window.history.pushState({}, '', targetPath)
|
|
@@ -376,23 +433,13 @@ export default function MintDashboard() {
|
|
|
376
433
|
const urlSessionId = getConversationIdFromUrl()
|
|
377
434
|
if (urlSessionId && urlSessionId !== conversationId) {
|
|
378
435
|
window.localStorage.setItem(ACTIVE_CONVERSATION_ID_KEY, urlSessionId)
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
setInteractions(reversed)
|
|
383
|
-
setAgentActivitySnapshots((current) => mergeActivitySnapshots(current, reversed))
|
|
436
|
+
activateConversation(urlSessionId)
|
|
437
|
+
conversationActions.refreshHistory().catch((error) => {
|
|
438
|
+
console.error('Failed to load conversation history:', error)
|
|
384
439
|
})
|
|
385
440
|
} else if (!urlSessionId && isRootOrNewChatRoute()) {
|
|
386
441
|
const next = createConversationId()
|
|
387
|
-
|
|
388
|
-
setInteractions([])
|
|
389
|
-
setAgentActivitySnapshots({})
|
|
390
|
-
setStreamedReply('')
|
|
391
|
-
setStreamedResponse(null)
|
|
392
|
-
setMessage('')
|
|
393
|
-
setImageAttachments([])
|
|
394
|
-
setDocumentAttachment(null)
|
|
395
|
-
setAgentProgress([])
|
|
442
|
+
activateConversation(next)
|
|
396
443
|
}
|
|
397
444
|
}
|
|
398
445
|
window.addEventListener('popstate', handleUrlChange)
|
|
@@ -417,69 +464,99 @@ export default function MintDashboard() {
|
|
|
417
464
|
}, [])
|
|
418
465
|
const [status, setStatus] = useState<RuntimeStatus | null>(null)
|
|
419
466
|
const [error, setError] = useState('')
|
|
420
|
-
const [
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
const
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
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
|
+
|
|
436
513
|
const [thinkingExpanded, setThinkingExpanded] = useState<Record<string, boolean>>({})
|
|
437
514
|
const liveThinkingOpenRef = useRef(true)
|
|
438
|
-
const
|
|
439
|
-
const [videoAttachments, setVideoAttachments] = useState<Array<{ dataUri: string; name: string }>>([])
|
|
440
|
-
const [documentAttachment, setDocumentAttachment] = useState<DocumentAttachment | null>(null)
|
|
441
|
-
const [pendingApproval, setPendingApproval] = useState<any | null>(null)
|
|
442
|
-
const [sessionAutoApproved, setSessionAutoApproved] = useState(false)
|
|
443
|
-
const sessionAutoApprovedRef = useRef(false)
|
|
515
|
+
const liveExtendedThinkingOpenRef = useRef(true)
|
|
444
516
|
const [sidebarCollapsed, setSidebarCollapsed] = useState(() => window.localStorage.getItem('mint:sidebar-collapsed') === 'true')
|
|
517
|
+
const [toolSurfaces, setToolSurfaces] = useState<ToolSurface[]>([])
|
|
518
|
+
const [activeSurfaceId, setActiveSurfaceId] = useState<string | null>(null)
|
|
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)
|
|
523
|
+
const [terminalRightWidth, setTerminalRightWidth] = useState(() => {
|
|
524
|
+
const saved = Number(window.localStorage.getItem('mint:terminal-right-width'))
|
|
525
|
+
return saved >= 280 && saved <= 900 ? saved : 440
|
|
526
|
+
})
|
|
527
|
+
const terminalSaveTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
|
445
528
|
const [sidebarWidth, setSidebarWidth] = useState(() => {
|
|
446
529
|
const saved = Number(window.localStorage.getItem('mint:sidebar-width'))
|
|
447
530
|
return saved >= SIDEBAR_MIN_WIDTH && saved <= SIDEBAR_MAX_WIDTH ? saved : SIDEBAR_DEFAULT_WIDTH
|
|
448
531
|
})
|
|
449
|
-
const
|
|
532
|
+
const recentAgentChanges = parseFileChangesFromProgress(agentProgress)
|
|
533
|
+
const conversationReviewChanges = mergeFileChanges([
|
|
534
|
+
...interactions.map((interaction) => {
|
|
535
|
+
const interactionId = String(interaction.id)
|
|
536
|
+
return parseFileChangesFromProgress(agentActivitySnapshots[interactionId] ?? interaction.agentActivity ?? [])
|
|
537
|
+
}),
|
|
538
|
+
parseFileChangesFromProgress(agentProgress),
|
|
539
|
+
])
|
|
540
|
+
|
|
450
541
|
const [agentMode, setAgentMode] = useState(() => window.localStorage.getItem('mint:agent-mode') === 'true')
|
|
451
542
|
const [planMode, setPlanMode] = useState(() => window.localStorage.getItem('mint:plan-mode') === 'true')
|
|
452
543
|
const [toastMessage, setToastMessage] = useState('')
|
|
453
544
|
const [dashboardDataReady, setDashboardDataReady] = useState(false)
|
|
454
545
|
const [startupTimedOut, setStartupTimedOut] = useState(false)
|
|
455
546
|
const [settingsConfig, setSettingsConfig] = useState<any>(null)
|
|
456
|
-
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])
|
|
457
556
|
const chatEnd = useRef<HTMLDivElement | null>(null)
|
|
458
557
|
const lastNativePasteTimeRef = useRef(0)
|
|
459
|
-
const {
|
|
460
|
-
|
|
461
|
-
scale,
|
|
462
|
-
interactionEnabled,
|
|
463
|
-
showInteractionGuide,
|
|
464
|
-
isLocked,
|
|
465
|
-
layoutPreset,
|
|
466
|
-
expressionIndex,
|
|
467
|
-
accessoryIndex,
|
|
468
|
-
modelReady,
|
|
469
|
-
proactiveSuggestion,
|
|
470
|
-
setScale,
|
|
471
|
-
setIsLocked,
|
|
472
|
-
setExpressionIndex,
|
|
473
|
-
setAccessoryIndex,
|
|
474
|
-
setModelReady,
|
|
475
|
-
toggleModel,
|
|
476
|
-
changeLayoutPreset,
|
|
477
|
-
updateInteractionEnabled,
|
|
478
|
-
updateInteractionGuide,
|
|
479
|
-
dismissProactiveSuggestion,
|
|
480
|
-
handleProactiveAction,
|
|
481
|
-
} = useCompanionWidget((message) => setError(message))
|
|
482
|
-
const startupReady = (dashboardDataReady && modelReady) || startupTimedOut
|
|
558
|
+
const { proactiveSuggestion, dismissProactiveSuggestion, handleProactiveAction } = useProactiveSuggestions((message) => setError(message))
|
|
559
|
+
const startupReady = dashboardDataReady || startupTimedOut
|
|
483
560
|
|
|
484
561
|
const [mcpName, setMcpName] = useState('')
|
|
485
562
|
const [mcpCmd, setMcpCmd] = useState('')
|
|
@@ -590,64 +667,6 @@ export default function MintDashboard() {
|
|
|
590
667
|
}
|
|
591
668
|
}, [isSearchOpen])
|
|
592
669
|
|
|
593
|
-
// Another process — the CLI's interactive chat, a scheduled task, a
|
|
594
|
-
// messaging bridge — can add messages to this same conversation while
|
|
595
|
-
// this page is open, and nothing here would otherwise notice: Mint's
|
|
596
|
-
// surfaces only share a SQLite file, not a live event bus, so this polls
|
|
597
|
-
// for changes instead of requiring a manual refresh. Kept in a ref rather
|
|
598
|
-
// than the effect's own dependency array so a poll landing doesn't tear
|
|
599
|
-
// down and recreate the interval on every tick.
|
|
600
|
-
const interactionsRef = useRef(interactions)
|
|
601
|
-
useEffect(() => {
|
|
602
|
-
interactionsRef.current = interactions
|
|
603
|
-
}, [interactions])
|
|
604
|
-
|
|
605
|
-
// Load the saved draft whenever the active conversation changes. Declared
|
|
606
|
-
// before the persist effect so it runs first within the same commit. The
|
|
607
|
-
// first run is a no-op: `message`'s initial value already came from the
|
|
608
|
-
// lazy `useState` initializer above.
|
|
609
|
-
const draftLoadedRef = useRef(false)
|
|
610
|
-
useEffect(() => {
|
|
611
|
-
if (!draftLoadedRef.current) {
|
|
612
|
-
draftLoadedRef.current = true
|
|
613
|
-
return
|
|
614
|
-
}
|
|
615
|
-
skipDraftPersistRef.current = true
|
|
616
|
-
setMessage(readDraft(conversationId))
|
|
617
|
-
}, [conversationId])
|
|
618
|
-
|
|
619
|
-
// Persist the composer text for the current conversation (debounced).
|
|
620
|
-
useEffect(() => {
|
|
621
|
-
if (skipDraftPersistRef.current) {
|
|
622
|
-
skipDraftPersistRef.current = false
|
|
623
|
-
return
|
|
624
|
-
}
|
|
625
|
-
const timer = window.setTimeout(() => writeDraft(conversationId, message), 300)
|
|
626
|
-
return () => window.clearTimeout(timer)
|
|
627
|
-
}, [message, conversationId])
|
|
628
|
-
|
|
629
|
-
useEffect(() => {
|
|
630
|
-
if (view !== 'chat' || !conversationId) return
|
|
631
|
-
const interval = window.setInterval(async () => {
|
|
632
|
-
// Skip while backgrounded (nothing to show anyone) or mid-send (a
|
|
633
|
-
// fetch landing here would clobber the in-flight optimistic/streamed
|
|
634
|
-
// reply with stale history).
|
|
635
|
-
if (document.visibilityState !== 'visible' || sending) return
|
|
636
|
-
try {
|
|
637
|
-
const history = (await getRecentInteractions(50, conversationId, workspacePath || null)).reverse()
|
|
638
|
-
const current = interactionsRef.current
|
|
639
|
-
const currentLast = current[current.length - 1]
|
|
640
|
-
const nextLast = history[history.length - 1]
|
|
641
|
-
if (current.length === history.length && currentLast?.id === nextLast?.id) return
|
|
642
|
-
setInteractions(history)
|
|
643
|
-
setAgentActivitySnapshots((snapshots) => mergeActivitySnapshots(snapshots, history))
|
|
644
|
-
} catch {
|
|
645
|
-
// Best-effort — a transient fetch failure just waits for the next tick.
|
|
646
|
-
}
|
|
647
|
-
}, 3000)
|
|
648
|
-
return () => window.clearInterval(interval)
|
|
649
|
-
}, [view, conversationId, sending, workspacePath])
|
|
650
|
-
|
|
651
670
|
const filteredSessions = chatSessions.filter((session) => {
|
|
652
671
|
if (session.kind === 'cli' || session.id === 'conversation-default') return false
|
|
653
672
|
return session.title.toLowerCase().includes(searchQuery.toLowerCase())
|
|
@@ -699,28 +718,42 @@ export default function MintDashboard() {
|
|
|
699
718
|
const groupedSearchSessions = groupSessionsByDate(filteredSessions)
|
|
700
719
|
|
|
701
720
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
async function refreshChatSessions() {
|
|
710
|
-
const sessions = await listChatSessions()
|
|
711
|
-
setChatSessions(sessions)
|
|
712
|
-
}
|
|
721
|
+
const refreshHistory = conversationActions.refreshHistory
|
|
722
|
+
const refreshChatSessions = useCallback(async () => {
|
|
723
|
+
try { await conversationActions.refreshSessions() }
|
|
724
|
+
catch (error) { console.error('Failed to refresh chat sessions:', error) }
|
|
725
|
+
}, [conversationActions])
|
|
726
|
+
const loadOlderInteractions = conversationActions.loadOlder
|
|
713
727
|
|
|
714
|
-
const
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
728
|
+
const workspaceUpdateQueues = useRef(new Map<string, Promise<void>>())
|
|
729
|
+
const handleUpdateSessionWorkspace = useCallback(async (sessionId: string, targetPath: string | null) => {
|
|
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 () => {
|
|
733
|
+
await updateChatSessionWorkspace(sessionId, targetPath)
|
|
734
|
+
await refreshChatSessions()
|
|
735
|
+
})
|
|
736
|
+
workspaceUpdateQueues.current.set(sessionId, update)
|
|
718
737
|
try {
|
|
719
|
-
|
|
738
|
+
await update
|
|
739
|
+
} catch (e) {
|
|
740
|
+
console.error('Failed to update session workspace:', e)
|
|
741
|
+
setError(errorMessage(e))
|
|
720
742
|
} finally {
|
|
721
|
-
|
|
743
|
+
if (workspaceUpdateQueues.current.get(sessionId) === update) {
|
|
744
|
+
workspaceUpdateQueues.current.delete(sessionId)
|
|
745
|
+
}
|
|
722
746
|
}
|
|
723
|
-
}
|
|
747
|
+
}, [refreshChatSessions])
|
|
748
|
+
|
|
749
|
+
const handleBrowseFolderForMove = useCallback(async () => {
|
|
750
|
+
try {
|
|
751
|
+
const selected = await selectWorkspaceDirectory()
|
|
752
|
+
return selected || null
|
|
753
|
+
} catch {
|
|
754
|
+
return null
|
|
755
|
+
}
|
|
756
|
+
}, [])
|
|
724
757
|
|
|
725
758
|
useEffect(() => {
|
|
726
759
|
Promise.allSettled([
|
|
@@ -729,8 +762,9 @@ export default function MintDashboard() {
|
|
|
729
762
|
refreshChatSessions(),
|
|
730
763
|
window.settingsApi?.getSettings()
|
|
731
764
|
.then((loaded: any) => {
|
|
732
|
-
|
|
733
|
-
|
|
765
|
+
const migrated = migrateFontFamily(migrateTypographyScale(loaded))
|
|
766
|
+
setSettingsConfig(migrated)
|
|
767
|
+
applyThemeStyles({ ...DEFAULT_CONFIG, ...migrated })
|
|
734
768
|
}),
|
|
735
769
|
]).then((results) => {
|
|
736
770
|
const failure = results.find((result) => result.status === 'rejected')
|
|
@@ -739,21 +773,15 @@ export default function MintDashboard() {
|
|
|
739
773
|
})
|
|
740
774
|
const unlistenSpotlight = window.api.onSpotlightToChat((query) => {
|
|
741
775
|
changeView('chat')
|
|
742
|
-
|
|
743
|
-
})
|
|
744
|
-
const unlistenVision = window.api.onVisionReady((image) => {
|
|
745
|
-
createTrimmedImagePreview(image)
|
|
746
|
-
.catch(() => image)
|
|
747
|
-
.then((previewDataUri) => {
|
|
748
|
-
setImageAttachments((current) => [...current, { dataUri: image, previewDataUri, name: 'Screen capture' }])
|
|
749
|
-
})
|
|
776
|
+
conversationActions.compose(query)
|
|
750
777
|
})
|
|
751
778
|
const handleWindowFocus = () => {
|
|
752
779
|
getRuntimeStatus().then(setStatus).catch(() => {})
|
|
753
780
|
window.settingsApi?.getSettings?.().then((loaded: any) => {
|
|
754
781
|
if (loaded) {
|
|
755
|
-
|
|
756
|
-
|
|
782
|
+
const migrated = migrateFontFamily(migrateTypographyScale(loaded))
|
|
783
|
+
setSettingsConfig(migrated)
|
|
784
|
+
applyThemeStyles(migrated)
|
|
757
785
|
}
|
|
758
786
|
}).catch(() => {})
|
|
759
787
|
window.api?.clearAiNotifications?.()
|
|
@@ -761,26 +789,20 @@ export default function MintDashboard() {
|
|
|
761
789
|
window.addEventListener('focus', handleWindowFocus)
|
|
762
790
|
|
|
763
791
|
window.api?.onSettingsChanged?.((loaded: any) => {
|
|
764
|
-
|
|
765
|
-
|
|
792
|
+
const migrated = migrateFontFamily(migrateTypographyScale(loaded))
|
|
793
|
+
setSettingsConfig(migrated)
|
|
794
|
+
applyThemeStyles(migrated)
|
|
766
795
|
getRuntimeStatus().then(setStatus).catch(() => {})
|
|
767
796
|
})
|
|
768
797
|
|
|
769
|
-
const unlistenPromise = listen
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
console.error("Auto approval failed:", err)
|
|
773
|
-
})
|
|
774
|
-
} else {
|
|
775
|
-
setPendingApproval(event.payload)
|
|
776
|
-
notifyPendingApproval(event.payload)
|
|
777
|
-
}
|
|
798
|
+
const unlistenPromise = listen('tool-approval-requested', (event: { payload: any }) => {
|
|
799
|
+
const chatId = event.payload.chatId as string | undefined
|
|
800
|
+
if (chatId) conversationActions.receiveApproval(chatId, event.payload)
|
|
778
801
|
})
|
|
779
802
|
return () => {
|
|
780
803
|
window.removeEventListener('focus', handleWindowFocus)
|
|
781
804
|
unlistenPromise?.then?.((unlisten) => unlisten?.())
|
|
782
805
|
unlistenSpotlight?.then?.((unlisten) => unlisten?.())
|
|
783
|
-
unlistenVision?.then?.((unlisten) => unlisten?.())
|
|
784
806
|
}
|
|
785
807
|
}, [])
|
|
786
808
|
|
|
@@ -789,23 +811,195 @@ export default function MintDashboard() {
|
|
|
789
811
|
return () => window.clearTimeout(timer)
|
|
790
812
|
}, [])
|
|
791
813
|
|
|
792
|
-
useEffect(() => {
|
|
793
|
-
if (view === 'pictures' || view === 'imagine') refreshPictures().catch((reason: unknown) => setError(errorMessage(reason)))
|
|
794
|
-
}, [view])
|
|
795
|
-
|
|
796
814
|
useEffect(() => {
|
|
797
815
|
if (view === 'workspace' && !agentMode) updateAgentMode(true)
|
|
798
816
|
}, [view, agentMode])
|
|
799
817
|
|
|
800
|
-
useEffect(() => {
|
|
801
|
-
chatEnd.current?.scrollIntoView({ behavior: 'smooth' })
|
|
802
|
-
}, [interactions, sending, streamedReply, pendingApproval, agentProgress])
|
|
803
|
-
|
|
804
818
|
const showToast = (nextMessage: string) => {
|
|
805
819
|
setToastMessage(nextMessage)
|
|
806
820
|
setTimeout(() => setToastMessage((current) => current === nextMessage ? '' : current), 3000)
|
|
807
821
|
}
|
|
808
822
|
|
|
823
|
+
const openMintBrowser = async (url: string, throwOnError = false) => {
|
|
824
|
+
if (!isDesktopApp) {
|
|
825
|
+
window.open(url, '_blank', 'noopener,noreferrer')
|
|
826
|
+
return
|
|
827
|
+
}
|
|
828
|
+
try {
|
|
829
|
+
showToast('Opening Co-browsing browser (Mint Auto)...')
|
|
830
|
+
const { invoke } = await import('@tauri-apps/api/core')
|
|
831
|
+
await invoke('open_mint_browser', { url })
|
|
832
|
+
} catch (error) {
|
|
833
|
+
if (throwOnError) throw error
|
|
834
|
+
showToast(`Could not open browser: ${String(error)}`)
|
|
835
|
+
}
|
|
836
|
+
}
|
|
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
|
+
|
|
862
|
+
const openTerminalSurface = () => {
|
|
863
|
+
setToolsPanelOpen(true)
|
|
864
|
+
const id = `terminal:${Date.now()}:${Math.random().toString(36).slice(2, 7)}`
|
|
865
|
+
setToolSurfaces((current) => {
|
|
866
|
+
const terminalCount = current.filter((surface) => surface.kind === 'terminal').length
|
|
867
|
+
let baseTitle = 'terminal'
|
|
868
|
+
if (workspacePath && workspacePath.trim()) {
|
|
869
|
+
const cleanPath = workspacePath.trim().replace(/[\\/]+$/, '')
|
|
870
|
+
const folderName = cleanPath.split(/[\\/]/).pop()
|
|
871
|
+
if (folderName) baseTitle = folderName
|
|
872
|
+
}
|
|
873
|
+
const title = terminalCount === 0 ? baseTitle : `${baseTitle} (${terminalCount + 1})`
|
|
874
|
+
const next = { id, kind: 'terminal' as const, title }
|
|
875
|
+
setActiveSurfaceId(id)
|
|
876
|
+
return [...current, next]
|
|
877
|
+
})
|
|
878
|
+
}
|
|
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
|
+
|
|
891
|
+
const openNativeBrowser = (url = 'https://www.google.com') => {
|
|
892
|
+
void openMintBrowser(url)
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
const duplicateToolSurface = (id: string) => {
|
|
896
|
+
setToolSurfaces((current) => {
|
|
897
|
+
const source = current.find((surface) => surface.id === id)
|
|
898
|
+
if (!source) return current
|
|
899
|
+
if (source.kind === 'mods' || source.kind === 'background') return current
|
|
900
|
+
const duplicateId = `${source.kind}:${Date.now()}:${Math.random().toString(36).slice(2, 7)}`
|
|
901
|
+
const duplicate = { ...source, id: duplicateId, title: `${source.title} copy` } as ToolSurface
|
|
902
|
+
setActiveSurfaceId(duplicateId)
|
|
903
|
+
return [...current, duplicate]
|
|
904
|
+
})
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
const renameToolSurface = (id: string) => {
|
|
908
|
+
const source = toolSurfaces.find((surface) => surface.id === id)
|
|
909
|
+
if (!source) return
|
|
910
|
+
const nextTitle = window.prompt('Rename tab', source.title)?.trim()
|
|
911
|
+
if (!nextTitle) return
|
|
912
|
+
setToolSurfaces((current) => current.map((surface) => surface.id === id ? { ...surface, title: nextTitle } : surface))
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
const closeOtherToolSurfaces = (id: string) => {
|
|
916
|
+
setToolSurfaces((current) => current.filter((surface) => surface.id === id))
|
|
917
|
+
setActiveSurfaceId(id)
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
const toggleTerminalSurface = () => {
|
|
921
|
+
setToolSurfaces((current) => {
|
|
922
|
+
const terminal = current.find((surface) => surface.kind === 'terminal')
|
|
923
|
+
if (!terminal) {
|
|
924
|
+
const id = `terminal:${Date.now()}:${Math.random().toString(36).slice(2, 7)}`
|
|
925
|
+
setActiveSurfaceId(id)
|
|
926
|
+
return [...current, { id, kind: 'terminal' as const, title: 'Terminal' }]
|
|
927
|
+
}
|
|
928
|
+
setActiveSurfaceId((active) => active === terminal.id ? null : terminal.id)
|
|
929
|
+
return current
|
|
930
|
+
})
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
const checkForUpdatesFromMenu = async () => {
|
|
934
|
+
try {
|
|
935
|
+
const update = await window.settingsApi.checkForUpdates()
|
|
936
|
+
showToast(update?.available ? `Mint ${update.version} is available.` : 'Mint is up to date.')
|
|
937
|
+
} catch (error) {
|
|
938
|
+
showToast(`Could not check for updates: ${String(error)}`)
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
const openArtifactSurface = (artifact: import('./ArtifactPreviewPanel').ArtifactFile) => {
|
|
943
|
+
setToolsPanelOpen(true)
|
|
944
|
+
const fileName = artifact.path.replace(/\\/g, '/').split('/').pop() || artifact.path
|
|
945
|
+
artifact = { ...artifact, workspacePath: artifact.workspacePath ?? workspacePath }
|
|
946
|
+
const id = `preview:${JSON.stringify([artifact.workspacePath, artifact.path])}`
|
|
947
|
+
setToolSurfaces((current) => {
|
|
948
|
+
const next = current.filter((surface) => surface.id !== id)
|
|
949
|
+
return [...next, { id, kind: 'preview', title: fileName, artifact }]
|
|
950
|
+
})
|
|
951
|
+
setActiveSurfaceId(id)
|
|
952
|
+
}
|
|
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
|
+
|
|
962
|
+
const openReviewSurface = (review: Extract<ToolSurface, { kind: 'review' }>) => {
|
|
963
|
+
setToolsPanelOpen(true)
|
|
964
|
+
setToolSurfaces((current) => [...current.filter((surface) => surface.id !== review.id), review])
|
|
965
|
+
setActiveSurfaceId(review.id)
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
const openConversationReview = () => {
|
|
969
|
+
setToolsPanelOpen(true)
|
|
970
|
+
setToolSurfaces((current) => {
|
|
971
|
+
const reviewCount = current.filter((surface) => surface.kind === 'review').length
|
|
972
|
+
const id = `review:${Date.now()}:${Math.random().toString(36).slice(2, 7)}`
|
|
973
|
+
const title = reviewCount === 0 ? 'Review' : `Review (${reviewCount + 1})`
|
|
974
|
+
const next = {
|
|
975
|
+
id,
|
|
976
|
+
kind: 'review' as const,
|
|
977
|
+
title,
|
|
978
|
+
reviewTitle: 'All conversation changes',
|
|
979
|
+
changes: conversationReviewChanges,
|
|
980
|
+
}
|
|
981
|
+
setActiveSurfaceId(id)
|
|
982
|
+
return [...current, next]
|
|
983
|
+
})
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
const closeToolSurface = (id: string) => {
|
|
987
|
+
setToolSurfaces((current) => {
|
|
988
|
+
const index = current.findIndex((surface) => surface.id === id)
|
|
989
|
+
const next = current.filter((surface) => surface.id !== id)
|
|
990
|
+
setActiveSurfaceId((active) => {
|
|
991
|
+
if (active !== id) return active
|
|
992
|
+
return next[Math.max(0, index - 1)]?.id ?? null
|
|
993
|
+
})
|
|
994
|
+
return next
|
|
995
|
+
})
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
const closeAllToolSurfaces = () => {
|
|
999
|
+
setToolSurfaces([])
|
|
1000
|
+
setActiveSurfaceId(null)
|
|
1001
|
+
}
|
|
1002
|
+
|
|
809
1003
|
const toggleSidebar = () => {
|
|
810
1004
|
if (window.innerWidth <= 760) {
|
|
811
1005
|
setMobileSidebarOpen(false)
|
|
@@ -835,11 +1029,6 @@ export default function MintDashboard() {
|
|
|
835
1029
|
window.localStorage.setItem('mint:sidebar-width', String(clamped))
|
|
836
1030
|
}
|
|
837
1031
|
|
|
838
|
-
const updateSmartContext = (enabled: boolean) => {
|
|
839
|
-
window.localStorage.setItem('mint:smart-context', String(enabled))
|
|
840
|
-
setSmartContext(enabled)
|
|
841
|
-
}
|
|
842
|
-
|
|
843
1032
|
const updateAgentMode = (enabled: boolean) => {
|
|
844
1033
|
window.localStorage.setItem('mint:agent-mode', String(enabled))
|
|
845
1034
|
setAgentMode(enabled)
|
|
@@ -850,176 +1039,25 @@ export default function MintDashboard() {
|
|
|
850
1039
|
setPlanMode(enabled)
|
|
851
1040
|
}
|
|
852
1041
|
|
|
853
|
-
const updateWorkspacePath = (path: string) => {
|
|
1042
|
+
const updateWorkspacePath = (path: string, persist = true) => {
|
|
854
1043
|
const next = path.trim()
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
1044
|
+
conversationActions.selectWorkspace(next)
|
|
1045
|
+
const activeId = conversationActions.getSnapshot().conversationId
|
|
1046
|
+
if (persist && isPersistedConversation(activeId, chatSessions)) {
|
|
1047
|
+
void handleUpdateSessionWorkspace(activeId, next || null)
|
|
859
1048
|
}
|
|
860
|
-
setWorkspacePath(next)
|
|
861
1049
|
}
|
|
862
1050
|
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
sessionAutoApprovedRef.current = false
|
|
866
|
-
setSessionAutoApproved(false)
|
|
867
|
-
}
|
|
868
|
-
}, [sending])
|
|
869
|
-
|
|
870
|
-
async function handleApproval(approved: boolean, autoApproveSession = false, answer?: string) {
|
|
871
|
-
if (!pendingApproval) return
|
|
872
|
-
try {
|
|
873
|
-
if (autoApproveSession) {
|
|
874
|
-
sessionAutoApprovedRef.current = true
|
|
875
|
-
setSessionAutoApproved(true)
|
|
876
|
-
}
|
|
877
|
-
await submitToolApproval(pendingApproval.token, approved, answer)
|
|
878
|
-
} catch (reason) {
|
|
879
|
-
setError(errorMessage(reason))
|
|
880
|
-
} finally {
|
|
881
|
-
setPendingApproval(null)
|
|
882
|
-
}
|
|
883
|
-
}
|
|
1051
|
+
const handleApproval = conversationActions.resolveApproval
|
|
1052
|
+
const handleCancelMessage = conversationActions.cancel
|
|
884
1053
|
|
|
885
|
-
async function
|
|
886
|
-
if (
|
|
887
|
-
try {
|
|
888
|
-
await cancelChatMessage(streamingConversationId)
|
|
889
|
-
} catch (e) {
|
|
890
|
-
console.error("Failed to cancel message stream:", e)
|
|
891
|
-
} finally {
|
|
892
|
-
setSending(false)
|
|
893
|
-
setStreamingConversationId(null)
|
|
894
|
-
setSendingMessage('')
|
|
895
|
-
setSendingImageCount(0)
|
|
896
|
-
setSendingVideoCount(0)
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
async function sendPrompt(
|
|
901
|
-
promptText: string,
|
|
902
|
-
options: {
|
|
903
|
-
imageAttachments?: Array<{ dataUri: string; name: string; previewDataUri?: string }>
|
|
904
|
-
videoAttachments?: Array<{ dataUri: string; name: string }>
|
|
905
|
-
audioDataUri?: string | null
|
|
906
|
-
documentAttachment?: DocumentAttachment | null
|
|
907
|
-
systemInstruction?: string
|
|
908
|
-
clearComposer?: boolean
|
|
909
|
-
pinnedMcpServer?: string
|
|
910
|
-
forceAgentMode?: boolean
|
|
911
|
-
} = {},
|
|
912
|
-
) {
|
|
913
|
-
if (sending) return
|
|
914
|
-
const outgoingImages = options.imageAttachments ?? []
|
|
915
|
-
const outgoingVideos = options.videoAttachments ?? []
|
|
916
|
-
const outgoingDocument = options.documentAttachment ?? null
|
|
917
|
-
const shouldUseAgentMode = agentMode || options.forceAgentMode || promptText.toLowerCase().startsWith('search web:')
|
|
918
|
-
const outgoingImage = outgoingImages.map((img) => img.dataUri).join(' ')
|
|
919
|
-
const outgoingVideo = outgoingVideos.map((vid) => vid.dataUri).join(' ')
|
|
920
|
-
const outgoingImageCount = outgoingImages.length
|
|
921
|
-
setSending(true)
|
|
922
|
-
setStreamingConversationId(conversationId)
|
|
923
|
-
setSendingMessage(promptText)
|
|
924
|
-
setSendingImageCount(outgoingImageCount)
|
|
925
|
-
setSendingVideoCount(outgoingVideos.length)
|
|
1054
|
+
async function sendPrompt(promptText: string, options: PromptOptions = {}) {
|
|
1055
|
+
if (conversationActions.getSnapshot().sending) return
|
|
926
1056
|
setError('')
|
|
927
|
-
setStreamedReply('')
|
|
928
|
-
setStreamedResponse(null)
|
|
929
|
-
setAgentProgress([])
|
|
930
1057
|
liveThinkingOpenRef.current = true
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
setMessage('')
|
|
935
|
-
setImageAttachments([])
|
|
936
|
-
setVideoAttachments([])
|
|
937
|
-
setDocumentAttachment(null)
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
try {
|
|
941
|
-
const response = await streamChatMessage(
|
|
942
|
-
shouldUseAgentMode ? promptText : `/chat ${promptText}`,
|
|
943
|
-
(chunk) => setStreamedReply((current) => `${current}${chunk}`),
|
|
944
|
-
outgoingImage,
|
|
945
|
-
options.audioDataUri ?? null,
|
|
946
|
-
outgoingVideo,
|
|
947
|
-
options.systemInstruction ?? '',
|
|
948
|
-
(progress) => {
|
|
949
|
-
progressSnapshot.push(progress)
|
|
950
|
-
setAgentProgress((current) => trimAgentProgress([...current, progress]))
|
|
951
|
-
},
|
|
952
|
-
outgoingDocument,
|
|
953
|
-
workspacePath || null,
|
|
954
|
-
conversationId,
|
|
955
|
-
undefined,
|
|
956
|
-
shouldUseAgentMode ? planMode : false,
|
|
957
|
-
options.pinnedMcpServer ?? null,
|
|
958
|
-
(payload) => {
|
|
959
|
-
if (sessionAutoApprovedRef.current) {
|
|
960
|
-
submitToolApproval(payload.token, true).catch((err) => {
|
|
961
|
-
console.error("Auto approval failed:", err)
|
|
962
|
-
})
|
|
963
|
-
} else {
|
|
964
|
-
setPendingApproval(payload)
|
|
965
|
-
notifyPendingApproval(payload)
|
|
966
|
-
}
|
|
967
|
-
},
|
|
968
|
-
)
|
|
969
|
-
setStreamedResponse(response)
|
|
970
|
-
if (document.hidden || !document.hasFocus()) {
|
|
971
|
-
window.api?.notifyAiResponse?.(truncateForNotification(response.text))
|
|
972
|
-
}
|
|
973
|
-
const history = (await getRecentInteractions(50, conversationId, workspacePath || null)).reverse()
|
|
974
|
-
let enrichedHistory = history
|
|
975
|
-
if (progressSnapshot.length > 0) {
|
|
976
|
-
const newestInteraction = [...history]
|
|
977
|
-
.reverse()
|
|
978
|
-
.find((interaction) => interaction.aiText === response.text || interaction.userText === promptText) ?? history[history.length - 1]
|
|
979
|
-
if (newestInteraction?.id != null) {
|
|
980
|
-
const interactionKey = String(newestInteraction.id)
|
|
981
|
-
enrichedHistory = history.map((interaction) =>
|
|
982
|
-
interaction.id === newestInteraction.id
|
|
983
|
-
? { ...interaction, agentActivity: progressSnapshot }
|
|
984
|
-
: interaction,
|
|
985
|
-
)
|
|
986
|
-
setAgentActivitySnapshots((current) => ({
|
|
987
|
-
...current,
|
|
988
|
-
[interactionKey]: progressSnapshot.slice(),
|
|
989
|
-
}))
|
|
990
|
-
if (liveThinkingOpenRef.current) {
|
|
991
|
-
setThinkingExpanded((current) => ({
|
|
992
|
-
...current,
|
|
993
|
-
[interactionKey]: true,
|
|
994
|
-
}))
|
|
995
|
-
}
|
|
996
|
-
await saveInteractionAgentActivity(newestInteraction.id, progressSnapshot)
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
setInteractions(enrichedHistory)
|
|
1000
|
-
setAgentActivitySnapshots((current) => mergeActivitySnapshots(current, enrichedHistory))
|
|
1001
|
-
await refreshChatSessions()
|
|
1002
|
-
await refreshPictures()
|
|
1003
|
-
if (typeof window !== 'undefined') {
|
|
1004
|
-
const pathname = (window.location.pathname || '').replace(/\/+$/, '')
|
|
1005
|
-
const hash = (window.location.hash || '').replace(/^#\/?/, '').replace(/\/+$/, '')
|
|
1006
|
-
const target = (pathname || hash).toLowerCase()
|
|
1007
|
-
if (!target || target === '' || target === '/chat' || target === 'chat' || target === '/index.html' || target === 'index.html') {
|
|
1008
|
-
window.history.replaceState({}, '', `/chat/${encodeURIComponent(conversationId)}`)
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
getRuntimeStatus().then(setStatus).catch(() => {})
|
|
1012
|
-
setStreamedReply('')
|
|
1013
|
-
setStreamedResponse(null)
|
|
1014
|
-
} catch (reason) {
|
|
1015
|
-
setError(errorMessage(reason))
|
|
1016
|
-
} finally {
|
|
1017
|
-
setSending(false)
|
|
1018
|
-
setStreamingConversationId(null)
|
|
1019
|
-
setSendingMessage('')
|
|
1020
|
-
setSendingImageCount(0)
|
|
1021
|
-
setSendingVideoCount(0)
|
|
1022
|
-
}
|
|
1058
|
+
liveExtendedThinkingOpenRef.current = true
|
|
1059
|
+
setThinkingExpanded(current => ({ ...current, live: true, 'live-extended': true }))
|
|
1060
|
+
await conversationActions.sendPrompt(promptText, { ...options, agentMode, planMode })
|
|
1023
1061
|
}
|
|
1024
1062
|
|
|
1025
1063
|
async function handleSubmit(event: FormEvent<HTMLFormElement>) {
|
|
@@ -1036,15 +1074,12 @@ export default function MintDashboard() {
|
|
|
1036
1074
|
// comes back as `not_handled` and falls through to the TS processor below.
|
|
1037
1075
|
let engineResp: SlashResponse | null = null
|
|
1038
1076
|
try {
|
|
1039
|
-
engineResp = await runSlashCommand(trimmed, workspacePath || null)
|
|
1077
|
+
engineResp = await runSlashCommand(trimmed, workspacePath || null, conversationId)
|
|
1040
1078
|
} catch {
|
|
1041
1079
|
engineResp = null
|
|
1042
1080
|
}
|
|
1043
1081
|
if (engineResp && engineResp.kind !== 'not_handled') {
|
|
1044
|
-
|
|
1045
|
-
setImageAttachments([])
|
|
1046
|
-
setVideoAttachments([])
|
|
1047
|
-
setDocumentAttachment(null)
|
|
1082
|
+
conversationActions.clearComposer()
|
|
1048
1083
|
await handleEngineSlashResponse(trimmed, engineResp)
|
|
1049
1084
|
return
|
|
1050
1085
|
}
|
|
@@ -1052,22 +1087,49 @@ export default function MintDashboard() {
|
|
|
1052
1087
|
const slashResult = executeSlashCommand(trimmed)
|
|
1053
1088
|
|
|
1054
1089
|
if (slashResult.handled) {
|
|
1055
|
-
|
|
1056
|
-
setImageAttachments([])
|
|
1057
|
-
setVideoAttachments([])
|
|
1058
|
-
setDocumentAttachment(null)
|
|
1090
|
+
conversationActions.clearComposer()
|
|
1059
1091
|
|
|
1060
1092
|
if (slashResult.action === 'open_image_picker') {
|
|
1061
1093
|
document.getElementById('vision-file-input')?.click()
|
|
1062
1094
|
return
|
|
1063
1095
|
} else if (slashResult.action === 'paste_image') {
|
|
1064
1096
|
readClipboardImage().then((uri) => {
|
|
1065
|
-
if (uri)
|
|
1097
|
+
if (uri) conversationActions.attachImage({ dataUri: uri, name: 'Clipboard Image' })
|
|
1066
1098
|
}).catch(() => {})
|
|
1067
1099
|
return
|
|
1068
1100
|
} else if (slashResult.action === 'generate_veo') {
|
|
1069
1101
|
changeView('veo')
|
|
1070
1102
|
return
|
|
1103
|
+
} else if (slashResult.action === 'resume_session') {
|
|
1104
|
+
const query = (slashResult.payload?.query || '').trim().toLowerCase()
|
|
1105
|
+
const target = query
|
|
1106
|
+
? chatSessions.find((s) => s.id.toLowerCase() === query || s.id.toLowerCase().includes(query) || s.title.toLowerCase().includes(query))
|
|
1107
|
+
: chatSessions.find((s) => s.id !== conversationId)
|
|
1108
|
+
if (target) {
|
|
1109
|
+
activateConversation(target.id)
|
|
1110
|
+
const targetPath = getCleanPathForView('chat', target.id)
|
|
1111
|
+
window.history.replaceState({}, '', targetPath)
|
|
1112
|
+
const systemMsg = {
|
|
1113
|
+
id: Date.now(),
|
|
1114
|
+
userText: trimmed,
|
|
1115
|
+
aiText: `🔄 Resumed session: **${target.title}** (\`${target.id}\`)`,
|
|
1116
|
+
createdAt: new Date().toISOString(),
|
|
1117
|
+
provider: 'system',
|
|
1118
|
+
model: 'mint-cli',
|
|
1119
|
+
}
|
|
1120
|
+
conversationActions.appendInteraction(systemMsg)
|
|
1121
|
+
} else {
|
|
1122
|
+
const systemMsg = {
|
|
1123
|
+
id: Date.now(),
|
|
1124
|
+
userText: trimmed,
|
|
1125
|
+
aiText: query ? `⚠️ No matching session found for "${query}".` : 'ℹ️ No other sessions found to resume.',
|
|
1126
|
+
createdAt: new Date().toISOString(),
|
|
1127
|
+
provider: 'system',
|
|
1128
|
+
model: 'mint-cli',
|
|
1129
|
+
}
|
|
1130
|
+
conversationActions.appendInteraction(systemMsg)
|
|
1131
|
+
}
|
|
1132
|
+
return
|
|
1071
1133
|
}
|
|
1072
1134
|
|
|
1073
1135
|
if (slashResult.systemText) {
|
|
@@ -1079,7 +1141,7 @@ export default function MintDashboard() {
|
|
|
1079
1141
|
provider: 'system',
|
|
1080
1142
|
model: 'mint-cli',
|
|
1081
1143
|
}
|
|
1082
|
-
|
|
1144
|
+
conversationActions.appendInteraction(systemMsg)
|
|
1083
1145
|
saveSystemInteraction(conversationId, trimmed, slashResult.systemText || '', 'system', 'mint-cli').catch(() => {})
|
|
1084
1146
|
}
|
|
1085
1147
|
return
|
|
@@ -1125,12 +1187,7 @@ export default function MintDashboard() {
|
|
|
1125
1187
|
const objectUrl = createObjectUrlPreview(file).objectUrl
|
|
1126
1188
|
const dataUri = await readImage(file)
|
|
1127
1189
|
const previewDataUri = await createTrimmedImagePreview(dataUri).catch(() => dataUri)
|
|
1128
|
-
|
|
1129
|
-
if (current.some((item) => item.name === file.name && item.dataUri === dataUri)) {
|
|
1130
|
-
return current
|
|
1131
|
-
}
|
|
1132
|
-
return [...current, { dataUri, previewDataUri, objectUrl, name: file.name }]
|
|
1133
|
-
})
|
|
1190
|
+
conversationActions.attachImage({ dataUri, previewDataUri, objectUrl, name: file.name })
|
|
1134
1191
|
} catch (reason) {
|
|
1135
1192
|
setError(errorMessage(reason))
|
|
1136
1193
|
} finally {
|
|
@@ -1152,12 +1209,7 @@ export default function MintDashboard() {
|
|
|
1152
1209
|
reader.onerror = reject
|
|
1153
1210
|
reader.readAsDataURL(file)
|
|
1154
1211
|
})
|
|
1155
|
-
|
|
1156
|
-
if (current.some((item) => item.name === file.name && item.dataUri === dataUri)) {
|
|
1157
|
-
return current
|
|
1158
|
-
}
|
|
1159
|
-
return [...current, { dataUri, name: file.name }]
|
|
1160
|
-
})
|
|
1212
|
+
conversationActions.attachVideo({ dataUri, name: file.name })
|
|
1161
1213
|
} catch (reason) {
|
|
1162
1214
|
setError(errorMessage(reason))
|
|
1163
1215
|
} finally {
|
|
@@ -1203,7 +1255,7 @@ export default function MintDashboard() {
|
|
|
1203
1255
|
createTrimmedImagePreview(dataUri)
|
|
1204
1256
|
.catch(() => dataUri)
|
|
1205
1257
|
.then((previewDataUri) => {
|
|
1206
|
-
|
|
1258
|
+
conversationActions.attachImage({ dataUri, previewDataUri, name })
|
|
1207
1259
|
})
|
|
1208
1260
|
}
|
|
1209
1261
|
}).catch((err) => {
|
|
@@ -1226,7 +1278,7 @@ export default function MintDashboard() {
|
|
|
1226
1278
|
createTrimmedImagePreview(dataUri)
|
|
1227
1279
|
.catch(() => dataUri)
|
|
1228
1280
|
.then((previewDataUri) => {
|
|
1229
|
-
|
|
1281
|
+
conversationActions.attachImage({ dataUri, previewDataUri, name })
|
|
1230
1282
|
})
|
|
1231
1283
|
})
|
|
1232
1284
|
.catch((reason) => setError(errorMessage(reason)))
|
|
@@ -1242,7 +1294,7 @@ export default function MintDashboard() {
|
|
|
1242
1294
|
if (!isSupportedDocument(file.name)) {
|
|
1243
1295
|
throw new Error('Unsupported document type')
|
|
1244
1296
|
}
|
|
1245
|
-
|
|
1297
|
+
conversationActions.attachDocument({
|
|
1246
1298
|
filename: file.name,
|
|
1247
1299
|
dataUri: await readDocument(file),
|
|
1248
1300
|
})
|
|
@@ -1255,22 +1307,28 @@ export default function MintDashboard() {
|
|
|
1255
1307
|
|
|
1256
1308
|
function startWebSearch() {
|
|
1257
1309
|
updateAgentMode(true)
|
|
1258
|
-
|
|
1310
|
+
conversationActions.compose(message.trim() ? `Search web: ${message.trim()}` : 'Search web: ')
|
|
1259
1311
|
}
|
|
1260
1312
|
|
|
1261
|
-
async function selectWorkspace() {
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
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
|
+
)
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
function captureScreen() {
|
|
1326
|
+
setScreenCaptureOpen(true)
|
|
1271
1327
|
}
|
|
1272
1328
|
|
|
1273
|
-
async function
|
|
1329
|
+
async function startLiveTranslation() {
|
|
1330
|
+
setScreenCaptureOpen(false)
|
|
1331
|
+
await new Promise<void>((resolve) => requestAnimationFrame(() => requestAnimationFrame(() => resolve())))
|
|
1274
1332
|
try {
|
|
1275
1333
|
await window.api.startVision()
|
|
1276
1334
|
} catch (reason) {
|
|
@@ -1278,20 +1336,28 @@ export default function MintDashboard() {
|
|
|
1278
1336
|
}
|
|
1279
1337
|
}
|
|
1280
1338
|
|
|
1281
|
-
|
|
1339
|
+
function attachScreenCapture(image: string) {
|
|
1340
|
+
void createTrimmedImagePreview(image)
|
|
1341
|
+
.catch(() => image)
|
|
1342
|
+
.then((previewDataUri) => {
|
|
1343
|
+
conversationActions.attachImage({ dataUri: image, previewDataUri, name: 'Screen capture' })
|
|
1344
|
+
setScreenCaptureOpen(false)
|
|
1345
|
+
})
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
async function clearHistory(action: 'New chat' | 'Clear history', targetWorkspacePath?: string | null, targetView: 'chat' | 'workspace' = 'chat') {
|
|
1282
1349
|
try {
|
|
1283
1350
|
if (action === 'New chat') {
|
|
1284
1351
|
const next = createConversationId()
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
setViewState('chat')
|
|
1352
|
+
activateConversation(next)
|
|
1353
|
+
setViewState(targetView)
|
|
1354
|
+
|
|
1355
|
+
if (targetWorkspacePath !== undefined) {
|
|
1356
|
+
updateWorkspacePath(targetWorkspacePath || '')
|
|
1357
|
+
} else {
|
|
1358
|
+
updateWorkspacePath(workspacePath)
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1295
1361
|
if (typeof window !== 'undefined') {
|
|
1296
1362
|
const currentPath = (window.location.pathname || '').replace(/\/+$/, '')
|
|
1297
1363
|
if (currentPath !== '' && currentPath !== '/chat') {
|
|
@@ -1301,14 +1367,8 @@ export default function MintDashboard() {
|
|
|
1301
1367
|
return
|
|
1302
1368
|
} else {
|
|
1303
1369
|
if (!window.confirm(`${action} will clear the current conversation history. Continue?`)) return
|
|
1304
|
-
await
|
|
1370
|
+
await conversationActions.clearHistory()
|
|
1305
1371
|
}
|
|
1306
|
-
setInteractions([])
|
|
1307
|
-
setAgentActivitySnapshots({})
|
|
1308
|
-
setStreamedReply('')
|
|
1309
|
-
setStreamedResponse(null)
|
|
1310
|
-
setMessage('')
|
|
1311
|
-
setImageAttachments([])
|
|
1312
1372
|
} catch (reason) {
|
|
1313
1373
|
setError(errorMessage(reason))
|
|
1314
1374
|
}
|
|
@@ -1326,7 +1386,7 @@ export default function MintDashboard() {
|
|
|
1326
1386
|
provider: 'system',
|
|
1327
1387
|
model: 'mint-cli',
|
|
1328
1388
|
}
|
|
1329
|
-
|
|
1389
|
+
conversationActions.appendInteraction(systemMsg)
|
|
1330
1390
|
saveSystemInteraction(conversationId, userText, aiText, 'system', 'mint-cli').catch(() => {})
|
|
1331
1391
|
}
|
|
1332
1392
|
|
|
@@ -1354,13 +1414,19 @@ export default function MintDashboard() {
|
|
|
1354
1414
|
async function handleEngineSlashResponse(userText: string, resp: SlashResponse) {
|
|
1355
1415
|
switch (resp.kind) {
|
|
1356
1416
|
case 'message':
|
|
1357
|
-
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
|
+
}
|
|
1358
1421
|
break
|
|
1359
1422
|
case 'applied': {
|
|
1360
1423
|
const wsChange = resp.effects.find((e) => e.kind === 'workspace_changed') as
|
|
1361
1424
|
| { kind: 'workspace_changed'; path: string }
|
|
1362
1425
|
| undefined
|
|
1363
|
-
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
|
+
}
|
|
1364
1430
|
const planModeChange = resp.effects.find((e) => e.kind === 'plan_mode_changed') as
|
|
1365
1431
|
| { kind: 'plan_mode_changed'; enabled: boolean }
|
|
1366
1432
|
| undefined
|
|
@@ -1372,21 +1438,17 @@ export default function MintDashboard() {
|
|
|
1372
1438
|
// Render the same "✨ Gemini • model" chip the GUI's own /models shows.
|
|
1373
1439
|
// The engine already logged the `provider_change` row into the shared
|
|
1374
1440
|
// "cli" conversation, so this is just the immediate local echo.
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
model: 'provider_change',
|
|
1384
|
-
},
|
|
1385
|
-
])
|
|
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
|
+
})
|
|
1386
1449
|
}
|
|
1387
1450
|
if (resp.effects.some((e) => e.kind === 'history_cleared')) {
|
|
1388
|
-
await
|
|
1389
|
-
setInteractions([])
|
|
1451
|
+
await conversationActions.clearHistory().catch(() => {})
|
|
1390
1452
|
}
|
|
1391
1453
|
if (resp.markdown) pushSystemMessage(userText, resp.markdown)
|
|
1392
1454
|
if (resp.effects.some((e) => e.kind !== 'history_cleared' && e.kind !== 'workspace_changed')) {
|
|
@@ -1415,40 +1477,64 @@ export default function MintDashboard() {
|
|
|
1415
1477
|
|
|
1416
1478
|
function handleThinkingExpandedChange(key: string, open: boolean) {
|
|
1417
1479
|
if (key === 'live') liveThinkingOpenRef.current = open
|
|
1480
|
+
if (key === 'live-extended') liveExtendedThinkingOpenRef.current = open
|
|
1418
1481
|
setThinkingExpanded((current) => ({ ...current, [key]: open }))
|
|
1419
1482
|
}
|
|
1420
1483
|
|
|
1421
|
-
async function selectConversation(id: string) {
|
|
1484
|
+
async function selectConversation(id: string, selectedSession?: ChatSession, targetView: 'chat' | 'workspace' = 'chat') {
|
|
1422
1485
|
window.localStorage.setItem(ACTIVE_CONVERSATION_ID_KEY, id)
|
|
1423
1486
|
touchActiveTimestamp()
|
|
1424
|
-
|
|
1425
|
-
changeView(
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1487
|
+
activateConversation(id)
|
|
1488
|
+
changeView(targetView, id)
|
|
1489
|
+
const session = selectedSession ?? chatSessions.find((item) => item.id === id)
|
|
1490
|
+
if (session) {
|
|
1491
|
+
if (session.workspacePath) {
|
|
1492
|
+
if (session.workspacePath !== workspacePath) {
|
|
1493
|
+
updateWorkspacePath(session.workspacePath, false)
|
|
1494
|
+
}
|
|
1495
|
+
} else {
|
|
1496
|
+
if (workspacePath) {
|
|
1497
|
+
updateWorkspacePath('', false)
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
try {
|
|
1502
|
+
await conversationActions.refreshHistory()
|
|
1503
|
+
} catch (reason) {
|
|
1504
|
+
setError(errorMessage(reason))
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
const handleNewChatInProject = (targetPath: string) => {
|
|
1509
|
+
void clearHistory('New chat', targetPath)
|
|
1436
1510
|
}
|
|
1437
1511
|
|
|
1438
1512
|
async function deleteConversation(id: string) {
|
|
1439
|
-
if (id === 'cli')
|
|
1513
|
+
if (id === 'cli') {
|
|
1514
|
+
if (!window.confirm('Clear history for default CLI session? This cannot be undone.')) return
|
|
1515
|
+
try {
|
|
1516
|
+
await clearChatHistory('cli')
|
|
1517
|
+
await refreshHistory()
|
|
1518
|
+
await refreshChatSessions()
|
|
1519
|
+
showToast('CLI session history cleared')
|
|
1520
|
+
} catch (reason) {
|
|
1521
|
+
setError(errorMessage(reason))
|
|
1522
|
+
}
|
|
1523
|
+
return
|
|
1524
|
+
}
|
|
1440
1525
|
const session = chatSessions.find((item) => item.id === id)
|
|
1441
1526
|
const title = session?.title || 'this chat'
|
|
1442
1527
|
if (!window.confirm(`Delete "${title}"? This will remove the conversation and its messages.`)) return
|
|
1443
1528
|
|
|
1444
1529
|
try {
|
|
1445
1530
|
await deleteChatSession(id)
|
|
1446
|
-
const remaining = chatSessions.filter((item) => item.id !== id && item.kind !== 'cli' && item.id !== 'conversation-default')
|
|
1447
|
-
const
|
|
1531
|
+
const remaining = chatSessions.filter((item) => item.id !== id && item.kind !== 'cli' && !item.id.startsWith('cli') && item.id !== 'conversation-default')
|
|
1532
|
+
const currentChatId = conversationActions.getSnapshot().conversationId
|
|
1533
|
+
const nextActive = id === currentChatId
|
|
1448
1534
|
? (remaining[0]?.id ?? createConversationId())
|
|
1449
|
-
:
|
|
1535
|
+
: currentChatId
|
|
1450
1536
|
|
|
1451
|
-
if (nextActive !==
|
|
1537
|
+
if (nextActive !== currentChatId) {
|
|
1452
1538
|
if (remaining.length > 0 && remaining[0]?.id) {
|
|
1453
1539
|
window.localStorage.setItem(ACTIVE_CONVERSATION_ID_KEY, nextActive)
|
|
1454
1540
|
if (typeof window !== 'undefined') {
|
|
@@ -1460,21 +1546,11 @@ export default function MintDashboard() {
|
|
|
1460
1546
|
window.history.replaceState({}, '', '/chat')
|
|
1461
1547
|
}
|
|
1462
1548
|
}
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
const history = await getRecentInteractions(50, nextActive, workspacePath || null)
|
|
1466
|
-
const reversed = history.reverse()
|
|
1467
|
-
setInteractions(reversed)
|
|
1468
|
-
setAgentActivitySnapshots((current) => mergeActivitySnapshots(current, reversed))
|
|
1549
|
+
activateConversation(nextActive)
|
|
1550
|
+
await conversationActions.refreshHistory()
|
|
1469
1551
|
}
|
|
1470
1552
|
|
|
1471
1553
|
await refreshChatSessions()
|
|
1472
|
-
if (id !== conversationId) return
|
|
1473
|
-
setStreamedReply('')
|
|
1474
|
-
setStreamedResponse(null)
|
|
1475
|
-
setMessage('')
|
|
1476
|
-
setImageAttachments([])
|
|
1477
|
-
setDocumentAttachment(null)
|
|
1478
1554
|
} catch (reason) {
|
|
1479
1555
|
setError(errorMessage(reason))
|
|
1480
1556
|
}
|
|
@@ -1652,62 +1728,157 @@ export default function MintDashboard() {
|
|
|
1652
1728
|
}
|
|
1653
1729
|
}
|
|
1654
1730
|
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
)
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
}
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1731
|
+
const chatConversation: ConversationViewModel = {
|
|
1732
|
+
interactions,
|
|
1733
|
+
hasOlder: hasOlderInteractions,
|
|
1734
|
+
sendingInteractionId: streamingConversationId === conversationId ? activeTurnId : null,
|
|
1735
|
+
sending: sending && streamingConversationId === conversationId,
|
|
1736
|
+
sendingMessage: streamingConversationId === conversationId ? sendingMessage : '',
|
|
1737
|
+
sendingImageCount: streamingConversationId === conversationId ? sendingImageCount : 0,
|
|
1738
|
+
sendingVideoCount: streamingConversationId === conversationId ? sendingVideoCount : 0,
|
|
1739
|
+
streamedReply: streamingConversationId === conversationId ? streamedReply : '',
|
|
1740
|
+
streamedResponse: streamingConversationId === conversationId ? streamedResponse : null,
|
|
1741
|
+
agentProgress: streamingConversationId === conversationId ? agentProgress : [],
|
|
1742
|
+
agentActivitySnapshots,
|
|
1743
|
+
thinkingExpanded,
|
|
1744
|
+
message,
|
|
1745
|
+
imageAttachments,
|
|
1746
|
+
videoAttachments,
|
|
1747
|
+
documentName: documentAttachment?.filename ?? '',
|
|
1748
|
+
pendingApproval: pendingApprovals[conversationId] ?? null,
|
|
1749
|
+
agentMode,
|
|
1750
|
+
planMode,
|
|
1751
|
+
status,
|
|
1752
|
+
workspacePath,
|
|
1753
|
+
chatId: conversationId,
|
|
1754
|
+
recentWorkspacePaths: availableWorkspacePaths,
|
|
1755
|
+
chatEnd,
|
|
1756
|
+
welcomeInteraction: MOCK_WELCOME_INTERACTION,
|
|
1757
|
+
settingsConfig,
|
|
1758
|
+
slashChoice: pendingSlashChoice,
|
|
1759
|
+
isCliSession: conversationId.startsWith('cli') || conversationId === 'cli',
|
|
1760
|
+
cliSessionId: conversationId.startsWith('cli') ? conversationId : undefined,
|
|
1761
|
+
conversationTitle: chatSessions.find((session) => session.id === conversationId)?.title,
|
|
1762
|
+
}
|
|
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),
|
|
1774
|
+
onLoadOlder: loadOlderInteractions,
|
|
1775
|
+
onThinkingExpandedChange: handleThinkingExpandedChange,
|
|
1776
|
+
onSubmit: handleSubmit,
|
|
1777
|
+
onSelectImage: selectImage,
|
|
1778
|
+
onSelectVideo: selectVideo,
|
|
1779
|
+
onSelectDocument: selectDocument,
|
|
1780
|
+
onPasteImage: pasteImage,
|
|
1781
|
+
onSetMessage: conversationActions.compose,
|
|
1782
|
+
onSendVoiceMessage: sendVoiceMessage,
|
|
1783
|
+
onRemoveImage: conversationActions.removeImage,
|
|
1784
|
+
onRemoveVideo: conversationActions.removeVideo,
|
|
1785
|
+
onRemoveDocument: () => conversationActions.attachDocument(null),
|
|
1786
|
+
onStartWebSearch: startWebSearch,
|
|
1787
|
+
onCaptureScreen: captureScreen,
|
|
1788
|
+
onSetAgentMode: updateAgentMode,
|
|
1789
|
+
onSetPlanMode: isDesktopApp ? updatePlanMode : undefined,
|
|
1790
|
+
onSetProvider: changeProvider,
|
|
1791
|
+
onSelectWorkspace: selectWorkspace,
|
|
1792
|
+
onWorkspaceChanged: () => setWorkspaceRefreshRevision((revision) => revision + 1),
|
|
1793
|
+
onApproval: handleApproval,
|
|
1794
|
+
onUpdateSettings: (updated) => setSettingsConfig(updated),
|
|
1795
|
+
onSetModel: changeModel,
|
|
1796
|
+
onSelectModelAndProvider: changeProviderAndModel,
|
|
1797
|
+
onCancelMessage: handleCancelMessage,
|
|
1798
|
+
onClearMessages: () => clearHistory('Clear history'),
|
|
1799
|
+
onSetGeminiLiveVoice: changeGeminiLiveVoice,
|
|
1800
|
+
onToggleMobileSidebar: () => setMobileSidebarOpen(!mobileSidebarOpen),
|
|
1801
|
+
onBackToCode: () => changeView('code'),
|
|
1802
|
+
onOpenArtifact: isDesktopApp ? openArtifactSurface : undefined,
|
|
1803
|
+
onOpenReview: isDesktopApp ? openReviewSurface : undefined,
|
|
1701
1804
|
}
|
|
1702
1805
|
|
|
1703
1806
|
return (
|
|
1704
1807
|
<div className={`app-container ${startupReady ? '' : 'is-loading'}`}>
|
|
1808
|
+
{screenCaptureOpen && (
|
|
1809
|
+
<ScreenCaptureDialog
|
|
1810
|
+
onClose={() => setScreenCaptureOpen(false)}
|
|
1811
|
+
onAttach={attachScreenCapture}
|
|
1812
|
+
capture={() => captureScreenForChat(isDesktopApp)}
|
|
1813
|
+
onLiveTranslate={isDesktopApp ? () => { void startLiveTranslation() } : undefined}
|
|
1814
|
+
/>
|
|
1815
|
+
)}
|
|
1816
|
+
{isDesktopApp && (
|
|
1817
|
+
<DesktopTitlebar
|
|
1818
|
+
sidebarCollapsed={sidebarCollapsed}
|
|
1819
|
+
onToggleSidebar={toggleSidebar}
|
|
1820
|
+
onNewChat={() => clearHistory('New chat')}
|
|
1821
|
+
onOpenWorkspace={() => selectWorkspace(undefined, true)}
|
|
1822
|
+
onOpenTerminal={openTerminalSurface}
|
|
1823
|
+
onToggleTerminal={toggleTerminalSurface}
|
|
1824
|
+
onOpenBrowser={() => openNativeBrowser()}
|
|
1825
|
+
toolsPanelOpen={toolsPanelOpen}
|
|
1826
|
+
backgroundTaskCount={backgroundTaskCount}
|
|
1827
|
+
onToggleToolsPanel={() => setToolsPanelOpen((open) => !open)}
|
|
1828
|
+
onOpenSettings={() => changeView('settings')}
|
|
1829
|
+
onCheckForUpdates={checkForUpdatesFromMenu}
|
|
1830
|
+
onShowAbout={() => showToast('Mint Agent — AI workspace')}
|
|
1831
|
+
workspacePath={workspacePath}
|
|
1832
|
+
workspaceActive={view === 'workspace' && !toolsPanelOpen}
|
|
1833
|
+
workspaceRevision={workspaceRefreshRevision}
|
|
1834
|
+
sending={sending}
|
|
1835
|
+
onWorkspaceUndoError={showToast}
|
|
1836
|
+
terminalCount={toolSurfaces.filter((surface) => surface.kind === 'terminal').length}
|
|
1837
|
+
chatId={conversationId}
|
|
1838
|
+
liveProgress={streamingConversationId === conversationId ? agentProgress : []}
|
|
1839
|
+
recentChanges={recentAgentChanges}
|
|
1840
|
+
onOpenReview={(changes) => openReviewSurface({ id: `review:workspace:${Date.now()}`, kind: 'review', title: 'Review', reviewTitle: 'Recent agent changes', changes })}
|
|
1841
|
+
onRefreshWorkspace={() => setWorkspaceRefreshRevision((revision) => revision + 1)}
|
|
1842
|
+
/>
|
|
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('')} />}
|
|
1705
1852
|
<div
|
|
1706
|
-
className={`app-body ${(sidebarCollapsed && window.innerWidth > 760) ? 'sidebar-collapsed' : ''} ${view === 'pictures' ? 'pictures-open' : ''} ${mobileSidebarOpen ? 'mobile-sidebar-open' : ''}`}
|
|
1707
|
-
style={{
|
|
1853
|
+
className={`app-body ${(sidebarCollapsed && window.innerWidth > 760) ? 'sidebar-collapsed' : ''} ${view === 'pictures' ? 'pictures-open' : ''} ${mobileSidebarOpen ? 'mobile-sidebar-open' : ''} ${toolsPanelOpen ? 'tool-surface-active' : ''}`}
|
|
1854
|
+
style={{
|
|
1855
|
+
'--sidebar-expanded-width': `${sidebarWidth}px`,
|
|
1856
|
+
'--terminal-dock-size': `${terminalRightWidth}px`,
|
|
1857
|
+
// A terminal shown in the right tool surface resizes the surface
|
|
1858
|
+
// itself (and therefore the remaining chat area), not just its
|
|
1859
|
+
// inner xterm viewport.
|
|
1860
|
+
'--tool-surface-width': `${terminalRightWidth}px`,
|
|
1861
|
+
} as CSSProperties}
|
|
1708
1862
|
>
|
|
1863
|
+
{!isDesktopApp && view !== 'chat' && (
|
|
1864
|
+
<button
|
|
1865
|
+
type="button"
|
|
1866
|
+
className="web-mobile-nav-btn"
|
|
1867
|
+
aria-label="Open navigation menu"
|
|
1868
|
+
aria-expanded={mobileSidebarOpen}
|
|
1869
|
+
onClick={() => setMobileSidebarOpen(true)}
|
|
1870
|
+
>
|
|
1871
|
+
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" aria-hidden="true">
|
|
1872
|
+
<line x1="3" y1="6" x2="21" y2="6" />
|
|
1873
|
+
<line x1="3" y1="12" x2="21" y2="12" />
|
|
1874
|
+
<line x1="3" y1="18" x2="21" y2="18" />
|
|
1875
|
+
</svg>
|
|
1876
|
+
</button>
|
|
1877
|
+
)}
|
|
1709
1878
|
{mobileSidebarOpen && (
|
|
1710
|
-
<
|
|
1879
|
+
<button
|
|
1880
|
+
type="button"
|
|
1881
|
+
aria-label="Close navigation menu"
|
|
1711
1882
|
className="sidebar-backdrop"
|
|
1712
1883
|
onClick={() => setMobileSidebarOpen(false)}
|
|
1713
1884
|
style={{
|
|
@@ -1722,17 +1893,11 @@ export default function MintDashboard() {
|
|
|
1722
1893
|
}}
|
|
1723
1894
|
/>
|
|
1724
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>}
|
|
1725
1897
|
<DashboardSidebar
|
|
1726
1898
|
view={view}
|
|
1727
1899
|
sidebarCollapsed={sidebarCollapsed}
|
|
1728
|
-
modelVisible={modelVisible}
|
|
1729
1900
|
sending={sending}
|
|
1730
|
-
expressionIndex={expressionIndex}
|
|
1731
|
-
accessoryIndex={accessoryIndex}
|
|
1732
|
-
expressions={EXPRESSIONS}
|
|
1733
|
-
accessories={ACCESSORIES}
|
|
1734
|
-
interactionEnabled={interactionEnabled}
|
|
1735
|
-
showInteractionGuide={showInteractionGuide}
|
|
1736
1901
|
onToggleSidebar={toggleSidebar}
|
|
1737
1902
|
onSidebarResize={handleSidebarResize}
|
|
1738
1903
|
onSidebarResizeEnd={handleSidebarResizeEnd}
|
|
@@ -1743,18 +1908,17 @@ export default function MintDashboard() {
|
|
|
1743
1908
|
onDeleteConversation={deleteConversation}
|
|
1744
1909
|
onRenameConversation={renameConversation}
|
|
1745
1910
|
onSetView={changeView}
|
|
1746
|
-
onToggleModel={toggleModel}
|
|
1747
|
-
onSetExpressionIndex={setExpressionIndex}
|
|
1748
|
-
onSetAccessoryIndex={setAccessoryIndex}
|
|
1749
|
-
onSetInteractionEnabled={updateInteractionEnabled}
|
|
1750
|
-
onSetShowInteractionGuide={updateInteractionGuide}
|
|
1751
|
-
onShowToast={showToast}
|
|
1752
1911
|
isSearchOpen={isSearchOpen}
|
|
1753
1912
|
onSetSearchOpen={setIsSearchOpen}
|
|
1754
1913
|
showWorkspaceTab={isDesktopApp}
|
|
1755
1914
|
promoteMediaStudios={!isDesktopApp}
|
|
1915
|
+
activeWorkspacePath={workspacePath}
|
|
1916
|
+
recentWorkspacePaths={recentWorkspacePaths}
|
|
1917
|
+
onBrowseFolder={isDesktopApp ? handleBrowseFolderForMove : undefined}
|
|
1918
|
+
onUpdateSessionWorkspace={handleUpdateSessionWorkspace}
|
|
1919
|
+
onNewChatInProject={handleNewChatInProject}
|
|
1756
1920
|
/>
|
|
1757
|
-
<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}>
|
|
1758
1922
|
{proactiveSuggestion && (
|
|
1759
1923
|
<div className="proactive-bar" style={{ position: 'absolute', top: 0, left: 0, right: 0, zIndex: 100 }}>
|
|
1760
1924
|
<div className="proactive-header">
|
|
@@ -1777,201 +1941,215 @@ export default function MintDashboard() {
|
|
|
1777
1941
|
</div>
|
|
1778
1942
|
</div>
|
|
1779
1943
|
)}
|
|
1780
|
-
{pendingSlashChoice && (
|
|
1781
|
-
<div className="proactive-bar" style={{ position: 'absolute', top: 0, left: 0, right: 0, zIndex: 100 }}>
|
|
1782
|
-
<div className="proactive-header">
|
|
1783
|
-
<span className="proactive-icon">⚡</span>
|
|
1784
|
-
<div className="proactive-message">{pendingSlashChoice.title}</div>
|
|
1785
|
-
<button className="proactive-dismiss-btn" onClick={() => setPendingSlashChoice(null)}>
|
|
1786
|
-
Dismiss
|
|
1787
|
-
</button>
|
|
1788
|
-
</div>
|
|
1789
|
-
<div className="proactive-chips">
|
|
1790
|
-
{pendingSlashChoice.options.map((opt) => (
|
|
1791
|
-
<button
|
|
1792
|
-
key={opt.value}
|
|
1793
|
-
className="suggestion-chip"
|
|
1794
|
-
onClick={() => {
|
|
1795
|
-
const next = `${pendingSlashChoice.command} ${opt.value}`
|
|
1796
|
-
setPendingSlashChoice(null)
|
|
1797
|
-
runSlashCommand(next, workspacePath || null)
|
|
1798
|
-
.then((r) => handleEngineSlashResponse(next, r))
|
|
1799
|
-
.catch(() => {})
|
|
1800
|
-
}}
|
|
1801
|
-
>
|
|
1802
|
-
{opt.label}
|
|
1803
|
-
</button>
|
|
1804
|
-
))}
|
|
1805
|
-
</div>
|
|
1806
|
-
</div>
|
|
1807
|
-
)}
|
|
1808
1944
|
{view === 'workspace' && (
|
|
1809
|
-
<
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1945
|
+
<Suspense fallback={<LazyPanelFallback />}>
|
|
1946
|
+
<WorkspacePanel
|
|
1947
|
+
key={workspacePath}
|
|
1948
|
+
agentMode={agentMode}
|
|
1949
|
+
sending={sending}
|
|
1950
|
+
workspacePath={workspacePath}
|
|
1951
|
+
onEnableAgentMode={() => updateAgentMode(true)}
|
|
1952
|
+
onSetMessage={conversationActions.compose}
|
|
1953
|
+
onWorkspaceReady={updateWorkspacePath}
|
|
1954
|
+
refreshRevision={workspaceRefreshRevision}
|
|
1955
|
+
onOpenHtml={openHtmlFile}
|
|
1956
|
+
onOpenPreview={openWorkspacePreview}
|
|
1957
|
+
/>
|
|
1958
|
+
</Suspense>
|
|
1817
1959
|
)}
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
isActive={modelVisible && view !== 'pictures' && view !== 'workspace' && view !== 'imagine' && view !== 'veo' && view !== 'skills' && view !== 'mcp' && view !== 'plugins'}
|
|
1824
|
-
layoutPreset={layoutPreset}
|
|
1825
|
-
sending={sending}
|
|
1826
|
-
interactionEnabled={interactionEnabled}
|
|
1827
|
-
showInteractionGuide={showInteractionGuide}
|
|
1828
|
-
toastMessage={toastMessage}
|
|
1829
|
-
onSetScale={setScale}
|
|
1830
|
-
onSetLocked={setIsLocked}
|
|
1831
|
-
onSetView={changeView}
|
|
1832
|
-
onChangeLayoutPreset={changeLayoutPreset}
|
|
1833
|
-
onDismissToast={() => setToastMessage('')}
|
|
1834
|
-
onInteract={handleModelInteraction}
|
|
1835
|
-
onModelLoadComplete={() => setModelReady(true)}
|
|
1836
|
-
/>
|
|
1837
|
-
<ChatPanel
|
|
1838
|
-
interactions={interactions}
|
|
1839
|
-
sending={sending && streamingConversationId === conversationId}
|
|
1840
|
-
sendingMessage={streamingConversationId === conversationId ? sendingMessage : ''}
|
|
1841
|
-
sendingImageCount={streamingConversationId === conversationId ? sendingImageCount : 0}
|
|
1842
|
-
streamedReply={streamingConversationId === conversationId ? streamedReply : ''}
|
|
1843
|
-
streamedResponse={streamingConversationId === conversationId ? streamedResponse : null}
|
|
1844
|
-
agentProgress={streamingConversationId === conversationId ? agentProgress : []}
|
|
1845
|
-
sendingVideoCount={streamingConversationId === conversationId ? sendingVideoCount : 0}
|
|
1846
|
-
agentActivitySnapshots={agentActivitySnapshots}
|
|
1847
|
-
thinkingExpanded={thinkingExpanded}
|
|
1848
|
-
onThinkingExpandedChange={handleThinkingExpandedChange}
|
|
1849
|
-
message={message}
|
|
1850
|
-
imageAttachments={imageAttachments}
|
|
1851
|
-
videoAttachments={videoAttachments}
|
|
1852
|
-
documentName={documentAttachment?.filename ?? ''}
|
|
1853
|
-
pendingApproval={streamingConversationId === conversationId ? pendingApproval : null}
|
|
1854
|
-
smartContext={smartContext}
|
|
1855
|
-
agentMode={agentMode}
|
|
1856
|
-
planMode={planMode}
|
|
1857
|
-
status={status}
|
|
1858
|
-
workspacePath={workspacePath}
|
|
1859
|
-
chatEnd={chatEnd}
|
|
1860
|
-
welcomeInteraction={MOCK_WELCOME_INTERACTION}
|
|
1861
|
-
onSubmit={handleSubmit}
|
|
1862
|
-
onSelectImage={selectImage}
|
|
1863
|
-
onSelectVideo={selectVideo}
|
|
1864
|
-
onSelectDocument={selectDocument}
|
|
1865
|
-
onPasteImage={pasteImage}
|
|
1866
|
-
onSetMessage={setMessage}
|
|
1867
|
-
onSendVoiceMessage={sendVoiceMessage}
|
|
1868
|
-
onRemoveImage={(idx: number) => {
|
|
1869
|
-
setImageAttachments((current) => current.filter((_, i) => i !== idx))
|
|
1870
|
-
}}
|
|
1871
|
-
onRemoveVideo={(idx: number) => {
|
|
1872
|
-
setVideoAttachments((current) => current.filter((_, i) => i !== idx))
|
|
1873
|
-
}}
|
|
1874
|
-
onRemoveDocument={() => setDocumentAttachment(null)}
|
|
1875
|
-
onStartWebSearch={startWebSearch}
|
|
1876
|
-
onCaptureScreen={captureScreen}
|
|
1877
|
-
onSetSmartContext={updateSmartContext}
|
|
1878
|
-
onSetAgentMode={updateAgentMode}
|
|
1879
|
-
onSetPlanMode={isDesktopApp ? updatePlanMode : undefined}
|
|
1880
|
-
onSetProvider={changeProvider}
|
|
1881
|
-
onSelectWorkspace={isDesktopApp ? selectWorkspace : undefined}
|
|
1882
|
-
settingsConfig={settingsConfig}
|
|
1883
|
-
onSetModel={changeModel}
|
|
1884
|
-
onSelectModelAndProvider={changeProviderAndModel}
|
|
1885
|
-
onSetGeminiLiveVoice={changeGeminiLiveVoice}
|
|
1886
|
-
onApproval={handleApproval}
|
|
1887
|
-
onCancelMessage={handleCancelMessage}
|
|
1888
|
-
onClearMessages={() => clearHistory('Clear history')}
|
|
1889
|
-
onToggleMobileSidebar={() => setMobileSidebarOpen(!mobileSidebarOpen)}
|
|
1890
|
-
/>
|
|
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
|
+
}} />
|
|
1891
1965
|
</main>
|
|
1892
|
-
{
|
|
1893
|
-
<
|
|
1894
|
-
<
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
deleteSkill={deleteLearnedSkill}
|
|
1966
|
+
{toolsPanelOpen && (
|
|
1967
|
+
<Suspense fallback={<LazyPanelFallback />}>
|
|
1968
|
+
<ToolSurfacePage
|
|
1969
|
+
surfaces={toolSurfaces}
|
|
1970
|
+
activeSurfaceId={activeSurfaceId}
|
|
1898
1971
|
workspacePath={workspacePath}
|
|
1972
|
+
desktopTools={isDesktopApp}
|
|
1973
|
+
backgroundTaskCount={backgroundTaskCount}
|
|
1974
|
+
onOpenMods={() => openUtilitySurface('mods')}
|
|
1975
|
+
onOpenBackgroundTasks={() => openUtilitySurface('background')}
|
|
1976
|
+
onModsPanelTarget={setModsPanelTarget}
|
|
1977
|
+
onBackgroundPanelTarget={setBackgroundPanelTarget}
|
|
1978
|
+
terminalSize={terminalRightWidth}
|
|
1979
|
+
onSelect={setActiveSurfaceId}
|
|
1980
|
+
onClose={closeToolSurface}
|
|
1981
|
+
onCloseAll={closeAllToolSurfaces}
|
|
1982
|
+
onDuplicate={duplicateToolSurface}
|
|
1983
|
+
onRename={renameToolSurface}
|
|
1984
|
+
onCloseOthers={closeOtherToolSurfaces}
|
|
1985
|
+
onOpenTerminal={openTerminalSurface}
|
|
1986
|
+
onOpenBrowser={() => openNativeBrowser()}
|
|
1987
|
+
onOpenReview={openConversationReview}
|
|
1988
|
+
onOpenFiles={() => {
|
|
1989
|
+
setActiveSurfaceId(null)
|
|
1990
|
+
setToolsPanelOpen(false)
|
|
1991
|
+
changeView('workspace')
|
|
1992
|
+
}}
|
|
1993
|
+
onOpenSideChat={() => { setActiveSurfaceId(null); setToolsPanelOpen(false) }}
|
|
1994
|
+
onClosePanel={closeToolsPanel}
|
|
1995
|
+
onResizeTerminal={(size) => {
|
|
1996
|
+
setTerminalRightWidth(size)
|
|
1997
|
+
if (terminalSaveTimeoutRef.current) clearTimeout(terminalSaveTimeoutRef.current)
|
|
1998
|
+
terminalSaveTimeoutRef.current = setTimeout(() => {
|
|
1999
|
+
window.localStorage.setItem('mint:terminal-right-width', String(size))
|
|
2000
|
+
}, 250)
|
|
2001
|
+
}}
|
|
2002
|
+
onResizePanel={(size) => {
|
|
2003
|
+
setTerminalRightWidth(size)
|
|
2004
|
+
if (terminalSaveTimeoutRef.current) clearTimeout(terminalSaveTimeoutRef.current)
|
|
2005
|
+
terminalSaveTimeoutRef.current = setTimeout(() => {
|
|
2006
|
+
window.localStorage.setItem('mint:terminal-right-width', String(size))
|
|
2007
|
+
}, 250)
|
|
2008
|
+
}}
|
|
1899
2009
|
/>
|
|
2010
|
+
</Suspense>
|
|
2011
|
+
)}
|
|
2012
|
+
<BackgroundTerminals workspacePath={workspacePath} panelTarget={backgroundPanelTarget} onCountChange={setBackgroundTaskCount} />
|
|
2013
|
+
{view === 'skills' && (
|
|
2014
|
+
<div className="web-view-scroll" style={{ flex: 1, overflowY: 'auto', background: 'transparent' }}>
|
|
2015
|
+
<Suspense fallback={<LazyPanelFallback />}>
|
|
2016
|
+
<SkillsView
|
|
2017
|
+
listSkills={listLearnedSkills}
|
|
2018
|
+
addSkill={addLearnedSkill}
|
|
2019
|
+
deleteSkill={deleteLearnedSkill}
|
|
2020
|
+
workspacePath={workspacePath}
|
|
2021
|
+
/>
|
|
2022
|
+
</Suspense>
|
|
1900
2023
|
</div>
|
|
1901
2024
|
)}
|
|
1902
2025
|
{view === 'mcp' && (
|
|
1903
|
-
<div style={{ flex: 1, overflowY: 'auto', background: 'transparent' }}>
|
|
1904
|
-
<
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
2026
|
+
<div className="web-view-scroll" style={{ flex: 1, overflowY: 'auto', background: 'transparent' }}>
|
|
2027
|
+
<Suspense fallback={<LazyPanelFallback />}>
|
|
2028
|
+
<McpServersView
|
|
2029
|
+
config={settingsConfig || DEFAULT_CONFIG}
|
|
2030
|
+
updateField={handleUpdateSettingsField}
|
|
2031
|
+
mcpName={mcpName}
|
|
2032
|
+
setMcpName={setMcpName}
|
|
2033
|
+
mcpCmd={mcpCmd}
|
|
2034
|
+
setMcpCmd={setMcpCmd}
|
|
2035
|
+
mcpArgs={mcpArgs}
|
|
2036
|
+
setMcpArgs={setMcpArgs}
|
|
2037
|
+
mcpEnv={mcpEnv}
|
|
2038
|
+
setMcpEnv={setMcpEnv}
|
|
2039
|
+
mcpIcon={mcpIcon}
|
|
2040
|
+
setMcpIcon={setMcpIcon}
|
|
2041
|
+
handleAddMcpServer={handleAddMcpServer}
|
|
2042
|
+
handleRemoveMcpServer={handleRemoveMcpServer}
|
|
2043
|
+
detectTools={detectSystemTools}
|
|
2044
|
+
onReauth={reauthMcpServer}
|
|
2045
|
+
listServerTools={listMcpServerTools}
|
|
2046
|
+
/>
|
|
2047
|
+
</Suspense>
|
|
1923
2048
|
</div>
|
|
1924
2049
|
)}
|
|
1925
2050
|
{view === 'plugins' && (
|
|
1926
|
-
<div style={{ flex: 1, overflowY: 'auto', background: 'transparent' }}>
|
|
1927
|
-
<
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
2051
|
+
<div className="web-view-scroll" style={{ flex: 1, overflowY: 'auto', background: 'transparent' }}>
|
|
2052
|
+
<Suspense fallback={<LazyPanelFallback />}>
|
|
2053
|
+
<PluginsView
|
|
2054
|
+
config={settingsConfig || DEFAULT_CONFIG}
|
|
2055
|
+
updateField={handleUpdateSettingsField}
|
|
2056
|
+
handleConnectPlugin={handleConnectPlugin}
|
|
2057
|
+
/>
|
|
2058
|
+
</Suspense>
|
|
1932
2059
|
</div>
|
|
1933
2060
|
)}
|
|
1934
2061
|
{view === 'cron' && (
|
|
1935
|
-
<div style={{ flex: 1, overflowY: 'auto', background: 'transparent' }}>
|
|
1936
|
-
<
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
2062
|
+
<div className="web-view-scroll" style={{ flex: 1, overflowY: 'auto', background: 'transparent' }}>
|
|
2063
|
+
<Suspense fallback={<LazyPanelFallback />}>
|
|
2064
|
+
<ScheduledTasksView
|
|
2065
|
+
listCronJobs={listCronJobs}
|
|
2066
|
+
addCronJob={addCronJob}
|
|
2067
|
+
removeCronJob={removeCronJob}
|
|
2068
|
+
setCronJobEnabled={setCronJobEnabled}
|
|
2069
|
+
workspacePath={workspacePath}
|
|
2070
|
+
/>
|
|
2071
|
+
</Suspense>
|
|
1943
2072
|
</div>
|
|
1944
2073
|
)}
|
|
1945
2074
|
{view === 'link' && (
|
|
1946
|
-
<div style={{ flex: 1, overflowY: 'auto', background: 'transparent' }}>
|
|
1947
|
-
<
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
2075
|
+
<div className="web-view-scroll" style={{ flex: 1, overflowY: 'auto', background: 'transparent' }}>
|
|
2076
|
+
<Suspense fallback={<LazyPanelFallback />}>
|
|
2077
|
+
<LinkedFoldersView
|
|
2078
|
+
listLinkedFolders={listLinkedFolders}
|
|
2079
|
+
addLinkedFolder={addLinkedFolder}
|
|
2080
|
+
removeLinkedFolder={removeLinkedFolder}
|
|
2081
|
+
linkedFolderStatus={linkedFolderStatus}
|
|
2082
|
+
refreshLinkedFolder={refreshLinkedFolder}
|
|
2083
|
+
listLinkedFolderNotes={listLinkedFolderNotes}
|
|
2084
|
+
readLinkedFolderNote={readLinkedFolderNote}
|
|
2085
|
+
openLinkedFolderNote={openLinkedFolderNote}
|
|
2086
|
+
canOpenNote={isTauriRuntime()}
|
|
2087
|
+
// Desktop: native Tauri picker. Web: asks `mint web` (same
|
|
2088
|
+
// machine) to open its own dialog via a loopback-gated route.
|
|
2089
|
+
selectFolder={selectLinkedFolderPath}
|
|
2090
|
+
/>
|
|
2091
|
+
</Suspense>
|
|
1955
2092
|
</div>
|
|
1956
2093
|
)}
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
2094
|
+
{view === 'code' && (
|
|
2095
|
+
<div className="web-view-scroll" style={{ flex: 1, overflowY: 'auto', background: 'transparent' }}>
|
|
2096
|
+
<Suspense fallback={<LazyPanelFallback />}>
|
|
2097
|
+
<CliSessionsView
|
|
2098
|
+
chatSessions={chatSessions}
|
|
2099
|
+
activeConversationId={conversationId}
|
|
2100
|
+
workspacePath={workspacePath}
|
|
2101
|
+
recentWorkspacePaths={availableWorkspacePaths}
|
|
2102
|
+
onSelectFolder={selectCodeHubFolder}
|
|
2103
|
+
onSelectSession={(id) => {
|
|
2104
|
+
selectConversation(id)
|
|
2105
|
+
}}
|
|
2106
|
+
onDeleteSession={deleteConversation}
|
|
2107
|
+
onRenameSession={renameConversation}
|
|
2108
|
+
onRefreshSessions={refreshChatSessions}
|
|
2109
|
+
onShowToast={showToast}
|
|
2110
|
+
/>
|
|
2111
|
+
</Suspense>
|
|
2112
|
+
</div>
|
|
2113
|
+
)}
|
|
2114
|
+
{view === 'pictures' && (
|
|
2115
|
+
<Suspense fallback={<LazyPanelFallback />}>
|
|
2116
|
+
<LibraryPage chatId={conversationId} onClose={() => changeView('chat')} onOpenConversation={id => { void selectConversation(id) }} />
|
|
2117
|
+
</Suspense>
|
|
2118
|
+
)}
|
|
2119
|
+
{view === 'imagine' && (
|
|
2120
|
+
<Suspense fallback={<LazyPanelFallback />}>
|
|
2121
|
+
<ImageStudioPanel
|
|
2122
|
+
view={view}
|
|
2123
|
+
onSendToChat={async (imagePath, imgPrompt) => {
|
|
2124
|
+
try {
|
|
2125
|
+
const response = await fetch(convertFileSrc(imagePath))
|
|
2126
|
+
if (!response.ok) throw new Error(`Unable to load image (${response.status})`)
|
|
2127
|
+
const blob = await response.blob()
|
|
2128
|
+
const imageName = imagePath.split(/[\\/]/).pop() || 'generated-image.png'
|
|
2129
|
+
const dataUri = await readImage(new File([blob], imageName, { type: blob.type || 'image/png' }))
|
|
2130
|
+
const previewDataUri = await createTrimmedImagePreview(dataUri).catch(() => dataUri)
|
|
2131
|
+
|
|
2132
|
+
changeView('chat')
|
|
2133
|
+
conversationActions.compose(imgPrompt)
|
|
2134
|
+
conversationActions.attachImage({ dataUri, previewDataUri, name: imageName })
|
|
2135
|
+
} catch (error) {
|
|
2136
|
+
showToast(`Could not attach image: ${errorMessage(error)}`)
|
|
2137
|
+
}
|
|
2138
|
+
}}
|
|
2139
|
+
/>
|
|
2140
|
+
</Suspense>
|
|
2141
|
+
)}
|
|
2142
|
+
{view === 'veo' && (
|
|
2143
|
+
<Suspense fallback={<LazyPanelFallback />}>
|
|
2144
|
+
<VeoStudioPanel
|
|
2145
|
+
view={view}
|
|
2146
|
+
onSendToChat={(vidPrompt) => {
|
|
2147
|
+
changeView('chat')
|
|
2148
|
+
conversationActions.compose(vidPrompt)
|
|
2149
|
+
}}
|
|
2150
|
+
/>
|
|
2151
|
+
</Suspense>
|
|
2152
|
+
)}
|
|
1975
2153
|
</div>
|
|
1976
2154
|
<div className={`startup-loading ${startupReady ? 'is-hidden' : ''}`} aria-live="polite" aria-busy={!startupReady}>
|
|
1977
2155
|
<div className="startup-loading-content">
|
|
@@ -1979,54 +2157,47 @@ export default function MintDashboard() {
|
|
|
1979
2157
|
<div className="startup-loading-text">Loading Mint Agent</div>
|
|
1980
2158
|
</div>
|
|
1981
2159
|
</div>
|
|
1982
|
-
{error && (
|
|
1983
|
-
<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' }}>
|
|
1984
|
-
<span>{error}</span>
|
|
1985
|
-
<button onClick={() => setError('')} style={{ background: 'transparent', border: 0, color: 'white', cursor: 'pointer', display: 'inline-flex', alignItems: 'center', padding: 0 }}>
|
|
1986
|
-
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
|
|
1987
|
-
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
1988
|
-
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
1989
|
-
</svg>
|
|
1990
|
-
</button>
|
|
1991
|
-
</div>
|
|
1992
|
-
)}
|
|
1993
2160
|
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2161
|
+
{isSearchOpen && (
|
|
2162
|
+
<Suspense fallback={null}>
|
|
2163
|
+
<CommandPalette
|
|
2164
|
+
isOpen
|
|
2165
|
+
onClose={() => setIsSearchOpen(false)}
|
|
2166
|
+
onSelectChat={(chatId) => {
|
|
2167
|
+
selectConversation(chatId)
|
|
2168
|
+
setIsSearchOpen(false)
|
|
2169
|
+
}}
|
|
2170
|
+
onNewChat={() => {
|
|
2171
|
+
clearHistory('New chat')
|
|
2172
|
+
setIsSearchOpen(false)
|
|
2173
|
+
}}
|
|
2174
|
+
onSelectWorkspace={isDesktopApp ? selectWorkspace : undefined}
|
|
2175
|
+
onOpenSettings={() => {
|
|
2176
|
+
changeView('settings')
|
|
2177
|
+
setIsSearchOpen(false)
|
|
2178
|
+
}}
|
|
2179
|
+
onChangeView={(targetView) => {
|
|
2180
|
+
changeView(targetView)
|
|
2181
|
+
setIsSearchOpen(false)
|
|
2182
|
+
}}
|
|
2183
|
+
onChangeModel={(model) => {
|
|
2184
|
+
handleUpdateSettingsField('model', model)
|
|
2185
|
+
setToastMessage(`Switched model to ${model}`)
|
|
2186
|
+
}}
|
|
2187
|
+
onChangeProvider={(provider) => {
|
|
2188
|
+
handleUpdateSettingsField('provider', provider)
|
|
2189
|
+
setToastMessage(`Switched provider to ${provider}`)
|
|
2190
|
+
}}
|
|
2191
|
+
onExecuteSlash={(cmd) => {
|
|
2192
|
+
conversationActions.compose(cmd + ' ')
|
|
2193
|
+
setIsSearchOpen(false)
|
|
2194
|
+
}}
|
|
2195
|
+
chatSessions={chatSessions}
|
|
2196
|
+
currentChatId={conversationId}
|
|
2197
|
+
workspacePath={workspacePath}
|
|
2198
|
+
/>
|
|
2199
|
+
</Suspense>
|
|
2200
|
+
)}
|
|
2030
2201
|
</div>
|
|
2031
2202
|
)
|
|
2032
2203
|
}
|