@pheem49/mint 1.8.1 → 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 (184) hide show
  1. package/Cargo.lock +3 -3
  2. package/Cargo.toml +1 -1
  3. package/README.md +0 -17
  4. package/Release_Note.md +92 -58
  5. package/bin/mint +0 -0
  6. package/crates/mint-cli/src/agent.rs +100 -6
  7. package/crates/mint-cli/src/main.rs +166 -52
  8. package/crates/mint-core/src/agent_loop.rs +1 -0
  9. package/crates/mint-core/src/api_server.rs +55 -2
  10. package/crates/mint-core/src/browser.rs +55 -0
  11. package/crates/mint-core/src/channels.rs +1 -0
  12. package/crates/mint-core/src/chat.rs +3 -0
  13. package/crates/mint-core/src/config.rs +61 -0
  14. package/crates/mint-core/src/lib.rs +14 -0
  15. package/crates/mint-core/src/orchestration.rs +180 -11
  16. package/crates/mint-core/src/tts.rs +3 -1
  17. package/flatpak/com.pheem49.mint.desktop +9 -0
  18. package/flatpak/com.pheem49.mint.metainfo.xml +35 -0
  19. package/flatpak/com.pheem49.mint.yaml +52 -0
  20. package/package.json +1 -1
  21. package/shared-modules/.github/workflows/ci.yml +120 -0
  22. package/shared-modules/.github/workflows/update.yaml +28 -0
  23. package/shared-modules/CODEOWNERS +23 -0
  24. package/shared-modules/README.md +79 -0
  25. package/shared-modules/SDL/README.md +3 -0
  26. package/shared-modules/SDL/SDL-1.2.15.json +51 -0
  27. package/shared-modules/SDL/SDL_Pango-0.1.2-API-adds.patch +118 -0
  28. package/shared-modules/SDL/SDL_image-1.2.12.json +25 -0
  29. package/shared-modules/SDL/SDL_mixer-1.2.12.json +27 -0
  30. package/shared-modules/SDL/SDL_net-1.2.8.json +19 -0
  31. package/shared-modules/SDL/SDL_pango-0.1.2.json +26 -0
  32. package/shared-modules/SDL/SDL_ttf-2.0.11.json +28 -0
  33. package/shared-modules/SDL/libsdl-1.2.15-strict-prototypes.patch +316 -0
  34. package/shared-modules/SDL/sdl-check-for-SDL_VIDEO_X11_BACKINGSTORE.patch +24 -0
  35. package/shared-modules/SDL/sdl-libx11-build.patch +59 -0
  36. package/shared-modules/SDL/sdl-sysloadso-buffer-length.patch +27 -0
  37. package/shared-modules/SDL/sdl12-compat.json +22 -0
  38. package/shared-modules/SDL2/SDL2_image.json +27 -0
  39. package/shared-modules/SDL2/SDL2_ttf.json +29 -0
  40. package/shared-modules/cld2/CMakeLists.txt +157 -0
  41. package/shared-modules/cld2/cld2.json +24 -0
  42. package/shared-modules/clutter/clutter.json +72 -0
  43. package/shared-modules/dbus-glib/dbus-glib.json +29 -0
  44. package/shared-modules/glew/glew.json +36 -0
  45. package/shared-modules/glu/glu-9.json +12 -0
  46. package/shared-modules/gtk2/arc-gtk2-theme-Replace-Inkscape-dependency-with-rsvg-convert.patch +180 -0
  47. package/shared-modules/gtk2/gtk2-common-themes.json +360 -0
  48. package/shared-modules/gtk2/gtk2-fix-crash-in-show-uri.patch +30 -0
  49. package/shared-modules/gtk2/gtk2-gcc14.patch +281 -0
  50. package/shared-modules/gtk2/gtk2-gcc15.patch +250 -0
  51. package/shared-modules/gtk2/gtk2-murrine-c99.patch +34 -0
  52. package/shared-modules/gtk2/gtk2-use-adwaita-theme.patch +80 -0
  53. package/shared-modules/gtk2/gtk2.json +120 -0
  54. package/shared-modules/gtk2/ibus-gcc15.patch +13 -0
  55. package/shared-modules/gtk2/murrine-engine-fix-crash.patch +12 -0
  56. package/shared-modules/gtk2/readme.md +10 -0
  57. package/shared-modules/intltool/intltool-0.51.json +20 -0
  58. package/shared-modules/intltool/intltool-perl5.26-regex-fixes.patch +59 -0
  59. package/shared-modules/lame/0001-Build-xmm_quantize_sub.c-with-msse.patch +34 -0
  60. package/shared-modules/lame/0002-Include-GTK-1-autoconf-directives-in-build-system.patch +222 -0
  61. package/shared-modules/lame/0003-Patch-out-remaining-ansi2knr.patch +70 -0
  62. package/shared-modules/lame/0004-initscr-is-not-used-anywhere-in-lame-sourcetree.patch +41 -0
  63. package/shared-modules/lame/0005-Update-autoconf.patch +81 -0
  64. package/shared-modules/lame/lame-3.99.5.json +32 -0
  65. package/shared-modules/libappindicator/libappindicator-gtk2-12.10.json +140 -0
  66. package/shared-modules/libappindicator/libappindicator-gtk3-12.10.json +140 -0
  67. package/shared-modules/libappindicator/libappindicator-gtk3-introspection-12.10.json +140 -0
  68. package/shared-modules/libappindicator/patches/0001-libappindicator-ftbfs.patch +20 -0
  69. package/shared-modules/libappindicator/patches/0002-libappindicator-no-python.patch +888 -0
  70. package/shared-modules/libappindicator/patches/0003-libappindicator-fix-crash-from-incorrect-signal-emission.patch +74 -0
  71. package/shared-modules/libappindicator/patches/0004-libappindicator-fix-crash-iterating-icon-themes.patch +11 -0
  72. package/shared-modules/libayatana-appindicator/0001-Fix-HAVE_VALGRIND-AM_CONDITIONAL.patch +51 -0
  73. package/shared-modules/libayatana-appindicator/0001-Make-introspection-configurable.patch +44 -0
  74. package/shared-modules/libayatana-appindicator/libayatana-appindicator-gtk3.json +121 -0
  75. package/shared-modules/libcanberra/0001-gtk-Don-t-assume-all-GdkDisplays-are-GdkX11Displays-.patch +123 -0
  76. package/shared-modules/libcanberra/libcanberra.json +44 -0
  77. package/shared-modules/libmad/libmad.json +19 -0
  78. package/shared-modules/libsecret/libsecret.json +23 -0
  79. package/shared-modules/libsoup/libsoup-2.4.json +14 -0
  80. package/shared-modules/libusb/libusb.json +27 -0
  81. package/shared-modules/linux-audio/dssi.json +31 -0
  82. package/shared-modules/linux-audio/fftw3f-static.json +44 -0
  83. package/shared-modules/linux-audio/fftw3f.json +42 -0
  84. package/shared-modules/linux-audio/fluidsynth2-static.json +30 -0
  85. package/shared-modules/linux-audio/fluidsynth2.json +19 -0
  86. package/shared-modules/linux-audio/ladspa.json +26 -0
  87. package/shared-modules/linux-audio/lash.json +35 -0
  88. package/shared-modules/linux-audio/libinstpatch.json +16 -0
  89. package/shared-modules/linux-audio/liblo-static.json +22 -0
  90. package/shared-modules/linux-audio/liblo.json +17 -0
  91. package/shared-modules/linux-audio/lilv-static.json +94 -0
  92. package/shared-modules/linux-audio/lilv.json +82 -0
  93. package/shared-modules/linux-audio/lrdf.json +57 -0
  94. package/shared-modules/linux-audio/lv2.json +21 -0
  95. package/shared-modules/linux-audio/patches/lash/0001-configure-remove-aclocal-m4.patch +29 -0
  96. package/shared-modules/linux-audio/patches/lash/0002-Fix-build-with-recent-gcc.patch +73 -0
  97. package/shared-modules/linux-audio/patches/lash/0003-Fix-linking.patch +136 -0
  98. package/shared-modules/linux-audio/patches/raptor-libxml.patch +31 -0
  99. package/shared-modules/linux-audio/patches/stk-install.sh +54 -0
  100. package/shared-modules/linux-audio/stk.json +28 -0
  101. package/shared-modules/lua5.1/0004-Fix-stack-overflow-in-vararg-functions.patch +21 -0
  102. package/shared-modules/lua5.1/lua-5.1.5-so.patch +43 -0
  103. package/shared-modules/lua5.1/lua-5.1.5.json +42 -0
  104. package/shared-modules/lua5.3/lua-5.3.5.json +41 -0
  105. package/shared-modules/lua5.3/lua.pc.in +8 -0
  106. package/shared-modules/lua5.3/luaconf.patch +47 -0
  107. package/shared-modules/lua5.3/makefile-add-liblua.so-rule.patch +47 -0
  108. package/shared-modules/lua5.4/lua-5.4.json +41 -0
  109. package/shared-modules/lua5.4/lua.pc.in +8 -0
  110. package/shared-modules/lua5.4/luaconf.patch +34 -0
  111. package/shared-modules/lua5.4/makefile-add-liblua.so-rule.patch +42 -0
  112. package/shared-modules/luajit/luajit.json +30 -0
  113. package/shared-modules/lzo/lzo.json +27 -0
  114. package/shared-modules/mac/mac.json +18 -0
  115. package/shared-modules/physfs/physfs.json +26 -0
  116. package/shared-modules/pygame/audiofile-gcc6.patch +21 -0
  117. package/shared-modules/pygame/cython-fixes.patch +34 -0
  118. package/shared-modules/pygame/fluidsynth-no-rawmidi.patch +69 -0
  119. package/shared-modules/pygame/glib.patch +25 -0
  120. package/shared-modules/pygame/pygame1-python2.json +157 -0
  121. package/shared-modules/pygtk/pygtk-c99.patch +15 -0
  122. package/shared-modules/pygtk/pygtk.json +117 -0
  123. package/shared-modules/pygtk/pygtk.patch +39 -0
  124. package/shared-modules/python2.7/python-2.7.json +48 -0
  125. package/shared-modules/smpeg/smpeg-0.4.5.json +50 -0
  126. package/shared-modules/smpeg/smpeg-am-prog-as.patch +12 -0
  127. package/shared-modules/smpeg/smpeg-export-mpegaudio-class.patch +17 -0
  128. package/shared-modules/smpeg/smpeg-gcc6.patch +40 -0
  129. package/shared-modules/smpeg/smpeg-no-gtk.patch +37 -0
  130. package/shared-modules/squashfs-tools/squashfs-tools.json +25 -0
  131. package/shared-modules/update-checker.sh +50 -0
  132. package/shared-modules/vorbisgain/0001-temp_files.patch +75 -0
  133. package/shared-modules/vorbisgain/0002-errno.patch +33 -0
  134. package/shared-modules/vorbisgain/0003-manpage.patch +248 -0
  135. package/shared-modules/vorbisgain/0004-vorbisgain_mtime.patch +183 -0
  136. package/shared-modules/vorbisgain/0005-double_fclose.patch +21 -0
  137. package/shared-modules/vorbisgain/0006-manpage_hyphens.patch +56 -0
  138. package/shared-modules/vorbisgain/0007-recursively_spelling.patch +14 -0
  139. package/shared-modules/vorbisgain/0008-manpage_recursion_mistake.patch +23 -0
  140. package/shared-modules/vorbisgain/0009-hardening.patch +13 -0
  141. package/shared-modules/vorbisgain/0010-fclose.patch +13 -0
  142. package/shared-modules/vorbisgain/README.md +23 -0
  143. package/shared-modules/vorbisgain/vorbisgain_0.37-2.json +29 -0
  144. package/src/renderer/shared/agentProgress.ts +145 -0
  145. package/src/renderer/shared/calculator.ts +52 -0
  146. package/src/renderer/shared/components/AgentActivityDrawer.tsx +72 -0
  147. package/src/renderer/shared/components/AgentActivityTable.tsx +66 -0
  148. package/src/renderer/shared/components/ApprovalCard.tsx +93 -0
  149. package/src/renderer/shared/components/ChatCodeBlock.tsx +75 -0
  150. package/src/renderer/shared/components/ThinkingBlock.tsx +101 -0
  151. package/src/renderer/shared/constants/models.ts +91 -0
  152. package/src/renderer/shared/platform.ts +82 -0
  153. package/src/renderer/shared/types.ts +140 -0
  154. package/src/renderer/shared/utils/agentActivity.ts +187 -0
  155. package/src/renderer/shared/utils/approval.ts +1 -0
  156. package/src/renderer/shared/utils/approval.tsx +64 -0
  157. package/src/renderer/shared/utils/markdown.tsx +347 -0
  158. package/src/renderer/shared/utils/providers.ts +36 -0
  159. package/src/renderer/shared/utils/speech.ts +216 -0
  160. package/src/renderer/shared/utils/ui.ts +147 -0
  161. package/src/renderer/src/agentProgress.ts +11 -39
  162. package/src/renderer/src/calculator.ts +3 -46
  163. package/src/renderer/src/components/ChatPanel.tsx +194 -1303
  164. package/src/renderer/src/components/MintDashboard.tsx +23 -169
  165. package/src/renderer/src/components/PicturesLibrary.tsx +32 -8
  166. package/src/renderer/src/components/Settings/AgentsTab.tsx +362 -0
  167. package/src/renderer/src/components/Settings/AutomationTab.tsx +0 -22
  168. package/src/renderer/src/components/SettingsWindow.tsx +53 -3
  169. package/src/renderer/src/css/styles.css +84 -0
  170. package/src/renderer/src/tauri.ts +128 -143
  171. package/src/renderer/src-web/agentProgress.ts +11 -39
  172. package/src/renderer/src-web/calculator.ts +3 -46
  173. package/src/renderer/src-web/components/ChatPanel.tsx +194 -1301
  174. package/src/renderer/src-web/components/MintDashboard.tsx +23 -169
  175. package/src/renderer/src-web/components/PicturesLibrary.tsx +23 -29
  176. package/src/renderer/src-web/components/Settings/AgentsTab.tsx +362 -0
  177. package/src/renderer/src-web/components/Settings/AutomationTab.tsx +0 -22
  178. package/src/renderer/src-web/components/SettingsWindow.tsx +53 -3
  179. package/src/renderer/src-web/css/styles.css +84 -0
  180. package/src/renderer/src-web/tauri.ts +180 -102
  181. package/src-tauri/src/lib.rs +137 -33
  182. package/src-tauri/src/webhooks.rs +1 -0
  183. package/src-tauri/src/workflows.rs +1 -0
  184. package/src-tauri/tauri.conf.json +1 -1
@@ -169,28 +169,6 @@ export default function AutomationTab({
169
169
  {!isDesktopApp && <p className="hint">Opening and reloading local workflow files requires the desktop app.</p>}
170
170
  </section>
171
171
 
172
- <section className="setting-section">
173
- <div className="section-heading">
174
- <div>
175
- <p className="section-kicker">Code mode</p>
176
- <h2 className="section-title">Agent Collaboration</h2>
177
- </div>
178
- </div>
179
- <div className="toggle-row">
180
- <div>
181
- <label>Enable Multi-Agent Review</label>
182
- <p className="hint">Allow a secondary model to review code written by the primary model.</p>
183
- </div>
184
- <label className="settings-toggle-switch">
185
- <input
186
- type="checkbox"
187
- checked={config.enableAgentCollaboration}
188
- onChange={(e) => updateField('enableAgentCollaboration', e.target.checked)}
189
- />
190
- <span className="settings-toggle-slider"></span>
191
- </label>
192
- </div>
193
- </section>
194
172
  </div>
195
173
  )
196
174
  }
@@ -6,6 +6,7 @@ import AudioTab from './Settings/AudioTab'
6
6
  import AutomationTab from './Settings/AutomationTab'
7
7
  import ThemeTab from './Settings/ThemeTab'
8
8
  import PluginsTab from './Settings/PluginsTab'
9
+ import AgentsTab from './Settings/AgentsTab'
9
10
 
10
11
  export const DEFAULT_CONFIG = {
11
12
  theme: 'dark',
@@ -30,7 +31,7 @@ export const DEFAULT_CONFIG = {
30
31
  proactiveCooldown: 120,
31
32
  enableVoiceReply: true,
32
33
  enableCustomWorkflows: true,
33
- enableAgentCollaboration: true,
34
+ enableAgentCollaboration: false,
34
35
  ttsProvider: 'google',
35
36
  ttsVolume: 1.0,
36
37
  ttsSpeed: 1.0,
@@ -91,10 +92,40 @@ export const DEFAULT_CONFIG = {
91
92
  imageGenProvider: 'gemini' as 'gemini' | 'dalle' | 'stability' | 'ideogram' | 'replicate',
92
93
  stabilityApiKey: '',
93
94
  ideogramApiKey: '',
94
- replicateApiKey: ''
95
+ replicateApiKey: '',
96
+ // Multi-Agent Configuration
97
+ agents: [
98
+ {
99
+ id: 'planner',
100
+ name: 'Planner',
101
+ provider: 'gemini',
102
+ model: 'gemini-2.5-flash',
103
+ apiKey: '',
104
+ systemInstruction: 'You are the Planner agent. Your task is to analyze the user request, inspect the workspace structure, and design a step-by-step implementation plan. Create or update the implementation_plan.md file to document your proposal.',
105
+ enabled: true
106
+ },
107
+ {
108
+ id: 'coder',
109
+ name: 'Coder',
110
+ provider: 'gemini',
111
+ model: 'gemini-2.5-flash',
112
+ apiKey: '',
113
+ systemInstruction: 'You are the Coder agent. Your task is to implement the changes specified in the approved implementation plan. Read relevant files, write clean and efficient code, and run terminal commands to build or verify. Stay focused on execution.',
114
+ enabled: true
115
+ },
116
+ {
117
+ id: 'reviewer',
118
+ name: 'Reviewer',
119
+ provider: 'gemini',
120
+ model: 'gemini-2.5-flash',
121
+ apiKey: '',
122
+ systemInstruction: 'You are the Reviewer agent. Your task is to verify the code modifications made by the Coder. Run the automated tests, check lint errors, and ensure the implementation is correct and complete.',
123
+ enabled: true
124
+ }
125
+ ]
95
126
  }
96
127
 
97
- type TabType = 'sect-general' | 'sect-audio' | 'sect-automation' | 'sect-theme' | 'sect-plugins' | 'sect-shortcuts' | 'sect-memory'
128
+ type TabType = 'sect-general' | 'sect-audio' | 'sect-automation' | 'sect-theme' | 'sect-plugins' | 'sect-shortcuts' | 'sect-memory' | 'sect-agents'
98
129
 
99
130
  export const GEMINI_MODELS = [
100
131
  'gemini-2.5-flash',
@@ -616,6 +647,17 @@ export default function SettingsWindow() {
616
647
  </span>
617
648
  <strong>Plugins</strong>
618
649
  </button>
650
+ <button className={`tab-btn ${activeTab === 'sect-agents' ? 'active' : ''}`} onClick={() => setActiveTab('sect-agents')}>
651
+ <span style={{ display: 'inline-flex', alignItems: 'center' }}>
652
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
653
+ <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
654
+ <circle cx="9" cy="7" r="4"></circle>
655
+ <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
656
+ <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
657
+ </svg>
658
+ </span>
659
+ <strong>Multi-Agent (Beta)</strong>
660
+ </button>
619
661
  </nav>
620
662
 
621
663
  <div className="settings-content">
@@ -705,6 +747,14 @@ export default function SettingsWindow() {
705
747
  handleConnectPlugin={handleConnectPlugin}
706
748
  />
707
749
  )}
750
+
751
+ {activeTab === 'sect-agents' && (
752
+ <AgentsTab
753
+ config={config}
754
+ updateField={updateField}
755
+ dynamicOllamaModels={dynamicOllamaModels}
756
+ />
757
+ )}
708
758
  </div>
709
759
  </main>
710
760
 
@@ -4167,3 +4167,87 @@ input:checked + .slider:before {
4167
4167
  -ms-user-select: text !important;
4168
4168
  }
4169
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
+
@@ -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__)
@@ -163,6 +86,7 @@ export async function sendChatMessage(
163
86
  documentAttachment?: DocumentAttachment | null,
164
87
  workspacePath?: string | null,
165
88
  chatId?: string | null,
89
+ agentId?: string | null,
166
90
  ): Promise<ChatResponse> {
167
91
  const outgoingMessage = withImagePlaceholder(message, imageDataUri)
168
92
  if (typeof window === 'undefined' || !isTauriRuntime()) {
@@ -171,7 +95,7 @@ export async function sendChatMessage(
171
95
  const res = await fetch(`${API_BASE}/chat`, {
172
96
  method: 'POST',
173
97
  headers: { 'Content-Type': 'application/json' },
174
- body: JSON.stringify({ message: outgoingMessage, systemInstruction: '', chatId, imageDataUri, audioDataUri, documentAttachment })
98
+ body: JSON.stringify({ message: outgoingMessage, systemInstruction: '', chatId, imageDataUri, audioDataUri, documentAttachment, agentId })
175
99
  });
176
100
  const data = await res.json().catch(() => null);
177
101
  if (!res.ok) {
@@ -196,7 +120,7 @@ export async function sendChatMessage(
196
120
  }
197
121
  const { invoke } = await import('@tauri-apps/api/core')
198
122
  const response = await invoke<ChatResponse>('send_chat_message', {
199
- request: { message: outgoingMessage, systemInstruction: '', chatId, imageDataUri, audioDataUri, documentAttachment, workspacePath },
123
+ request: { message: outgoingMessage, systemInstruction: '', chatId, imageDataUri, audioDataUri, documentAttachment, workspacePath, agentId },
200
124
  })
201
125
  if (imageDataUri) {
202
126
  await invoke('save_pictures', {
@@ -218,6 +142,7 @@ export async function streamChatMessage(
218
142
  documentAttachment?: DocumentAttachment | null,
219
143
  workspacePath?: string | null,
220
144
  chatId?: string | null,
145
+ agentId?: string | null,
221
146
  ): Promise<ChatResponse> {
222
147
  if (typeof window === 'undefined' || !isTauriRuntime()) {
223
148
  const API_BASE = getApiBase();
@@ -225,7 +150,7 @@ export async function streamChatMessage(
225
150
  const res = await fetch(`${API_BASE}/chat-stream`, {
226
151
  method: 'POST',
227
152
  headers: { 'Content-Type': 'application/json' },
228
- body: JSON.stringify({ message: outgoingMessage, systemInstruction, chatId, imageDataUri, audioDataUri, documentAttachment })
153
+ body: JSON.stringify({ message: outgoingMessage, systemInstruction, chatId, imageDataUri, audioDataUri, documentAttachment, agentId })
229
154
  });
230
155
  if (!res.ok) {
231
156
  const data = await res.json().catch(() => null);
@@ -271,7 +196,7 @@ export async function streamChatMessage(
271
196
  else onProgress?.(event.progress)
272
197
  }
273
198
  const response = await invoke<ChatResponse>('stream_chat_message', {
274
- request: { message: outgoingMessage, systemInstruction, chatId, imageDataUri, audioDataUri, documentAttachment, workspacePath },
199
+ request: { message: outgoingMessage, systemInstruction, chatId, imageDataUri, audioDataUri, documentAttachment, workspacePath, agentId },
275
200
  onEvent,
276
201
  })
277
202
  if (imageDataUri) {
@@ -298,6 +223,20 @@ export async function getTtsUrls(text: string): Promise<TtsUrl[]> {
298
223
  return invoke<TtsUrl[]>('get_tts_urls', { text })
299
224
  }
300
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
+
301
240
  export async function getRecentInteractions(limit = 50, chatId?: string | null): Promise<InteractionMemory[]> {
302
241
  if (typeof window === 'undefined' || !isTauriRuntime()) {
303
242
  const API_BASE = getApiBase();
@@ -476,11 +415,12 @@ export async function listSavedPictures(): Promise<PictureEntry[]> {
476
415
  if (typeof window === 'undefined' || !isTauriRuntime()) {
477
416
  const API_BASE = getApiBase();
478
417
  try {
479
- const res = await fetch(`${API_BASE}/pictures`);
418
+ const res = await fetch(`${API_BASE}/pictures?_t=${Date.now()}`);
480
419
  const pictures = await res.json();
420
+ const timestamp = Date.now();
481
421
  return Array.isArray(pictures)
482
422
  ? pictures.map((picture) => {
483
- 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
484
424
  return {
485
425
  ...picture,
486
426
  path: pictureUrl || picture.path,
@@ -1176,8 +1116,109 @@ async function captureSharedScreen(): Promise<string> {
1176
1116
  }
1177
1117
  }
1178
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
+
1179
1219
  export async function readClipboardImage(): Promise<string | null> {
1180
1220
  if (typeof window === 'undefined' || !isTauriRuntime()) {
1221
+
1181
1222
  return null
1182
1223
  }
1183
1224
  const { invoke } = await import('@tauri-apps/api/core')
@@ -1188,3 +1229,40 @@ export async function readClipboardImage(): Promise<string | null> {
1188
1229
  return null
1189
1230
  }
1190
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
+