@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
|
@@ -12,9 +12,10 @@ import {
|
|
|
12
12
|
selectWorkspaceDirectory,
|
|
13
13
|
saveInteractionAgentActivity,
|
|
14
14
|
streamChatMessage,
|
|
15
|
+
cancelChatMessage,
|
|
15
16
|
submitToolApproval,
|
|
16
17
|
listen,
|
|
17
|
-
readClipboardImage
|
|
18
|
+
readClipboardImage,
|
|
18
19
|
type AgentProgress,
|
|
19
20
|
type ChatResponse,
|
|
20
21
|
type ChatSession,
|
|
@@ -22,6 +23,7 @@ import {
|
|
|
22
23
|
type PictureEntry,
|
|
23
24
|
type RuntimeStatus,
|
|
24
25
|
} from '../tauri'
|
|
26
|
+
|
|
25
27
|
import ChatPanel from './ChatPanel'
|
|
26
28
|
import DashboardSidebar, { type DashboardView } from './DashboardSidebar'
|
|
27
29
|
import ImageStudioPanel from './ImageStudioPanel'
|
|
@@ -30,6 +32,13 @@ import type { ModelInteraction } from './ModelPanel'
|
|
|
30
32
|
import PicturesLibrary from './PicturesLibrary'
|
|
31
33
|
import WorkspacePanel from './WorkspacePanel'
|
|
32
34
|
import WorkflowBuilderPanel from './WorkflowBuilderPanel'
|
|
35
|
+
import {
|
|
36
|
+
errorMessage,
|
|
37
|
+
readImage,
|
|
38
|
+
readDocument,
|
|
39
|
+
createTrimmedImagePreview,
|
|
40
|
+
applyThemeStyles,
|
|
41
|
+
} from '../../shared/utils/ui'
|
|
33
42
|
|
|
34
43
|
const EXPRESSIONS = [
|
|
35
44
|
"Default",
|
|
@@ -88,142 +97,6 @@ const MOCK_WELCOME_INTERACTION = {
|
|
|
88
97
|
createdAt: new Date().toISOString(),
|
|
89
98
|
}
|
|
90
99
|
|
|
91
|
-
function errorMessage(reason: unknown) {
|
|
92
|
-
return reason instanceof Error ? reason.message : String(reason)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function readImage(file: File): Promise<string> {
|
|
96
|
-
return new Promise((resolve, reject) => {
|
|
97
|
-
const reader = new FileReader()
|
|
98
|
-
reader.onload = () => resolve(String(reader.result))
|
|
99
|
-
reader.onerror = () => reject(reader.error ?? new Error('Unable to read image'))
|
|
100
|
-
reader.readAsDataURL(file)
|
|
101
|
-
})
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function readDocument(file: File): Promise<string> {
|
|
105
|
-
return new Promise((resolve, reject) => {
|
|
106
|
-
const reader = new FileReader()
|
|
107
|
-
reader.onload = () => resolve(String(reader.result))
|
|
108
|
-
reader.onerror = () => reject(reader.error ?? new Error('Unable to read document'))
|
|
109
|
-
reader.readAsDataURL(file)
|
|
110
|
-
})
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
async function createTrimmedImagePreview(dataUri: string): Promise<string> {
|
|
114
|
-
const image = await new Promise<HTMLImageElement>((resolve, reject) => {
|
|
115
|
-
const nextImage = new Image()
|
|
116
|
-
nextImage.onload = () => resolve(nextImage)
|
|
117
|
-
nextImage.onerror = () => reject(new Error('Unable to prepare image preview'))
|
|
118
|
-
nextImage.src = dataUri
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
const canvas = document.createElement('canvas')
|
|
122
|
-
canvas.width = image.naturalWidth || image.width
|
|
123
|
-
canvas.height = image.naturalHeight || image.height
|
|
124
|
-
const context = canvas.getContext('2d', { willReadFrequently: true })
|
|
125
|
-
if (!context || canvas.width === 0 || canvas.height === 0) return dataUri
|
|
126
|
-
|
|
127
|
-
context.drawImage(image, 0, 0)
|
|
128
|
-
const pixels = context.getImageData(0, 0, canvas.width, canvas.height)
|
|
129
|
-
let minX = canvas.width
|
|
130
|
-
let minY = canvas.height
|
|
131
|
-
let maxX = -1
|
|
132
|
-
let maxY = -1
|
|
133
|
-
|
|
134
|
-
for (let y = 0; y < canvas.height; y += 1) {
|
|
135
|
-
for (let x = 0; x < canvas.width; x += 1) {
|
|
136
|
-
const alpha = pixels.data[(y * canvas.width + x) * 4 + 3]
|
|
137
|
-
if (alpha > 12) {
|
|
138
|
-
minX = Math.min(minX, x)
|
|
139
|
-
minY = Math.min(minY, y)
|
|
140
|
-
maxX = Math.max(maxX, x)
|
|
141
|
-
maxY = Math.max(maxY, y)
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (maxX < minX || maxY < minY) return dataUri
|
|
147
|
-
|
|
148
|
-
const padding = 8
|
|
149
|
-
const sx = Math.max(0, minX - padding)
|
|
150
|
-
const sy = Math.max(0, minY - padding)
|
|
151
|
-
const sw = Math.min(canvas.width - sx, maxX - minX + 1 + padding * 2)
|
|
152
|
-
const sh = Math.min(canvas.height - sy, maxY - minY + 1 + padding * 2)
|
|
153
|
-
|
|
154
|
-
if (sw >= canvas.width * 0.92 && sh >= canvas.height * 0.92) return dataUri
|
|
155
|
-
|
|
156
|
-
const previewCanvas = document.createElement('canvas')
|
|
157
|
-
previewCanvas.width = sw
|
|
158
|
-
previewCanvas.height = sh
|
|
159
|
-
const previewContext = previewCanvas.getContext('2d')
|
|
160
|
-
if (!previewContext) return dataUri
|
|
161
|
-
previewContext.drawImage(canvas, sx, sy, sw, sh, 0, 0, sw, sh)
|
|
162
|
-
return previewCanvas.toDataURL('image/png')
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const lightenColor = (hex: string, amount: number) => {
|
|
166
|
-
const clean = hex.replace('#', '')
|
|
167
|
-
if (clean.length !== 6) return hex
|
|
168
|
-
const num = parseInt(clean, 16)
|
|
169
|
-
const r = Math.min(255, (num >> 16) + amount)
|
|
170
|
-
const g = Math.min(255, ((num >> 8) & 0x00FF) + amount)
|
|
171
|
-
const b = Math.min(255, (num & 0x0000FF) + amount)
|
|
172
|
-
return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const hexToRgb = (hex: string) => {
|
|
176
|
-
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
|
|
177
|
-
return result ? {
|
|
178
|
-
r: parseInt(result[1], 16),
|
|
179
|
-
g: parseInt(result[2], 16),
|
|
180
|
-
b: parseInt(result[3], 16),
|
|
181
|
-
} : { r: 15, g: 23, b: 42 }
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const applyThemeStyles = (cfg: any) => {
|
|
185
|
-
const theme = cfg.theme || 'dark'
|
|
186
|
-
const accentColor = cfg.accentColor || '#4f83e6'
|
|
187
|
-
const systemTextColor = cfg.systemTextColor || '#f8fafc'
|
|
188
|
-
|
|
189
|
-
document.documentElement.setAttribute('data-theme', theme)
|
|
190
|
-
document.documentElement.style.setProperty('--accent', accentColor)
|
|
191
|
-
document.documentElement.style.setProperty('--accent-hover', lightenColor(accentColor, 20))
|
|
192
|
-
document.documentElement.style.setProperty('--text-main', systemTextColor)
|
|
193
|
-
document.documentElement.style.setProperty('--glass-blur', cfg.glassBlur || 'blur(16px)')
|
|
194
|
-
document.body.style.fontFamily = cfg.fontFamily || "'Outfit', sans-serif"
|
|
195
|
-
document.documentElement.style.fontSize = cfg.fontSize || '18px'
|
|
196
|
-
|
|
197
|
-
if (theme === 'custom') {
|
|
198
|
-
if (cfg.customBgStart && cfg.customBgEnd) {
|
|
199
|
-
document.documentElement.style.setProperty('--bg-color', cfg.customBgStart)
|
|
200
|
-
document.documentElement.style.setProperty('--bg-gradient', `linear-gradient(135deg, ${cfg.customBgStart} 0%, ${cfg.customBgEnd} 100%)`)
|
|
201
|
-
}
|
|
202
|
-
if (cfg.customPanelBg) {
|
|
203
|
-
const rgb = hexToRgb(cfg.customPanelBg)
|
|
204
|
-
document.documentElement.style.setProperty('--panel-bg', `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.75)`)
|
|
205
|
-
document.documentElement.style.setProperty('--panel-raised', `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.82)`)
|
|
206
|
-
document.documentElement.style.setProperty('--panel-soft', `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.46)`)
|
|
207
|
-
document.documentElement.style.setProperty('--chrome-bg', `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.88)`)
|
|
208
|
-
document.documentElement.style.setProperty('--surface-bg', `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.62)`)
|
|
209
|
-
document.documentElement.style.setProperty('--surface-strong', `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.86)`)
|
|
210
|
-
document.documentElement.style.setProperty('--input-bg', `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.72)`)
|
|
211
|
-
}
|
|
212
|
-
return
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
;[
|
|
216
|
-
'--bg-color',
|
|
217
|
-
'--bg-gradient',
|
|
218
|
-
'--panel-bg',
|
|
219
|
-
'--panel-raised',
|
|
220
|
-
'--panel-soft',
|
|
221
|
-
'--chrome-bg',
|
|
222
|
-
'--surface-bg',
|
|
223
|
-
'--surface-strong',
|
|
224
|
-
'--input-bg',
|
|
225
|
-
].forEach((name) => document.documentElement.style.removeProperty(name))
|
|
226
|
-
}
|
|
227
100
|
|
|
228
101
|
export default function MintDashboard() {
|
|
229
102
|
const [view, setView] = useState<DashboardView>('chat')
|
|
@@ -267,6 +140,7 @@ export default function MintDashboard() {
|
|
|
267
140
|
const [conversationId, setConversationId] = useState(activeConversationId)
|
|
268
141
|
const [chatSessions, setChatSessions] = useState<ChatSession[]>([])
|
|
269
142
|
const chatEnd = useRef<HTMLDivElement | null>(null)
|
|
143
|
+
const lastNativePasteTimeRef = useRef(0)
|
|
270
144
|
const startupReady = (dashboardDataReady && modelReady) || startupTimedOut
|
|
271
145
|
const [proactiveSuggestion, setProactiveSuggestion] = useState<any>(null)
|
|
272
146
|
|
|
@@ -522,6 +396,20 @@ export default function MintDashboard() {
|
|
|
522
396
|
}
|
|
523
397
|
}
|
|
524
398
|
|
|
399
|
+
async function handleCancelMessage() {
|
|
400
|
+
if (!sending || !streamingConversationId) return
|
|
401
|
+
try {
|
|
402
|
+
await cancelChatMessage(streamingConversationId)
|
|
403
|
+
} catch (e) {
|
|
404
|
+
console.error("Failed to cancel message stream:", e)
|
|
405
|
+
} finally {
|
|
406
|
+
setSending(false)
|
|
407
|
+
setStreamingConversationId(null)
|
|
408
|
+
setSendingMessage('')
|
|
409
|
+
setSendingImageCount(0)
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
525
413
|
async function sendPrompt(
|
|
526
414
|
promptText: string,
|
|
527
415
|
options: {
|
|
@@ -690,7 +578,28 @@ export default function MintDashboard() {
|
|
|
690
578
|
}
|
|
691
579
|
}
|
|
692
580
|
|
|
693
|
-
if (!file)
|
|
581
|
+
if (!file) {
|
|
582
|
+
// Fallback for Tauri desktop app where WebKitGTK/WebView clipboard paste events do not provide file handles
|
|
583
|
+
const now = Date.now()
|
|
584
|
+
if (now - lastNativePasteTimeRef.current > 100) {
|
|
585
|
+
lastNativePasteTimeRef.current = now
|
|
586
|
+
readClipboardImage().then((dataUri) => {
|
|
587
|
+
if (dataUri) {
|
|
588
|
+
const name = 'Pasted image'
|
|
589
|
+
createTrimmedImagePreview(dataUri)
|
|
590
|
+
.catch(() => dataUri)
|
|
591
|
+
.then((previewDataUri) => {
|
|
592
|
+
setImageAttachments((current) => [...current, { dataUri, previewDataUri, name }])
|
|
593
|
+
})
|
|
594
|
+
}
|
|
595
|
+
}).catch((err) => {
|
|
596
|
+
console.warn('Failed to read clipboard image via Tauri API:', err)
|
|
597
|
+
})
|
|
598
|
+
}
|
|
599
|
+
return false
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
|
|
694
603
|
|
|
695
604
|
readImage(file)
|
|
696
605
|
.then((dataUri) => {
|
|
@@ -705,37 +614,7 @@ export default function MintDashboard() {
|
|
|
705
614
|
return true
|
|
706
615
|
}
|
|
707
616
|
|
|
708
|
-
async function readClipboardImage() {
|
|
709
|
-
try {
|
|
710
|
-
const dataUri = await readTauriClipboardImage()
|
|
711
|
-
if (dataUri) {
|
|
712
|
-
const previewDataUri = await createTrimmedImagePreview(dataUri).catch(() => dataUri)
|
|
713
|
-
setImageAttachments((current) => [...current, { dataUri, previewDataUri, name: 'Pasted image' }])
|
|
714
|
-
return true
|
|
715
|
-
}
|
|
716
|
-
} catch (err) {
|
|
717
|
-
console.warn('Tauri clipboard fallback error:', err)
|
|
718
|
-
}
|
|
719
617
|
|
|
720
|
-
try {
|
|
721
|
-
if (!navigator.clipboard?.read) return false
|
|
722
|
-
const items = await navigator.clipboard.read()
|
|
723
|
-
for (const item of items) {
|
|
724
|
-
const imageType = item.types.find((type) => type.startsWith('image/'))
|
|
725
|
-
if (!imageType) continue
|
|
726
|
-
const blob = await item.getType(imageType)
|
|
727
|
-
const file = new File([blob], 'Pasted image', { type: imageType })
|
|
728
|
-
const dataUri = await readImage(file)
|
|
729
|
-
const previewDataUri = await createTrimmedImagePreview(dataUri).catch(() => dataUri)
|
|
730
|
-
setImageAttachments((current) => [...current, { dataUri, previewDataUri, name: 'Pasted image' }])
|
|
731
|
-
return true
|
|
732
|
-
}
|
|
733
|
-
return false
|
|
734
|
-
} catch {
|
|
735
|
-
// Some environments expose pasted images only through ClipboardEvent.
|
|
736
|
-
return false
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
618
|
|
|
740
619
|
async function selectDocument(event: ChangeEvent<HTMLInputElement>) {
|
|
741
620
|
const file = event.target.files?.[0]
|
|
@@ -882,6 +761,11 @@ export default function MintDashboard() {
|
|
|
882
761
|
else if (provider === 'huggingface') providerName = 'HF'
|
|
883
762
|
else if (provider === 'local_openai') providerName = 'Local'
|
|
884
763
|
else if (provider === 'ollama') providerName = 'Ollama'
|
|
764
|
+
else if (provider.startsWith('custom:')) {
|
|
765
|
+
const id = provider.replace(/^custom:/, '')
|
|
766
|
+
const cp = (settingsConfig?.customProviders ?? []).find((p: any) => p.id === id)
|
|
767
|
+
providerName = cp?.displayName || id
|
|
768
|
+
}
|
|
885
769
|
|
|
886
770
|
if (providerName && providerName === provider) {
|
|
887
771
|
providerName = providerName.charAt(0).toUpperCase() + providerName.slice(1)
|
|
@@ -899,7 +783,14 @@ export default function MintDashboard() {
|
|
|
899
783
|
case 'huggingface': return config.hfModel || 'meta-llama/Meta-Llama-3-8B-Instruct'
|
|
900
784
|
case 'local_openai': return config.localModelName || 'llama3'
|
|
901
785
|
case 'ollama': return config.ollamaModel || 'llama3:latest'
|
|
902
|
-
default:
|
|
786
|
+
default: {
|
|
787
|
+
if (provider.startsWith('custom:')) {
|
|
788
|
+
const id = provider.replace(/^custom:/, '')
|
|
789
|
+
const cp = (config.customProviders ?? []).find((p: any) => p.id === id)
|
|
790
|
+
return (config.customModelSelections ?? {})[id] ?? cp?.models[0]?.modelId ?? ''
|
|
791
|
+
}
|
|
792
|
+
return ''
|
|
793
|
+
}
|
|
903
794
|
}
|
|
904
795
|
}
|
|
905
796
|
|
|
@@ -941,6 +832,12 @@ export default function MintDashboard() {
|
|
|
941
832
|
config.localModelName = modelName
|
|
942
833
|
} else if (provider === 'ollama') {
|
|
943
834
|
config.ollamaModel = modelName
|
|
835
|
+
} else if (provider.startsWith('custom:')) {
|
|
836
|
+
const id = provider.replace(/^custom:/, '')
|
|
837
|
+
config.customModelSelections = {
|
|
838
|
+
...(config.customModelSelections ?? {}),
|
|
839
|
+
[id]: modelName
|
|
840
|
+
}
|
|
944
841
|
}
|
|
945
842
|
await window.settingsApi.saveSettings(config)
|
|
946
843
|
setSettingsConfig(config)
|
|
@@ -1110,7 +1007,6 @@ export default function MintDashboard() {
|
|
|
1110
1007
|
onSelectImage={selectImage}
|
|
1111
1008
|
onSelectDocument={selectDocument}
|
|
1112
1009
|
onPasteImage={pasteImage}
|
|
1113
|
-
onReadClipboardImage={readClipboardImage}
|
|
1114
1010
|
onSetMessage={setMessage}
|
|
1115
1011
|
onSendVoiceMessage={sendVoiceMessage}
|
|
1116
1012
|
onRemoveImage={(idx: number) => {
|
|
@@ -1126,6 +1022,7 @@ export default function MintDashboard() {
|
|
|
1126
1022
|
settingsConfig={settingsConfig}
|
|
1127
1023
|
onSetModel={changeModel}
|
|
1128
1024
|
onApproval={handleApproval}
|
|
1025
|
+
onCancelMessage={handleCancelMessage}
|
|
1129
1026
|
/>
|
|
1130
1027
|
</main>
|
|
1131
1028
|
<PicturesLibrary view={view} pictures={pictures} onSetView={setView} onRefreshPictures={refreshPictures} />
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useEffect, useMemo, useState } from 'react'
|
|
1
2
|
import { type PictureEntry, convertFileSrc } from '../tauri'
|
|
2
3
|
import type { DashboardView } from './DashboardSidebar'
|
|
3
4
|
|
|
@@ -9,6 +10,16 @@ interface PicturesLibraryProps {
|
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
export default function PicturesLibrary({ view, pictures, onSetView, onRefreshPictures }: PicturesLibraryProps) {
|
|
13
|
+
const [visibleCount, setVisibleCount] = useState(24)
|
|
14
|
+
const visiblePictures = useMemo(
|
|
15
|
+
() => pictures.slice(0, visibleCount),
|
|
16
|
+
[pictures, visibleCount],
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
setVisibleCount(24)
|
|
21
|
+
}, [view, pictures])
|
|
22
|
+
|
|
12
23
|
return (
|
|
13
24
|
<section className={`pictures-library ${view === 'pictures' ? 'is-visible' : ''}`} aria-hidden={view !== 'pictures'}>
|
|
14
25
|
<header className="pictures-header">
|
|
@@ -34,14 +45,27 @@ export default function PicturesLibrary({ view, pictures, onSetView, onRefreshPi
|
|
|
34
45
|
<span>Images appear here after a message with an attachment is sent successfully.</span>
|
|
35
46
|
</div>
|
|
36
47
|
) : (
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
<
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
<>
|
|
49
|
+
<div className="pictures-grid">
|
|
50
|
+
{visiblePictures.map((picture, index) => (
|
|
51
|
+
<article className="picture-card" key={picture.id}>
|
|
52
|
+
<img src={convertFileSrc(picture.thumbnailPath || picture.thumbnailUrl || picture.path)} alt={picture.message || picture.filename} loading={index < 6 ? 'eager' : 'lazy'} decoding="async" />
|
|
53
|
+
<div className="picture-card-meta"><span>{picture.message || picture.filename}</span></div>
|
|
54
|
+
</article>
|
|
55
|
+
))}
|
|
56
|
+
</div>
|
|
57
|
+
{visibleCount < pictures.length && (
|
|
58
|
+
<div className="pictures-load-more-container">
|
|
59
|
+
<button
|
|
60
|
+
type="button"
|
|
61
|
+
className="pictures-load-more-btn"
|
|
62
|
+
onClick={() => setVisibleCount((prev) => prev + 24)}
|
|
63
|
+
>
|
|
64
|
+
Load More ({pictures.length - visibleCount} remaining)
|
|
65
|
+
</button>
|
|
66
|
+
</div>
|
|
67
|
+
)}
|
|
68
|
+
</>
|
|
45
69
|
)}
|
|
46
70
|
</section>
|
|
47
71
|
)
|