@pheem49/mint 1.8.2 → 1.10.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 +55 -3
- package/Cargo.toml +2 -1
- package/Release_Note.md +297 -107
- package/bin/mint +0 -0
- package/crates/mint-cli/Cargo.toml +1 -0
- package/crates/mint-cli/src/actions.rs +233 -0
- package/crates/mint-cli/src/agent.rs +382 -127
- package/crates/mint-cli/src/gmail.rs +22 -2
- package/crates/mint-cli/src/image.rs +8 -8
- package/crates/mint-cli/src/interactive.rs +2888 -0
- package/crates/mint-cli/src/main.rs +391 -2506
- package/crates/mint-cli/src/markdown.rs +294 -0
- package/crates/mint-cli/src/onboard.rs +152 -109
- package/crates/mint-cli/src/setup.rs +143 -143
- package/crates/mint-cli/src/updater.rs +48 -6
- package/crates/mint-core/Cargo.toml +1 -0
- package/crates/mint-core/src/agent_loop.rs +1 -0
- package/crates/mint-core/src/api_server.rs +431 -65
- package/crates/mint-core/src/browser.rs +630 -102
- package/crates/mint-core/src/channels.rs +105 -6
- package/crates/mint-core/src/chat.rs +174 -11
- package/crates/mint-core/src/code_tools.rs +47 -31
- package/crates/mint-core/src/config.rs +302 -17
- package/crates/mint-core/src/image_gen.rs +299 -38
- package/crates/mint-core/src/lib.rs +10 -7
- package/crates/mint-core/src/mcp.rs +119 -6
- package/crates/mint-core/src/memory.rs +6 -1
- package/crates/mint-core/src/orchestration.rs +237 -96
- package/crates/mint-core/src/pictures.rs +67 -5
- 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 +128 -25
- package/crates/mint-core/src/video_gen.rs +235 -0
- package/package.json +8 -2
- package/shared-modules/linux-audio/fluidsynth2-static.json +9 -3
- package/shared-modules/linux-audio/fluidsynth2.json +8 -2
- package/shared-modules/linux-audio/lilv.json +26 -19
- package/shared-modules/linux-audio/lv2.json +0 -1
- package/shared-modules/luajit/luajit.json +2 -2
- package/skills-lock.json +41 -0
- package/src/renderer/index-web.html +1 -1
- package/src/renderer/index.html +1 -1
- package/src/renderer/shared/components/AgentActivityTable.tsx +25 -6
- package/src/renderer/shared/constants/slashCommands.ts +27 -0
- package/src/renderer/shared/platform.ts +3 -0
- package/src/renderer/shared/types.ts +4 -0
- package/src/renderer/shared/utils/approval.tsx +86 -7
- package/src/renderer/shared/utils/fileIcons.ts +135 -0
- package/src/renderer/shared/utils/markdown.tsx +217 -88
- package/src/renderer/shared/utils/slashCommandProcessor.ts +239 -0
- package/src/renderer/src/components/ChatPanel.tsx +486 -69
- package/src/renderer/src/components/DashboardSidebar.tsx +11 -2
- package/src/renderer/src/components/ImageStudioPanel.tsx +87 -4
- package/src/renderer/src/components/MintDashboard.tsx +195 -7
- package/src/renderer/src/components/PicturesLibrary.tsx +156 -15
- package/src/renderer/src/components/Settings/AgentsTab.tsx +21 -2
- package/src/renderer/src/components/Settings/AutomationTab.tsx +316 -18
- package/src/renderer/src/components/Settings/GeneralTab.tsx +795 -413
- package/src/renderer/src/components/Settings/PluginsTab.tsx +304 -70
- package/src/renderer/src/components/Settings/ThemeTab.tsx +6 -1
- package/src/renderer/src/components/SettingsWindow.tsx +106 -3
- package/src/renderer/src/components/VeoStudioPanel.tsx +549 -0
- package/src/renderer/src/components/WorkspacePanel.tsx +7 -125
- package/src/renderer/src/css/image-studio.css +106 -0
- package/src/renderer/src/css/settings.css +158 -0
- package/src/renderer/src/css/styles.css +368 -1
- package/src/renderer/src/css/veo-studio.css +626 -0
- package/src/renderer/src/index.css +1 -0
- package/src/renderer/src/tauri.ts +144 -17
- package/src/renderer/src-web/components/ChatPanel.tsx +385 -93
- package/src/renderer/src-web/components/DashboardSidebar.tsx +16 -1
- package/src/renderer/src-web/components/ImageStudioPanel.tsx +87 -4
- package/src/renderer/src-web/components/MintDashboard.tsx +156 -5
- package/src/renderer/src-web/components/PicturesLibrary.tsx +155 -15
- package/src/renderer/src-web/components/Settings/AgentsTab.tsx +21 -2
- package/src/renderer/src-web/components/Settings/AutomationTab.tsx +316 -18
- package/src/renderer/src-web/components/Settings/GeneralTab.tsx +795 -411
- package/src/renderer/src-web/components/Settings/PluginsTab.tsx +304 -70
- package/src/renderer/src-web/components/Settings/ThemeTab.tsx +6 -1
- package/src/renderer/src-web/components/SettingsWindow.tsx +110 -3
- package/src/renderer/src-web/components/VeoStudioPanel.tsx +549 -0
- package/src/renderer/src-web/css/image-studio.css +106 -0
- package/src/renderer/src-web/css/settings.css +158 -0
- package/src/renderer/src-web/css/styles.css +369 -1
- package/src/renderer/src-web/css/veo-studio.css +650 -0
- package/src/renderer/src-web/index.css +1 -0
- package/src/renderer/src-web/tauri.ts +135 -16
- package/src-tauri/src/desktop.rs +18 -16
- package/src-tauri/src/discord_rpc.rs +1 -1
- package/src-tauri/src/lib.rs +155 -25
- package/src-tauri/src/webhooks.rs +45 -31
- package/src-tauri/src/workflows.rs +1 -0
- package/src-tauri/tauri.conf.json +1 -1
- package/temp_gridgeist/AGENTS.md +8 -0
- package/temp_gridgeist/CHANGELOG.md +130 -0
- package/temp_gridgeist/LICENSE +21 -0
- package/temp_gridgeist/README.md +323 -0
- package/temp_gridgeist/README.th.md +325 -0
- package/temp_gridgeist/skills/gridgeist/SKILL.md +88 -0
- package/temp_gridgeist/skills/gridgeist/agents/openai.yaml +9 -0
- package/temp_gridgeist/skills/gridgeist/assets/gridgeist-small.svg +10 -0
- package/temp_gridgeist/skills/gridgeist/assets/gridgeist.png +0 -0
- package/temp_gridgeist/skills/gridgeist/assets/gridgeist.svg +18 -0
- package/temp_gridgeist/skills/gridgeist/references/design-language.md +88 -0
- package/temp_gridgeist/skills/gridgeist/references/review-checklist.md +128 -0
- package/temp_gridgeist/skills/gridgeist/references/system-contract.md +109 -0
|
@@ -57,6 +57,40 @@ export async function getRuntimeStatus(): Promise<RuntimeStatus> {
|
|
|
57
57
|
return invoke<RuntimeStatus>('get_runtime_status')
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
export async function setActiveModel(provider: string, model?: string): Promise<string> {
|
|
61
|
+
if (typeof window === 'undefined' || !isTauriRuntime()) {
|
|
62
|
+
const API_BASE = getApiBase()
|
|
63
|
+
try {
|
|
64
|
+
const res = await fetch(`${API_BASE}/active-model`, {
|
|
65
|
+
method: 'POST',
|
|
66
|
+
headers: { 'Content-Type': 'application/json' },
|
|
67
|
+
body: JSON.stringify({ provider, model }),
|
|
68
|
+
})
|
|
69
|
+
const data = await res.json()
|
|
70
|
+
return data.displayName || `Changed model to ${provider}`
|
|
71
|
+
} catch (e) {
|
|
72
|
+
console.error('Failed to set active model via API:', e)
|
|
73
|
+
return `Changed model to ${provider}`
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const { invoke } = await import('@tauri-apps/api/core')
|
|
77
|
+
return invoke<string>('set_active_model', { provider, model })
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export async function uploadFile(file: File): Promise<string> {
|
|
81
|
+
const API_BASE = getApiBase();
|
|
82
|
+
const res = await fetch(`${API_BASE}/uploads?filename=${encodeURIComponent(file.name)}`, {
|
|
83
|
+
method: 'POST',
|
|
84
|
+
body: file,
|
|
85
|
+
});
|
|
86
|
+
if (!res.ok) {
|
|
87
|
+
const data = await res.json().catch(() => null);
|
|
88
|
+
throw new Error(data?.error || `HTTP ${res.status}`);
|
|
89
|
+
}
|
|
90
|
+
const data = await res.json();
|
|
91
|
+
return data.url;
|
|
92
|
+
}
|
|
93
|
+
|
|
60
94
|
export interface DetectedTools {
|
|
61
95
|
docker: boolean
|
|
62
96
|
git: boolean
|
|
@@ -83,19 +117,20 @@ export async function sendChatMessage(
|
|
|
83
117
|
message: string,
|
|
84
118
|
imageDataUri?: string | null,
|
|
85
119
|
audioDataUri?: string | null,
|
|
120
|
+
videoDataUri?: string | null,
|
|
86
121
|
documentAttachment?: DocumentAttachment | null,
|
|
87
122
|
workspacePath?: string | null,
|
|
88
123
|
chatId?: string | null,
|
|
89
124
|
agentId?: string | null,
|
|
90
125
|
): Promise<ChatResponse> {
|
|
91
|
-
const outgoingMessage = withImagePlaceholder(message, imageDataUri)
|
|
126
|
+
const outgoingMessage = withImagePlaceholder(message, imageDataUri, videoDataUri)
|
|
92
127
|
if (typeof window === 'undefined' || !isTauriRuntime()) {
|
|
93
128
|
const API_BASE = getApiBase();
|
|
94
129
|
try {
|
|
95
130
|
const res = await fetch(`${API_BASE}/chat`, {
|
|
96
131
|
method: 'POST',
|
|
97
132
|
headers: { 'Content-Type': 'application/json' },
|
|
98
|
-
body: JSON.stringify({ message: outgoingMessage, systemInstruction: '', chatId, imageDataUri, audioDataUri, documentAttachment, agentId })
|
|
133
|
+
body: JSON.stringify({ message: outgoingMessage, systemInstruction: '', chatId, imageDataUri, audioDataUri, videoDataUri, documentAttachment, agentId })
|
|
99
134
|
});
|
|
100
135
|
const data = await res.json().catch(() => null);
|
|
101
136
|
if (!res.ok) {
|
|
@@ -120,7 +155,7 @@ export async function sendChatMessage(
|
|
|
120
155
|
}
|
|
121
156
|
const { invoke } = await import('@tauri-apps/api/core')
|
|
122
157
|
const response = await invoke<ChatResponse>('send_chat_message', {
|
|
123
|
-
request: { message: outgoingMessage, systemInstruction: '', chatId, imageDataUri, audioDataUri, documentAttachment, workspacePath, agentId },
|
|
158
|
+
request: { message: outgoingMessage, systemInstruction: '', chatId, imageDataUri, audioDataUri, videoDataUri, documentAttachment, workspacePath, agentId },
|
|
124
159
|
})
|
|
125
160
|
if (imageDataUri) {
|
|
126
161
|
await invoke('save_pictures', {
|
|
@@ -129,6 +164,13 @@ export async function sendChatMessage(
|
|
|
129
164
|
message: outgoingMessage,
|
|
130
165
|
})
|
|
131
166
|
}
|
|
167
|
+
if (videoDataUri) {
|
|
168
|
+
await invoke('save_pictures', {
|
|
169
|
+
images: videoDataUri.split(' '),
|
|
170
|
+
source: 'chat',
|
|
171
|
+
message: outgoingMessage,
|
|
172
|
+
})
|
|
173
|
+
}
|
|
132
174
|
return response
|
|
133
175
|
}
|
|
134
176
|
|
|
@@ -137,6 +179,7 @@ export async function streamChatMessage(
|
|
|
137
179
|
onChunk: (chunk: string) => void,
|
|
138
180
|
imageDataUri?: string | null,
|
|
139
181
|
audioDataUri?: string | null,
|
|
182
|
+
videoDataUri?: string | null,
|
|
140
183
|
systemInstruction = '',
|
|
141
184
|
onProgress?: (progress: AgentProgress) => void,
|
|
142
185
|
documentAttachment?: DocumentAttachment | null,
|
|
@@ -146,11 +189,11 @@ export async function streamChatMessage(
|
|
|
146
189
|
): Promise<ChatResponse> {
|
|
147
190
|
if (typeof window === 'undefined' || !isTauriRuntime()) {
|
|
148
191
|
const API_BASE = getApiBase();
|
|
149
|
-
const outgoingMessage = withImagePlaceholder(message, imageDataUri);
|
|
192
|
+
const outgoingMessage = withImagePlaceholder(message, imageDataUri, videoDataUri);
|
|
150
193
|
const res = await fetch(`${API_BASE}/chat-stream`, {
|
|
151
194
|
method: 'POST',
|
|
152
195
|
headers: { 'Content-Type': 'application/json' },
|
|
153
|
-
body: JSON.stringify({ message: outgoingMessage, systemInstruction, chatId, imageDataUri, audioDataUri, documentAttachment, agentId })
|
|
196
|
+
body: JSON.stringify({ message: outgoingMessage, systemInstruction, chatId, imageDataUri, audioDataUri, videoDataUri, documentAttachment, agentId })
|
|
154
197
|
});
|
|
155
198
|
if (!res.ok) {
|
|
156
199
|
const data = await res.json().catch(() => null);
|
|
@@ -189,14 +232,14 @@ export async function streamChatMessage(
|
|
|
189
232
|
throw new Error("Stream closed without a final response");
|
|
190
233
|
}
|
|
191
234
|
const { invoke, Channel } = await import('@tauri-apps/api/core')
|
|
192
|
-
const outgoingMessage = withImagePlaceholder(message, imageDataUri)
|
|
235
|
+
const outgoingMessage = withImagePlaceholder(message, imageDataUri, videoDataUri)
|
|
193
236
|
const onEvent = new Channel<DesktopStreamEvent>()
|
|
194
237
|
onEvent.onmessage = (event) => {
|
|
195
238
|
if (event.type === 'chunk') onChunk(event.chunk)
|
|
196
239
|
else onProgress?.(event.progress)
|
|
197
240
|
}
|
|
198
241
|
const response = await invoke<ChatResponse>('stream_chat_message', {
|
|
199
|
-
request: { message: outgoingMessage, systemInstruction, chatId, imageDataUri, audioDataUri, documentAttachment, workspacePath, agentId },
|
|
242
|
+
request: { message: outgoingMessage, systemInstruction, chatId, imageDataUri, audioDataUri, videoDataUri, documentAttachment, workspacePath, agentId },
|
|
200
243
|
onEvent,
|
|
201
244
|
})
|
|
202
245
|
if (imageDataUri) {
|
|
@@ -206,14 +249,29 @@ export async function streamChatMessage(
|
|
|
206
249
|
message: outgoingMessage,
|
|
207
250
|
})
|
|
208
251
|
}
|
|
252
|
+
if (videoDataUri) {
|
|
253
|
+
await invoke('save_pictures', {
|
|
254
|
+
images: videoDataUri.split(' '),
|
|
255
|
+
source: 'chat',
|
|
256
|
+
message: outgoingMessage,
|
|
257
|
+
})
|
|
258
|
+
}
|
|
209
259
|
return response
|
|
210
260
|
}
|
|
211
261
|
|
|
212
|
-
function withImagePlaceholder(message: string, imageDataUri?: string | null) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
262
|
+
function withImagePlaceholder(message: string, imageDataUri?: string | null, videoDataUri?: string | null) {
|
|
263
|
+
let finalMessage = message
|
|
264
|
+
if (imageDataUri && !finalMessage.includes('[Image #1]')) {
|
|
265
|
+
const imageCount = imageDataUri.split(/\s+/).filter(Boolean).length
|
|
266
|
+
const markers = Array.from({ length: imageCount }, (_, index) => `[Image #${index + 1}]`).join(' ')
|
|
267
|
+
if (markers) finalMessage = `${finalMessage} ${markers}`
|
|
268
|
+
}
|
|
269
|
+
if (videoDataUri && !finalMessage.includes('[Video #1]')) {
|
|
270
|
+
const videoCount = videoDataUri.split(/\s+/).filter(Boolean).length
|
|
271
|
+
const markers = Array.from({ length: videoCount }, (_, index) => `[Video #${index + 1}]`).join(' ')
|
|
272
|
+
if (markers) finalMessage = `${finalMessage} ${markers}`
|
|
273
|
+
}
|
|
274
|
+
return finalMessage
|
|
217
275
|
}
|
|
218
276
|
|
|
219
277
|
export async function getTtsUrls(text: string): Promise<TtsUrl[]> {
|
|
@@ -257,6 +315,7 @@ export async function getRecentInteractions(limit = 50, chatId?: string | null):
|
|
|
257
315
|
export async function saveSystemInteraction(
|
|
258
316
|
chatId: string,
|
|
259
317
|
userText: string,
|
|
318
|
+
aiText: string,
|
|
260
319
|
provider: string,
|
|
261
320
|
model: string,
|
|
262
321
|
): Promise<any> {
|
|
@@ -266,7 +325,7 @@ export async function saveSystemInteraction(
|
|
|
266
325
|
const res = await fetch(`${API_BASE}/interactions`, {
|
|
267
326
|
method: 'POST',
|
|
268
327
|
headers: { 'Content-Type': 'application/json' },
|
|
269
|
-
body: JSON.stringify({ chatId, userText, provider, model }),
|
|
328
|
+
body: JSON.stringify({ chatId, userText, aiText, provider, model }),
|
|
270
329
|
});
|
|
271
330
|
return await res.json();
|
|
272
331
|
} catch (e) {
|
|
@@ -275,7 +334,7 @@ export async function saveSystemInteraction(
|
|
|
275
334
|
}
|
|
276
335
|
}
|
|
277
336
|
const { invoke } = await import('@tauri-apps/api/core')
|
|
278
|
-
return invoke('save_system_interaction', { chatId, userText, provider, model })
|
|
337
|
+
return invoke('save_system_interaction', { chatId, userText, aiText, provider, model })
|
|
279
338
|
}
|
|
280
339
|
|
|
281
340
|
export async function saveInteractionAgentActivity(
|
|
@@ -972,7 +1031,7 @@ export function installTauriAdapters() {
|
|
|
972
1031
|
}
|
|
973
1032
|
|
|
974
1033
|
window.api = {
|
|
975
|
-
sendMessage: (message, imageDataUri, audioDataUri, documentAttachment) => sendChatMessage(message, imageDataUri, audioDataUri, documentAttachment),
|
|
1034
|
+
sendMessage: (message, imageDataUri, audioDataUri, documentAttachment) => sendChatMessage(message, imageDataUri, audioDataUri, undefined, documentAttachment),
|
|
976
1035
|
closeWindow: async () => {
|
|
977
1036
|
const { invoke } = await import('@tauri-apps/api/core')
|
|
978
1037
|
const { getCurrentWindow } = await import('@tauri-apps/api/window')
|
|
@@ -1119,13 +1178,18 @@ async function captureSharedScreen(): Promise<string> {
|
|
|
1119
1178
|
export async function listLearnedSkills(workspacePath?: string): Promise<LearnedSkill[]> {
|
|
1120
1179
|
if (typeof window === 'undefined' || !isTauriRuntime()) {
|
|
1121
1180
|
try {
|
|
1181
|
+
const API_BASE = getLocalApiBase()
|
|
1182
|
+
const res = await fetch(`${API_BASE}/learned-skills`)
|
|
1183
|
+
if (res.ok) {
|
|
1184
|
+
return await res.json()
|
|
1185
|
+
}
|
|
1122
1186
|
const val = await getProfileValue('learned-skills-web-mock')
|
|
1123
1187
|
if (val) {
|
|
1124
1188
|
return JSON.parse(val)
|
|
1125
1189
|
}
|
|
1126
1190
|
return []
|
|
1127
1191
|
} catch (e) {
|
|
1128
|
-
console.error("Failed to load web
|
|
1192
|
+
console.error("Failed to load web skills:", e)
|
|
1129
1193
|
return []
|
|
1130
1194
|
}
|
|
1131
1195
|
}
|
|
@@ -1230,6 +1294,61 @@ export async function readClipboardImage(): Promise<string | null> {
|
|
|
1230
1294
|
}
|
|
1231
1295
|
}
|
|
1232
1296
|
|
|
1297
|
+
// ─── Veo Studio — Video Generation (stub; real Tauri command in follow-up) ───
|
|
1298
|
+
|
|
1299
|
+
export interface VideoGenRequest {
|
|
1300
|
+
prompt: string
|
|
1301
|
+
negativePrompt?: string
|
|
1302
|
+
aspectRatio: '16:9' | '9:16' | '1:1'
|
|
1303
|
+
duration: 5 | 8
|
|
1304
|
+
model?: string
|
|
1305
|
+
provider: string
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
export interface VideoGenEntry {
|
|
1309
|
+
id: string
|
|
1310
|
+
url: string
|
|
1311
|
+
path: string
|
|
1312
|
+
message?: string
|
|
1313
|
+
createdAt?: string
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
export interface VideoGenResponse {
|
|
1317
|
+
videos: VideoGenEntry[]
|
|
1318
|
+
provider: string
|
|
1319
|
+
model: string
|
|
1320
|
+
description?: string
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
export interface VideoGenProviders {
|
|
1324
|
+
active: string
|
|
1325
|
+
available: string[]
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
/**
|
|
1329
|
+
* Generate a video using the configured provider.
|
|
1330
|
+
* NOTE: This is a frontend stub — the real Tauri backend command will be
|
|
1331
|
+
* added in a follow-up PR once the Veo REST API integration is ready.
|
|
1332
|
+
*/
|
|
1333
|
+
export async function generateVideo(request: VideoGenRequest): Promise<VideoGenResponse> {
|
|
1334
|
+
const apiBase = getLocalApiBase()
|
|
1335
|
+
const response = await fetch(`${apiBase}/video-generate`, {
|
|
1336
|
+
method: 'POST',
|
|
1337
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1338
|
+
body: JSON.stringify(request)
|
|
1339
|
+
})
|
|
1340
|
+
if (!response.ok) {
|
|
1341
|
+
const errorData = await response.json().catch(() => ({}))
|
|
1342
|
+
throw new Error(errorData.error || `HTTP ${response.status} from API`)
|
|
1343
|
+
}
|
|
1344
|
+
return response.json()
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
export async function getVideoGenProviders(): Promise<VideoGenProviders> {
|
|
1348
|
+
return { active: 'veo', available: ['veo'] }
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
|
|
1233
1352
|
// Enforce compile-time check against the shared platform interface
|
|
1234
1353
|
const _apiCheck: MintPlatformApi = {
|
|
1235
1354
|
getRuntimeStatus,
|
package/src-tauri/src/desktop.rs
CHANGED
|
@@ -201,28 +201,30 @@ pub fn capture_screen() -> Result<String, String> {
|
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
pub fn read_clipboard_image() -> Result<String, String> {
|
|
204
|
-
let output = Command::new("wl-paste").args(
|
|
204
|
+
let output = Command::new("wl-paste").args(["-t", "image/png"]).output();
|
|
205
205
|
|
|
206
|
-
if let Ok(out) = output
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
206
|
+
if let Ok(out) = output
|
|
207
|
+
&& out.status.success()
|
|
208
|
+
&& !out.stdout.is_empty()
|
|
209
|
+
{
|
|
210
|
+
return Ok(format!(
|
|
211
|
+
"data:image/png;base64,{}",
|
|
212
|
+
STANDARD.encode(&out.stdout)
|
|
213
|
+
));
|
|
213
214
|
}
|
|
214
215
|
|
|
215
216
|
let output = Command::new("xclip")
|
|
216
|
-
.args(
|
|
217
|
+
.args(["-selection", "clipboard", "-t", "image/png", "-o"])
|
|
217
218
|
.output();
|
|
218
219
|
|
|
219
|
-
if let Ok(out) = output
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
220
|
+
if let Ok(out) = output
|
|
221
|
+
&& out.status.success()
|
|
222
|
+
&& !out.stdout.is_empty()
|
|
223
|
+
{
|
|
224
|
+
return Ok(format!(
|
|
225
|
+
"data:image/png;base64,{}",
|
|
226
|
+
STANDARD.encode(&out.stdout)
|
|
227
|
+
));
|
|
226
228
|
}
|
|
227
229
|
|
|
228
230
|
Err("No image found in clipboard".into())
|
|
@@ -14,7 +14,7 @@ pub fn set_activity(config: &MintConfig, instruction: &str) -> Result<String, St
|
|
|
14
14
|
.filter(|value| !value.trim().is_empty())
|
|
15
15
|
.ok_or("missing config value 'discordApplicationId'")?;
|
|
16
16
|
let input: Value = serde_json::from_str(instruction).unwrap_or_else(|_| {
|
|
17
|
-
json!({ "details": instruction.trim().is_empty()
|
|
17
|
+
json!({ "details": if instruction.trim().is_empty() { "Using Mint Assistant" } else { instruction } })
|
|
18
18
|
});
|
|
19
19
|
let activity = json!({
|
|
20
20
|
"details": input["details"].as_str().unwrap_or("Using Mint Assistant"),
|