@pheem49/mint 1.6.3 → 1.7.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 +82 -21
- package/assets/Mint_CLI.png +0 -0
- package/assets/Mint_Desktop.png +0 -0
- package/assets/Mint_Web.png +0 -0
- package/assets/Mint_WorkSpace.png +0 -0
- package/assets/Setting.png +0 -0
- package/assets/bridges.svg +4 -0
- package/assets/chat.svg +3 -0
- package/assets/code.svg +4 -0
- package/assets/features.svg +3 -0
- package/assets/imagegen.svg +5 -0
- package/assets/live2d.svg +6 -0
- package/assets/memory.svg +5 -0
- package/assets/screencapture.svg +4 -0
- package/assets/setup.svg +3 -0
- package/assets/tools.svg +4 -0
- package/bin/mint +0 -0
- package/crates/mint-cli/src/agent.rs +47 -15
- package/crates/mint-cli/src/main.rs +534 -7
- package/crates/mint-cli/src/onboard.rs +134 -1
- package/crates/mint-cli/src/setup.rs +173 -32
- package/crates/mint-core/src/api_server.rs +147 -3
- package/crates/mint-core/src/config.rs +22 -3
- package/crates/mint-core/src/image_gen.rs +895 -0
- package/crates/mint-core/src/lib.rs +4 -0
- package/crates/mint-core/src/memory.rs +27 -1
- package/crates/mint-core/src/orchestration.rs +1 -1
- package/crates/mint-core/src/plugins.rs +32 -0
- package/crates/mint-core/tests/memory_persistence.rs +28 -0
- package/package.json +1 -1
- package/src/bin/index.js +0 -0
- package/src/renderer/src/agentProgress.ts +39 -0
- package/src/renderer/src/components/ChatPanel.tsx +547 -47
- package/src/renderer/src/components/DashboardSidebar.tsx +12 -4
- package/src/renderer/src/components/ImageStudioPanel.tsx +638 -0
- package/src/renderer/src/components/MintDashboard.tsx +84 -31
- package/src/renderer/src/components/ModelPanel.tsx +2 -2
- package/src/renderer/src/components/PicturesLibrary.tsx +5 -1
- package/src/renderer/src/components/SettingsWindow.tsx +29 -20
- package/src/renderer/src/components/SpotlightWindow.tsx +8 -8
- package/src/renderer/src/components/WorkspacePanel.tsx +1 -1
- package/src/renderer/src/css/image-studio.css +722 -0
- package/src/renderer/src/css/settings.css +13 -3
- package/src/renderer/src/css/styles.css +245 -43
- package/src/renderer/src/index.css +152 -0
- package/src/renderer/src/tauri.ts +148 -0
- package/src/renderer/src-web/App.tsx +16 -1
- package/src/renderer/src-web/agentProgress.ts +39 -0
- package/src/renderer/src-web/components/ChatPanel.tsx +568 -46
- package/src/renderer/src-web/components/DashboardSidebar.tsx +10 -2
- package/src/renderer/src-web/components/ImageStudioPanel.tsx +638 -0
- package/src/renderer/src-web/components/MintDashboard.tsx +65 -19
- package/src/renderer/src-web/components/PicturesLibrary.tsx +5 -1
- package/src/renderer/src-web/components/SettingsWindow.tsx +29 -20
- package/src/renderer/src-web/css/image-studio.css +722 -0
- package/src/renderer/src-web/css/settings.css +14 -4
- package/src/renderer/src-web/css/styles.css +292 -44
- package/src/renderer/src-web/index.css +152 -0
- package/src/renderer/src-web/tauri.ts +149 -0
- package/src-tauri/src/lib.rs +65 -5
- package/src-tauri/tauri.conf.json +1 -1
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
@import './css/settings.css';
|
|
3
3
|
@import './css/spotlight.css';
|
|
4
4
|
@import './css/widget.css';
|
|
5
|
+
@import './css/image-studio.css';
|
|
5
6
|
|
|
6
7
|
* {
|
|
7
8
|
box-sizing: border-box;
|
|
@@ -377,3 +378,154 @@ button {
|
|
|
377
378
|
text-align: center;
|
|
378
379
|
}
|
|
379
380
|
}
|
|
381
|
+
|
|
382
|
+
/* Premium Markdown Styles for Chat Messages */
|
|
383
|
+
.chat-inline-code {
|
|
384
|
+
background: rgba(16, 185, 129, 0.15);
|
|
385
|
+
border: 1px solid rgba(16, 185, 129, 0.25);
|
|
386
|
+
color: #34d399;
|
|
387
|
+
padding: 2px 6px;
|
|
388
|
+
border-radius: 6px;
|
|
389
|
+
font-family: 'Fira Code', 'Courier New', Courier, monospace;
|
|
390
|
+
font-size: 0.88em;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.chat-code-block-container {
|
|
394
|
+
display: flex;
|
|
395
|
+
flex-direction: column;
|
|
396
|
+
background: var(--input-bg, #0f172a);
|
|
397
|
+
border: 1px solid var(--border);
|
|
398
|
+
border-radius: 8px;
|
|
399
|
+
margin: 12px 0;
|
|
400
|
+
overflow: hidden;
|
|
401
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
.chat-code-block-header {
|
|
405
|
+
display: flex;
|
|
406
|
+
align-items: center;
|
|
407
|
+
justify-content: space-between;
|
|
408
|
+
background: var(--surface-bg, #1e293b);
|
|
409
|
+
padding: 8px 14px;
|
|
410
|
+
border-bottom: 1px solid var(--border);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
.chat-code-block-lang {
|
|
414
|
+
color: var(--accent);
|
|
415
|
+
font-size: 0.78rem;
|
|
416
|
+
font-weight: 650;
|
|
417
|
+
text-transform: capitalize;
|
|
418
|
+
font-family: ui-sans-serif, system-ui, sans-serif;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
.chat-code-block-actions {
|
|
422
|
+
display: flex;
|
|
423
|
+
gap: 10px;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.chat-code-action-btn {
|
|
427
|
+
background: transparent;
|
|
428
|
+
border: none;
|
|
429
|
+
color: var(--text-soft, #94a3b8);
|
|
430
|
+
cursor: pointer;
|
|
431
|
+
padding: 4px;
|
|
432
|
+
border-radius: 4px;
|
|
433
|
+
display: flex;
|
|
434
|
+
align-items: center;
|
|
435
|
+
justify-content: center;
|
|
436
|
+
transition: all 0.2s ease;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
.chat-code-action-btn:hover {
|
|
440
|
+
background: rgba(255, 255, 255, 0.05);
|
|
441
|
+
color: var(--accent-hover, #34d399);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.chat-code-block-body {
|
|
445
|
+
margin: 0;
|
|
446
|
+
padding: 14px;
|
|
447
|
+
overflow-x: auto;
|
|
448
|
+
background: var(--input-bg, #0f172a);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.chat-code-block-body code {
|
|
452
|
+
font-family: 'Fira Code', 'Courier New', Courier, monospace;
|
|
453
|
+
font-size: 0.88rem;
|
|
454
|
+
color: var(--text-main, #e2e8f0);
|
|
455
|
+
line-height: 1.5;
|
|
456
|
+
white-space: pre;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
.chat-ordered-list,
|
|
460
|
+
.chat-unordered-list {
|
|
461
|
+
margin: 8px 0;
|
|
462
|
+
padding-left: 24px;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
.chat-ordered-list {
|
|
466
|
+
list-style-type: decimal;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
.chat-unordered-list {
|
|
470
|
+
list-style-type: disc;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
.chat-bold-highlight {
|
|
474
|
+
color: var(--accent) !important;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
.chat-inline-code {
|
|
478
|
+
background: color-mix(in srgb, var(--accent) 12%, transparent);
|
|
479
|
+
border: 1px solid color-mix(in srgb, var(--accent) 24%, transparent);
|
|
480
|
+
color: var(--accent);
|
|
481
|
+
padding: 2px 6px;
|
|
482
|
+
border-radius: 4px;
|
|
483
|
+
font-family: 'Fira Code', 'Courier New', Courier, monospace;
|
|
484
|
+
font-size: 0.9em;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/* Premium Table Styles for Chat Panel */
|
|
488
|
+
.chat-table-container {
|
|
489
|
+
overflow-x: auto;
|
|
490
|
+
margin: 14px 0;
|
|
491
|
+
width: 100%;
|
|
492
|
+
border-radius: 8px;
|
|
493
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
494
|
+
background: rgba(30, 41, 59, 0.35);
|
|
495
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
.chat-table {
|
|
499
|
+
width: 100%;
|
|
500
|
+
border-collapse: collapse;
|
|
501
|
+
font-size: 0.86rem;
|
|
502
|
+
text-align: left;
|
|
503
|
+
line-height: 1.5;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
.chat-table th {
|
|
507
|
+
padding: 12px 16px;
|
|
508
|
+
font-weight: 700;
|
|
509
|
+
color: var(--accent);
|
|
510
|
+
background: rgba(255, 255, 255, 0.04);
|
|
511
|
+
border-bottom: 2px solid rgba(255, 255, 255, 0.15);
|
|
512
|
+
font-family: ui-sans-serif, system-ui, sans-serif;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
.chat-table td {
|
|
516
|
+
padding: 12px 16px;
|
|
517
|
+
color: var(--text-main, #e2e8f0);
|
|
518
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
.chat-table tbody tr {
|
|
522
|
+
transition: background 0.15s ease;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
.chat-table tbody tr:hover {
|
|
526
|
+
background: rgba(255, 255, 255, 0.03);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
.chat-table tbody tr:last-child td {
|
|
530
|
+
border-bottom: none;
|
|
531
|
+
}
|
|
@@ -43,6 +43,7 @@ export interface InteractionMemory {
|
|
|
43
43
|
model: string
|
|
44
44
|
fallbackProvider?: string | null
|
|
45
45
|
createdAt: string
|
|
46
|
+
agentActivity?: AgentProgress[] | null
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
export interface ChatSession {
|
|
@@ -66,6 +67,30 @@ export interface PictureEntry {
|
|
|
66
67
|
thumbnailUrl?: string
|
|
67
68
|
}
|
|
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
|
+
|
|
69
94
|
export interface CodeEdit {
|
|
70
95
|
path: string
|
|
71
96
|
content: string
|
|
@@ -268,6 +293,30 @@ export async function getRecentInteractions(limit = 50, chatId?: string | null):
|
|
|
268
293
|
return invoke<InteractionMemory[]>('get_recent_interactions', { limit, chatId })
|
|
269
294
|
}
|
|
270
295
|
|
|
296
|
+
export async function saveInteractionAgentActivity(
|
|
297
|
+
interactionId: number,
|
|
298
|
+
activity: AgentProgress[],
|
|
299
|
+
): Promise<void> {
|
|
300
|
+
if (typeof window === 'undefined' || !isTauriRuntime()) {
|
|
301
|
+
const API_BASE = getApiBase();
|
|
302
|
+
try {
|
|
303
|
+
const res = await fetch(`${API_BASE}/interactions/agent-activity`, {
|
|
304
|
+
method: 'POST',
|
|
305
|
+
headers: { 'Content-Type': 'application/json' },
|
|
306
|
+
body: JSON.stringify({ interactionId, activity }),
|
|
307
|
+
});
|
|
308
|
+
if (!res.ok) {
|
|
309
|
+
throw new Error(`HTTP ${res.status}`);
|
|
310
|
+
}
|
|
311
|
+
} catch (error) {
|
|
312
|
+
console.error('Failed to persist agent activity:', error);
|
|
313
|
+
}
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
const { invoke } = await import('@tauri-apps/api/core')
|
|
317
|
+
await invoke('save_interaction_agent_activity', { interactionId, activity })
|
|
318
|
+
}
|
|
319
|
+
|
|
271
320
|
export async function listChatSessions(): Promise<ChatSession[]> {
|
|
272
321
|
if (typeof window === 'undefined' || !isTauriRuntime()) {
|
|
273
322
|
const API_BASE = getApiBase();
|
|
@@ -404,6 +453,106 @@ export async function listSavedPictures(): Promise<PictureEntry[]> {
|
|
|
404
453
|
return invoke<PictureEntry[]>('list_pictures')
|
|
405
454
|
}
|
|
406
455
|
|
|
456
|
+
export async function generateImages(
|
|
457
|
+
request: ImageGenRequest
|
|
458
|
+
): Promise<ImageGenResponse> {
|
|
459
|
+
if (typeof window === 'undefined' || !isTauriRuntime()) {
|
|
460
|
+
const API_BASE = getApiBase()
|
|
461
|
+
const res = await fetch(`${API_BASE}/image-generate`, {
|
|
462
|
+
method: 'POST',
|
|
463
|
+
headers: { 'Content-Type': 'application/json' },
|
|
464
|
+
body: JSON.stringify({
|
|
465
|
+
prompt: request.prompt,
|
|
466
|
+
negativePrompt: request.negativePrompt,
|
|
467
|
+
aspectRatio: request.aspectRatio ?? '1:1',
|
|
468
|
+
numImages: request.numImages ?? 1,
|
|
469
|
+
model: request.model,
|
|
470
|
+
provider: request.provider,
|
|
471
|
+
}),
|
|
472
|
+
})
|
|
473
|
+
if (!res.ok) {
|
|
474
|
+
const err = await res.json().catch(() => null)
|
|
475
|
+
throw new Error(err?.error || `Image generation failed: HTTP ${res.status}`)
|
|
476
|
+
}
|
|
477
|
+
const data = await res.json()
|
|
478
|
+
// Normalize image URLs for web mode
|
|
479
|
+
const images: PictureEntry[] = Array.isArray(data.images)
|
|
480
|
+
? data.images.map((pic: PictureEntry) => {
|
|
481
|
+
const pictureUrl = pic.url ? `${API_BASE.replace('/api', '')}${pic.url}` : pic.url
|
|
482
|
+
return { ...pic, url: pictureUrl, thumbnailUrl: pictureUrl }
|
|
483
|
+
})
|
|
484
|
+
: []
|
|
485
|
+
return { ...data, images }
|
|
486
|
+
}
|
|
487
|
+
// Desktop / Tauri mode
|
|
488
|
+
const { invoke } = await import('@tauri-apps/api/core')
|
|
489
|
+
return invoke<ImageGenResponse>('generate_images', { request })
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/** Fetch which image-generation providers are currently configured on the backend. */
|
|
493
|
+
export async function getImageGenProviders(): Promise<ImageGenProviders> {
|
|
494
|
+
if (typeof window === 'undefined' || !isTauriRuntime()) {
|
|
495
|
+
const API_BASE = getApiBase()
|
|
496
|
+
try {
|
|
497
|
+
const res = await fetch(`${API_BASE}/image-gen/providers`)
|
|
498
|
+
if (res.ok) return await res.json()
|
|
499
|
+
} catch (_) { /* ignore */ }
|
|
500
|
+
return { active: 'nanobanana', available: ['nanobanana'] }
|
|
501
|
+
}
|
|
502
|
+
// Desktop / Tauri: read config to know which keys are set
|
|
503
|
+
try {
|
|
504
|
+
const { invoke } = await import('@tauri-apps/api/core')
|
|
505
|
+
const config = await invoke<Record<string, string>>('get_config')
|
|
506
|
+
const available: string[] = []
|
|
507
|
+
if (config.api_key) available.push('nanobanana')
|
|
508
|
+
if (config.openai_api_key) available.push('dalle')
|
|
509
|
+
if (config.stability_api_key) available.push('stability')
|
|
510
|
+
if (config.ideogram_api_key) available.push('ideogram')
|
|
511
|
+
if (config.replicate_api_key) available.push('replicate')
|
|
512
|
+
if (available.length === 0) available.push('nanobanana')
|
|
513
|
+
const active = available.includes(config.image_gen_provider)
|
|
514
|
+
? config.image_gen_provider
|
|
515
|
+
: available[0]
|
|
516
|
+
return { active, available }
|
|
517
|
+
} catch (_) {
|
|
518
|
+
return { active: 'nanobanana', available: ['nanobanana'] }
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/** Updates the default image generation provider in the configuration. */
|
|
523
|
+
export async function setDefaultImageProvider(provider: string): Promise<boolean> {
|
|
524
|
+
if (typeof window === 'undefined' || !isTauriRuntime()) {
|
|
525
|
+
const API_BASE = getApiBase()
|
|
526
|
+
try {
|
|
527
|
+
const getRes = await fetch(`${API_BASE}/config`)
|
|
528
|
+
if (!getRes.ok) return false
|
|
529
|
+
const config = await getRes.json()
|
|
530
|
+
config.image_gen_provider = provider
|
|
531
|
+
const saveRes = await fetch(`${API_BASE}/config`, {
|
|
532
|
+
method: 'POST',
|
|
533
|
+
headers: { 'Content-Type': 'application/json' },
|
|
534
|
+
body: JSON.stringify(config)
|
|
535
|
+
})
|
|
536
|
+
return saveRes.ok
|
|
537
|
+
} catch (_) {
|
|
538
|
+
return false
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// Desktop / Tauri
|
|
543
|
+
try {
|
|
544
|
+
const { invoke } = await import('@tauri-apps/api/core')
|
|
545
|
+
const config = await invoke<any>('get_config')
|
|
546
|
+
config.image_gen_provider = provider
|
|
547
|
+
await invoke('update_config', { config })
|
|
548
|
+
return true
|
|
549
|
+
} catch (_) {
|
|
550
|
+
return false
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
|
|
407
556
|
export async function submitToolApproval(token: string, approved: boolean): Promise<void> {
|
|
408
557
|
if (typeof window === 'undefined' || !isTauriRuntime()) {
|
|
409
558
|
return;
|
package/src-tauri/src/lib.rs
CHANGED
|
@@ -32,11 +32,12 @@ use tokio::sync::oneshot;
|
|
|
32
32
|
use integrations::{channel_inventory, list_plugins};
|
|
33
33
|
use mint_core::{
|
|
34
34
|
AgentApproval, AgentProgress, AppliedCodeEdit, ApprovalOutcome, ChatRequest, ChatResponse,
|
|
35
|
-
ChatSession, CodeEdit, CodeEditProposal, InteractionMemory, MemoryStore,
|
|
36
|
-
PictureEntry, TtsUrl, WeatherReport, apply_code_edits, classify_shell_command,
|
|
37
|
-
extract_document_text, google_tts_urls, list_saved_pictures, load_config,
|
|
38
|
-
orchestrate_agent_loop, orchestrate_chat_stream_with_fallback,
|
|
39
|
-
propose_code_edits, save_chat_images, save_config,
|
|
35
|
+
ChatSession, CodeEdit, CodeEditProposal, ImageGenRequest, InteractionMemory, MemoryStore,
|
|
36
|
+
MintConfig, PictureEntry, TtsUrl, WeatherReport, apply_code_edits, classify_shell_command,
|
|
37
|
+
config_path, extract_document_text, google_tts_urls, list_saved_pictures, load_config,
|
|
38
|
+
load_workflows, orchestrate_agent_loop, orchestrate_chat_stream_with_fallback,
|
|
39
|
+
orchestrate_chat_with_fallback, propose_code_edits, save_chat_images, save_config,
|
|
40
|
+
start_channels, weather, workflows_path,
|
|
40
41
|
};
|
|
41
42
|
use plugins::execute_plugin;
|
|
42
43
|
|
|
@@ -546,6 +547,22 @@ async fn stream_chat_message(
|
|
|
546
547
|
})
|
|
547
548
|
}
|
|
548
549
|
|
|
550
|
+
#[tauri::command]
|
|
551
|
+
fn save_interaction_agent_activity(
|
|
552
|
+
interaction_id: i64,
|
|
553
|
+
activity: Vec<AgentProgress>,
|
|
554
|
+
) -> Result<(), String> {
|
|
555
|
+
let activity_json =
|
|
556
|
+
serde_json::to_string(&activity).map_err(|error| error.to_string())?;
|
|
557
|
+
MemoryStore::open_default()
|
|
558
|
+
.and_then(|memory| {
|
|
559
|
+
memory
|
|
560
|
+
.set_interaction_agent_activity_json(interaction_id, &activity_json)
|
|
561
|
+
.map(|_| ())
|
|
562
|
+
})
|
|
563
|
+
.map_err(|error| error.to_string())
|
|
564
|
+
}
|
|
565
|
+
|
|
549
566
|
#[tauri::command]
|
|
550
567
|
fn get_recent_interactions(
|
|
551
568
|
limit: Option<usize>,
|
|
@@ -626,6 +643,47 @@ async fn submit_tool_approval(
|
|
|
626
643
|
}
|
|
627
644
|
}
|
|
628
645
|
|
|
646
|
+
#[derive(serde::Serialize)]
|
|
647
|
+
#[serde(rename_all = "camelCase")]
|
|
648
|
+
struct DesktopImageGenResponse {
|
|
649
|
+
images: Vec<PictureEntry>,
|
|
650
|
+
model: String,
|
|
651
|
+
provider: String,
|
|
652
|
+
prompt: String,
|
|
653
|
+
description: Option<String>,
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
#[tauri::command]
|
|
657
|
+
async fn generate_images(request: ImageGenRequest) -> Result<DesktopImageGenResponse, String> {
|
|
658
|
+
let config = load_config().map_err(|error| error.to_string())?;
|
|
659
|
+
|
|
660
|
+
// Call core generate_images logic
|
|
661
|
+
let result = mint_core::generate_images(&config, &request)
|
|
662
|
+
.await
|
|
663
|
+
.map_err(|error| error.to_string())?;
|
|
664
|
+
|
|
665
|
+
// Save images to Pictures library (just like api_server does)
|
|
666
|
+
let data_uris: Vec<String> = result
|
|
667
|
+
.images
|
|
668
|
+
.iter()
|
|
669
|
+
.map(|img| img.data_uri.clone())
|
|
670
|
+
.collect();
|
|
671
|
+
let saved = save_chat_images(
|
|
672
|
+
data_uris,
|
|
673
|
+
Some("nanobanana".into()),
|
|
674
|
+
Some(request.prompt.clone()),
|
|
675
|
+
)
|
|
676
|
+
.map_err(|error| error.to_string())?;
|
|
677
|
+
|
|
678
|
+
Ok(DesktopImageGenResponse {
|
|
679
|
+
images: saved,
|
|
680
|
+
model: result.model,
|
|
681
|
+
provider: result.provider,
|
|
682
|
+
prompt: result.prompt,
|
|
683
|
+
description: result.description,
|
|
684
|
+
})
|
|
685
|
+
}
|
|
686
|
+
|
|
629
687
|
#[tauri::command]
|
|
630
688
|
fn list_pictures() -> Result<Vec<PictureEntry>, String> {
|
|
631
689
|
list_saved_pictures().map_err(|error| error.to_string())
|
|
@@ -978,6 +1036,7 @@ pub fn run() {
|
|
|
978
1036
|
.invoke_handler(tauri::generate_handler![
|
|
979
1037
|
get_runtime_status,
|
|
980
1038
|
get_workspace_tree,
|
|
1039
|
+
generate_images,
|
|
981
1040
|
select_workspace_directory,
|
|
982
1041
|
get_config,
|
|
983
1042
|
get_updater_status,
|
|
@@ -989,6 +1048,7 @@ pub fn run() {
|
|
|
989
1048
|
stream_chat_message,
|
|
990
1049
|
submit_tool_approval,
|
|
991
1050
|
get_recent_interactions,
|
|
1051
|
+
save_interaction_agent_activity,
|
|
992
1052
|
list_chat_sessions,
|
|
993
1053
|
delete_chat_session,
|
|
994
1054
|
rename_chat_session,
|