@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,10 +1,12 @@
|
|
|
1
1
|
use std::path::{Path, PathBuf};
|
|
2
2
|
|
|
3
|
-
use rusqlite::{Connection, OptionalExtension, params};
|
|
3
|
+
use rusqlite::{Connection, OptionalExtension, TransactionBehavior, params};
|
|
4
4
|
use serde::{Deserialize, Serialize};
|
|
5
5
|
use thiserror::Error;
|
|
6
6
|
|
|
7
7
|
use crate::search::text_embedding::{encode_embedding, fact_embedding_backend};
|
|
8
|
+
mod sources;
|
|
9
|
+
pub use sources::{ConversationSources, SessionAttachment, SourceAttachment};
|
|
8
10
|
|
|
9
11
|
pub const CHAT_CLI_ID: &str = "cli";
|
|
10
12
|
pub const DEFAULT_CONVERSATION_ID: &str = "conversation-default";
|
|
@@ -27,11 +29,17 @@ pub fn scoped_chat_id(chat_id: &str, _workspace_path: Option<&str>) -> String {
|
|
|
27
29
|
/// (`"cli::subagent::<name>"`, or `"cli::<hash>::subagent::<name>"`) —
|
|
28
30
|
/// those must keep behaving like a normal, deletable conversation exactly
|
|
29
31
|
/// as they do today, unaffected by workspace scoping.
|
|
30
|
-
fn is_cli_chat_id(chat_id: &str) -> bool {
|
|
32
|
+
pub fn is_cli_chat_id(chat_id: &str) -> bool {
|
|
31
33
|
chat_id == CHAT_CLI_ID
|
|
32
34
|
|| (chat_id.starts_with(&format!("{CHAT_CLI_ID}::")) && !chat_id.contains("::subagent::"))
|
|
33
35
|
}
|
|
34
36
|
|
|
37
|
+
pub fn generate_cli_session_id() -> String {
|
|
38
|
+
let raw_uuid = uuid::Uuid::new_v4().to_string();
|
|
39
|
+
let short_id = &raw_uuid.replace('-', "")[..12];
|
|
40
|
+
format!("cli::{short_id}")
|
|
41
|
+
}
|
|
42
|
+
|
|
35
43
|
/// The subagent name embedded in a chat id of the form
|
|
36
44
|
/// `"<parent>::subagent::<name>"` (see `dispatch_one_subagent`), or `None` for
|
|
37
45
|
/// an ordinary conversation. Used to scope which agent a fact belongs to and
|
|
@@ -45,6 +53,8 @@ pub fn subagent_name(chat_id: &str) -> Option<&str> {
|
|
|
45
53
|
|
|
46
54
|
#[derive(Debug, Error)]
|
|
47
55
|
pub enum MemoryError {
|
|
56
|
+
#[error("library error: {0}")]
|
|
57
|
+
Library(String),
|
|
48
58
|
#[error("unable to determine the user config directory")]
|
|
49
59
|
ConfigDirectoryUnavailable,
|
|
50
60
|
#[error("unable to create database directory {path}: {source}")]
|
|
@@ -72,11 +82,36 @@ pub struct InteractionMemory {
|
|
|
72
82
|
pub model: String,
|
|
73
83
|
pub fallback_provider: Option<String>,
|
|
74
84
|
pub created_at: String,
|
|
85
|
+
pub status: String,
|
|
75
86
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
76
87
|
pub agent_activity: Option<serde_json::Value>,
|
|
77
88
|
}
|
|
78
89
|
|
|
79
|
-
#[derive(Debug, Clone, Serialize
|
|
90
|
+
#[derive(Debug, Clone, Serialize)]
|
|
91
|
+
#[serde(rename_all = "camelCase")]
|
|
92
|
+
pub struct ConversationChange {
|
|
93
|
+
pub sequence: i64,
|
|
94
|
+
pub interaction_id: i64,
|
|
95
|
+
pub interaction: Option<InteractionMemory>,
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
#[derive(Debug, Clone, Serialize)]
|
|
99
|
+
#[serde(rename_all = "camelCase")]
|
|
100
|
+
pub struct ConversationChanges {
|
|
101
|
+
pub changes: Vec<ConversationChange>,
|
|
102
|
+
pub cursor: i64,
|
|
103
|
+
pub has_more: bool,
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
#[derive(Debug, Clone, Serialize)]
|
|
107
|
+
#[serde(rename_all = "camelCase")]
|
|
108
|
+
pub struct ConversationSnapshot {
|
|
109
|
+
pub interactions: Vec<InteractionMemory>,
|
|
110
|
+
pub cursor: i64,
|
|
111
|
+
pub has_older: bool,
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
|
80
115
|
#[serde(rename_all = "camelCase")]
|
|
81
116
|
pub struct ChatSession {
|
|
82
117
|
pub id: String,
|
|
@@ -84,6 +119,16 @@ pub struct ChatSession {
|
|
|
84
119
|
pub kind: String,
|
|
85
120
|
pub created_at: String,
|
|
86
121
|
pub updated_at: String,
|
|
122
|
+
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
123
|
+
pub workspace_path: Option<String>,
|
|
124
|
+
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
125
|
+
pub git_branch: Option<String>,
|
|
126
|
+
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
127
|
+
pub main_language: Option<String>,
|
|
128
|
+
#[serde(default)]
|
|
129
|
+
pub message_count: usize,
|
|
130
|
+
#[serde(default)]
|
|
131
|
+
pub total_bytes: usize,
|
|
87
132
|
}
|
|
88
133
|
|
|
89
134
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
|
@@ -220,6 +265,232 @@ impl MemoryStore {
|
|
|
220
265
|
Ok(connection.last_insert_rowid())
|
|
221
266
|
}
|
|
222
267
|
|
|
268
|
+
/// Insert a visible prompt before any provider or tool work begins.
|
|
269
|
+
pub fn start_turn(&self, chat_id: &str, user_text: &str) -> Result<i64, MemoryError> {
|
|
270
|
+
let chat_id = normalized_chat_id(chat_id);
|
|
271
|
+
let mut connection = self.connection()?;
|
|
272
|
+
let tx = connection.transaction_with_behavior(TransactionBehavior::Immediate)?;
|
|
273
|
+
ensure_chat_session_row(&tx, &chat_id)?;
|
|
274
|
+
tx.execute(
|
|
275
|
+
"INSERT INTO interaction_memories (chat_id, user_text, ai_text, status, lease_until)
|
|
276
|
+
VALUES (?1, ?2, '', 'queued', unixepoch() + 45)",
|
|
277
|
+
params![chat_id, user_text],
|
|
278
|
+
)?;
|
|
279
|
+
let id = tx.last_insert_rowid();
|
|
280
|
+
tx.execute(
|
|
281
|
+
"UPDATE chat_sessions SET title = CASE
|
|
282
|
+
WHEN title = 'New chat' AND trim(?2) != '' THEN substr(trim(?2), 1, 80)
|
|
283
|
+
ELSE title END, updated_at = CURRENT_TIMESTAMP WHERE id = ?1",
|
|
284
|
+
params![chat_id, user_text],
|
|
285
|
+
)?;
|
|
286
|
+
tx.commit()?;
|
|
287
|
+
Ok(id)
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/// Claim only the oldest unfinished turn. The short transaction never spans AI work.
|
|
291
|
+
pub fn claim_turn(&self, chat_id: &str, id: i64) -> Result<bool, MemoryError> {
|
|
292
|
+
let chat_id = normalized_chat_id(chat_id);
|
|
293
|
+
let mut connection = self.connection()?;
|
|
294
|
+
let tx = connection.transaction_with_behavior(TransactionBehavior::Immediate)?;
|
|
295
|
+
tx.execute(
|
|
296
|
+
"UPDATE interaction_memories SET status = 'interrupted', lease_until = 0
|
|
297
|
+
WHERE chat_id = ?1 AND status IN ('queued', 'running') AND lease_until < unixepoch()",
|
|
298
|
+
params![chat_id],
|
|
299
|
+
)?;
|
|
300
|
+
let own_status: Option<String> = tx
|
|
301
|
+
.query_row(
|
|
302
|
+
"SELECT status FROM interaction_memories WHERE id = ?1 AND chat_id = ?2",
|
|
303
|
+
params![id, chat_id],
|
|
304
|
+
|row| row.get(0),
|
|
305
|
+
)
|
|
306
|
+
.optional()?;
|
|
307
|
+
if own_status.as_deref() != Some("queued") {
|
|
308
|
+
tx.commit()?;
|
|
309
|
+
return Err(MemoryError::Database(rusqlite::Error::QueryReturnedNoRows));
|
|
310
|
+
}
|
|
311
|
+
let earlier: i64 = tx.query_row(
|
|
312
|
+
"SELECT count(*) FROM interaction_memories
|
|
313
|
+
WHERE chat_id = ?1 AND id < ?2 AND status IN ('queued', 'running')",
|
|
314
|
+
params![chat_id, id],
|
|
315
|
+
|row| row.get(0),
|
|
316
|
+
)?;
|
|
317
|
+
let claimed = if earlier == 0 {
|
|
318
|
+
tx.execute(
|
|
319
|
+
"UPDATE interaction_memories SET status = 'running', lease_until = unixepoch() + 45
|
|
320
|
+
WHERE id = ?1 AND chat_id = ?2 AND status = 'queued'",
|
|
321
|
+
params![id, chat_id],
|
|
322
|
+
)? == 1
|
|
323
|
+
} else {
|
|
324
|
+
false
|
|
325
|
+
};
|
|
326
|
+
tx.commit()?;
|
|
327
|
+
Ok(claimed)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
pub fn renew_turn(&self, id: i64) -> Result<(), MemoryError> {
|
|
331
|
+
self.connection()?.execute(
|
|
332
|
+
"UPDATE interaction_memories SET lease_until = unixepoch() + 45
|
|
333
|
+
WHERE id = ?1 AND status IN ('queued', 'running')",
|
|
334
|
+
params![id],
|
|
335
|
+
)?;
|
|
336
|
+
Ok(())
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
fn expire_abandoned_turns(&self, chat_id: &str) -> Result<(), MemoryError> {
|
|
340
|
+
self.connection()?.execute(
|
|
341
|
+
"UPDATE interaction_memories SET status = 'interrupted', lease_until = 0
|
|
342
|
+
WHERE chat_id = ?1 AND status IN ('queued', 'running') AND lease_until < unixepoch()",
|
|
343
|
+
params![normalized_chat_id(chat_id)],
|
|
344
|
+
)?;
|
|
345
|
+
Ok(())
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
pub fn finish_turn(
|
|
349
|
+
&self,
|
|
350
|
+
id: i64,
|
|
351
|
+
ai_text: &str,
|
|
352
|
+
provider: &str,
|
|
353
|
+
model: &str,
|
|
354
|
+
fallback_provider: Option<&str>,
|
|
355
|
+
) -> Result<(), MemoryError> {
|
|
356
|
+
let connection = self.connection()?;
|
|
357
|
+
let changed = connection.execute(
|
|
358
|
+
"UPDATE interaction_memories SET ai_text = ?2, provider = ?3, model = ?4,
|
|
359
|
+
fallback_provider = ?5, status = 'completed', lease_until = 0
|
|
360
|
+
WHERE id = ?1 AND status = 'running'",
|
|
361
|
+
params![id, ai_text, provider, model, fallback_provider],
|
|
362
|
+
)?;
|
|
363
|
+
if changed != 1 {
|
|
364
|
+
return Err(MemoryError::Database(rusqlite::Error::QueryReturnedNoRows));
|
|
365
|
+
}
|
|
366
|
+
Ok(())
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
pub fn end_turn(&self, id: i64, status: &str) -> Result<(), MemoryError> {
|
|
370
|
+
if !matches!(status, "failed" | "interrupted") {
|
|
371
|
+
return Ok(());
|
|
372
|
+
}
|
|
373
|
+
self.connection()?.execute(
|
|
374
|
+
"UPDATE interaction_memories SET status = ?2, lease_until = 0
|
|
375
|
+
WHERE id = ?1 AND status IN ('queued', 'running')",
|
|
376
|
+
params![id, status],
|
|
377
|
+
)?;
|
|
378
|
+
Ok(())
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
pub fn conversation_changes(
|
|
382
|
+
&self,
|
|
383
|
+
chat_id: &str,
|
|
384
|
+
after: i64,
|
|
385
|
+
limit: usize,
|
|
386
|
+
) -> Result<ConversationChanges, MemoryError> {
|
|
387
|
+
let chat_id = normalized_chat_id(chat_id);
|
|
388
|
+
self.expire_abandoned_turns(&chat_id)?;
|
|
389
|
+
let connection = self.connection()?;
|
|
390
|
+
let mut statement = connection.prepare(
|
|
391
|
+
"SELECT c.sequence, c.interaction_id,
|
|
392
|
+
m.id, m.chat_id, m.user_text, m.ai_text, m.provider, m.model,
|
|
393
|
+
m.fallback_provider, m.created_at, m.agent_activity_json, m.status
|
|
394
|
+
FROM conversation_changes c
|
|
395
|
+
LEFT JOIN interaction_memories m ON m.id = c.interaction_id AND m.chat_id = c.chat_id
|
|
396
|
+
WHERE c.chat_id = ?1 AND c.sequence > ?2 ORDER BY c.sequence LIMIT ?3",
|
|
397
|
+
)?;
|
|
398
|
+
let rows = statement.query_map(
|
|
399
|
+
params![chat_id, after, limit.clamp(1, 200) as i64 + 1],
|
|
400
|
+
|row| {
|
|
401
|
+
let sequence: i64 = row.get(0)?;
|
|
402
|
+
let interaction_id: i64 = row.get(1)?;
|
|
403
|
+
let interaction = if row.get::<_, Option<i64>>(2)?.is_some() {
|
|
404
|
+
let agent_activity = row
|
|
405
|
+
.get::<_, Option<String>>(10)?
|
|
406
|
+
.and_then(|raw| serde_json::from_str(&raw).ok());
|
|
407
|
+
let created: String = row.get(9)?;
|
|
408
|
+
Some(InteractionMemory {
|
|
409
|
+
id: row.get(2)?,
|
|
410
|
+
chat_id: row.get(3)?,
|
|
411
|
+
user_text: row.get(4)?,
|
|
412
|
+
ai_text: row.get(5)?,
|
|
413
|
+
provider: row.get(6)?,
|
|
414
|
+
model: row.get(7)?,
|
|
415
|
+
fallback_provider: row.get(8)?,
|
|
416
|
+
created_at: normalize_sqlite_utc_timestamp(&created),
|
|
417
|
+
agent_activity,
|
|
418
|
+
status: row.get(11)?,
|
|
419
|
+
})
|
|
420
|
+
} else {
|
|
421
|
+
None
|
|
422
|
+
};
|
|
423
|
+
Ok(ConversationChange {
|
|
424
|
+
sequence,
|
|
425
|
+
interaction_id,
|
|
426
|
+
interaction,
|
|
427
|
+
})
|
|
428
|
+
},
|
|
429
|
+
)?;
|
|
430
|
+
let mut changes = rows.collect::<Result<Vec<_>, _>>()?;
|
|
431
|
+
let has_more = changes.len() > limit.clamp(1, 200);
|
|
432
|
+
if has_more {
|
|
433
|
+
changes.pop();
|
|
434
|
+
}
|
|
435
|
+
let cursor = changes.last().map_or(after, |change| change.sequence);
|
|
436
|
+
Ok(ConversationChanges {
|
|
437
|
+
changes,
|
|
438
|
+
cursor,
|
|
439
|
+
has_more,
|
|
440
|
+
})
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
pub fn latest_conversation_sequence(&self, chat_id: &str) -> Result<i64, MemoryError> {
|
|
444
|
+
self.expire_abandoned_turns(chat_id)?;
|
|
445
|
+
let connection = self.connection()?;
|
|
446
|
+
Ok(connection.query_row(
|
|
447
|
+
"SELECT coalesce(max(sequence), 0) FROM conversation_changes WHERE chat_id = ?1",
|
|
448
|
+
params![normalized_chat_id(chat_id)],
|
|
449
|
+
|row| row.get(0),
|
|
450
|
+
)?)
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
pub fn conversation_snapshot(
|
|
454
|
+
&self,
|
|
455
|
+
chat_id: &str,
|
|
456
|
+
before_id: Option<i64>,
|
|
457
|
+
limit: usize,
|
|
458
|
+
) -> Result<ConversationSnapshot, MemoryError> {
|
|
459
|
+
let chat_id = normalized_chat_id(chat_id);
|
|
460
|
+
self.expire_abandoned_turns(&chat_id)?;
|
|
461
|
+
let mut connection = self.connection()?;
|
|
462
|
+
let tx = connection.transaction()?;
|
|
463
|
+
let cursor: i64 = tx.query_row(
|
|
464
|
+
"SELECT coalesce(max(sequence), 0) FROM conversation_changes WHERE chat_id = ?1",
|
|
465
|
+
params![chat_id],
|
|
466
|
+
|row| row.get(0),
|
|
467
|
+
)?;
|
|
468
|
+
let mut statement = tx.prepare(
|
|
469
|
+
"SELECT id, chat_id, user_text, ai_text, provider, model, fallback_provider,
|
|
470
|
+
created_at, agent_activity_json, status FROM interaction_memories
|
|
471
|
+
WHERE chat_id = ?1 AND (?2 IS NULL OR id < ?2)
|
|
472
|
+
ORDER BY id DESC LIMIT ?3",
|
|
473
|
+
)?;
|
|
474
|
+
let page_size = limit.clamp(1, 200);
|
|
475
|
+
let rows = statement.query_map(
|
|
476
|
+
params![chat_id, before_id, page_size as i64 + 1],
|
|
477
|
+
interaction_row,
|
|
478
|
+
)?;
|
|
479
|
+
let mut interactions = rows.collect::<Result<Vec<_>, _>>()?;
|
|
480
|
+
let has_older = interactions.len() > page_size;
|
|
481
|
+
if has_older {
|
|
482
|
+
interactions.pop();
|
|
483
|
+
}
|
|
484
|
+
interactions.reverse();
|
|
485
|
+
drop(statement);
|
|
486
|
+
tx.commit()?;
|
|
487
|
+
Ok(ConversationSnapshot {
|
|
488
|
+
interactions,
|
|
489
|
+
cursor,
|
|
490
|
+
has_older,
|
|
491
|
+
})
|
|
492
|
+
}
|
|
493
|
+
|
|
223
494
|
pub fn recent_interactions(&self, limit: usize) -> Result<Vec<InteractionMemory>, MemoryError> {
|
|
224
495
|
self.recent_interactions_for_chat(DEFAULT_CONVERSATION_ID, limit)
|
|
225
496
|
}
|
|
@@ -233,7 +504,7 @@ impl MemoryStore {
|
|
|
233
504
|
let connection = self.connection()?;
|
|
234
505
|
ensure_builtin_chat_sessions(&connection)?;
|
|
235
506
|
let mut statement = connection.prepare(
|
|
236
|
-
"SELECT id, chat_id, user_text, ai_text, provider, model, fallback_provider, created_at, agent_activity_json
|
|
507
|
+
"SELECT id, chat_id, user_text, ai_text, provider, model, fallback_provider, created_at, agent_activity_json, status
|
|
237
508
|
FROM interaction_memories
|
|
238
509
|
WHERE chat_id = ?1
|
|
239
510
|
ORDER BY id DESC
|
|
@@ -243,6 +514,45 @@ impl MemoryStore {
|
|
|
243
514
|
rows.collect::<Result<Vec<_>, _>>().map_err(Into::into)
|
|
244
515
|
}
|
|
245
516
|
|
|
517
|
+
pub fn recent_completed_interactions_for_chat(
|
|
518
|
+
&self,
|
|
519
|
+
chat_id: &str,
|
|
520
|
+
limit: usize,
|
|
521
|
+
) -> Result<Vec<InteractionMemory>, MemoryError> {
|
|
522
|
+
let connection = self.connection()?;
|
|
523
|
+
let mut statement = connection.prepare(
|
|
524
|
+
"SELECT id, chat_id, user_text, ai_text, provider, model, fallback_provider,
|
|
525
|
+
created_at, agent_activity_json, status FROM interaction_memories
|
|
526
|
+
WHERE chat_id = ?1 AND status = 'completed' ORDER BY id DESC LIMIT ?2",
|
|
527
|
+
)?;
|
|
528
|
+
let rows = statement.query_map(
|
|
529
|
+
params![normalized_chat_id(chat_id), limit as i64],
|
|
530
|
+
interaction_row,
|
|
531
|
+
)?;
|
|
532
|
+
rows.collect::<Result<Vec<_>, _>>().map_err(Into::into)
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/// Returns the complete transcript for one conversation in display order.
|
|
536
|
+
/// This deliberately has no caller supplied `LIMIT`: passing `usize::MAX`
|
|
537
|
+
/// through SQLite's signed limit is not portable and can wrap on 64-bit
|
|
538
|
+
/// platforms.
|
|
539
|
+
pub fn interactions_for_chat(
|
|
540
|
+
&self,
|
|
541
|
+
chat_id: &str,
|
|
542
|
+
) -> Result<Vec<InteractionMemory>, MemoryError> {
|
|
543
|
+
let chat_id = normalized_chat_id(chat_id);
|
|
544
|
+
let connection = self.connection()?;
|
|
545
|
+
ensure_builtin_chat_sessions(&connection)?;
|
|
546
|
+
let mut statement = connection.prepare(
|
|
547
|
+
"SELECT id, chat_id, user_text, ai_text, provider, model, fallback_provider, created_at, agent_activity_json, status
|
|
548
|
+
FROM interaction_memories
|
|
549
|
+
WHERE chat_id = ?1
|
|
550
|
+
ORDER BY id ASC",
|
|
551
|
+
)?;
|
|
552
|
+
let rows = statement.query_map(params![chat_id], interaction_row)?;
|
|
553
|
+
rows.collect::<Result<Vec<_>, _>>().map_err(Into::into)
|
|
554
|
+
}
|
|
555
|
+
|
|
246
556
|
/// Full-text search over `chat_id`'s past interactions for the turns most
|
|
247
557
|
/// relevant to `query` (BM25 ranked), skipping the `exclude_recent` newest
|
|
248
558
|
/// rows since those are already injected verbatim elsewhere. Returns
|
|
@@ -262,11 +572,12 @@ impl MemoryStore {
|
|
|
262
572
|
let connection = self.connection()?;
|
|
263
573
|
let mut statement = connection.prepare(
|
|
264
574
|
"SELECT m.id, m.chat_id, m.user_text, m.ai_text, m.provider, m.model,
|
|
265
|
-
m.fallback_provider, m.created_at, m.agent_activity_json
|
|
575
|
+
m.fallback_provider, m.created_at, m.agent_activity_json, m.status
|
|
266
576
|
FROM interaction_fts
|
|
267
577
|
JOIN interaction_memories m ON m.id = interaction_fts.rowid
|
|
268
578
|
WHERE interaction_fts MATCH ?1
|
|
269
579
|
AND m.chat_id = ?2
|
|
580
|
+
AND m.status = 'completed'
|
|
270
581
|
AND m.id NOT IN (
|
|
271
582
|
SELECT id FROM interaction_memories
|
|
272
583
|
WHERE chat_id = ?2 ORDER BY id DESC LIMIT ?3
|
|
@@ -286,31 +597,122 @@ impl MemoryStore {
|
|
|
286
597
|
ensure_builtin_chat_sessions(&connection)?;
|
|
287
598
|
let _ = connection.execute(
|
|
288
599
|
"DELETE FROM chat_sessions
|
|
289
|
-
WHERE
|
|
290
|
-
AND id != ?
|
|
600
|
+
WHERE id != ?1
|
|
601
|
+
AND id != ?2
|
|
602
|
+
AND kind = 'conversation'
|
|
291
603
|
AND id NOT LIKE 'cron::%'
|
|
292
604
|
AND (SELECT COUNT(*) FROM interaction_memories WHERE interaction_memories.chat_id = chat_sessions.id) = 0",
|
|
293
|
-
params![DEFAULT_CONVERSATION_ID],
|
|
605
|
+
params![DEFAULT_CONVERSATION_ID, CHAT_CLI_ID],
|
|
294
606
|
);
|
|
295
607
|
let mut statement = connection.prepare(
|
|
296
|
-
"SELECT id, title, kind, created_at, updated_at
|
|
297
|
-
|
|
298
|
-
|
|
608
|
+
"SELECT s.id, s.title, s.kind, s.created_at, s.updated_at,
|
|
609
|
+
s.workspace_path, s.git_branch, s.main_language,
|
|
610
|
+
COUNT(m.id) AS msg_count,
|
|
611
|
+
COALESCE(SUM(LENGTH(m.user_text) + LENGTH(m.ai_text)), 0) AS total_bytes
|
|
612
|
+
FROM chat_sessions s
|
|
613
|
+
LEFT JOIN interaction_memories m ON m.chat_id = s.id
|
|
614
|
+
GROUP BY s.id
|
|
615
|
+
ORDER BY CASE WHEN s.id = ?1 THEN 0 ELSE 1 END, s.updated_at DESC",
|
|
299
616
|
)?;
|
|
300
617
|
let rows = statement.query_map(params![CHAT_CLI_ID], |row| {
|
|
301
618
|
let created_raw: String = row.get(3)?;
|
|
302
619
|
let updated_raw: String = row.get(4)?;
|
|
620
|
+
let msg_count: i64 = row.get(8)?;
|
|
621
|
+
let bytes: i64 = row.get(9)?;
|
|
303
622
|
Ok(ChatSession {
|
|
304
623
|
id: row.get(0)?,
|
|
305
624
|
title: row.get(1)?,
|
|
306
625
|
kind: row.get(2)?,
|
|
307
626
|
created_at: normalize_sqlite_utc_timestamp(&created_raw),
|
|
308
627
|
updated_at: normalize_sqlite_utc_timestamp(&updated_raw),
|
|
628
|
+
workspace_path: row.get(5)?,
|
|
629
|
+
git_branch: row.get(6)?,
|
|
630
|
+
main_language: row.get(7)?,
|
|
631
|
+
message_count: msg_count.max(0) as usize,
|
|
632
|
+
total_bytes: bytes.max(0) as usize,
|
|
309
633
|
})
|
|
310
634
|
})?;
|
|
311
635
|
rows.collect::<Result<Vec<_>, _>>().map_err(Into::into)
|
|
312
636
|
}
|
|
313
637
|
|
|
638
|
+
pub fn update_chat_session_metadata(
|
|
639
|
+
&self,
|
|
640
|
+
chat_id: &str,
|
|
641
|
+
workspace_path: Option<&str>,
|
|
642
|
+
git_branch: Option<&str>,
|
|
643
|
+
main_language: Option<&str>,
|
|
644
|
+
) -> Result<(), MemoryError> {
|
|
645
|
+
let chat_id = normalized_chat_id(chat_id);
|
|
646
|
+
let connection = self.connection()?;
|
|
647
|
+
ensure_builtin_chat_sessions(&connection)?;
|
|
648
|
+
ensure_chat_session_row(&connection, &chat_id)?;
|
|
649
|
+
connection.execute(
|
|
650
|
+
"UPDATE chat_sessions
|
|
651
|
+
SET workspace_path = COALESCE(?2, workspace_path),
|
|
652
|
+
git_branch = COALESCE(?3, git_branch),
|
|
653
|
+
main_language = COALESCE(?4, main_language),
|
|
654
|
+
updated_at = CURRENT_TIMESTAMP
|
|
655
|
+
WHERE id = ?1",
|
|
656
|
+
params![chat_id, workspace_path, git_branch, main_language],
|
|
657
|
+
)?;
|
|
658
|
+
Ok(())
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
pub fn set_chat_session_workspace(
|
|
662
|
+
&self,
|
|
663
|
+
chat_id: &str,
|
|
664
|
+
workspace_path: Option<&str>,
|
|
665
|
+
) -> Result<(), MemoryError> {
|
|
666
|
+
let chat_id = normalized_chat_id(chat_id);
|
|
667
|
+
let connection = self.connection()?;
|
|
668
|
+
ensure_builtin_chat_sessions(&connection)?;
|
|
669
|
+
ensure_chat_session_row(&connection, &chat_id)?;
|
|
670
|
+
connection.execute(
|
|
671
|
+
"UPDATE chat_sessions
|
|
672
|
+
SET workspace_path = ?2,
|
|
673
|
+
updated_at = CURRENT_TIMESTAMP
|
|
674
|
+
WHERE id = ?1",
|
|
675
|
+
params![chat_id, workspace_path],
|
|
676
|
+
)?;
|
|
677
|
+
Ok(())
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
pub fn create_cli_session(
|
|
681
|
+
&self,
|
|
682
|
+
workspace_path: Option<&str>,
|
|
683
|
+
git_branch: Option<&str>,
|
|
684
|
+
main_language: Option<&str>,
|
|
685
|
+
) -> Result<String, MemoryError> {
|
|
686
|
+
let session_id = generate_cli_session_id();
|
|
687
|
+
self.register_cli_session(&session_id, workspace_path, git_branch, main_language)?;
|
|
688
|
+
Ok(session_id)
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
pub fn register_cli_session(
|
|
692
|
+
&self,
|
|
693
|
+
session_id: &str,
|
|
694
|
+
workspace_path: Option<&str>,
|
|
695
|
+
git_branch: Option<&str>,
|
|
696
|
+
main_language: Option<&str>,
|
|
697
|
+
) -> Result<(), MemoryError> {
|
|
698
|
+
let connection = self.connection()?;
|
|
699
|
+
ensure_builtin_chat_sessions(&connection)?;
|
|
700
|
+
connection.execute(
|
|
701
|
+
"INSERT OR IGNORE INTO chat_sessions (id, title, kind, workspace_path, git_branch, main_language)
|
|
702
|
+
VALUES (?1, 'New chat', 'cli', ?2, ?3, ?4)",
|
|
703
|
+
params![session_id, workspace_path, git_branch, main_language],
|
|
704
|
+
)?;
|
|
705
|
+
Ok(())
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
pub fn get_session_preview(
|
|
709
|
+
&self,
|
|
710
|
+
chat_id: &str,
|
|
711
|
+
limit: usize,
|
|
712
|
+
) -> Result<Vec<InteractionMemory>, MemoryError> {
|
|
713
|
+
self.recent_interactions_for_chat(chat_id, limit)
|
|
714
|
+
}
|
|
715
|
+
|
|
314
716
|
/// Registers a chat session with an explicit title/kind up front instead
|
|
315
717
|
/// of the "New chat" placeholder — used to give a scheduled task's
|
|
316
718
|
/// conversation its task name immediately (visible in the sidebar even
|
|
@@ -353,6 +755,14 @@ impl MemoryStore {
|
|
|
353
755
|
pub fn clear_interactions_for_chat(&self, chat_id: &str) -> Result<usize, MemoryError> {
|
|
354
756
|
let chat_id = normalized_chat_id(chat_id);
|
|
355
757
|
let connection = self.connection()?;
|
|
758
|
+
connection.execute(
|
|
759
|
+
"DELETE FROM library_references WHERE chat_id = ?1",
|
|
760
|
+
params![chat_id],
|
|
761
|
+
)?;
|
|
762
|
+
connection.execute(
|
|
763
|
+
"DELETE FROM session_skill_reads WHERE chat_id = ?1",
|
|
764
|
+
params![chat_id],
|
|
765
|
+
)?;
|
|
356
766
|
Ok(connection.execute(
|
|
357
767
|
"DELETE FROM interaction_memories WHERE chat_id = ?1",
|
|
358
768
|
params![chat_id],
|
|
@@ -361,11 +771,19 @@ impl MemoryStore {
|
|
|
361
771
|
|
|
362
772
|
pub fn delete_chat_session(&self, chat_id: &str) -> Result<usize, MemoryError> {
|
|
363
773
|
let chat_id = normalized_chat_id(chat_id);
|
|
364
|
-
if
|
|
774
|
+
if chat_id == CHAT_CLI_ID {
|
|
365
775
|
return Ok(0);
|
|
366
776
|
}
|
|
367
777
|
let connection = self.connection()?;
|
|
368
778
|
let transaction = connection.unchecked_transaction()?;
|
|
779
|
+
transaction.execute(
|
|
780
|
+
"DELETE FROM library_references WHERE chat_id = ?1",
|
|
781
|
+
params![chat_id],
|
|
782
|
+
)?;
|
|
783
|
+
transaction.execute(
|
|
784
|
+
"DELETE FROM session_skill_reads WHERE chat_id = ?1",
|
|
785
|
+
params![chat_id],
|
|
786
|
+
)?;
|
|
369
787
|
transaction.execute(
|
|
370
788
|
"DELETE FROM interaction_memories WHERE chat_id = ?1",
|
|
371
789
|
params![chat_id],
|
|
@@ -497,6 +915,14 @@ impl MemoryStore {
|
|
|
497
915
|
)?)
|
|
498
916
|
}
|
|
499
917
|
|
|
918
|
+
/// Source lookup for edit policy without loading every skill's full body.
|
|
919
|
+
pub(crate) fn learned_skill_sources(&self) -> Result<Vec<String>, MemoryError> {
|
|
920
|
+
let connection = self.connection()?;
|
|
921
|
+
let mut statement = connection.prepare("SELECT source_path FROM learned_skills")?;
|
|
922
|
+
let rows = statement.query_map([], |row| row.get(0))?;
|
|
923
|
+
Ok(rows.collect::<Result<Vec<_>, _>>()?)
|
|
924
|
+
}
|
|
925
|
+
|
|
500
926
|
pub fn learned_skills(&self, limit: usize) -> Result<Vec<LearnedSkill>, MemoryError> {
|
|
501
927
|
let connection = self.connection()?;
|
|
502
928
|
let mut statement = connection.prepare(
|
|
@@ -507,6 +933,37 @@ impl MemoryStore {
|
|
|
507
933
|
rows.collect::<Result<Vec<_>, _>>().map_err(Into::into)
|
|
508
934
|
}
|
|
509
935
|
|
|
936
|
+
/// A receipt contains the exact bytes returned by a successful full skill read.
|
|
937
|
+
/// It is not a claim that the model still has those bytes in its context.
|
|
938
|
+
pub fn record_skill_read(
|
|
939
|
+
&self,
|
|
940
|
+
chat_id: &str,
|
|
941
|
+
path: &str,
|
|
942
|
+
content: &str,
|
|
943
|
+
) -> Result<(), MemoryError> {
|
|
944
|
+
self.connection()?.execute(
|
|
945
|
+
"INSERT INTO session_skill_reads (chat_id, path, content) VALUES (?1, ?2, ?3)
|
|
946
|
+
ON CONFLICT(chat_id, path) DO UPDATE SET content = excluded.content",
|
|
947
|
+
params![normalized_chat_id(chat_id), path, content],
|
|
948
|
+
)?;
|
|
949
|
+
Ok(())
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
pub fn skill_read_content(
|
|
953
|
+
&self,
|
|
954
|
+
chat_id: &str,
|
|
955
|
+
path: &str,
|
|
956
|
+
) -> Result<Option<String>, MemoryError> {
|
|
957
|
+
Ok(self
|
|
958
|
+
.connection()?
|
|
959
|
+
.query_row(
|
|
960
|
+
"SELECT content FROM session_skill_reads WHERE chat_id = ?1 AND path = ?2",
|
|
961
|
+
params![normalized_chat_id(chat_id), path],
|
|
962
|
+
|row| row.get(0),
|
|
963
|
+
)
|
|
964
|
+
.optional()?)
|
|
965
|
+
}
|
|
966
|
+
|
|
510
967
|
pub fn delete_learned_skill(&self, identifier: &str) -> Result<usize, MemoryError> {
|
|
511
968
|
let connection = self.connection()?;
|
|
512
969
|
Ok(connection.execute(
|
|
@@ -718,7 +1175,11 @@ impl MemoryStore {
|
|
|
718
1175
|
)?)
|
|
719
1176
|
}
|
|
720
1177
|
|
|
721
|
-
fn
|
|
1178
|
+
pub(crate) fn path(&self) -> &std::path::Path {
|
|
1179
|
+
&self.path
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
pub(crate) fn connection(&self) -> Result<Connection, MemoryError> {
|
|
722
1183
|
if let Some(directory) = self.path.parent() {
|
|
723
1184
|
std::fs::create_dir_all(directory).map_err(|source| MemoryError::CreateDirectory {
|
|
724
1185
|
path: directory.to_path_buf(),
|
|
@@ -738,24 +1199,22 @@ impl MemoryStore {
|
|
|
738
1199
|
std::sync::Mutex<std::collections::HashSet<PathBuf>>,
|
|
739
1200
|
> = std::sync::LazyLock::new(|| std::sync::Mutex::new(std::collections::HashSet::new()));
|
|
740
1201
|
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
if
|
|
1202
|
+
// Publish readiness only after initialization succeeds. Companion and API
|
|
1203
|
+
// reads may open the same database concurrently during startup.
|
|
1204
|
+
let mut initialized = INITIALIZED_DATABASES
|
|
1205
|
+
.lock()
|
|
1206
|
+
.unwrap_or_else(|e| e.into_inner());
|
|
1207
|
+
if !initialized.contains(&self.path) {
|
|
747
1208
|
initialize(
|
|
748
1209
|
&connection,
|
|
749
1210
|
memory_path().is_ok_and(|default_path| default_path == self.path),
|
|
750
1211
|
)?;
|
|
751
|
-
//
|
|
752
|
-
//
|
|
753
|
-
// to owner-only rather than leaving it at default (typically
|
|
754
|
-
// world-readable) permissions. `needs_init` already gates this to
|
|
755
|
-
// once per path per process, and any pre-existing database from
|
|
756
|
-
// before this fix gets tightened the same way on its first open.
|
|
1212
|
+
// OAuth tokens live beside chat history; restrict the file once per
|
|
1213
|
+
// path per process, including databases created by older versions.
|
|
757
1214
|
restrict_to_owner(&self.path);
|
|
1215
|
+
initialized.insert(self.path.clone());
|
|
758
1216
|
}
|
|
1217
|
+
drop(initialized);
|
|
759
1218
|
Ok(connection)
|
|
760
1219
|
}
|
|
761
1220
|
}
|
|
@@ -910,13 +1369,33 @@ fn initialize(
|
|
|
910
1369
|
keywords TEXT DEFAULT '',
|
|
911
1370
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
912
1371
|
);
|
|
913
|
-
CREATE TABLE IF NOT EXISTS
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
918
|
-
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
1372
|
+
CREATE TABLE IF NOT EXISTS conversation_changes (
|
|
1373
|
+
sequence INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1374
|
+
chat_id TEXT NOT NULL,
|
|
1375
|
+
interaction_id INTEGER NOT NULL
|
|
919
1376
|
);
|
|
1377
|
+
CREATE TABLE IF NOT EXISTS conversation_source_attachments (
|
|
1378
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1379
|
+
interaction_id INTEGER NOT NULL,
|
|
1380
|
+
metadata TEXT NOT NULL,
|
|
1381
|
+
UNIQUE(interaction_id, metadata)
|
|
1382
|
+
);
|
|
1383
|
+
CREATE TRIGGER IF NOT EXISTS trg_interaction_sources_delete
|
|
1384
|
+
AFTER DELETE ON interaction_memories BEGIN
|
|
1385
|
+
DELETE FROM conversation_source_attachments WHERE interaction_id = OLD.id;
|
|
1386
|
+
END;
|
|
1387
|
+
CREATE INDEX IF NOT EXISTS idx_conversation_changes_chat_sequence
|
|
1388
|
+
ON conversation_changes(chat_id, sequence);
|
|
1389
|
+
CREATE TABLE IF NOT EXISTS chat_sessions (
|
|
1390
|
+
id TEXT PRIMARY KEY,
|
|
1391
|
+
title TEXT NOT NULL DEFAULT 'New chat',
|
|
1392
|
+
kind TEXT NOT NULL DEFAULT 'conversation',
|
|
1393
|
+
workspace_path TEXT DEFAULT NULL,
|
|
1394
|
+
git_branch TEXT DEFAULT NULL,
|
|
1395
|
+
main_language TEXT DEFAULT NULL,
|
|
1396
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
1397
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
1398
|
+
);
|
|
920
1399
|
CREATE TABLE IF NOT EXISTS learned_skills (
|
|
921
1400
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
922
1401
|
name TEXT NOT NULL,
|
|
@@ -925,6 +1404,12 @@ fn initialize(
|
|
|
925
1404
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
926
1405
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
927
1406
|
);
|
|
1407
|
+
CREATE TABLE IF NOT EXISTS session_skill_reads (
|
|
1408
|
+
chat_id TEXT NOT NULL,
|
|
1409
|
+
path TEXT NOT NULL,
|
|
1410
|
+
content TEXT NOT NULL,
|
|
1411
|
+
PRIMARY KEY(chat_id, path)
|
|
1412
|
+
);
|
|
928
1413
|
CREATE TABLE IF NOT EXISTS workspace_sessions (
|
|
929
1414
|
workspace_path TEXT PRIMARY KEY,
|
|
930
1415
|
summary TEXT NOT NULL,
|
|
@@ -970,13 +1455,14 @@ fn initialize(
|
|
|
970
1455
|
VALUES ('delete', old.id, old.user_text, old.ai_text);
|
|
971
1456
|
END;
|
|
972
1457
|
CREATE TRIGGER IF NOT EXISTS trg_interaction_fts_au
|
|
973
|
-
AFTER UPDATE ON interaction_memories BEGIN
|
|
1458
|
+
AFTER UPDATE OF user_text, ai_text ON interaction_memories BEGIN
|
|
974
1459
|
INSERT INTO interaction_fts(interaction_fts, rowid, user_text, ai_text)
|
|
975
1460
|
VALUES ('delete', old.id, old.user_text, old.ai_text);
|
|
976
1461
|
INSERT INTO interaction_fts(rowid, user_text, ai_text)
|
|
977
1462
|
VALUES (new.id, new.user_text, new.ai_text);
|
|
978
1463
|
END;",
|
|
979
1464
|
)?;
|
|
1465
|
+
crate::library::initialize(connection)?;
|
|
980
1466
|
ensure_column(
|
|
981
1467
|
connection,
|
|
982
1468
|
"interaction_memories",
|
|
@@ -1007,12 +1493,66 @@ fn initialize(
|
|
|
1007
1493
|
"agent_activity_json",
|
|
1008
1494
|
"TEXT DEFAULT NULL",
|
|
1009
1495
|
)?;
|
|
1496
|
+
ensure_column(
|
|
1497
|
+
connection,
|
|
1498
|
+
"interaction_memories",
|
|
1499
|
+
"status",
|
|
1500
|
+
"TEXT NOT NULL DEFAULT 'completed'",
|
|
1501
|
+
)?;
|
|
1502
|
+
ensure_column(
|
|
1503
|
+
connection,
|
|
1504
|
+
"interaction_memories",
|
|
1505
|
+
"lease_until",
|
|
1506
|
+
"INTEGER NOT NULL DEFAULT 0",
|
|
1507
|
+
)?;
|
|
1508
|
+
connection.execute_batch(
|
|
1509
|
+
"DROP TRIGGER IF EXISTS trg_interaction_fts_au;
|
|
1510
|
+
CREATE TRIGGER trg_interaction_fts_au
|
|
1511
|
+
AFTER UPDATE OF user_text, ai_text ON interaction_memories BEGIN
|
|
1512
|
+
INSERT INTO interaction_fts(interaction_fts, rowid, user_text, ai_text)
|
|
1513
|
+
VALUES ('delete', old.id, old.user_text, old.ai_text);
|
|
1514
|
+
INSERT INTO interaction_fts(rowid, user_text, ai_text)
|
|
1515
|
+
VALUES (new.id, new.user_text, new.ai_text);
|
|
1516
|
+
END;
|
|
1517
|
+
DROP TRIGGER IF EXISTS trg_conversation_change_update;
|
|
1518
|
+
CREATE TRIGGER IF NOT EXISTS trg_conversation_change_insert
|
|
1519
|
+
AFTER INSERT ON interaction_memories BEGIN
|
|
1520
|
+
INSERT INTO conversation_changes(chat_id, interaction_id) VALUES (new.chat_id, new.id);
|
|
1521
|
+
END;
|
|
1522
|
+
CREATE TRIGGER trg_conversation_change_update
|
|
1523
|
+
AFTER UPDATE OF user_text, ai_text, provider, model, fallback_provider,
|
|
1524
|
+
status, agent_activity_json, chat_id ON interaction_memories BEGIN
|
|
1525
|
+
INSERT INTO conversation_changes(chat_id, interaction_id) VALUES (new.chat_id, new.id);
|
|
1526
|
+
END;
|
|
1527
|
+
CREATE TRIGGER IF NOT EXISTS trg_conversation_change_delete
|
|
1528
|
+
AFTER DELETE ON interaction_memories BEGIN
|
|
1529
|
+
INSERT INTO conversation_changes(chat_id, interaction_id) VALUES (old.chat_id, old.id);
|
|
1530
|
+
END;",
|
|
1531
|
+
)?;
|
|
1010
1532
|
ensure_column(
|
|
1011
1533
|
connection,
|
|
1012
1534
|
"chat_sessions",
|
|
1013
1535
|
"kind",
|
|
1014
1536
|
"TEXT NOT NULL DEFAULT 'conversation'",
|
|
1015
1537
|
)?;
|
|
1538
|
+
ensure_column(
|
|
1539
|
+
connection,
|
|
1540
|
+
"chat_sessions",
|
|
1541
|
+
"workspace_path",
|
|
1542
|
+
"TEXT DEFAULT NULL",
|
|
1543
|
+
)?;
|
|
1544
|
+
ensure_column(
|
|
1545
|
+
connection,
|
|
1546
|
+
"chat_sessions",
|
|
1547
|
+
"git_branch",
|
|
1548
|
+
"TEXT DEFAULT NULL",
|
|
1549
|
+
)?;
|
|
1550
|
+
ensure_column(
|
|
1551
|
+
connection,
|
|
1552
|
+
"chat_sessions",
|
|
1553
|
+
"main_language",
|
|
1554
|
+
"TEXT DEFAULT NULL",
|
|
1555
|
+
)?;
|
|
1016
1556
|
// `agent_id` scopes a fact to the subagent that produced it (NULL = shared /
|
|
1017
1557
|
// user-authored); `embedding` is the on-device similarity vector used for
|
|
1018
1558
|
// relevance-ranked recall. Both are additive for databases created before
|
|
@@ -1233,6 +1773,7 @@ fn interaction_row(row: &rusqlite::Row<'_>) -> Result<InteractionMemory, rusqlit
|
|
|
1233
1773
|
model: row.get(5)?,
|
|
1234
1774
|
fallback_provider: row.get(6)?,
|
|
1235
1775
|
created_at: normalize_sqlite_utc_timestamp(&raw_created),
|
|
1776
|
+
status: row.get(9)?,
|
|
1236
1777
|
agent_activity,
|
|
1237
1778
|
})
|
|
1238
1779
|
}
|
|
@@ -1267,8 +1808,10 @@ fn ensure_builtin_chat_sessions(connection: &Connection) -> Result<(), rusqlite:
|
|
|
1267
1808
|
}
|
|
1268
1809
|
|
|
1269
1810
|
fn ensure_chat_session_row(connection: &Connection, chat_id: &str) -> Result<(), rusqlite::Error> {
|
|
1270
|
-
let (title, kind) = if
|
|
1811
|
+
let (title, kind) = if chat_id == CHAT_CLI_ID {
|
|
1271
1812
|
("Chat CLI", "cli")
|
|
1813
|
+
} else if is_cli_chat_id(chat_id) {
|
|
1814
|
+
("New chat", "cli")
|
|
1272
1815
|
} else {
|
|
1273
1816
|
("New chat", "conversation")
|
|
1274
1817
|
};
|
|
@@ -1280,6 +1823,235 @@ fn ensure_chat_session_row(connection: &Connection, chat_id: &str) -> Result<(),
|
|
|
1280
1823
|
Ok(())
|
|
1281
1824
|
}
|
|
1282
1825
|
|
|
1826
|
+
#[cfg(test)]
|
|
1827
|
+
mod conversation_sync_tests {
|
|
1828
|
+
#[test]
|
|
1829
|
+
fn concurrent_first_reads_wait_for_database_schema_initialization() {
|
|
1830
|
+
use std::sync::{Arc, Barrier};
|
|
1831
|
+
for _ in 0..3 {
|
|
1832
|
+
let root =
|
|
1833
|
+
std::env::temp_dir().join(format!("mint-schema-ordering-{}", uuid::Uuid::new_v4()));
|
|
1834
|
+
let store = super::MemoryStore::open(root.join("memory.sqlite"));
|
|
1835
|
+
let barrier = Arc::new(Barrier::new(16));
|
|
1836
|
+
let results = std::thread::scope(|scope| {
|
|
1837
|
+
let handles: Vec<_> = (0..16)
|
|
1838
|
+
.map(|_| {
|
|
1839
|
+
let barrier = Arc::clone(&barrier);
|
|
1840
|
+
let store = store.clone();
|
|
1841
|
+
scope.spawn(move || {
|
|
1842
|
+
barrier.wait();
|
|
1843
|
+
store.learned_skills(100)
|
|
1844
|
+
})
|
|
1845
|
+
})
|
|
1846
|
+
.collect();
|
|
1847
|
+
handles
|
|
1848
|
+
.into_iter()
|
|
1849
|
+
.map(|handle| handle.join().unwrap())
|
|
1850
|
+
.collect::<Vec<_>>()
|
|
1851
|
+
});
|
|
1852
|
+
let _ = std::fs::remove_dir_all(root);
|
|
1853
|
+
for result in results {
|
|
1854
|
+
assert!(result.is_ok(), "concurrent inventory read: {result:?}");
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1859
|
+
use super::*;
|
|
1860
|
+
|
|
1861
|
+
fn store() -> MemoryStore {
|
|
1862
|
+
MemoryStore::open(std::env::temp_dir().join(format!(
|
|
1863
|
+
"mint-conversation-sync-{}.sqlite",
|
|
1864
|
+
uuid::Uuid::new_v4()
|
|
1865
|
+
)))
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
#[test]
|
|
1869
|
+
fn listing_sessions_removes_empty_project_chat_placeholders() {
|
|
1870
|
+
let memory = store();
|
|
1871
|
+
memory
|
|
1872
|
+
.set_chat_session_workspace("conversation-empty", Some("/projects/demo"))
|
|
1873
|
+
.unwrap();
|
|
1874
|
+
memory
|
|
1875
|
+
.start_turn("conversation-used", "first message")
|
|
1876
|
+
.unwrap();
|
|
1877
|
+
|
|
1878
|
+
let sessions = memory.list_chat_sessions().unwrap();
|
|
1879
|
+
|
|
1880
|
+
assert!(
|
|
1881
|
+
!sessions
|
|
1882
|
+
.iter()
|
|
1883
|
+
.any(|session| session.id == "conversation-empty")
|
|
1884
|
+
);
|
|
1885
|
+
assert!(
|
|
1886
|
+
sessions
|
|
1887
|
+
.iter()
|
|
1888
|
+
.any(|session| session.id == "conversation-used")
|
|
1889
|
+
);
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1892
|
+
#[test]
|
|
1893
|
+
fn prompt_and_reply_use_one_id_and_emit_changes() {
|
|
1894
|
+
let memory = store();
|
|
1895
|
+
let first = memory.start_turn("cli::one", "hello").unwrap();
|
|
1896
|
+
let other_process = MemoryStore::open(memory.path.clone());
|
|
1897
|
+
let second = other_process.start_turn("cli::one", "next").unwrap();
|
|
1898
|
+
let other = memory.start_turn("cli::two", "separate").unwrap();
|
|
1899
|
+
assert!(memory.claim_turn("cli::one", first).unwrap());
|
|
1900
|
+
assert!(!other_process.claim_turn("cli::one", second).unwrap());
|
|
1901
|
+
assert!(memory.claim_turn("cli::two", other).unwrap());
|
|
1902
|
+
assert_eq!(
|
|
1903
|
+
memory
|
|
1904
|
+
.recent_completed_interactions_for_chat("cli::one", 3)
|
|
1905
|
+
.unwrap()
|
|
1906
|
+
.len(),
|
|
1907
|
+
0
|
|
1908
|
+
);
|
|
1909
|
+
|
|
1910
|
+
memory
|
|
1911
|
+
.finish_turn(first, "world", "test", "model", None)
|
|
1912
|
+
.unwrap();
|
|
1913
|
+
assert!(other_process.claim_turn("cli::one", second).unwrap());
|
|
1914
|
+
memory
|
|
1915
|
+
.finish_turn(second, "done", "test", "model", None)
|
|
1916
|
+
.unwrap();
|
|
1917
|
+
|
|
1918
|
+
let rows = memory.interactions_for_chat("cli::one").unwrap();
|
|
1919
|
+
assert_eq!(rows.len(), 2);
|
|
1920
|
+
assert_eq!(rows[0].id, first);
|
|
1921
|
+
assert_eq!(rows[0].ai_text, "world");
|
|
1922
|
+
assert_eq!(rows[1].status, "completed");
|
|
1923
|
+
let changes = memory.conversation_changes("cli::one", 0, 100).unwrap();
|
|
1924
|
+
assert!(changes.changes.iter().any(|c| {
|
|
1925
|
+
c.interaction_id == first
|
|
1926
|
+
&& c.interaction
|
|
1927
|
+
.as_ref()
|
|
1928
|
+
.is_some_and(|row| row.ai_text == "world")
|
|
1929
|
+
}));
|
|
1930
|
+
assert!(changes.changes.iter().all(|c| c.interaction_id != other));
|
|
1931
|
+
assert!(
|
|
1932
|
+
memory
|
|
1933
|
+
.conversation_changes("cli::one", changes.cursor, 100)
|
|
1934
|
+
.unwrap()
|
|
1935
|
+
.changes
|
|
1936
|
+
.is_empty()
|
|
1937
|
+
);
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1940
|
+
#[test]
|
|
1941
|
+
fn interrupted_turn_unblocks_queue_and_snapshot_pages() {
|
|
1942
|
+
let memory = store();
|
|
1943
|
+
let first = memory.start_turn("cli::one", "first").unwrap();
|
|
1944
|
+
let second = memory.start_turn("cli::one", "second").unwrap();
|
|
1945
|
+
assert!(memory.claim_turn("cli::one", first).unwrap());
|
|
1946
|
+
memory.end_turn(first, "interrupted").unwrap();
|
|
1947
|
+
assert!(memory.claim_turn("cli::one", second).unwrap());
|
|
1948
|
+
let page = memory.conversation_snapshot("cli::one", None, 1).unwrap();
|
|
1949
|
+
assert_eq!(page.interactions[0].id, second);
|
|
1950
|
+
assert!(page.has_older);
|
|
1951
|
+
let older = memory
|
|
1952
|
+
.conversation_snapshot("cli::one", Some(second), 1)
|
|
1953
|
+
.unwrap();
|
|
1954
|
+
assert_eq!(older.interactions[0].status, "interrupted");
|
|
1955
|
+
assert!(!older.has_older);
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1958
|
+
#[test]
|
|
1959
|
+
fn abandoned_turn_is_reported_after_lease_expires() {
|
|
1960
|
+
let memory = store();
|
|
1961
|
+
let id = memory.start_turn("cli::one", "unfinished").unwrap();
|
|
1962
|
+
assert!(memory.claim_turn("cli::one", id).unwrap());
|
|
1963
|
+
memory
|
|
1964
|
+
.connection()
|
|
1965
|
+
.unwrap()
|
|
1966
|
+
.execute(
|
|
1967
|
+
"UPDATE interaction_memories SET lease_until = 0 WHERE id = ?1",
|
|
1968
|
+
params![id],
|
|
1969
|
+
)
|
|
1970
|
+
.unwrap();
|
|
1971
|
+
let changes = memory.conversation_changes("cli::one", 0, 100).unwrap();
|
|
1972
|
+
assert_eq!(
|
|
1973
|
+
changes
|
|
1974
|
+
.changes
|
|
1975
|
+
.last()
|
|
1976
|
+
.unwrap()
|
|
1977
|
+
.interaction
|
|
1978
|
+
.as_ref()
|
|
1979
|
+
.unwrap()
|
|
1980
|
+
.status,
|
|
1981
|
+
"interrupted"
|
|
1982
|
+
);
|
|
1983
|
+
assert!(
|
|
1984
|
+
memory
|
|
1985
|
+
.finish_turn(id, "late", "test", "model", None)
|
|
1986
|
+
.is_err()
|
|
1987
|
+
);
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
#[test]
|
|
1991
|
+
fn old_completed_rows_migrate_without_losing_content() {
|
|
1992
|
+
let path = std::env::temp_dir().join(format!(
|
|
1993
|
+
"mint-conversation-legacy-{}.sqlite",
|
|
1994
|
+
uuid::Uuid::new_v4()
|
|
1995
|
+
));
|
|
1996
|
+
let connection = Connection::open(&path).unwrap();
|
|
1997
|
+
connection
|
|
1998
|
+
.execute_batch(
|
|
1999
|
+
"CREATE TABLE interaction_memories (
|
|
2000
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
2001
|
+
chat_id TEXT NOT NULL DEFAULT 'conversation-default',
|
|
2002
|
+
user_text TEXT NOT NULL, ai_text TEXT NOT NULL,
|
|
2003
|
+
provider TEXT NOT NULL DEFAULT '', model TEXT NOT NULL DEFAULT '',
|
|
2004
|
+
fallback_provider TEXT DEFAULT NULL, keywords TEXT DEFAULT '',
|
|
2005
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
2006
|
+
);
|
|
2007
|
+
INSERT INTO interaction_memories(chat_id, user_text, ai_text)
|
|
2008
|
+
VALUES ('cli::old', 'old prompt', 'old reply');",
|
|
2009
|
+
)
|
|
2010
|
+
.unwrap();
|
|
2011
|
+
drop(connection);
|
|
2012
|
+
let memory = MemoryStore::open(path);
|
|
2013
|
+
let rows = memory.interactions_for_chat("cli::old").unwrap();
|
|
2014
|
+
assert_eq!(rows.len(), 1);
|
|
2015
|
+
assert_eq!(rows[0].status, "completed");
|
|
2016
|
+
assert_eq!(rows[0].ai_text, "old reply");
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
#[test]
|
|
2020
|
+
fn clearing_history_emits_tombstones_for_open_views() {
|
|
2021
|
+
let memory = store();
|
|
2022
|
+
let id = memory
|
|
2023
|
+
.add_interaction_for_chat("cli::one", "hello", "world", "test", "model")
|
|
2024
|
+
.unwrap();
|
|
2025
|
+
let cursor = memory.latest_conversation_sequence("cli::one").unwrap();
|
|
2026
|
+
memory.clear_interactions_for_chat("cli::one").unwrap();
|
|
2027
|
+
let changes = memory
|
|
2028
|
+
.conversation_changes("cli::one", cursor, 100)
|
|
2029
|
+
.unwrap();
|
|
2030
|
+
assert!(
|
|
2031
|
+
changes
|
|
2032
|
+
.changes
|
|
2033
|
+
.iter()
|
|
2034
|
+
.any(|change| change.interaction_id == id && change.interaction.is_none())
|
|
2035
|
+
);
|
|
2036
|
+
}
|
|
2037
|
+
|
|
2038
|
+
#[test]
|
|
2039
|
+
fn heartbeat_does_not_emit_visible_changes() {
|
|
2040
|
+
let memory = store();
|
|
2041
|
+
let id = memory.start_turn("cli::one", "hello").unwrap();
|
|
2042
|
+
assert!(memory.claim_turn("cli::one", id).unwrap());
|
|
2043
|
+
let cursor = memory.latest_conversation_sequence("cli::one").unwrap();
|
|
2044
|
+
memory.renew_turn(id).unwrap();
|
|
2045
|
+
assert!(
|
|
2046
|
+
memory
|
|
2047
|
+
.conversation_changes("cli::one", cursor, 100)
|
|
2048
|
+
.unwrap()
|
|
2049
|
+
.changes
|
|
2050
|
+
.is_empty()
|
|
2051
|
+
);
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
|
|
1283
2055
|
#[cfg(test)]
|
|
1284
2056
|
mod scoped_chat_id_tests {
|
|
1285
2057
|
use super::*;
|