@pheem49/mint 1.8.1 → 1.9.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 +3 -3
- package/Cargo.toml +1 -1
- package/README.md +0 -17
- package/Release_Note.md +137 -58
- package/bin/mint +0 -0
- package/crates/mint-cli/src/agent.rs +150 -45
- package/crates/mint-cli/src/image.rs +8 -8
- package/crates/mint-cli/src/main.rs +929 -412
- package/crates/mint-cli/src/onboard.rs +108 -108
- package/crates/mint-cli/src/setup.rs +143 -143
- package/crates/mint-core/src/agent_loop.rs +1 -0
- package/crates/mint-core/src/api_server.rs +108 -52
- package/crates/mint-core/src/browser.rs +56 -1
- package/crates/mint-core/src/channels.rs +1 -0
- package/crates/mint-core/src/chat.rs +126 -8
- package/crates/mint-core/src/code_tools.rs +18 -20
- package/crates/mint-core/src/config.rs +245 -17
- package/crates/mint-core/src/image_gen.rs +5 -5
- package/crates/mint-core/src/lib.rs +16 -2
- package/crates/mint-core/src/memory.rs +6 -1
- package/crates/mint-core/src/orchestration.rs +260 -72
- package/crates/mint-core/src/pictures.rs +3 -4
- package/crates/mint-core/src/semantic.rs +1 -1
- package/crates/mint-core/src/shell.rs +1 -1
- package/crates/mint-core/src/skills.rs +46 -19
- package/crates/mint-core/src/tts.rs +3 -1
- package/flatpak/com.pheem49.mint.desktop +9 -0
- package/flatpak/com.pheem49.mint.metainfo.xml +35 -0
- package/flatpak/com.pheem49.mint.yaml +52 -0
- package/package.json +1 -1
- package/shared-modules/.github/workflows/ci.yml +120 -0
- package/shared-modules/.github/workflows/update.yaml +28 -0
- package/shared-modules/CODEOWNERS +23 -0
- package/shared-modules/README.md +79 -0
- package/shared-modules/SDL/README.md +3 -0
- package/shared-modules/SDL/SDL-1.2.15.json +51 -0
- package/shared-modules/SDL/SDL_Pango-0.1.2-API-adds.patch +118 -0
- package/shared-modules/SDL/SDL_image-1.2.12.json +25 -0
- package/shared-modules/SDL/SDL_mixer-1.2.12.json +27 -0
- package/shared-modules/SDL/SDL_net-1.2.8.json +19 -0
- package/shared-modules/SDL/SDL_pango-0.1.2.json +26 -0
- package/shared-modules/SDL/SDL_ttf-2.0.11.json +28 -0
- package/shared-modules/SDL/libsdl-1.2.15-strict-prototypes.patch +316 -0
- package/shared-modules/SDL/sdl-check-for-SDL_VIDEO_X11_BACKINGSTORE.patch +24 -0
- package/shared-modules/SDL/sdl-libx11-build.patch +59 -0
- package/shared-modules/SDL/sdl-sysloadso-buffer-length.patch +27 -0
- package/shared-modules/SDL/sdl12-compat.json +22 -0
- package/shared-modules/SDL2/SDL2_image.json +27 -0
- package/shared-modules/SDL2/SDL2_ttf.json +29 -0
- package/shared-modules/cld2/CMakeLists.txt +157 -0
- package/shared-modules/cld2/cld2.json +24 -0
- package/shared-modules/clutter/clutter.json +72 -0
- package/shared-modules/dbus-glib/dbus-glib.json +29 -0
- package/shared-modules/glew/glew.json +36 -0
- package/shared-modules/glu/glu-9.json +12 -0
- package/shared-modules/gtk2/arc-gtk2-theme-Replace-Inkscape-dependency-with-rsvg-convert.patch +180 -0
- package/shared-modules/gtk2/gtk2-common-themes.json +360 -0
- package/shared-modules/gtk2/gtk2-fix-crash-in-show-uri.patch +30 -0
- package/shared-modules/gtk2/gtk2-gcc14.patch +281 -0
- package/shared-modules/gtk2/gtk2-gcc15.patch +250 -0
- package/shared-modules/gtk2/gtk2-murrine-c99.patch +34 -0
- package/shared-modules/gtk2/gtk2-use-adwaita-theme.patch +80 -0
- package/shared-modules/gtk2/gtk2.json +120 -0
- package/shared-modules/gtk2/ibus-gcc15.patch +13 -0
- package/shared-modules/gtk2/murrine-engine-fix-crash.patch +12 -0
- package/shared-modules/gtk2/readme.md +10 -0
- package/shared-modules/intltool/intltool-0.51.json +20 -0
- package/shared-modules/intltool/intltool-perl5.26-regex-fixes.patch +59 -0
- package/shared-modules/lame/0001-Build-xmm_quantize_sub.c-with-msse.patch +34 -0
- package/shared-modules/lame/0002-Include-GTK-1-autoconf-directives-in-build-system.patch +222 -0
- package/shared-modules/lame/0003-Patch-out-remaining-ansi2knr.patch +70 -0
- package/shared-modules/lame/0004-initscr-is-not-used-anywhere-in-lame-sourcetree.patch +41 -0
- package/shared-modules/lame/0005-Update-autoconf.patch +81 -0
- package/shared-modules/lame/lame-3.99.5.json +32 -0
- package/shared-modules/libappindicator/libappindicator-gtk2-12.10.json +140 -0
- package/shared-modules/libappindicator/libappindicator-gtk3-12.10.json +140 -0
- package/shared-modules/libappindicator/libappindicator-gtk3-introspection-12.10.json +140 -0
- package/shared-modules/libappindicator/patches/0001-libappindicator-ftbfs.patch +20 -0
- package/shared-modules/libappindicator/patches/0002-libappindicator-no-python.patch +888 -0
- package/shared-modules/libappindicator/patches/0003-libappindicator-fix-crash-from-incorrect-signal-emission.patch +74 -0
- package/shared-modules/libappindicator/patches/0004-libappindicator-fix-crash-iterating-icon-themes.patch +11 -0
- package/shared-modules/libayatana-appindicator/0001-Fix-HAVE_VALGRIND-AM_CONDITIONAL.patch +51 -0
- package/shared-modules/libayatana-appindicator/0001-Make-introspection-configurable.patch +44 -0
- package/shared-modules/libayatana-appindicator/libayatana-appindicator-gtk3.json +121 -0
- package/shared-modules/libcanberra/0001-gtk-Don-t-assume-all-GdkDisplays-are-GdkX11Displays-.patch +123 -0
- package/shared-modules/libcanberra/libcanberra.json +44 -0
- package/shared-modules/libmad/libmad.json +19 -0
- package/shared-modules/libsecret/libsecret.json +23 -0
- package/shared-modules/libsoup/libsoup-2.4.json +14 -0
- package/shared-modules/libusb/libusb.json +27 -0
- package/shared-modules/linux-audio/dssi.json +31 -0
- package/shared-modules/linux-audio/fftw3f-static.json +44 -0
- package/shared-modules/linux-audio/fftw3f.json +42 -0
- package/shared-modules/linux-audio/fluidsynth2-static.json +36 -0
- package/shared-modules/linux-audio/fluidsynth2.json +25 -0
- package/shared-modules/linux-audio/ladspa.json +26 -0
- package/shared-modules/linux-audio/lash.json +35 -0
- package/shared-modules/linux-audio/libinstpatch.json +16 -0
- package/shared-modules/linux-audio/liblo-static.json +22 -0
- package/shared-modules/linux-audio/liblo.json +17 -0
- package/shared-modules/linux-audio/lilv-static.json +94 -0
- package/shared-modules/linux-audio/lilv.json +89 -0
- package/shared-modules/linux-audio/lrdf.json +57 -0
- package/shared-modules/linux-audio/lv2.json +20 -0
- package/shared-modules/linux-audio/patches/lash/0001-configure-remove-aclocal-m4.patch +29 -0
- package/shared-modules/linux-audio/patches/lash/0002-Fix-build-with-recent-gcc.patch +73 -0
- package/shared-modules/linux-audio/patches/lash/0003-Fix-linking.patch +136 -0
- package/shared-modules/linux-audio/patches/raptor-libxml.patch +31 -0
- package/shared-modules/linux-audio/patches/stk-install.sh +54 -0
- package/shared-modules/linux-audio/stk.json +28 -0
- package/shared-modules/lua5.1/0004-Fix-stack-overflow-in-vararg-functions.patch +21 -0
- package/shared-modules/lua5.1/lua-5.1.5-so.patch +43 -0
- package/shared-modules/lua5.1/lua-5.1.5.json +42 -0
- package/shared-modules/lua5.3/lua-5.3.5.json +41 -0
- package/shared-modules/lua5.3/lua.pc.in +8 -0
- package/shared-modules/lua5.3/luaconf.patch +47 -0
- package/shared-modules/lua5.3/makefile-add-liblua.so-rule.patch +47 -0
- package/shared-modules/lua5.4/lua-5.4.json +41 -0
- package/shared-modules/lua5.4/lua.pc.in +8 -0
- package/shared-modules/lua5.4/luaconf.patch +34 -0
- package/shared-modules/lua5.4/makefile-add-liblua.so-rule.patch +42 -0
- package/shared-modules/luajit/luajit.json +30 -0
- package/shared-modules/lzo/lzo.json +27 -0
- package/shared-modules/mac/mac.json +18 -0
- package/shared-modules/physfs/physfs.json +26 -0
- package/shared-modules/pygame/audiofile-gcc6.patch +21 -0
- package/shared-modules/pygame/cython-fixes.patch +34 -0
- package/shared-modules/pygame/fluidsynth-no-rawmidi.patch +69 -0
- package/shared-modules/pygame/glib.patch +25 -0
- package/shared-modules/pygame/pygame1-python2.json +157 -0
- package/shared-modules/pygtk/pygtk-c99.patch +15 -0
- package/shared-modules/pygtk/pygtk.json +117 -0
- package/shared-modules/pygtk/pygtk.patch +39 -0
- package/shared-modules/python2.7/python-2.7.json +48 -0
- package/shared-modules/smpeg/smpeg-0.4.5.json +50 -0
- package/shared-modules/smpeg/smpeg-am-prog-as.patch +12 -0
- package/shared-modules/smpeg/smpeg-export-mpegaudio-class.patch +17 -0
- package/shared-modules/smpeg/smpeg-gcc6.patch +40 -0
- package/shared-modules/smpeg/smpeg-no-gtk.patch +37 -0
- package/shared-modules/squashfs-tools/squashfs-tools.json +25 -0
- package/shared-modules/update-checker.sh +50 -0
- package/shared-modules/vorbisgain/0001-temp_files.patch +75 -0
- package/shared-modules/vorbisgain/0002-errno.patch +33 -0
- package/shared-modules/vorbisgain/0003-manpage.patch +248 -0
- package/shared-modules/vorbisgain/0004-vorbisgain_mtime.patch +183 -0
- package/shared-modules/vorbisgain/0005-double_fclose.patch +21 -0
- package/shared-modules/vorbisgain/0006-manpage_hyphens.patch +56 -0
- package/shared-modules/vorbisgain/0007-recursively_spelling.patch +14 -0
- package/shared-modules/vorbisgain/0008-manpage_recursion_mistake.patch +23 -0
- package/shared-modules/vorbisgain/0009-hardening.patch +13 -0
- package/shared-modules/vorbisgain/0010-fclose.patch +13 -0
- package/shared-modules/vorbisgain/README.md +23 -0
- package/shared-modules/vorbisgain/vorbisgain_0.37-2.json +29 -0
- package/src/renderer/shared/agentProgress.ts +145 -0
- package/src/renderer/shared/calculator.ts +52 -0
- package/src/renderer/shared/components/AgentActivityDrawer.tsx +72 -0
- package/src/renderer/shared/components/AgentActivityTable.tsx +85 -0
- package/src/renderer/shared/components/ApprovalCard.tsx +93 -0
- package/src/renderer/shared/components/ChatCodeBlock.tsx +75 -0
- package/src/renderer/shared/components/ThinkingBlock.tsx +101 -0
- package/src/renderer/shared/constants/models.ts +91 -0
- package/src/renderer/shared/platform.ts +82 -0
- package/src/renderer/shared/types.ts +140 -0
- package/src/renderer/shared/utils/agentActivity.ts +187 -0
- package/src/renderer/shared/utils/approval.ts +1 -0
- package/src/renderer/shared/utils/approval.tsx +64 -0
- package/src/renderer/shared/utils/fileIcons.ts +135 -0
- package/src/renderer/shared/utils/markdown.tsx +347 -0
- package/src/renderer/shared/utils/providers.ts +36 -0
- package/src/renderer/shared/utils/speech.ts +216 -0
- package/src/renderer/shared/utils/ui.ts +147 -0
- package/src/renderer/src/agentProgress.ts +11 -39
- package/src/renderer/src/calculator.ts +3 -46
- package/src/renderer/src/components/ChatPanel.tsx +219 -1308
- package/src/renderer/src/components/MintDashboard.tsx +67 -170
- package/src/renderer/src/components/PicturesLibrary.tsx +32 -8
- package/src/renderer/src/components/Settings/AgentsTab.tsx +381 -0
- package/src/renderer/src/components/Settings/AutomationTab.tsx +0 -22
- package/src/renderer/src/components/Settings/GeneralTab.tsx +256 -2
- package/src/renderer/src/components/SettingsWindow.tsx +120 -3
- package/src/renderer/src/components/WorkspacePanel.tsx +7 -125
- package/src/renderer/src/css/styles.css +100 -0
- package/src/renderer/src/tauri.ts +128 -143
- package/src/renderer/src-web/agentProgress.ts +11 -39
- package/src/renderer/src-web/calculator.ts +3 -46
- package/src/renderer/src-web/components/ChatPanel.tsx +219 -1306
- package/src/renderer/src-web/components/MintDashboard.tsx +42 -170
- package/src/renderer/src-web/components/PicturesLibrary.tsx +23 -29
- package/src/renderer/src-web/components/Settings/AgentsTab.tsx +381 -0
- package/src/renderer/src-web/components/Settings/AutomationTab.tsx +0 -22
- package/src/renderer/src-web/components/Settings/GeneralTab.tsx +254 -3
- package/src/renderer/src-web/components/SettingsWindow.tsx +127 -3
- package/src/renderer/src-web/css/styles.css +100 -0
- package/src/renderer/src-web/tauri.ts +180 -102
- package/src-tauri/src/desktop.rs +18 -16
- package/src-tauri/src/discord_rpc.rs +1 -1
- package/src-tauri/src/lib.rs +168 -40
- package/src-tauri/src/webhooks.rs +1 -0
- package/src-tauri/src/workflows.rs +1 -0
- package/src-tauri/tauri.conf.json +1 -1
package/Cargo.lock
CHANGED
|
@@ -2095,7 +2095,7 @@ dependencies = [
|
|
|
2095
2095
|
|
|
2096
2096
|
[[package]]
|
|
2097
2097
|
name = "mint-cli"
|
|
2098
|
-
version = "1.8.
|
|
2098
|
+
version = "1.8.2"
|
|
2099
2099
|
dependencies = [
|
|
2100
2100
|
"anyhow",
|
|
2101
2101
|
"base64 0.22.1",
|
|
@@ -2114,7 +2114,7 @@ dependencies = [
|
|
|
2114
2114
|
|
|
2115
2115
|
[[package]]
|
|
2116
2116
|
name = "mint-core"
|
|
2117
|
-
version = "1.8.
|
|
2117
|
+
version = "1.8.2"
|
|
2118
2118
|
dependencies = [
|
|
2119
2119
|
"base64 0.22.1",
|
|
2120
2120
|
"chrono",
|
|
@@ -2135,7 +2135,7 @@ dependencies = [
|
|
|
2135
2135
|
|
|
2136
2136
|
[[package]]
|
|
2137
2137
|
name = "mint-desktop"
|
|
2138
|
-
version = "1.8.
|
|
2138
|
+
version = "1.8.2"
|
|
2139
2139
|
dependencies = [
|
|
2140
2140
|
"base64 0.22.1",
|
|
2141
2141
|
"dirs",
|
package/Cargo.toml
CHANGED
package/README.md
CHANGED
|
@@ -113,23 +113,6 @@ Mint is a local-first AI assistant running on your machine, capable of handling
|
|
|
113
113
|
- Right-click context menu to delete files/folders with confirmation modals.
|
|
114
114
|
- Drag-and-drop file mentions in the chat input with automatic spacing and dynamic accent-colored history bubble highlighting.
|
|
115
115
|
|
|
116
|
-
## What's New in v1.8.1
|
|
117
|
-
|
|
118
|
-
- **File-System Based AI Skills & UI Badges**: Scan and load AI skills from the Global folder (`~/.config/mint/mint-skills/`) and Workspace folders (`.agents/skills/` & `skills/`). Shows source badges (`Workspace` 🟢, `Global` 🔵, `Taught` 🟣) in settings UI and CLI listings (`mint learn --list` and `/learn`) with a clean hidden-content list view.
|
|
119
|
-
- **Unified MCP Servers UI & Toggle Controls**: Merged system-discovered servers into a unified list with toggles to enable/disable or install, and red trash can buttons to remove custom servers.
|
|
120
|
-
- **Advanced Workspace File Tree & Operations**: Manage files directly from the sidebar UI with file/folder creation buttons, right-click deletion modals, and automatic polling + focus-based syncing.
|
|
121
|
-
- **Drag-and-Drop File Mentions**: Drag files from the sidebar to chat input to insert `@filename` with auto-spacing, rendered as outline pills styled with your selected accent color.
|
|
122
|
-
- **CLI Agent Interface Polish & Terminal Line Wrapping Fix**: Indented status blocks and confirmation prompts by 2 spaces to align text. Implemented the *Dynamic Breathing Circle System* (`●` ⇄ `○` pulsing during thinking) and fixed terminal duplicate line bugs by counting physical terminal wrapping width and filtering Thai tone marks.
|
|
123
|
-
- **AskUser Text Input Modal (Desktop & Web)**: When the agent asks questions, a text input field is rendered inside the approval card so users can write and submit typed answers back to the agent backend.
|
|
124
|
-
- **Dynamic Language AI Suggestions**: Auto-translates process suggestions dynamically based on your configured `config.language`.
|
|
125
|
-
- **Mobile & Navigation Optimizations**: Mobile-fit Image Studio layout, hamburger menu access, and headers glass-morphism overlay fixes.
|
|
126
|
-
|
|
127
|
-
## What's New in v1.8.0
|
|
128
|
-
|
|
129
|
-
- **Integrated Web Search Settings**: Easily toggle between **Brave Search API** and **Google Custom Search API** directly from the General settings tab.
|
|
130
|
-
- **Image Generation Providers**: Choose and configure credentials for Stability AI, Ideogram, Replicate, OpenAI DALL-E, and Google NanoBanana (Gemini Images) inside dedicated inline settings cards.
|
|
131
|
-
- **Inline Productivity Settings**: Set up Client IDs, secrets, and API keys for native Gmail, Google Calendar, and Notion integrations inline inside the General settings tab.
|
|
132
|
-
- **Revamped Plugins Layout**: Moved **Learned AI Skills** (equivalent to `mint learn` in CLI) to the top of the Plugins tab, followed by MCP Servers (External tools), and Built-in Plugins (Spotify and Discord RPC) at the bottom.
|
|
133
116
|
|
|
134
117
|
## <img src="assets/setup.svg" width="24" height="24" valign="middle" /> Prerequisites
|
|
135
118
|
|
package/Release_Note.md
CHANGED
|
@@ -1,70 +1,109 @@
|
|
|
1
|
-
# Release Notes - Mint Agent v1.
|
|
1
|
+
# Release Notes - Mint Agent v1.9.0
|
|
2
2
|
|
|
3
|
-
We are excited to release **Mint Agent v1.
|
|
3
|
+
We are excited to release **Mint Agent v1.9.0**! This release introduces a configurable Multi-Agent system for sequential collaboration, powerful local workspace file management features, real-time AI-generated workflow suggestions in the user's active language, mobile layout optimization, and general UI/UX polish.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## 🔌 Custom Provider Support
|
|
8
|
+
|
|
9
|
+
Users can now add any **OpenAI-compatible endpoint** as a fully configurable custom AI provider, giving complete control over which LLM backend Mint uses.
|
|
10
|
+
|
|
11
|
+
### Backend (`config.rs`, `chat.rs`)
|
|
12
|
+
- **New data model:** Added `CustomProvider`, `CustomProviderModel`, and `CustomProviderHeader` structs to `MintConfig`. Custom providers are persisted to `mint-config.json` under the `customProviders` key.
|
|
13
|
+
- **Provider ID format:** Each custom provider is stored with a user-defined slug ID and is referenced in `ai_provider` as `"custom:<id>"` (e.g. `"custom:myprovider"`).
|
|
14
|
+
- **Chat routing:** `send_chat()` and `stream_chat()` now dispatch `custom:*` providers through `call_custom_provider()` / `stream_custom_provider()`, which use the existing OpenAI-compatible HTTP code path.
|
|
15
|
+
- **Multiple models:** Each provider stores a list of models; the active model is resolved from `customModelSelections` extra config (set by the UI model selector dropdown).
|
|
16
|
+
- **Custom HTTP headers:** All configured headers are applied to every request sent to that provider.
|
|
17
|
+
- **`available_providers()`** now returns `Vec<String>` (up from `Vec<&'static str>`) to accommodate dynamic custom provider IDs.
|
|
18
|
+
- **`resolve_custom_provider()`** helper added to look up a `CustomProvider` by key (strips the `custom:` prefix automatically).
|
|
19
|
+
|
|
20
|
+
### Frontend (`SettingsWindow.tsx`, `GeneralTab.tsx`, `AgentsTab.tsx`)
|
|
21
|
+
- **Settings → General → Active Provider dropdown** now includes all configured custom providers dynamically.
|
|
22
|
+
- **Model selector:** When a custom provider is selected as the active provider, a second dropdown appears to pick among that provider's configured models.
|
|
23
|
+
- **Custom Providers section:** A new section at the bottom of General settings displays each custom provider as a card. Each card allows inline editing of: Provider ID (slug-validated), Display Name, Base URL, API Key (password), per-model rows (model ID + display name), and per-header rows (name + value). Providers can be added with `+ Add custom provider` and deleted inline.
|
|
24
|
+
- **Agents tab:** Custom providers (with a configured base URL) now appear in the AI Provider dropdown when creating or editing an agent. The model selector shows that provider's configured models.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 🔍 Web Search Source Cards
|
|
29
|
+
|
|
30
|
+
- **Favicon Source Cards:** After a web search, compact clickable source cards now appear above the AI response bubble — each showing the website's favicon, domain name, and a tooltip with the page snippet. Clicking a card opens the source in the browser.
|
|
31
|
+
- **Frontend-only change:** Parsed directly from existing `AgentProgress` `ToolEnd` events — no backend changes required.
|
|
32
|
+
- The AI response also includes a plain-text `Sources:` section listing title and URL for each result used.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
|
|
7
37
|
## 🚀 Key Features & Enhancements
|
|
8
38
|
|
|
9
|
-
###
|
|
10
|
-
You can now
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
- **
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
- **
|
|
29
|
-
- **
|
|
30
|
-
- **
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
-
|
|
35
|
-
- **
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
- **
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
- **
|
|
46
|
-
- **
|
|
47
|
-
- **
|
|
48
|
-
|
|
49
|
-
###
|
|
50
|
-
|
|
51
|
-
- **
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
- **
|
|
58
|
-
- **
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
- **
|
|
63
|
-
|
|
64
|
-
|
|
39
|
+
### 🛑 1. Escape (Esc) Key & Stop Button to Cancel AI Agent / Chat
|
|
40
|
+
You can now cancel or stop an active AI stream or agent loop at any point in the web and desktop applications:
|
|
41
|
+
- **Escape Key Press:** Pressing the `Esc` key while the AI is thinking or executing automatically aborts the active stream.
|
|
42
|
+
- **Red Stop Composer Button:** When the AI is running, the composer "Send" button turns into a red "Stop" square icon button, allowing users to stop the generation instantly.
|
|
43
|
+
- **Thinking Label Hints:** Updated the progress indicator label to explicitly display "Thinking for Xs (Esc to cancel)" so users are aware of the shortcut.
|
|
44
|
+
|
|
45
|
+
### 🎙️ 2. Microphone Active Breathing Aura Glow
|
|
46
|
+
When the microphone/voice mode is active, the boundaries of the chat composer box and the voice status bar light up with a dynamic, breathing green aura, providing intuitive visual feedback.
|
|
47
|
+
|
|
48
|
+
### 🤖 3. Configurable Multi-Agent System & Collaboration Pipeline
|
|
49
|
+
Users can now configure and run multiple specialized AI agents (e.g. Planner, Coder, Reviewer) within the desktop and web settings panel, allocating custom models, providers, and instructions to each agent:
|
|
50
|
+
- **Global Toggle Switch:** Added a main "Enable Multi-Agent Collaboration" toggle switch at the top of the new "Multi-Agent (Beta)" settings tab to globally turn on/off the agent routing pipeline.
|
|
51
|
+
- **Provider-Specific Dropdowns:** Replaced the text input for model selection with provider-specific dropdown select lists matching the models available in General settings.
|
|
52
|
+
- **Disable All Button:** Added a "Disable All" button allowing users to disable all configured agents instantly in one click.
|
|
53
|
+
- **Real-Time Agent & Model Indicators:** The live thinking message bubble in the chat panel dynamically displays the active agent's name and model in real-time (e.g. `Planner (gemini-2.5-flash) is thinking...`).
|
|
54
|
+
|
|
55
|
+
### 🖥️ 4. CLI Suggestions Pagination & Ordering
|
|
56
|
+
Improved the autocomplete experience in the terminal:
|
|
57
|
+
- **Pagination (5 Items Max):** Autocomplete suggestions now display a maximum of 5 commands at a time with a page indicator (e.g., `Suggestions (1/4)`), preventing long list clutter.
|
|
58
|
+
- **Alphabetical Sorting:** Autocomplete suggestions are sorted alphabetically at source.
|
|
59
|
+
- **Simplified Exit Options:** Removed `/quit` from the autocomplete suggestions and help output (while retaining hidden execution support) to clean up the interface.
|
|
60
|
+
- **Real-Time Agent & Model Status:** The CLI live thinking status bar dynamically displays which agent and model is executing.
|
|
61
|
+
|
|
62
|
+
### 📋 5. Fix Clipboard Permission Popup on Text Paste (Ctrl+V) & Desktop Image Paste Fallback
|
|
63
|
+
- Fixed a bug where pasting text (or pressing `Ctrl + V`) would trigger a browser-level clipboard permission warning popup (asking to "Allow Paste").
|
|
64
|
+
- Removed the redundant global `keydown` Ctrl+V listener and the async `navigator.clipboard.read()` fallback on text paste events. The application now correctly relies on standard, synchronous `event.clipboardData` values during paste events, ensuring seamless pasting of both images and text without prompting the user.
|
|
65
|
+
- **Tauri Native Fallback:** Restored an asynchronous fallback using Tauri's native backend `readClipboardImage` command specifically for the desktop application. This solves the Linux/Windows WebView limitations where WebKitGTK and standard web APIs fail to expose file handles in standard paste events.
|
|
66
|
+
- **Double Paste Throttling:** Implemented a 100ms throttle wrapper around the native clipboard read callback, preventing duplicate image attachments caused by concurrent window-level capture and element-level paste event propagation.
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
### 📦 6. Codebase Refactoring & Shared Utilities
|
|
71
|
+
- **Shared UI & Progress Helpers:** Refactored duplicate helper functions and TypeScript interfaces from the desktop renderer (`src/renderer/src`) and web renderer (`src/renderer/src-web`) into the unified `shared` codebase.
|
|
72
|
+
- **Maintainability:** Standardized helper functions across both application targets to prevent future regressions.
|
|
73
|
+
|
|
74
|
+
### 🖥️ 7. Horizontal Scrolling for CLI Input Box
|
|
75
|
+
- **Arbitrary Input Length:** Removed the single-line input constraint (previously restricted to `term_width - 4`) in the CLI interactive prompt, allowing users to type or edit long prompt instructions.
|
|
76
|
+
- **Dynamic Sliding Window:** Implemented a horizontal scrolling viewport for the single-line prompt box. It dynamically slices and displays a subset of characters surrounding the cursor position to preserve console alignment and layout integrity.
|
|
77
|
+
- **Interactive Cursor Navigation:** Bounded the arrow keys (`Left` and `Right` navigation) to trigger full box redraws, enabling the visible text window to scroll back and forward dynamically as the cursor moves.
|
|
78
|
+
|
|
79
|
+
### 🖥️ 8. Browser Automation Visual Indicator (Green Aura)
|
|
80
|
+
- **Visual Feedback:** Injects a breathing green glowing border overlay around the viewport of any browser page under active AI control.
|
|
81
|
+
- **Non-Intrusive Design:** Built with `pointer-events: none` and a high z-index to ensure it sits on top of all page elements without blocking clicks, scrolling, or user interactions.
|
|
82
|
+
|
|
83
|
+
### 🎙️ 9. Client-Side Speech-to-Text Microphone Consolidation
|
|
84
|
+
- **Consolidated Flow**: Standardized the voice interface to client-side Speech-to-Text (`SpeechRecognition`), enabling compatibility with all AI models (Gemini, OpenAI, Claude, etc.) by transcribing voice to text before sending.
|
|
85
|
+
- **Accurate Speech End Detection**: Configured the Speech-to-Text engine to run in continuous mode (`continuous = true`) so it keeps listening continuously across normal speaking pauses. Added a custom silence timer that triggers sending only after a full 2 seconds of silence, and fixed a loop bug by triggering the timer only after the user starts speaking (preventing the mic from cycling on and off during initial silence).
|
|
86
|
+
- **TTS Language Auto-Detection**: Added automatic Thai character detection in both frontend system voice lookup (now matching language tags case-insensitively) and backend Google Translate TTS generation, resolving the issue where Thai responses were read aloud in English voices.
|
|
87
|
+
- **Codebase Simplification & Hook Refactoring**: Extracted all Speech-to-Text logic, Web Speech APIs, silence timers, and React states into a shared, reusable custom hook `useSpeechToText` in [speech.ts](file:///home/pheem49/vscode/Project/Mint-CLI/src/renderer/shared/utils/speech.ts). This cleaned up ~150 lines of duplicate code in both desktop and web `ChatPanel.tsx` components.
|
|
88
|
+
- **Native App Guidance**: Added a helper prompt to notify users if they attempt to record voice in a browser or WebView that doesn't natively support SpeechRecognition (such as Firefox, Safari, or the Tauri desktop application on Linux/Windows), guiding them to use Google Chrome or Microsoft Edge instead.
|
|
89
|
+
|
|
90
|
+
### 🖼️ 10. Saved Pictures Gallery Pagination & Caching
|
|
91
|
+
- **24-Picture Pagination**: Refactored the Saved Pictures library component to load exactly 24 images initially, replacing the buggy automatic timer loading with a clean, manual "Load More" button at the bottom of the grid.
|
|
92
|
+
- **Cache-Busting Image URLs**: Appended a dynamic timestamp query parameter (`?_t=...`) to the static API picture fetches and individual image URLs. This prevents the browser from loading stale lists or caching broken images, ensuring that clicking "Refresh" successfully resolves any missing or incomplete pictures.
|
|
93
|
+
|
|
94
|
+
### 🤖 11. AI Model Self-Awareness Context Injection
|
|
95
|
+
- **Dynamic Context Injection**: Updated the core prompt compilation layer to automatically append an `[Active Environment Context]` block to the system instructions. This supplies the active AI model name and provider to the AI model itself, allowing the AI to successfully know its own model configurations in real-time when queried by the user.
|
|
96
|
+
|
|
97
|
+
### 🎨 12. Material Icon Theme in Agent Activity Tracker
|
|
98
|
+
- **Visual File & Folder Tracking**: The agent activity tracker (e.g. "Exploring file" progress log) now resolves target filenames/foldernames to display specific Material Icon Theme SVGs (e.g. JavaScript icon for `.js`, Rust icon for `.rs` / Cargo directories). This replaces the generic wireframe outline icons, resulting in a cleaner and more polished UI.
|
|
99
|
+
|
|
100
|
+
### 🎙️ 13. Stricter Voice Reply Settings Control
|
|
101
|
+
- **Strict Control Switch**: The global "Enable Voice Reply" toggle now acts as a strict master switch. When disabled, Mint will never speak responses out loud under any circumstances (including when using voice conversation/microphone mode).
|
|
102
|
+
- **Voice Mode Loop Resumption**: When "Enable Voice Reply" is disabled but voice conversation mode is active, the microphone automatically resumes listening after the AI response is printed on screen, maintaining the continuous hands-free voice loop.
|
|
65
103
|
|
|
66
104
|
---
|
|
67
105
|
|
|
106
|
+
|
|
68
107
|
## 🛠️ Codebase Changes
|
|
69
108
|
|
|
70
109
|
### Tauri Backend (`src-tauri` & `crates/mint-core`)
|
|
@@ -75,6 +114,15 @@ Upgraded the AI skills loading pipeline and settings interface:
|
|
|
75
114
|
- Change `submit_tool_approval` signature and `ApprovalsState` pending channel type to support `ApprovalOutcome` in `src-tauri/src/lib.rs`.
|
|
76
115
|
- Add executable search helper `which` and GitKraken auto-detection hooks to `load_config_from` in `crates/mint-core/src/config.rs`.
|
|
77
116
|
- Support multiple source directory scanning and deduplication of learned skills in `crates/mint-core/src/skills.rs`.
|
|
117
|
+
- Introduce a global `ACTIVE_AGENTS` thread-safe hash map registry and `cancel_agent` API in `crates/mint-core/src/lib.rs` to track active tokio tasks.
|
|
118
|
+
- Register Tauri command `cancel_chat_message` in `src-tauri/src/lib.rs`.
|
|
119
|
+
- Implement `POST /api/cancel-chat` in `crates/mint-core/src/api_server.rs` to cancel running web agent tasks.
|
|
120
|
+
- Add `enable_agent_collaboration` config parameter (defaulting to `false`) in `crates/mint-core/src/config.rs`.
|
|
121
|
+
- Update `resolve_agent_config` in `crates/mint-core/src/orchestration.rs` to return a tuple containing the active agent name and model, and check `enable_agent_collaboration`.
|
|
122
|
+
- Expand `AgentProgress::Thinking` in `crates/mint-core/src/orchestration.rs` to optionally contain `agent_name` and `model_name`.
|
|
123
|
+
- Inject active AI provider and model name environment context inside `enrich_request` and the initial prompt observation inside `crates/mint-core/src/orchestration.rs` so that the model becomes fully self-aware of its configuration and execution metadata.
|
|
124
|
+
- Inject a green aura viewport border style and DOM overlay (`#mint-browser-aura`) into the active browser page before executing CDP automation actions in `crates/mint-core/src/browser.rs` to visually notify users of active AI control.
|
|
125
|
+
|
|
78
126
|
|
|
79
127
|
### Desktop/Web Frontend (`src/renderer`)
|
|
80
128
|
- Integrate creation/deletion actions and focus/polling lifecycle listeners inside `WorkspacePanel.tsx`.
|
|
@@ -84,12 +132,43 @@ Upgraded the AI skills loading pipeline and settings interface:
|
|
|
84
132
|
- Update `activitiesFrom` and `AgentActivity` structure to parse and append the user's answer into the active `ask_user` tool target block upon `ToolEnd`.
|
|
85
133
|
- Update `LearnedSkill` TypeScript interface in `src/renderer/src/tauri.ts` to include optional `location`.
|
|
86
134
|
- Render colored location badges, strip lengthy content text boxes, and unify MCP toggles/delete controls in `src/renderer/src/components/Settings/PluginsTab.tsx` and `src/renderer/src-web/components/Settings/PluginsTab.tsx`.
|
|
135
|
+
- Implement `cancelChatMessage` API helpers in `tauri.ts` for desktop and web.
|
|
136
|
+
- Bind global Window keydown listeners for `Escape` key and dynamic "Stop" buttons in `ChatPanel.tsx` and `MintDashboard.tsx` under desktop and web source directories.
|
|
137
|
+
- Enhance microphone connection/permission alert dialogs in `ChatPanel.tsx` to print the exact Web API error message for easier debugging.
|
|
138
|
+
- Add voice-active class state and breathing keyframe animation effects around the chat input boundaries when microphone mode is active.
|
|
139
|
+
- Refine the voice status bar rendering logic to prevent displaying redundant text (such as "Listening Listening...") and display actual user speech transcripts wrapped inside quotes instead.
|
|
140
|
+
- Create new settings tab `AgentsTab.tsx` in desktop and web source directories supporting CRUD operations, provider-specific model dropdown selects, "Disable All" button, and global collaboration toggle.
|
|
141
|
+
- Register the `Multi-Agent (Beta)` tab in the sidebar of `SettingsWindow.tsx`.
|
|
142
|
+
- Update `ChatPanel.tsx` in desktop and web source directories to render the active agent and model names inside the live thinking status message.
|
|
143
|
+
- Remove duplicate "Enable Multi-Agent Review" checkbox from `AutomationTab.tsx`.
|
|
144
|
+
- Remove redundant `handleWindowKeyDown` Ctrl+V listeners, unused `onReadClipboardImage` prop, and `navigator.clipboard.read()` async fallback routines from `ChatPanel.tsx` and `MintDashboard.tsx` in both desktop and web directories to resolve browser clipboard permission warning popups during text pasting.
|
|
145
|
+
- Refactor duplicated types (`DiffHunk`, `FileChange`), helper functions (`numericSetting`, `errorMessage`, `readImage`, `readDocument`, `createTrimmedImagePreview`, `lightenColor`, `hexToRgb`, `applyThemeStyles`), and progress parsers (`parseFileChangesFromProgress`) from the desktop and web components to a central `src/renderer/shared` repository. Corrected a type checking issue by exporting `AgentProgress` and `InteractionMemory` from `shared/agentProgress.ts`.
|
|
146
|
+
- Consolidate microphone interface to client-side Speech-to-Text (`SpeechRecognition`), extract STT states, silence-detection timers, and event listeners into a reusable React hook `useSpeechToText` in [speech.ts](file:///home/pheem49/vscode/Project/Mint-CLI/src/renderer/shared/utils/speech.ts), and clean up both desktop (`src/renderer/src/components/ChatPanel.tsx`) and web (`src/renderer/src-web/components/ChatPanel.tsx`) `ChatPanel` components.
|
|
147
|
+
- Implement 24-picture pagination, a manual "Load More" button, and API/image fetch cache-busters in `PicturesLibrary.tsx` and `tauri.ts` across desktop and web directories.
|
|
148
|
+
- Refactor file and folder icon mappings from `WorkspacePanel.tsx` into a central, reusable utility `src/renderer/shared/utils/fileIcons.ts`.
|
|
149
|
+
- Update `AgentActivityTable.tsx` to resolve target filenames/foldernames and display their respective Material Icon Theme SVGs instead of default wireframe outlines.
|
|
150
|
+
- Update Desktop and Web CSS stylesheets (`styles.css`) to support rendering and scaling Material Icon SVGs inside the agent activity tracker.
|
|
151
|
+
- Update `ChatPanel.tsx` (Desktop and Web) to strictly check the global `enableVoiceReply` setting. If voice reply is disabled but voice conversation mode is active, the microphone listening loop is automatically scheduled to resume without reading the AI response out loud.
|
|
87
152
|
|
|
88
153
|
### CLI Agent (`crates/mint-cli`)
|
|
89
154
|
- Redefine live status print lines (`plan_lines`, `tasks_lines`, `activities_lines`, `explored_lines`) to accept progress tick state and apply the `get_bullet` helper.
|
|
90
155
|
- Update `render_live_status` in `crates/mint-cli/src/agent.rs` to compute true physical lines of terminal wrapped text, using a new `is_thai_combining` filter.
|
|
91
156
|
- Modify `confirm` in `crates/mint-cli/src/main.rs` to indent confirmation prompts.
|
|
92
157
|
- Format `mint learn --list` and `/learn` CLI output into a bullet-point summary showing active skill locations and source paths.
|
|
158
|
+
- Register `/multi-agent` slash command to display configured agents and toggle collaboration status via `/multi-agent on` and `/multi-agent off` in `crates/mint-cli/src/main.rs`.
|
|
159
|
+
- Reorder `AUTOCOMPLETE_COMMANDS` alphabetically and simplify exit suggestions by keeping only `/exit`.
|
|
160
|
+
- Paginate suggestions to display at most 5 items per page with page numbers.
|
|
161
|
+
- Fixed `AgentProgress::Thinking` pattern matching compiler error (E0027) in `crates/mint-cli/src/agent.rs` and render active agent and model names in the live thinking terminal status bar.
|
|
162
|
+
- Implement horizontal scrolling viewport for the CLI prompt input box in `crates/mint-cli/src/main.rs`, slicing the visible text to fit the terminal screen and adjusting the cursor column offset accordingly, allowing arbitrary length instructions.
|
|
163
|
+
- Save `provider_change` system interaction events to the database and render a beautiful styled horizontal divider in the console when switching models via `/models` inside `crates/mint-cli/src/main.rs`.
|
|
164
|
+
- Implement dynamic skill invocation with `$` prefix in the CLI interactive chat.
|
|
165
|
+
- Add realtime autocomplete and pagination dropdown list for local/workspace and global skills under the `$` trigger, resolving and rendering skill descriptions.
|
|
166
|
+
- Add frontmatter YAML parser in `crates/mint-core/src/skills.rs` to fetch skill description values.
|
|
167
|
+
- Support confirmation dialogue to display skill contents and confirm activation before running the Agent, allowing inline or prompted tasks.
|
|
168
|
+
- Register `/skill add <path>` (and `/skill install <path>`) slash commands to automatically copy/install a skill file or folder into the global `~/.config/mint/mint-skills/` directory.
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
93
172
|
|
|
94
173
|
### Github CI/CD Workflows
|
|
95
174
|
- Modify `Publish GitHub release` step in `.github/workflows/release.yml` to use `body_path: Release_Note.md`.
|
package/bin/mint
CHANGED
|
Binary file
|
|
@@ -184,38 +184,52 @@ pub async fn run_code_agent_with_options(
|
|
|
184
184
|
}
|
|
185
185
|
let progress_live_status = Arc::clone(&live_status);
|
|
186
186
|
let progress_cb = |progress: AgentProgress| match progress {
|
|
187
|
-
AgentProgress::Thinking {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
187
|
+
AgentProgress::Thinking {
|
|
188
|
+
elapsed_secs,
|
|
189
|
+
agent_name,
|
|
190
|
+
model_name,
|
|
191
|
+
} => {
|
|
192
|
+
if !options.fast_mode
|
|
193
|
+
&& let Ok(mut status) = progress_live_status.lock()
|
|
194
|
+
{
|
|
195
|
+
let label = if let (Some(a), Some(m)) = (agent_name, model_name) {
|
|
196
|
+
format!(
|
|
197
|
+
"{} ({}) is thinking ({} • Esc to interrupt)",
|
|
198
|
+
a,
|
|
199
|
+
m,
|
|
200
|
+
format_elapsed(Duration::from_secs(elapsed_secs))
|
|
201
|
+
)
|
|
202
|
+
} else {
|
|
203
|
+
format!(
|
|
191
204
|
"Thinking ({} • Esc to interrupt)",
|
|
192
205
|
format_elapsed(Duration::from_secs(elapsed_secs))
|
|
193
|
-
)
|
|
194
|
-
|
|
195
|
-
|
|
206
|
+
)
|
|
207
|
+
};
|
|
208
|
+
status.thinking = Some(label);
|
|
209
|
+
render_live_status(&mut status);
|
|
196
210
|
}
|
|
197
211
|
}
|
|
198
212
|
AgentProgress::Thought { thought } => {
|
|
199
|
-
if !options.fast_mode
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
213
|
+
if !options.fast_mode
|
|
214
|
+
&& let Ok(mut status) = progress_live_status.lock()
|
|
215
|
+
{
|
|
216
|
+
commit_activity_snapshot(&mut status);
|
|
217
|
+
print_timeline_note(&thought);
|
|
218
|
+
status.thinking = None;
|
|
219
|
+
render_live_status(&mut status);
|
|
206
220
|
}
|
|
207
221
|
}
|
|
208
222
|
AgentProgress::ToolStart { action, input } => {
|
|
209
223
|
if !options.fast_mode {
|
|
210
|
-
if action == "create_plan" || action == "update_plan"
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
return;
|
|
224
|
+
if (action == "create_plan" || action == "update_plan")
|
|
225
|
+
&& let Some(steps) = extract_plan_steps(&input)
|
|
226
|
+
{
|
|
227
|
+
if let Ok(mut status) = progress_live_status.lock() {
|
|
228
|
+
status.thinking = None;
|
|
229
|
+
status.plan_steps = steps;
|
|
230
|
+
render_live_status(&mut status);
|
|
218
231
|
}
|
|
232
|
+
return;
|
|
219
233
|
}
|
|
220
234
|
if let Some(label) = explored_action_label(&action, &input) {
|
|
221
235
|
if let Ok(mut status) = progress_live_status.lock() {
|
|
@@ -307,12 +321,12 @@ pub async fn run_code_agent_with_options(
|
|
|
307
321
|
} => {
|
|
308
322
|
if !options.fast_mode {
|
|
309
323
|
if action == "create_plan" || action == "update_plan" {
|
|
310
|
-
if let Some(steps) = extract_plan_steps(&input)
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
324
|
+
if let Some(steps) = extract_plan_steps(&input)
|
|
325
|
+
&& let Ok(mut status) = progress_live_status.lock()
|
|
326
|
+
{
|
|
327
|
+
status.thinking = None;
|
|
328
|
+
status.plan_steps = steps;
|
|
329
|
+
render_live_status(&mut status);
|
|
316
330
|
}
|
|
317
331
|
} else if command_was_run(&result)
|
|
318
332
|
&& let Some(commands) = ran_command_labels(&action, &input)
|
|
@@ -325,21 +339,44 @@ pub async fn run_code_agent_with_options(
|
|
|
325
339
|
render_live_status(&mut status);
|
|
326
340
|
}
|
|
327
341
|
}
|
|
342
|
+
// Parse web search sources from the result and store them for display
|
|
343
|
+
if action == "web_search"
|
|
344
|
+
&& !result.starts_with("Web search error:")
|
|
345
|
+
&& result != "No web search results found."
|
|
346
|
+
&& let Ok(mut status) = progress_live_status.lock()
|
|
347
|
+
{
|
|
348
|
+
let sources = parse_web_search_sources(&result);
|
|
349
|
+
status.web_sources.extend(sources);
|
|
350
|
+
}
|
|
328
351
|
}
|
|
329
352
|
};
|
|
330
353
|
|
|
331
354
|
let chunk_live_status = Arc::clone(&live_status);
|
|
332
355
|
let on_chunk = |summary: String| {
|
|
333
|
-
if !options.fast_mode
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
356
|
+
if !options.fast_mode
|
|
357
|
+
&& let Ok(mut status) = chunk_live_status.lock()
|
|
358
|
+
{
|
|
359
|
+
status.thinking = None;
|
|
360
|
+
commit_activity_snapshot(&mut status);
|
|
361
|
+
clear_live_status(&mut status);
|
|
339
362
|
}
|
|
340
|
-
let formatted_summary = format_markdown_bold(&summary);
|
|
363
|
+
let formatted_summary = format_markdown_bold(&sanitize_latex(&summary));
|
|
341
364
|
print!("\n {MINT}Mint:{RESET} ");
|
|
342
365
|
render_live_summary(&formatted_summary);
|
|
366
|
+
|
|
367
|
+
// Print web search sources if any were collected
|
|
368
|
+
if let Ok(mut status) = chunk_live_status.lock()
|
|
369
|
+
&& !status.web_sources.is_empty()
|
|
370
|
+
{
|
|
371
|
+
println!();
|
|
372
|
+
println!(" {DIM}Sources:{RESET}");
|
|
373
|
+
for (i, (title, url)) in status.web_sources.iter().enumerate() {
|
|
374
|
+
println!(" {DIM}{}.{RESET} {BLUE}{}{RESET}", i + 1, title);
|
|
375
|
+
println!(" {DIM}{}{RESET}", url);
|
|
376
|
+
}
|
|
377
|
+
status.web_sources.clear();
|
|
378
|
+
}
|
|
379
|
+
|
|
343
380
|
println!();
|
|
344
381
|
};
|
|
345
382
|
|
|
@@ -349,6 +386,7 @@ pub async fn run_code_agent_with_options(
|
|
|
349
386
|
root,
|
|
350
387
|
image_data_uri,
|
|
351
388
|
Some(CHAT_CLI_ID),
|
|
389
|
+
None,
|
|
352
390
|
options.fast_mode,
|
|
353
391
|
approve_cb,
|
|
354
392
|
progress_cb,
|
|
@@ -365,14 +403,14 @@ pub async fn run_code_agent_with_options(
|
|
|
365
403
|
}
|
|
366
404
|
};
|
|
367
405
|
agent_done.store(true, Ordering::Relaxed);
|
|
368
|
-
if !options.fast_mode
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
clear_live_status(&mut status);
|
|
406
|
+
if !options.fast_mode
|
|
407
|
+
&& let Ok(mut status) = live_status.lock()
|
|
408
|
+
{
|
|
409
|
+
status.thinking = None;
|
|
410
|
+
if res.is_err() {
|
|
411
|
+
commit_activity_snapshot(&mut status);
|
|
375
412
|
}
|
|
413
|
+
clear_live_status(&mut status);
|
|
376
414
|
}
|
|
377
415
|
let res = res.map_err(|e| anyhow!("{}", e))?;
|
|
378
416
|
|
|
@@ -396,6 +434,34 @@ fn clear_working_status() {
|
|
|
396
434
|
let _ = io::stdout().flush();
|
|
397
435
|
}
|
|
398
436
|
|
|
437
|
+
/// Parse (title, url) pairs from the formatted `web_search` ToolEnd result text.
|
|
438
|
+
/// The format produced by orchestration.rs is:
|
|
439
|
+
/// 1. Title\n URL: https://...\n Snippet\n
|
|
440
|
+
fn parse_web_search_sources(result: &str) -> Vec<(String, String)> {
|
|
441
|
+
let mut sources = Vec::new();
|
|
442
|
+
let mut current_title: Option<String> = None;
|
|
443
|
+
for line in result.lines() {
|
|
444
|
+
let trimmed = line.trim();
|
|
445
|
+
// Match numbered title lines: "1. Title text"
|
|
446
|
+
if let Some(rest) = trimmed.split_once(". ")
|
|
447
|
+
&& rest.0.parse::<usize>().is_ok()
|
|
448
|
+
{
|
|
449
|
+
current_title = Some(rest.1.trim().to_owned());
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
// Match URL lines: "URL: https://..."
|
|
453
|
+
if let Some(url) = trimmed.strip_prefix("URL: ")
|
|
454
|
+
&& let Some(title) = current_title.take()
|
|
455
|
+
{
|
|
456
|
+
let url = url.trim().to_owned();
|
|
457
|
+
if !url.is_empty() {
|
|
458
|
+
sources.push((title, url));
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
sources
|
|
463
|
+
}
|
|
464
|
+
|
|
399
465
|
fn format_elapsed(duration: Duration) -> String {
|
|
400
466
|
let total_seconds = duration.as_secs();
|
|
401
467
|
let minutes = total_seconds / 60;
|
|
@@ -487,6 +553,8 @@ struct LiveStatus {
|
|
|
487
553
|
committed_tasks: usize,
|
|
488
554
|
rendered_lines: usize,
|
|
489
555
|
spinner_tick: usize,
|
|
556
|
+
/// Sources collected from web_search ToolEnd results (title, url)
|
|
557
|
+
web_sources: Vec<(String, String)>,
|
|
490
558
|
}
|
|
491
559
|
|
|
492
560
|
#[derive(Debug, Clone)]
|
|
@@ -619,7 +687,7 @@ fn render_live_status(status: &mut LiveStatus) {
|
|
|
619
687
|
let stripped = strip_ansi_escapes(line);
|
|
620
688
|
let line_len = stripped.chars().filter(|&c| !is_thai_combining(c)).count();
|
|
621
689
|
let physical_lines = if width > 0 {
|
|
622
|
-
(
|
|
690
|
+
line_len.div_ceil(width)
|
|
623
691
|
} else {
|
|
624
692
|
1
|
|
625
693
|
}
|
|
@@ -692,7 +760,11 @@ fn clear_live_status(status: &mut LiveStatus) {
|
|
|
692
760
|
|
|
693
761
|
fn get_bullet(name: &str, is_thinking: bool, tick: usize) -> String {
|
|
694
762
|
let char_str = if is_thinking {
|
|
695
|
-
if (tick / 4)
|
|
763
|
+
if (tick / 4).is_multiple_of(2) {
|
|
764
|
+
"●"
|
|
765
|
+
} else {
|
|
766
|
+
"○"
|
|
767
|
+
}
|
|
696
768
|
} else {
|
|
697
769
|
"●"
|
|
698
770
|
};
|
|
@@ -905,7 +977,7 @@ fn format_markdown_bold(text: &str) -> String {
|
|
|
905
977
|
} else {
|
|
906
978
|
if c == '-' || c == '*' || c == '+' {
|
|
907
979
|
let after = &line[idx + c.len_utf8()..];
|
|
908
|
-
if after.chars().next().
|
|
980
|
+
if after.chars().next().is_some_and(|c| c.is_whitespace()) {
|
|
909
981
|
is_list_item = true;
|
|
910
982
|
marker_char = c;
|
|
911
983
|
}
|
|
@@ -975,3 +1047,36 @@ fn process_inline_bold(text: &str) -> String {
|
|
|
975
1047
|
}
|
|
976
1048
|
result
|
|
977
1049
|
}
|
|
1050
|
+
|
|
1051
|
+
/// Replace common LaTeX math symbols with Unicode equivalents.
|
|
1052
|
+
/// Fixes garbled output like "ightarrow$" from models that emit LaTeX notation.
|
|
1053
|
+
fn sanitize_latex(text: &str) -> String {
|
|
1054
|
+
let mut s = text.to_owned();
|
|
1055
|
+
for (pat, uni) in [
|
|
1056
|
+
// arrows
|
|
1057
|
+
("$\\rightarrow$", "→"),
|
|
1058
|
+
("$\\leftarrow$", "←"),
|
|
1059
|
+
("$\\Rightarrow$", "⇒"),
|
|
1060
|
+
("$\\Leftarrow$", "⇐"),
|
|
1061
|
+
("$\\leftrightarrow$", "↔"),
|
|
1062
|
+
// comparison
|
|
1063
|
+
("$\\leq$", "≤"),
|
|
1064
|
+
("$\\geq$", "≥"),
|
|
1065
|
+
("$\\neq$", "≠"),
|
|
1066
|
+
("$\\approx$", "≈"),
|
|
1067
|
+
// math
|
|
1068
|
+
("$\\times$", "×"),
|
|
1069
|
+
("$\\div$", "÷"),
|
|
1070
|
+
("$\\pm$", "±"),
|
|
1071
|
+
("$\\infty$", "∞"),
|
|
1072
|
+
("$\\cdot$", "·"),
|
|
1073
|
+
// sets
|
|
1074
|
+
("$\\in$", "∈"),
|
|
1075
|
+
("$\\subset$", "⊂"),
|
|
1076
|
+
("$\\cup$", "∪"),
|
|
1077
|
+
("$\\cap$", "∩"),
|
|
1078
|
+
] {
|
|
1079
|
+
s = s.replace(pat, uni);
|
|
1080
|
+
}
|
|
1081
|
+
s
|
|
1082
|
+
}
|