@pheem49/mint 1.8.0 → 1.8.2

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.
Files changed (200) hide show
  1. package/.github/workflows/release.yml +1 -1
  2. package/Cargo.lock +34 -3
  3. package/Cargo.toml +2 -2
  4. package/README.md +20 -6
  5. package/Release_Note.md +129 -0
  6. package/assets/Mint_CLI.png +0 -0
  7. package/bin/mint +0 -0
  8. package/crates/mint-cli/Cargo.toml +1 -0
  9. package/crates/mint-cli/src/agent.rs +242 -54
  10. package/crates/mint-cli/src/main.rs +397 -74
  11. package/crates/mint-core/src/agent_loop.rs +1 -0
  12. package/crates/mint-core/src/api_server.rs +64 -2
  13. package/crates/mint-core/src/browser.rs +456 -0
  14. package/crates/mint-core/src/channels.rs +1 -0
  15. package/crates/mint-core/src/chat.rs +3 -0
  16. package/crates/mint-core/src/config.rs +130 -1
  17. package/crates/mint-core/src/lib.rs +19 -0
  18. package/crates/mint-core/src/orchestration.rs +317 -12
  19. package/crates/mint-core/src/skills.rs +113 -4
  20. package/crates/mint-core/src/tts.rs +3 -1
  21. package/crates/mint-core/src/workflows.rs +1 -22
  22. package/flatpak/com.pheem49.mint.desktop +9 -0
  23. package/flatpak/com.pheem49.mint.metainfo.xml +35 -0
  24. package/flatpak/com.pheem49.mint.yaml +52 -0
  25. package/package.json +1 -1
  26. package/shared-modules/.github/workflows/ci.yml +120 -0
  27. package/shared-modules/.github/workflows/update.yaml +28 -0
  28. package/shared-modules/CODEOWNERS +23 -0
  29. package/shared-modules/README.md +79 -0
  30. package/shared-modules/SDL/README.md +3 -0
  31. package/shared-modules/SDL/SDL-1.2.15.json +51 -0
  32. package/shared-modules/SDL/SDL_Pango-0.1.2-API-adds.patch +118 -0
  33. package/shared-modules/SDL/SDL_image-1.2.12.json +25 -0
  34. package/shared-modules/SDL/SDL_mixer-1.2.12.json +27 -0
  35. package/shared-modules/SDL/SDL_net-1.2.8.json +19 -0
  36. package/shared-modules/SDL/SDL_pango-0.1.2.json +26 -0
  37. package/shared-modules/SDL/SDL_ttf-2.0.11.json +28 -0
  38. package/shared-modules/SDL/libsdl-1.2.15-strict-prototypes.patch +316 -0
  39. package/shared-modules/SDL/sdl-check-for-SDL_VIDEO_X11_BACKINGSTORE.patch +24 -0
  40. package/shared-modules/SDL/sdl-libx11-build.patch +59 -0
  41. package/shared-modules/SDL/sdl-sysloadso-buffer-length.patch +27 -0
  42. package/shared-modules/SDL/sdl12-compat.json +22 -0
  43. package/shared-modules/SDL2/SDL2_image.json +27 -0
  44. package/shared-modules/SDL2/SDL2_ttf.json +29 -0
  45. package/shared-modules/cld2/CMakeLists.txt +157 -0
  46. package/shared-modules/cld2/cld2.json +24 -0
  47. package/shared-modules/clutter/clutter.json +72 -0
  48. package/shared-modules/dbus-glib/dbus-glib.json +29 -0
  49. package/shared-modules/glew/glew.json +36 -0
  50. package/shared-modules/glu/glu-9.json +12 -0
  51. package/shared-modules/gtk2/arc-gtk2-theme-Replace-Inkscape-dependency-with-rsvg-convert.patch +180 -0
  52. package/shared-modules/gtk2/gtk2-common-themes.json +360 -0
  53. package/shared-modules/gtk2/gtk2-fix-crash-in-show-uri.patch +30 -0
  54. package/shared-modules/gtk2/gtk2-gcc14.patch +281 -0
  55. package/shared-modules/gtk2/gtk2-gcc15.patch +250 -0
  56. package/shared-modules/gtk2/gtk2-murrine-c99.patch +34 -0
  57. package/shared-modules/gtk2/gtk2-use-adwaita-theme.patch +80 -0
  58. package/shared-modules/gtk2/gtk2.json +120 -0
  59. package/shared-modules/gtk2/ibus-gcc15.patch +13 -0
  60. package/shared-modules/gtk2/murrine-engine-fix-crash.patch +12 -0
  61. package/shared-modules/gtk2/readme.md +10 -0
  62. package/shared-modules/intltool/intltool-0.51.json +20 -0
  63. package/shared-modules/intltool/intltool-perl5.26-regex-fixes.patch +59 -0
  64. package/shared-modules/lame/0001-Build-xmm_quantize_sub.c-with-msse.patch +34 -0
  65. package/shared-modules/lame/0002-Include-GTK-1-autoconf-directives-in-build-system.patch +222 -0
  66. package/shared-modules/lame/0003-Patch-out-remaining-ansi2knr.patch +70 -0
  67. package/shared-modules/lame/0004-initscr-is-not-used-anywhere-in-lame-sourcetree.patch +41 -0
  68. package/shared-modules/lame/0005-Update-autoconf.patch +81 -0
  69. package/shared-modules/lame/lame-3.99.5.json +32 -0
  70. package/shared-modules/libappindicator/libappindicator-gtk2-12.10.json +140 -0
  71. package/shared-modules/libappindicator/libappindicator-gtk3-12.10.json +140 -0
  72. package/shared-modules/libappindicator/libappindicator-gtk3-introspection-12.10.json +140 -0
  73. package/shared-modules/libappindicator/patches/0001-libappindicator-ftbfs.patch +20 -0
  74. package/shared-modules/libappindicator/patches/0002-libappindicator-no-python.patch +888 -0
  75. package/shared-modules/libappindicator/patches/0003-libappindicator-fix-crash-from-incorrect-signal-emission.patch +74 -0
  76. package/shared-modules/libappindicator/patches/0004-libappindicator-fix-crash-iterating-icon-themes.patch +11 -0
  77. package/shared-modules/libayatana-appindicator/0001-Fix-HAVE_VALGRIND-AM_CONDITIONAL.patch +51 -0
  78. package/shared-modules/libayatana-appindicator/0001-Make-introspection-configurable.patch +44 -0
  79. package/shared-modules/libayatana-appindicator/libayatana-appindicator-gtk3.json +121 -0
  80. package/shared-modules/libcanberra/0001-gtk-Don-t-assume-all-GdkDisplays-are-GdkX11Displays-.patch +123 -0
  81. package/shared-modules/libcanberra/libcanberra.json +44 -0
  82. package/shared-modules/libmad/libmad.json +19 -0
  83. package/shared-modules/libsecret/libsecret.json +23 -0
  84. package/shared-modules/libsoup/libsoup-2.4.json +14 -0
  85. package/shared-modules/libusb/libusb.json +27 -0
  86. package/shared-modules/linux-audio/dssi.json +31 -0
  87. package/shared-modules/linux-audio/fftw3f-static.json +44 -0
  88. package/shared-modules/linux-audio/fftw3f.json +42 -0
  89. package/shared-modules/linux-audio/fluidsynth2-static.json +30 -0
  90. package/shared-modules/linux-audio/fluidsynth2.json +19 -0
  91. package/shared-modules/linux-audio/ladspa.json +26 -0
  92. package/shared-modules/linux-audio/lash.json +35 -0
  93. package/shared-modules/linux-audio/libinstpatch.json +16 -0
  94. package/shared-modules/linux-audio/liblo-static.json +22 -0
  95. package/shared-modules/linux-audio/liblo.json +17 -0
  96. package/shared-modules/linux-audio/lilv-static.json +94 -0
  97. package/shared-modules/linux-audio/lilv.json +82 -0
  98. package/shared-modules/linux-audio/lrdf.json +57 -0
  99. package/shared-modules/linux-audio/lv2.json +21 -0
  100. package/shared-modules/linux-audio/patches/lash/0001-configure-remove-aclocal-m4.patch +29 -0
  101. package/shared-modules/linux-audio/patches/lash/0002-Fix-build-with-recent-gcc.patch +73 -0
  102. package/shared-modules/linux-audio/patches/lash/0003-Fix-linking.patch +136 -0
  103. package/shared-modules/linux-audio/patches/raptor-libxml.patch +31 -0
  104. package/shared-modules/linux-audio/patches/stk-install.sh +54 -0
  105. package/shared-modules/linux-audio/stk.json +28 -0
  106. package/shared-modules/lua5.1/0004-Fix-stack-overflow-in-vararg-functions.patch +21 -0
  107. package/shared-modules/lua5.1/lua-5.1.5-so.patch +43 -0
  108. package/shared-modules/lua5.1/lua-5.1.5.json +42 -0
  109. package/shared-modules/lua5.3/lua-5.3.5.json +41 -0
  110. package/shared-modules/lua5.3/lua.pc.in +8 -0
  111. package/shared-modules/lua5.3/luaconf.patch +47 -0
  112. package/shared-modules/lua5.3/makefile-add-liblua.so-rule.patch +47 -0
  113. package/shared-modules/lua5.4/lua-5.4.json +41 -0
  114. package/shared-modules/lua5.4/lua.pc.in +8 -0
  115. package/shared-modules/lua5.4/luaconf.patch +34 -0
  116. package/shared-modules/lua5.4/makefile-add-liblua.so-rule.patch +42 -0
  117. package/shared-modules/luajit/luajit.json +30 -0
  118. package/shared-modules/lzo/lzo.json +27 -0
  119. package/shared-modules/mac/mac.json +18 -0
  120. package/shared-modules/physfs/physfs.json +26 -0
  121. package/shared-modules/pygame/audiofile-gcc6.patch +21 -0
  122. package/shared-modules/pygame/cython-fixes.patch +34 -0
  123. package/shared-modules/pygame/fluidsynth-no-rawmidi.patch +69 -0
  124. package/shared-modules/pygame/glib.patch +25 -0
  125. package/shared-modules/pygame/pygame1-python2.json +157 -0
  126. package/shared-modules/pygtk/pygtk-c99.patch +15 -0
  127. package/shared-modules/pygtk/pygtk.json +117 -0
  128. package/shared-modules/pygtk/pygtk.patch +39 -0
  129. package/shared-modules/python2.7/python-2.7.json +48 -0
  130. package/shared-modules/smpeg/smpeg-0.4.5.json +50 -0
  131. package/shared-modules/smpeg/smpeg-am-prog-as.patch +12 -0
  132. package/shared-modules/smpeg/smpeg-export-mpegaudio-class.patch +17 -0
  133. package/shared-modules/smpeg/smpeg-gcc6.patch +40 -0
  134. package/shared-modules/smpeg/smpeg-no-gtk.patch +37 -0
  135. package/shared-modules/squashfs-tools/squashfs-tools.json +25 -0
  136. package/shared-modules/update-checker.sh +50 -0
  137. package/shared-modules/vorbisgain/0001-temp_files.patch +75 -0
  138. package/shared-modules/vorbisgain/0002-errno.patch +33 -0
  139. package/shared-modules/vorbisgain/0003-manpage.patch +248 -0
  140. package/shared-modules/vorbisgain/0004-vorbisgain_mtime.patch +183 -0
  141. package/shared-modules/vorbisgain/0005-double_fclose.patch +21 -0
  142. package/shared-modules/vorbisgain/0006-manpage_hyphens.patch +56 -0
  143. package/shared-modules/vorbisgain/0007-recursively_spelling.patch +14 -0
  144. package/shared-modules/vorbisgain/0008-manpage_recursion_mistake.patch +23 -0
  145. package/shared-modules/vorbisgain/0009-hardening.patch +13 -0
  146. package/shared-modules/vorbisgain/0010-fclose.patch +13 -0
  147. package/shared-modules/vorbisgain/README.md +23 -0
  148. package/shared-modules/vorbisgain/vorbisgain_0.37-2.json +29 -0
  149. package/src/renderer/shared/agentProgress.ts +145 -0
  150. package/src/renderer/shared/calculator.ts +52 -0
  151. package/src/renderer/shared/components/AgentActivityDrawer.tsx +72 -0
  152. package/src/renderer/shared/components/AgentActivityTable.tsx +66 -0
  153. package/src/renderer/shared/components/ApprovalCard.tsx +93 -0
  154. package/src/renderer/shared/components/ChatCodeBlock.tsx +75 -0
  155. package/src/renderer/shared/components/ThinkingBlock.tsx +101 -0
  156. package/src/renderer/shared/constants/models.ts +91 -0
  157. package/src/renderer/shared/platform.ts +82 -0
  158. package/src/renderer/shared/types.ts +140 -0
  159. package/src/renderer/shared/utils/agentActivity.ts +187 -0
  160. package/src/renderer/shared/utils/approval.ts +1 -0
  161. package/src/renderer/shared/utils/approval.tsx +64 -0
  162. package/src/renderer/shared/utils/markdown.tsx +347 -0
  163. package/src/renderer/shared/utils/providers.ts +36 -0
  164. package/src/renderer/shared/utils/speech.ts +216 -0
  165. package/src/renderer/shared/utils/ui.ts +147 -0
  166. package/src/renderer/src/agentProgress.ts +11 -39
  167. package/src/renderer/src/calculator.ts +3 -46
  168. package/src/renderer/src/components/ChatPanel.tsx +230 -1202
  169. package/src/renderer/src/components/ImageStudioPanel.tsx +11 -1
  170. package/src/renderer/src/components/MintDashboard.tsx +63 -171
  171. package/src/renderer/src/components/PicturesLibrary.tsx +32 -8
  172. package/src/renderer/src/components/Settings/AgentsTab.tsx +362 -0
  173. package/src/renderer/src/components/Settings/AutomationTab.tsx +0 -22
  174. package/src/renderer/src/components/Settings/PluginsTab.tsx +221 -41
  175. package/src/renderer/src/components/SettingsWindow.tsx +54 -12
  176. package/src/renderer/src/components/WorkspacePanel.tsx +66 -9
  177. package/src/renderer/src/css/image-studio.css +6 -0
  178. package/src/renderer/src/css/styles.css +148 -11
  179. package/src/renderer/src/index.css +12 -1
  180. package/src/renderer/src/tauri.ts +169 -143
  181. package/src/renderer/src-web/agentProgress.ts +11 -39
  182. package/src/renderer/src-web/calculator.ts +3 -46
  183. package/src/renderer/src-web/components/ChatPanel.tsx +223 -1199
  184. package/src/renderer/src-web/components/ImageStudioPanel.tsx +11 -1
  185. package/src/renderer/src-web/components/MintDashboard.tsx +31 -172
  186. package/src/renderer/src-web/components/PicturesLibrary.tsx +23 -29
  187. package/src/renderer/src-web/components/Settings/AgentsTab.tsx +362 -0
  188. package/src/renderer/src-web/components/Settings/AutomationTab.tsx +0 -22
  189. package/src/renderer/src-web/components/Settings/PluginsTab.tsx +221 -41
  190. package/src/renderer/src-web/components/SettingsWindow.tsx +54 -12
  191. package/src/renderer/src-web/css/image-studio.css +6 -0
  192. package/src/renderer/src-web/css/styles.css +184 -12
  193. package/src/renderer/src-web/index.css +12 -1
  194. package/src/renderer/src-web/tauri.ts +204 -104
  195. package/src-tauri/src/browser.rs +1 -141
  196. package/src-tauri/src/headless.rs +3 -2
  197. package/src-tauri/src/lib.rs +254 -59
  198. package/src-tauri/src/webhooks.rs +1 -0
  199. package/src-tauri/src/workflows.rs +57 -4
  200. package/src-tauri/tauri.conf.json +1 -1
@@ -916,7 +916,7 @@ h1 {
916
916
 
917
917
  .assistant-workspace.model-hidden .conversation-panel {
918
918
  flex: 1;
919
- max-width: 900px;
919
+ max-width: 1100px;
920
920
  margin: 0 auto;
921
921
  }
922
922
 
@@ -1486,7 +1486,7 @@ h1 {
1486
1486
  gap: 8px;
1487
1487
  margin-bottom: 8px;
1488
1488
  margin-top: 0;
1489
- max-width: min(680px, 100%);
1489
+ max-width: 100%;
1490
1490
  }
1491
1491
 
1492
1492
  .agent-activity-toggle {
@@ -1521,7 +1521,7 @@ h1 {
1521
1521
  border: 0;
1522
1522
  border-radius: 0;
1523
1523
  color: var(--text-main);
1524
- width: min(680px, 100%);
1524
+ width: 100%;
1525
1525
  max-width: 100%;
1526
1526
  padding: 4px 0;
1527
1527
  box-shadow: none;
@@ -3047,12 +3047,12 @@ input:checked + .slider:before {
3047
3047
  .assistant-workspace.model-hidden .conversation-panel {
3048
3048
  position: relative;
3049
3049
  display: grid;
3050
- grid-template-rows: minmax(0, 1fr) auto;
3051
- width: min(840px, calc(100% - 64px));
3050
+ grid-template-rows: auto minmax(0, 1fr) auto auto;
3051
+ width: min(1100px, calc(100% - 64px));
3052
3052
  height: 100%;
3053
3053
  max-width: none;
3054
3054
  margin: 0 auto;
3055
- padding: 56px 0 28px;
3055
+ padding: 32px 0 8px;
3056
3056
  grid-column: 1 / -1;
3057
3057
  z-index: 1;
3058
3058
  }
@@ -3075,13 +3075,13 @@ input:checked + .slider:before {
3075
3075
  }
3076
3076
 
3077
3077
  .assistant-workspace.model-hidden .conversation-panel.is-empty {
3078
- grid-template-rows: auto minmax(0, 1fr);
3079
- align-content: center;
3078
+ grid-template-rows: auto minmax(0, 1fr) auto auto;
3079
+ align-content: stretch;
3080
3080
  justify-content: stretch;
3081
3081
  width: min(840px, calc(100% - 64px));
3082
3082
  margin: 0 auto;
3083
- padding-top: 56px;
3084
- padding-bottom: 0;
3083
+ padding-top: 0;
3084
+ padding-bottom: 8px;
3085
3085
  }
3086
3086
 
3087
3087
  .conversation-panel.is-empty .chat-container {
@@ -3643,9 +3643,14 @@ input:checked + .slider:before {
3643
3643
 
3644
3644
  .assistant-workspace {
3645
3645
  display: flex;
3646
+ flex-direction: column;
3646
3647
  margin-left: 0;
3647
- padding: 12px;
3648
- gap: 12px;
3648
+ padding: 0;
3649
+ gap: 0;
3650
+ flex: 1;
3651
+ min-height: 0;
3652
+ height: 100%;
3653
+ overflow: hidden;
3649
3654
  }
3650
3655
 
3651
3656
  .assistant-workspace.layout-chat {
@@ -3654,6 +3659,10 @@ input:checked + .slider:before {
3654
3659
 
3655
3660
  .app-body {
3656
3661
  grid-template-columns: 1fr;
3662
+ display: flex;
3663
+ flex-direction: column;
3664
+ min-height: 0;
3665
+ flex: 1;
3657
3666
  }
3658
3667
 
3659
3668
  .sidebar-toggle {
@@ -3701,15 +3710,28 @@ input:checked + .slider:before {
3701
3710
  .conversation-panel {
3702
3711
  position: static;
3703
3712
  width: 100%;
3713
+ height: 100%;
3704
3714
  max-height: none;
3705
3715
  transform: none;
3706
3716
  flex: 1;
3707
3717
  min-width: 0;
3718
+ min-height: 0;
3719
+ border-radius: 0;
3720
+ overflow: hidden;
3708
3721
  }
3709
3722
 
3710
3723
  .chat-container {
3711
3724
  max-height: none;
3712
3725
  }
3726
+
3727
+ .input-area {
3728
+ padding: 10px;
3729
+ }
3730
+
3731
+ #chat-form {
3732
+ min-height: auto;
3733
+ padding: 6px;
3734
+ }
3713
3735
  }
3714
3736
 
3715
3737
  /* Chat Bold Highlight styling */
@@ -3726,6 +3748,19 @@ input:checked + .slider:before {
3726
3748
  color: #38bdf8; /* Sky-400 for midnight theme */
3727
3749
  }
3728
3750
 
3751
+ /* Input Disclaimer Footer */
3752
+ .input-disclaimer {
3753
+ text-align: center;
3754
+ font-size: 0.7rem;
3755
+ color: var(--text-muted);
3756
+ opacity: 0.55;
3757
+ padding: 6px 20px 10px;
3758
+ margin: 0;
3759
+ flex-shrink: 0;
3760
+ line-height: 1.5;
3761
+ user-select: none;
3762
+ }
3763
+
3729
3764
  /* Web-Native Chat Header */
3730
3765
  .chat-header {
3731
3766
  display: flex;
@@ -3839,6 +3874,51 @@ input:checked + .slider:before {
3839
3874
  .mobile-menu-btn {
3840
3875
  display: flex;
3841
3876
  }
3877
+
3878
+ /* Override desktop grid layout so chat-header (hamburger) is visible on mobile */
3879
+ .assistant-workspace.model-hidden .conversation-panel,
3880
+ .assistant-workspace.model-hidden .conversation-panel.is-empty {
3881
+ display: flex;
3882
+ flex-direction: column;
3883
+ width: 100%;
3884
+ height: 100%;
3885
+ padding: 0;
3886
+ margin: 0;
3887
+ grid-template-rows: none;
3888
+ grid-column: auto;
3889
+ }
3890
+
3891
+ /* Solid header fixed to top with background and blur */
3892
+ .chat-header {
3893
+ position: fixed;
3894
+ top: 0;
3895
+ left: 0;
3896
+ right: 0;
3897
+ z-index: 200;
3898
+ background: var(--chrome-bg);
3899
+ backdrop-filter: var(--glass-blur);
3900
+ -webkit-backdrop-filter: var(--glass-blur);
3901
+ border-bottom: 1px solid var(--border);
3902
+ height: 52px;
3903
+ padding: 10px 16px;
3904
+ }
3905
+
3906
+ .assistant-workspace.model-hidden .chat-header {
3907
+ display: flex;
3908
+ flex-shrink: 0;
3909
+ }
3910
+
3911
+ /* Push chat content below fixed header */
3912
+ .assistant-workspace.model-hidden .chat-container {
3913
+ flex: 1;
3914
+ overflow-y: auto;
3915
+ padding: 64px 12px 8px;
3916
+ }
3917
+
3918
+ .assistant-workspace.model-hidden .input-area {
3919
+ width: 100%;
3920
+ flex-shrink: 0;
3921
+ }
3842
3922
  }
3843
3923
 
3844
3924
  /* System Event Divider with Pill */
@@ -4079,3 +4159,95 @@ input:checked + .slider:before {
4079
4159
  font-size: 0.9rem;
4080
4160
  }
4081
4161
 
4162
+ /* Allow global text selection everywhere */
4163
+ * {
4164
+ user-select: text !important;
4165
+ -webkit-user-select: text !important;
4166
+ -moz-user-select: text !important;
4167
+ -ms-user-select: text !important;
4168
+ }
4169
+
4170
+ /* Stop button styling overrides for ChatPanel */
4171
+ #send-btn.stop-btn {
4172
+ background: #ef4444 !important;
4173
+ color: #ffffff !important;
4174
+ box-shadow: 0 8px 18px rgba(239, 68, 68, 0.28) !important;
4175
+ }
4176
+
4177
+ #send-btn.stop-btn:hover {
4178
+ background: #dc2626 !important;
4179
+ }
4180
+
4181
+ /* Breathing voice-active aura glow */
4182
+ @keyframes aura-breathe-form {
4183
+ 0% {
4184
+ box-shadow: 0 4px 15px color-mix(in srgb, var(--accent) 22%, transparent);
4185
+ }
4186
+ 50% {
4187
+ box-shadow: 0 4px 25px color-mix(in srgb, var(--accent) 42%, transparent);
4188
+ }
4189
+ 100% {
4190
+ box-shadow: 0 4px 15px color-mix(in srgb, var(--accent) 22%, transparent);
4191
+ }
4192
+ }
4193
+
4194
+ @keyframes aura-breathe-bar {
4195
+ 0% {
4196
+ box-shadow: 0 -4px 15px color-mix(in srgb, var(--accent) 22%, transparent);
4197
+ }
4198
+ 50% {
4199
+ box-shadow: 0 -4px 25px color-mix(in srgb, var(--accent) 42%, transparent);
4200
+ }
4201
+ 100% {
4202
+ box-shadow: 0 -4px 15px color-mix(in srgb, var(--accent) 22%, transparent);
4203
+ }
4204
+ }
4205
+
4206
+ .input-area.voice-active #chat-form {
4207
+ border-color: var(--accent) !important;
4208
+ animation: aura-breathe-form 2s infinite ease-in-out;
4209
+ transition: border-color 0.3s ease;
4210
+ }
4211
+
4212
+ .input-area.voice-active .voice-mode-bar {
4213
+ border-color: var(--accent) !important;
4214
+ animation: aura-breathe-bar 2s infinite ease-in-out;
4215
+ transition: border-color 0.3s ease;
4216
+ }
4217
+
4218
+ /* Saved Pictures Gallery Load More styles */
4219
+ .pictures-load-more-container {
4220
+ display: flex;
4221
+ justify-content: center;
4222
+ margin-top: 36px;
4223
+ margin-bottom: 24px;
4224
+ }
4225
+
4226
+ .pictures-load-more-btn {
4227
+ height: 40px;
4228
+ padding: 0 24px;
4229
+ border: 1px solid var(--border);
4230
+ border-radius: 10px;
4231
+ background: var(--card-bg, rgba(255, 255, 255, 0.04));
4232
+ color: var(--text-main);
4233
+ font-size: 0.88rem;
4234
+ font-weight: 500;
4235
+ cursor: pointer;
4236
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
4237
+ display: flex;
4238
+ align-items: center;
4239
+ gap: 8px;
4240
+ }
4241
+
4242
+ .pictures-load-more-btn:hover {
4243
+ background: var(--border);
4244
+ border-color: var(--accent);
4245
+ color: var(--accent);
4246
+ box-shadow: 0 0 12px color-mix(in srgb, var(--accent) 20%, transparent);
4247
+ }
4248
+
4249
+ .pictures-load-more-btn:active {
4250
+ transform: scale(0.98);
4251
+ }
4252
+
4253
+
@@ -379,7 +379,6 @@ button {
379
379
  }
380
380
  }
381
381
 
382
- /* Premium Markdown Styles for Chat Messages */
383
382
  .chat-inline-code {
384
383
  background: rgba(16, 185, 129, 0.15);
385
384
  border: 1px solid rgba(16, 185, 129, 0.25);
@@ -390,6 +389,18 @@ button {
390
389
  font-size: 0.88em;
391
390
  }
392
391
 
392
+ .chat-mention {
393
+ background: color-mix(in srgb, var(--accent, #10b981) 12%, transparent);
394
+ border: 1px solid color-mix(in srgb, var(--accent, #10b981) 25%, transparent);
395
+ color: var(--accent, #34d399);
396
+ padding: 2px 6px;
397
+ border-radius: 6px;
398
+ font-weight: 500;
399
+ font-size: 0.9em;
400
+ display: inline-block;
401
+ margin: 0 2px;
402
+ }
403
+
393
404
  .chat-code-block-container {
394
405
  display: flex;
395
406
  flex-direction: column;
@@ -1,106 +1,29 @@
1
- export interface RuntimeStatus {
2
- backend: string
3
- configPath: string
4
- activeProvider: string
5
- availableProviders: string[]
6
- integrations: Record<string, unknown>
7
- localIp?: string
8
- }
9
-
10
- export interface ChatResponse {
11
- provider: string
12
- model: string
13
- text: string
14
- fallbackProvider?: string | null
15
- }
1
+ export * from '../shared/types'
2
+ import type { MintPlatformApi } from '../shared/platform'
3
+ import type {
16
4
 
17
- export interface TtsUrl {
18
- shortText: string
19
- url: string
20
- }
21
-
22
- export interface DocumentAttachment {
23
- filename: string
24
- dataUri: string
25
- }
5
+ RuntimeStatus,
6
+ ChatResponse,
7
+ TtsUrl,
8
+ DocumentAttachment,
9
+ AgentProgress,
10
+ InteractionMemory,
11
+ ChatSession,
12
+ PictureEntry,
13
+ ImageGenRequest,
14
+ ImageGenProviders,
15
+ ImageGenResponse,
16
+ WorkspaceTreeEntry,
17
+ CodeEdit,
18
+ CodeEditProposal,
19
+ LearnedSkill,
20
+ } from '../shared/types'
26
21
 
27
- export type AgentProgress =
28
- | { type: 'Thinking'; data: { elapsed_secs: number } }
29
- | { type: 'Thought'; data: { thought: string } }
30
- | { type: 'ToolStart'; data: { action: string; input: Record<string, unknown> } }
31
- | { type: 'ToolEnd'; data: { action: string; input: Record<string, unknown>; result: string } }
32
22
 
33
23
  type DesktopStreamEvent =
34
24
  | { type: 'chunk'; chunk: string }
35
25
  | { type: 'progress'; progress: AgentProgress }
36
26
 
37
- export interface InteractionMemory {
38
- id: number
39
- chatId: string
40
- userText: string
41
- aiText: string
42
- provider: string
43
- model: string
44
- fallbackProvider?: string | null
45
- createdAt: string
46
- agentActivity?: AgentProgress[] | null
47
- }
48
-
49
- export interface ChatSession {
50
- id: string
51
- title: string
52
- kind: string
53
- createdAt: string
54
- updatedAt: string
55
- }
56
-
57
- export interface PictureEntry {
58
- id: string
59
- filename: string
60
- path: string
61
- mimeType: string
62
- createdAt: string
63
- source: string
64
- message: string
65
- thumbnailPath?: string
66
- url?: string
67
- thumbnailUrl?: string
68
- }
69
-
70
- export interface ImageGenRequest {
71
- prompt: string
72
- negativePrompt?: string
73
- aspectRatio?: '1:1' | '16:9' | '9:16' | '4:3'
74
- numImages?: number
75
- model?: string
76
- /** Which image generation provider to use. Falls back to config default when omitted. */
77
- provider?: string
78
- }
79
-
80
- export interface ImageGenProviders {
81
- active: string
82
- available: string[]
83
- }
84
-
85
- export interface ImageGenResponse {
86
- images: PictureEntry[]
87
- model: string
88
- provider: string
89
- prompt: string
90
- description?: string | null
91
- }
92
-
93
-
94
- export interface CodeEdit {
95
- path: string
96
- content: string
97
- }
98
-
99
- export interface CodeEditProposal {
100
- approvalRequired: boolean
101
- approvalToken: string
102
- edits: Array<{ path: string; existed: boolean; diff: string }>
103
- }
104
27
 
105
28
  export const isTauriRuntime = () => (
106
29
  typeof window !== 'undefined' && Boolean((window as any).__TAURI_INTERNALS__)
@@ -134,6 +57,28 @@ export async function getRuntimeStatus(): Promise<RuntimeStatus> {
134
57
  return invoke<RuntimeStatus>('get_runtime_status')
135
58
  }
136
59
 
60
+ export interface DetectedTools {
61
+ docker: boolean
62
+ git: boolean
63
+ gh: boolean
64
+ node: boolean
65
+ }
66
+
67
+ export async function detectSystemTools(): Promise<DetectedTools> {
68
+ if (typeof window === 'undefined' || !isTauriRuntime()) {
69
+ const API_BASE = getApiBase();
70
+ try {
71
+ const res = await fetch(`${API_BASE}/detect-tools`);
72
+ return await res.json();
73
+ } catch (e) {
74
+ console.error("Failed to detect tools from local server:", e);
75
+ return { docker: false, git: false, gh: false, node: false };
76
+ }
77
+ }
78
+ const { invoke } = await import('@tauri-apps/api/core')
79
+ return invoke<DetectedTools>('detect_system_tools')
80
+ }
81
+
137
82
  export async function sendChatMessage(
138
83
  message: string,
139
84
  imageDataUri?: string | null,
@@ -141,6 +86,7 @@ export async function sendChatMessage(
141
86
  documentAttachment?: DocumentAttachment | null,
142
87
  workspacePath?: string | null,
143
88
  chatId?: string | null,
89
+ agentId?: string | null,
144
90
  ): Promise<ChatResponse> {
145
91
  const outgoingMessage = withImagePlaceholder(message, imageDataUri)
146
92
  if (typeof window === 'undefined' || !isTauriRuntime()) {
@@ -149,7 +95,7 @@ export async function sendChatMessage(
149
95
  const res = await fetch(`${API_BASE}/chat`, {
150
96
  method: 'POST',
151
97
  headers: { 'Content-Type': 'application/json' },
152
- body: JSON.stringify({ message: outgoingMessage, systemInstruction: '', chatId, imageDataUri, audioDataUri, documentAttachment })
98
+ body: JSON.stringify({ message: outgoingMessage, systemInstruction: '', chatId, imageDataUri, audioDataUri, documentAttachment, agentId })
153
99
  });
154
100
  const data = await res.json().catch(() => null);
155
101
  if (!res.ok) {
@@ -174,7 +120,7 @@ export async function sendChatMessage(
174
120
  }
175
121
  const { invoke } = await import('@tauri-apps/api/core')
176
122
  const response = await invoke<ChatResponse>('send_chat_message', {
177
- request: { message: outgoingMessage, systemInstruction: '', chatId, imageDataUri, audioDataUri, documentAttachment, workspacePath },
123
+ request: { message: outgoingMessage, systemInstruction: '', chatId, imageDataUri, audioDataUri, documentAttachment, workspacePath, agentId },
178
124
  })
179
125
  if (imageDataUri) {
180
126
  await invoke('save_pictures', {
@@ -196,6 +142,7 @@ export async function streamChatMessage(
196
142
  documentAttachment?: DocumentAttachment | null,
197
143
  workspacePath?: string | null,
198
144
  chatId?: string | null,
145
+ agentId?: string | null,
199
146
  ): Promise<ChatResponse> {
200
147
  if (typeof window === 'undefined' || !isTauriRuntime()) {
201
148
  const API_BASE = getApiBase();
@@ -203,7 +150,7 @@ export async function streamChatMessage(
203
150
  const res = await fetch(`${API_BASE}/chat-stream`, {
204
151
  method: 'POST',
205
152
  headers: { 'Content-Type': 'application/json' },
206
- body: JSON.stringify({ message: outgoingMessage, systemInstruction, chatId, imageDataUri, audioDataUri, documentAttachment })
153
+ body: JSON.stringify({ message: outgoingMessage, systemInstruction, chatId, imageDataUri, audioDataUri, documentAttachment, agentId })
207
154
  });
208
155
  if (!res.ok) {
209
156
  const data = await res.json().catch(() => null);
@@ -249,7 +196,7 @@ export async function streamChatMessage(
249
196
  else onProgress?.(event.progress)
250
197
  }
251
198
  const response = await invoke<ChatResponse>('stream_chat_message', {
252
- request: { message: outgoingMessage, systemInstruction, chatId, imageDataUri, audioDataUri, documentAttachment, workspacePath },
199
+ request: { message: outgoingMessage, systemInstruction, chatId, imageDataUri, audioDataUri, documentAttachment, workspacePath, agentId },
253
200
  onEvent,
254
201
  })
255
202
  if (imageDataUri) {
@@ -276,6 +223,20 @@ export async function getTtsUrls(text: string): Promise<TtsUrl[]> {
276
223
  return invoke<TtsUrl[]>('get_tts_urls', { text })
277
224
  }
278
225
 
226
+ export async function cancelChatMessage(chatId: string): Promise<void> {
227
+ if (typeof window === 'undefined' || !isTauriRuntime()) {
228
+ const API_BASE = getApiBase();
229
+ await fetch(`${API_BASE}/cancel-chat`, {
230
+ method: 'POST',
231
+ headers: { 'Content-Type': 'application/json' },
232
+ body: JSON.stringify({ chatId })
233
+ });
234
+ return;
235
+ }
236
+ const { invoke } = await import('@tauri-apps/api/core')
237
+ await invoke('cancel_chat_message', { chatId })
238
+ }
239
+
279
240
  export async function getRecentInteractions(limit = 50, chatId?: string | null): Promise<InteractionMemory[]> {
280
241
  if (typeof window === 'undefined' || !isTauriRuntime()) {
281
242
  const API_BASE = getApiBase();
@@ -454,11 +415,12 @@ export async function listSavedPictures(): Promise<PictureEntry[]> {
454
415
  if (typeof window === 'undefined' || !isTauriRuntime()) {
455
416
  const API_BASE = getApiBase();
456
417
  try {
457
- const res = await fetch(`${API_BASE}/pictures`);
418
+ const res = await fetch(`${API_BASE}/pictures?_t=${Date.now()}`);
458
419
  const pictures = await res.json();
420
+ const timestamp = Date.now();
459
421
  return Array.isArray(pictures)
460
422
  ? pictures.map((picture) => {
461
- const pictureUrl = picture.url ? `${API_BASE.replace('/api', '')}${picture.url}` : undefined
423
+ const pictureUrl = picture.url ? `${API_BASE.replace('/api', '')}${picture.url}?_t=${timestamp}` : undefined
462
424
  return {
463
425
  ...picture,
464
426
  path: pictureUrl || picture.path,
@@ -577,12 +539,12 @@ export async function setDefaultImageProvider(provider: string): Promise<boolean
577
539
 
578
540
 
579
541
 
580
- export async function submitToolApproval(token: string, approved: boolean): Promise<void> {
542
+ export async function submitToolApproval(token: string, approved: boolean, answer?: string): Promise<void> {
581
543
  if (typeof window === 'undefined' || !isTauriRuntime()) {
582
544
  return;
583
545
  }
584
546
  const { invoke } = await import('@tauri-apps/api/core')
585
- return invoke('submit_tool_approval', { token, approved })
547
+ return invoke('submit_tool_approval', { token, approved, answer })
586
548
  }
587
549
 
588
550
  export async function proposeCodeEdits(root: string, edits: CodeEdit[]): Promise<CodeEditProposal> {
@@ -1154,8 +1116,109 @@ async function captureSharedScreen(): Promise<string> {
1154
1116
  }
1155
1117
  }
1156
1118
 
1119
+ export async function listLearnedSkills(workspacePath?: string): Promise<LearnedSkill[]> {
1120
+ if (typeof window === 'undefined' || !isTauriRuntime()) {
1121
+ try {
1122
+ const val = await getProfileValue('learned-skills-web-mock')
1123
+ if (val) {
1124
+ return JSON.parse(val)
1125
+ }
1126
+ return []
1127
+ } catch (e) {
1128
+ console.error("Failed to load web mock skills:", e)
1129
+ return []
1130
+ }
1131
+ }
1132
+ const { invoke } = await import('@tauri-apps/api/core')
1133
+ return invoke<LearnedSkill[]>('list_learned_skills', { workspacePath })
1134
+ }
1135
+
1136
+ export async function addLearnedSkill(name: string, content: string): Promise<LearnedSkill> {
1137
+ if (typeof window === 'undefined' || !isTauriRuntime()) {
1138
+ try {
1139
+ const list = await listLearnedSkills()
1140
+ const newSkill: LearnedSkill = {
1141
+ id: Date.now(),
1142
+ name,
1143
+ sourcePath: 'ui_manual',
1144
+ content,
1145
+ updatedAt: new Date().toISOString()
1146
+ }
1147
+ list.push(newSkill)
1148
+ await setProfileValue('learned-skills-web-mock', JSON.stringify(list))
1149
+ return newSkill
1150
+ } catch (e) {
1151
+ console.error("Failed to add web mock skill:", e)
1152
+ throw e
1153
+ }
1154
+ }
1155
+ const { invoke } = await import('@tauri-apps/api/core')
1156
+ return invoke<LearnedSkill>('add_learned_skill', { name, content })
1157
+ }
1158
+
1159
+ export async function deleteLearnedSkill(name: string): Promise<number> {
1160
+ if (typeof window === 'undefined' || !isTauriRuntime()) {
1161
+ try {
1162
+ const list = await listLearnedSkills()
1163
+ const filtered = list.filter(s => s.name !== name)
1164
+ const deletedCount = list.length - filtered.length
1165
+ await setProfileValue('learned-skills-web-mock', JSON.stringify(filtered))
1166
+ return deletedCount
1167
+ } catch (e) {
1168
+ console.error("Failed to delete web mock skill:", e)
1169
+ return 0
1170
+ }
1171
+ }
1172
+ const { invoke } = await import('@tauri-apps/api/core')
1173
+ return invoke<number>('delete_learned_skill', { name })
1174
+ }
1175
+
1176
+ export async function getWorkspaceTree(path?: string | null): Promise<WorkspaceTreeEntry> {
1177
+ if (typeof window === 'undefined' || !isTauriRuntime()) {
1178
+ return {
1179
+ name: 'Workspace',
1180
+ path: '.',
1181
+ kind: 'directory',
1182
+ children: [
1183
+ { name: 'src', path: 'src', kind: 'directory', children: [] },
1184
+ { name: 'package.json', path: 'package.json', kind: 'file', children: [] },
1185
+ ],
1186
+ }
1187
+ }
1188
+ const { invoke } = await import('@tauri-apps/api/core')
1189
+ return invoke<WorkspaceTreeEntry>('get_workspace_tree', { path })
1190
+ }
1191
+
1192
+ export async function createWorkspaceFile(path: string): Promise<void> {
1193
+ if (typeof window === 'undefined' || !isTauriRuntime()) return
1194
+ const { invoke } = await import('@tauri-apps/api/core')
1195
+ return invoke('create_workspace_file', { path })
1196
+ }
1197
+
1198
+ export async function createWorkspaceFolder(path: string): Promise<void> {
1199
+ if (typeof window === 'undefined' || !isTauriRuntime()) return
1200
+ const { invoke } = await import('@tauri-apps/api/core')
1201
+ return invoke('create_workspace_folder', { path })
1202
+ }
1203
+
1204
+ export async function deleteWorkspaceItem(path: string): Promise<void> {
1205
+ if (typeof window === 'undefined' || !isTauriRuntime()) return
1206
+ const { invoke } = await import('@tauri-apps/api/core')
1207
+ return invoke('delete_workspace_item', { path })
1208
+ }
1209
+
1210
+ export async function selectWorkspaceDirectory(): Promise<string | null> {
1211
+ if (typeof window === 'undefined' || !isTauriRuntime()) {
1212
+ return null
1213
+ }
1214
+ const { invoke } = await import('@tauri-apps/api/core')
1215
+ const selected = await invoke<string | null>('select_workspace_directory')
1216
+ return selected
1217
+ }
1218
+
1157
1219
  export async function readClipboardImage(): Promise<string | null> {
1158
1220
  if (typeof window === 'undefined' || !isTauriRuntime()) {
1221
+
1159
1222
  return null
1160
1223
  }
1161
1224
  const { invoke } = await import('@tauri-apps/api/core')
@@ -1166,3 +1229,40 @@ export async function readClipboardImage(): Promise<string | null> {
1166
1229
  return null
1167
1230
  }
1168
1231
  }
1232
+
1233
+ // Enforce compile-time check against the shared platform interface
1234
+ const _apiCheck: MintPlatformApi = {
1235
+ getRuntimeStatus,
1236
+ detectSystemTools,
1237
+ sendChatMessage,
1238
+ streamChatMessage,
1239
+ getTtsUrls,
1240
+ cancelChatMessage,
1241
+ getRecentInteractions,
1242
+ saveSystemInteraction,
1243
+ saveInteractionAgentActivity,
1244
+ listChatSessions,
1245
+ deleteChatSession,
1246
+ renameChatSession,
1247
+ getProfileValue,
1248
+ setProfileValue,
1249
+ listLearnedSkills,
1250
+ addLearnedSkill,
1251
+ deleteLearnedSkill,
1252
+ clearChatHistory,
1253
+ listSavedPictures,
1254
+ generateImages,
1255
+ getImageGenProviders,
1256
+ setDefaultImageProvider,
1257
+ getWorkspaceTree,
1258
+ createWorkspaceFile,
1259
+ createWorkspaceFolder,
1260
+ deleteWorkspaceItem,
1261
+ selectWorkspaceDirectory,
1262
+ submitToolApproval,
1263
+ proposeCodeEdits,
1264
+ applyCodeEdits,
1265
+ listen,
1266
+ readClipboardImage,
1267
+ }
1268
+