@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
|
@@ -11,9 +11,9 @@ import {
|
|
|
11
11
|
listSavedPictures,
|
|
12
12
|
saveInteractionAgentActivity,
|
|
13
13
|
streamChatMessage,
|
|
14
|
+
cancelChatMessage,
|
|
14
15
|
submitToolApproval,
|
|
15
16
|
listen,
|
|
16
|
-
readClipboardImage as readTauriClipboardImage,
|
|
17
17
|
type AgentProgress,
|
|
18
18
|
type ChatResponse,
|
|
19
19
|
type ChatSession,
|
|
@@ -25,6 +25,13 @@ import ChatPanel from './ChatPanel'
|
|
|
25
25
|
import DashboardSidebar, { type DashboardView } from './DashboardSidebar'
|
|
26
26
|
import PicturesLibrary from './PicturesLibrary'
|
|
27
27
|
import ImageStudioPanel from './ImageStudioPanel'
|
|
28
|
+
import {
|
|
29
|
+
errorMessage,
|
|
30
|
+
readImage,
|
|
31
|
+
readDocument,
|
|
32
|
+
createTrimmedImagePreview,
|
|
33
|
+
applyThemeStyles,
|
|
34
|
+
} from '../../shared/utils/ui'
|
|
28
35
|
|
|
29
36
|
const DEFAULT_CONFIG = {
|
|
30
37
|
theme: 'dark',
|
|
@@ -66,142 +73,6 @@ const MOCK_WELCOME_INTERACTION = {
|
|
|
66
73
|
createdAt: new Date().toISOString(),
|
|
67
74
|
}
|
|
68
75
|
|
|
69
|
-
function errorMessage(reason: unknown) {
|
|
70
|
-
return reason instanceof Error ? reason.message : String(reason)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function readImage(file: File): Promise<string> {
|
|
74
|
-
return new Promise((resolve, reject) => {
|
|
75
|
-
const reader = new FileReader()
|
|
76
|
-
reader.onload = () => resolve(String(reader.result))
|
|
77
|
-
reader.onerror = () => reject(reader.error ?? new Error('Unable to read image'))
|
|
78
|
-
reader.readAsDataURL(file)
|
|
79
|
-
})
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function readDocument(file: File): Promise<string> {
|
|
83
|
-
return new Promise((resolve, reject) => {
|
|
84
|
-
const reader = new FileReader()
|
|
85
|
-
reader.onload = () => resolve(String(reader.result))
|
|
86
|
-
reader.onerror = () => reject(reader.error ?? new Error('Unable to read document'))
|
|
87
|
-
reader.readAsDataURL(file)
|
|
88
|
-
})
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
async function createTrimmedImagePreview(dataUri: string): Promise<string> {
|
|
92
|
-
const image = await new Promise<HTMLImageElement>((resolve, reject) => {
|
|
93
|
-
const nextImage = new Image()
|
|
94
|
-
nextImage.onload = () => resolve(nextImage)
|
|
95
|
-
nextImage.onerror = () => reject(new Error('Unable to prepare image preview'))
|
|
96
|
-
nextImage.src = dataUri
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
const canvas = document.createElement('canvas')
|
|
100
|
-
canvas.width = image.naturalWidth || image.width
|
|
101
|
-
canvas.height = image.naturalHeight || image.height
|
|
102
|
-
const context = canvas.getContext('2d', { willReadFrequently: true })
|
|
103
|
-
if (!context || canvas.width === 0 || canvas.height === 0) return dataUri
|
|
104
|
-
|
|
105
|
-
context.drawImage(image, 0, 0)
|
|
106
|
-
const pixels = context.getImageData(0, 0, canvas.width, canvas.height)
|
|
107
|
-
let minX = canvas.width
|
|
108
|
-
let minY = canvas.height
|
|
109
|
-
let maxX = -1
|
|
110
|
-
let maxY = -1
|
|
111
|
-
|
|
112
|
-
for (let y = 0; y < canvas.height; y += 1) {
|
|
113
|
-
for (let x = 0; x < canvas.width; x += 1) {
|
|
114
|
-
const alpha = pixels.data[(y * canvas.width + x) * 4 + 3]
|
|
115
|
-
if (alpha > 12) {
|
|
116
|
-
minX = Math.min(minX, x)
|
|
117
|
-
minY = Math.min(minY, y)
|
|
118
|
-
maxX = Math.max(maxX, x)
|
|
119
|
-
maxY = Math.max(maxY, y)
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (maxX < minX || maxY < minY) return dataUri
|
|
125
|
-
|
|
126
|
-
const padding = 8
|
|
127
|
-
const sx = Math.max(0, minX - padding)
|
|
128
|
-
const sy = Math.max(0, minY - padding)
|
|
129
|
-
const sw = Math.min(canvas.width - sx, maxX - minX + 1 + padding * 2)
|
|
130
|
-
const sh = Math.min(canvas.height - sy, maxY - minY + 1 + padding * 2)
|
|
131
|
-
|
|
132
|
-
if (sw >= canvas.width * 0.92 && sh >= canvas.height * 0.92) return dataUri
|
|
133
|
-
|
|
134
|
-
const previewCanvas = document.createElement('canvas')
|
|
135
|
-
previewCanvas.width = sw
|
|
136
|
-
previewCanvas.height = sh
|
|
137
|
-
const previewContext = previewCanvas.getContext('2d')
|
|
138
|
-
if (!previewContext) return dataUri
|
|
139
|
-
previewContext.drawImage(canvas, sx, sy, sw, sh, 0, 0, sw, sh)
|
|
140
|
-
return previewCanvas.toDataURL('image/png')
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const lightenColor = (hex: string, amount: number) => {
|
|
144
|
-
const clean = hex.replace('#', '')
|
|
145
|
-
if (clean.length !== 6) return hex
|
|
146
|
-
const num = parseInt(clean, 16)
|
|
147
|
-
const r = Math.min(255, (num >> 16) + amount)
|
|
148
|
-
const g = Math.min(255, ((num >> 8) & 0x00FF) + amount)
|
|
149
|
-
const b = Math.min(255, (num & 0x0000FF) + amount)
|
|
150
|
-
return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const hexToRgb = (hex: string) => {
|
|
154
|
-
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
|
|
155
|
-
return result ? {
|
|
156
|
-
r: parseInt(result[1], 16),
|
|
157
|
-
g: parseInt(result[2], 16),
|
|
158
|
-
b: parseInt(result[3], 16),
|
|
159
|
-
} : { r: 15, g: 23, b: 42 }
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const applyThemeStyles = (cfg: any) => {
|
|
163
|
-
const theme = cfg.theme || 'dark'
|
|
164
|
-
const accentColor = cfg.accentColor || '#4f83e6'
|
|
165
|
-
const systemTextColor = cfg.systemTextColor || '#f8fafc'
|
|
166
|
-
|
|
167
|
-
document.documentElement.setAttribute('data-theme', theme)
|
|
168
|
-
document.documentElement.style.setProperty('--accent', accentColor)
|
|
169
|
-
document.documentElement.style.setProperty('--accent-hover', lightenColor(accentColor, 20))
|
|
170
|
-
document.documentElement.style.setProperty('--text-main', systemTextColor)
|
|
171
|
-
document.documentElement.style.setProperty('--glass-blur', cfg.glassBlur || 'blur(16px)')
|
|
172
|
-
document.body.style.fontFamily = cfg.fontFamily || "'Outfit', sans-serif"
|
|
173
|
-
document.documentElement.style.fontSize = cfg.fontSize || '18px'
|
|
174
|
-
|
|
175
|
-
if (theme === 'custom') {
|
|
176
|
-
if (cfg.customBgStart && cfg.customBgEnd) {
|
|
177
|
-
document.documentElement.style.setProperty('--bg-color', cfg.customBgStart)
|
|
178
|
-
document.documentElement.style.setProperty('--bg-gradient', `linear-gradient(135deg, ${cfg.customBgStart} 0%, ${cfg.customBgEnd} 100%)`)
|
|
179
|
-
}
|
|
180
|
-
if (cfg.customPanelBg) {
|
|
181
|
-
const rgb = hexToRgb(cfg.customPanelBg)
|
|
182
|
-
document.documentElement.style.setProperty('--panel-bg', `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.75)`)
|
|
183
|
-
document.documentElement.style.setProperty('--panel-raised', `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.82)`)
|
|
184
|
-
document.documentElement.style.setProperty('--panel-soft', `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.46)`)
|
|
185
|
-
document.documentElement.style.setProperty('--chrome-bg', `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.88)`)
|
|
186
|
-
document.documentElement.style.setProperty('--surface-bg', `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.62)`)
|
|
187
|
-
document.documentElement.style.setProperty('--surface-strong', `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.86)`)
|
|
188
|
-
document.documentElement.style.setProperty('--input-bg', `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.72)`)
|
|
189
|
-
}
|
|
190
|
-
return
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
;[
|
|
194
|
-
'--bg-color',
|
|
195
|
-
'--bg-gradient',
|
|
196
|
-
'--panel-bg',
|
|
197
|
-
'--panel-raised',
|
|
198
|
-
'--panel-soft',
|
|
199
|
-
'--chrome-bg',
|
|
200
|
-
'--surface-bg',
|
|
201
|
-
'--surface-strong',
|
|
202
|
-
'--input-bg',
|
|
203
|
-
].forEach((name) => document.documentElement.style.removeProperty(name))
|
|
204
|
-
}
|
|
205
76
|
|
|
206
77
|
export default function MintDashboard() {
|
|
207
78
|
const [view, setView] = useState<DashboardView>('chat')
|
|
@@ -415,6 +286,20 @@ export default function MintDashboard() {
|
|
|
415
286
|
}
|
|
416
287
|
}
|
|
417
288
|
|
|
289
|
+
async function handleCancelMessage() {
|
|
290
|
+
if (!sending || !streamingConversationId) return
|
|
291
|
+
try {
|
|
292
|
+
await cancelChatMessage(streamingConversationId)
|
|
293
|
+
} catch (e) {
|
|
294
|
+
console.error("Failed to cancel message stream:", e)
|
|
295
|
+
} finally {
|
|
296
|
+
setSending(false)
|
|
297
|
+
setStreamingConversationId(null)
|
|
298
|
+
setSendingMessage('')
|
|
299
|
+
setSendingImageCount(0)
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
418
303
|
async function sendPrompt(
|
|
419
304
|
promptText: string,
|
|
420
305
|
options: {
|
|
@@ -587,37 +472,6 @@ export default function MintDashboard() {
|
|
|
587
472
|
return true
|
|
588
473
|
}
|
|
589
474
|
|
|
590
|
-
async function readClipboardImage() {
|
|
591
|
-
try {
|
|
592
|
-
const dataUri = await readTauriClipboardImage()
|
|
593
|
-
if (dataUri) {
|
|
594
|
-
const previewDataUri = await createTrimmedImagePreview(dataUri).catch(() => dataUri)
|
|
595
|
-
setImageAttachments((current) => [...current, { dataUri, previewDataUri, name: 'Pasted image' }])
|
|
596
|
-
return true
|
|
597
|
-
}
|
|
598
|
-
} catch (err) {
|
|
599
|
-
console.warn('Tauri clipboard fallback error:', err)
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
try {
|
|
603
|
-
if (!navigator.clipboard?.read) return false
|
|
604
|
-
const items = await navigator.clipboard.read()
|
|
605
|
-
for (const item of items) {
|
|
606
|
-
const imageType = item.types.find((type) => type.startsWith('image/'))
|
|
607
|
-
if (!imageType) continue
|
|
608
|
-
const blob = await item.getType(imageType)
|
|
609
|
-
const file = new File([blob], 'Pasted image', { type: imageType })
|
|
610
|
-
const dataUri = await readImage(file)
|
|
611
|
-
const previewDataUri = await createTrimmedImagePreview(dataUri).catch(() => dataUri)
|
|
612
|
-
setImageAttachments((current) => [...current, { dataUri, previewDataUri, name: 'Pasted image' }])
|
|
613
|
-
return true
|
|
614
|
-
}
|
|
615
|
-
return false
|
|
616
|
-
} catch {
|
|
617
|
-
// Some environments expose pasted images only through ClipboardEvent.
|
|
618
|
-
return false
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
475
|
|
|
622
476
|
async function selectDocument(event: ChangeEvent<HTMLInputElement>) {
|
|
623
477
|
const file = event.target.files?.[0]
|
|
@@ -752,6 +606,11 @@ export default function MintDashboard() {
|
|
|
752
606
|
else if (provider === 'huggingface') providerName = 'HF'
|
|
753
607
|
else if (provider === 'local_openai') providerName = 'Local'
|
|
754
608
|
else if (provider === 'ollama') providerName = 'Ollama'
|
|
609
|
+
else if (provider.startsWith('custom:')) {
|
|
610
|
+
const id = provider.replace(/^custom:/, '')
|
|
611
|
+
const cp = (settingsConfig?.customProviders ?? []).find((p: any) => p.id === id)
|
|
612
|
+
providerName = cp?.displayName || id
|
|
613
|
+
}
|
|
755
614
|
|
|
756
615
|
if (providerName && providerName === provider) {
|
|
757
616
|
providerName = providerName.charAt(0).toUpperCase() + providerName.slice(1)
|
|
@@ -769,7 +628,14 @@ export default function MintDashboard() {
|
|
|
769
628
|
case 'huggingface': return config.hfModel || 'meta-llama/Meta-Llama-3-8B-Instruct'
|
|
770
629
|
case 'local_openai': return config.localModelName || 'llama3'
|
|
771
630
|
case 'ollama': return config.ollamaModel || 'llama3:latest'
|
|
772
|
-
default:
|
|
631
|
+
default: {
|
|
632
|
+
if (provider.startsWith('custom:')) {
|
|
633
|
+
const id = provider.replace(/^custom:/, '')
|
|
634
|
+
const cp = (config.customProviders ?? []).find((p: any) => p.id === id)
|
|
635
|
+
return (config.customModelSelections ?? {})[id] ?? cp?.models[0]?.modelId ?? ''
|
|
636
|
+
}
|
|
637
|
+
return ''
|
|
638
|
+
}
|
|
773
639
|
}
|
|
774
640
|
}
|
|
775
641
|
|
|
@@ -811,6 +677,12 @@ export default function MintDashboard() {
|
|
|
811
677
|
config.localModelName = modelName
|
|
812
678
|
} else if (provider === 'ollama') {
|
|
813
679
|
config.ollamaModel = modelName
|
|
680
|
+
} else if (provider.startsWith('custom:')) {
|
|
681
|
+
const id = provider.replace(/^custom:/, '')
|
|
682
|
+
config.customModelSelections = {
|
|
683
|
+
...(config.customModelSelections ?? {}),
|
|
684
|
+
[id]: modelName
|
|
685
|
+
}
|
|
814
686
|
}
|
|
815
687
|
await window.settingsApi.saveSettings(config)
|
|
816
688
|
setSettingsConfig(config)
|
|
@@ -886,7 +758,6 @@ export default function MintDashboard() {
|
|
|
886
758
|
onSelectImage={selectImage}
|
|
887
759
|
onSelectDocument={selectDocument}
|
|
888
760
|
onPasteImage={pasteImage}
|
|
889
|
-
onReadClipboardImage={readClipboardImage}
|
|
890
761
|
onSetMessage={setMessage}
|
|
891
762
|
onSendVoiceMessage={sendVoiceMessage}
|
|
892
763
|
onRemoveImage={(idx: number) => {
|
|
@@ -901,6 +772,7 @@ export default function MintDashboard() {
|
|
|
901
772
|
settingsConfig={settingsConfig}
|
|
902
773
|
onSetModel={changeModel}
|
|
903
774
|
onApproval={handleApproval}
|
|
775
|
+
onCancelMessage={handleCancelMessage}
|
|
904
776
|
onToggleMobileSidebar={() => setMobileSidebarOpen(!mobileSidebarOpen)}
|
|
905
777
|
/>
|
|
906
778
|
</main>
|
|
@@ -2,10 +2,6 @@ import { useEffect, useMemo, useState } from 'react'
|
|
|
2
2
|
import { type PictureEntry, convertFileSrc } from '../tauri'
|
|
3
3
|
import type { DashboardView } from './DashboardSidebar'
|
|
4
4
|
|
|
5
|
-
const INITIAL_VISIBLE_PICTURES = 18
|
|
6
|
-
const PICTURE_RENDER_BATCH_SIZE = 18
|
|
7
|
-
const PICTURE_RENDER_BATCH_DELAY_MS = 80
|
|
8
|
-
|
|
9
5
|
interface PicturesLibraryProps {
|
|
10
6
|
view: DashboardView
|
|
11
7
|
pictures: PictureEntry[]
|
|
@@ -14,31 +10,16 @@ interface PicturesLibraryProps {
|
|
|
14
10
|
}
|
|
15
11
|
|
|
16
12
|
export default function PicturesLibrary({ view, pictures, onSetView, onRefreshPictures }: PicturesLibraryProps) {
|
|
17
|
-
const [visibleCount, setVisibleCount] = useState(
|
|
13
|
+
const [visibleCount, setVisibleCount] = useState(24)
|
|
18
14
|
const visiblePictures = useMemo(
|
|
19
15
|
() => pictures.slice(0, visibleCount),
|
|
20
16
|
[pictures, visibleCount],
|
|
21
17
|
)
|
|
22
18
|
|
|
23
19
|
useEffect(() => {
|
|
24
|
-
|
|
25
|
-
setVisibleCount(INITIAL_VISIBLE_PICTURES)
|
|
26
|
-
return
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
setVisibleCount(INITIAL_VISIBLE_PICTURES)
|
|
20
|
+
setVisibleCount(24)
|
|
30
21
|
}, [view, pictures])
|
|
31
22
|
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
if (view !== 'pictures' || visibleCount >= pictures.length) return
|
|
34
|
-
|
|
35
|
-
const timer = window.setTimeout(() => {
|
|
36
|
-
setVisibleCount((current) => Math.min(current + PICTURE_RENDER_BATCH_SIZE, pictures.length))
|
|
37
|
-
}, PICTURE_RENDER_BATCH_DELAY_MS)
|
|
38
|
-
|
|
39
|
-
return () => window.clearTimeout(timer)
|
|
40
|
-
}, [view, pictures.length, visibleCount])
|
|
41
|
-
|
|
42
23
|
return (
|
|
43
24
|
<section className={`pictures-library ${view === 'pictures' ? 'is-visible' : ''}`} aria-hidden={view !== 'pictures'}>
|
|
44
25
|
<header className="pictures-header">
|
|
@@ -61,14 +42,27 @@ export default function PicturesLibrary({ view, pictures, onSetView, onRefreshPi
|
|
|
61
42
|
<span>Images appear here after a message with an attachment is sent successfully.</span>
|
|
62
43
|
</div>
|
|
63
44
|
) : (
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
<
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
45
|
+
<>
|
|
46
|
+
<div className="pictures-grid">
|
|
47
|
+
{visiblePictures.map((picture, index) => (
|
|
48
|
+
<article className="picture-card" key={picture.id}>
|
|
49
|
+
<img src={convertFileSrc(picture.thumbnailPath || picture.thumbnailUrl || picture.path)} alt={picture.message || picture.filename} loading={index < 6 ? 'eager' : 'lazy'} decoding="async" />
|
|
50
|
+
<div className="picture-card-meta"><span>{picture.message || picture.filename}</span></div>
|
|
51
|
+
</article>
|
|
52
|
+
))}
|
|
53
|
+
</div>
|
|
54
|
+
{visibleCount < pictures.length && (
|
|
55
|
+
<div className="pictures-load-more-container">
|
|
56
|
+
<button
|
|
57
|
+
type="button"
|
|
58
|
+
className="pictures-load-more-btn"
|
|
59
|
+
onClick={() => setVisibleCount((prev) => prev + 24)}
|
|
60
|
+
>
|
|
61
|
+
Load More ({pictures.length - visibleCount} remaining)
|
|
62
|
+
</button>
|
|
63
|
+
</div>
|
|
64
|
+
)}
|
|
65
|
+
</>
|
|
72
66
|
)}
|
|
73
67
|
</section>
|
|
74
68
|
)
|