@pheem49/mint 1.6.3 → 1.6.4
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 +6 -2
- package/crates/mint-cli/src/main.rs +145 -5
- package/crates/mint-cli/src/onboard.rs +134 -1
- package/crates/mint-core/src/api_server.rs +108 -3
- package/crates/mint-core/src/config.rs +20 -1
- package/crates/mint-core/src/image_gen.rs +895 -0
- package/crates/mint-core/src/lib.rs +4 -0
- package/package.json +1 -1
- package/src/bin/index.js +0 -0
- package/src/renderer/src/components/ChatPanel.tsx +252 -26
- package/src/renderer/src/components/DashboardSidebar.tsx +9 -1
- package/src/renderer/src/components/ImageStudioPanel.tsx +638 -0
- package/src/renderer/src/components/MintDashboard.tsx +13 -4
- package/src/renderer/src/components/SettingsWindow.tsx +29 -20
- 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 +50 -26
- package/src/renderer/src/index.css +106 -0
- package/src/renderer/src/tauri.ts +123 -0
- package/src/renderer/src-web/components/ChatPanel.tsx +272 -24
- package/src/renderer/src-web/components/DashboardSidebar.tsx +9 -1
- package/src/renderer/src-web/components/ImageStudioPanel.tsx +638 -0
- package/src/renderer/src-web/components/MintDashboard.tsx +12 -3
- 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 +50 -26
- package/src/renderer/src-web/index.css +106 -0
- package/src/renderer/src-web/tauri.ts +124 -0
- package/src-tauri/src/lib.rs +48 -5
- package/src-tauri/tauri.conf.json +1 -1
|
@@ -269,7 +269,7 @@ h1 {
|
|
|
269
269
|
flex-direction: column;
|
|
270
270
|
gap: 18px;
|
|
271
271
|
width: 100%;
|
|
272
|
-
max-width:
|
|
272
|
+
max-width: 1000px;
|
|
273
273
|
margin: 0 auto;
|
|
274
274
|
animation: fadeTab 0.18s ease;
|
|
275
275
|
}
|
|
@@ -341,7 +341,7 @@ h1 {
|
|
|
341
341
|
|
|
342
342
|
.form-grid.single {
|
|
343
343
|
grid-template-columns: minmax(0, 1fr);
|
|
344
|
-
max-width:
|
|
344
|
+
max-width: 100%;
|
|
345
345
|
}
|
|
346
346
|
|
|
347
347
|
.setting-row {
|
|
@@ -595,7 +595,7 @@ input:checked + .toggle-slider::before {
|
|
|
595
595
|
.slider-stack {
|
|
596
596
|
display: grid;
|
|
597
597
|
gap: 16px;
|
|
598
|
-
max-width:
|
|
598
|
+
max-width: 100%;
|
|
599
599
|
}
|
|
600
600
|
|
|
601
601
|
.slider-group {
|
|
@@ -1055,3 +1055,13 @@ kbd {
|
|
|
1055
1055
|
grid-template-columns: minmax(0, 1fr);
|
|
1056
1056
|
}
|
|
1057
1057
|
}
|
|
1058
|
+
|
|
1059
|
+
.memory-field-container {
|
|
1060
|
+
display: flex;
|
|
1061
|
+
flex-direction: column;
|
|
1062
|
+
gap: 8px;
|
|
1063
|
+
width: 100%;
|
|
1064
|
+
align-items: flex-start;
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
|
|
@@ -18,6 +18,16 @@
|
|
|
18
18
|
--border-light: rgba(255, 255, 255, 0.11);
|
|
19
19
|
--shadow: none;
|
|
20
20
|
--glass-blur: none;
|
|
21
|
+
--status-listening: #7dd3fc;
|
|
22
|
+
--status-thinking: var(--accent);
|
|
23
|
+
--status-speaking: #22c55e;
|
|
24
|
+
--status-error: #ef4444;
|
|
25
|
+
--hover-delete: #fca5a5;
|
|
26
|
+
--hover-delete-bg: rgba(248, 113, 113, 0.12);
|
|
27
|
+
--hover-edit: #c7d2fe;
|
|
28
|
+
--hover-edit-bg: rgba(99, 102, 241, 0.12);
|
|
29
|
+
--close-btn-hover-bg: #3a2020;
|
|
30
|
+
--close-btn-hover-color: #ff8a8a;
|
|
21
31
|
}
|
|
22
32
|
|
|
23
33
|
[data-theme="light"] {
|
|
@@ -37,6 +47,16 @@
|
|
|
37
47
|
--border: rgba(0, 0, 0, 0.06);
|
|
38
48
|
--border-light: rgba(255, 255, 255, 0.6);
|
|
39
49
|
--shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
|
|
50
|
+
--status-listening: #0284c7;
|
|
51
|
+
--status-thinking: var(--accent);
|
|
52
|
+
--status-speaking: #16a34a;
|
|
53
|
+
--status-error: #dc2626;
|
|
54
|
+
--hover-delete: #dc2626;
|
|
55
|
+
--hover-delete-bg: rgba(220, 38, 38, 0.08);
|
|
56
|
+
--hover-edit: #4f46e5;
|
|
57
|
+
--hover-edit-bg: rgba(79, 70, 229, 0.08);
|
|
58
|
+
--close-btn-hover-bg: #fee2e2;
|
|
59
|
+
--close-btn-hover-color: #dc2626;
|
|
40
60
|
}
|
|
41
61
|
|
|
42
62
|
[data-theme="midnight"] {
|
|
@@ -56,6 +76,16 @@
|
|
|
56
76
|
--border: rgba(99, 102, 241, 0.16);
|
|
57
77
|
--border-light: rgba(99, 102, 241, 0.26);
|
|
58
78
|
--shadow: none;
|
|
79
|
+
--status-listening: #7dd3fc;
|
|
80
|
+
--status-thinking: var(--accent);
|
|
81
|
+
--status-speaking: #22c55e;
|
|
82
|
+
--status-error: #fca5a5;
|
|
83
|
+
--hover-delete: #fca5a5;
|
|
84
|
+
--hover-delete-bg: rgba(248, 113, 113, 0.12);
|
|
85
|
+
--hover-edit: #c7d2fe;
|
|
86
|
+
--hover-edit-bg: rgba(99, 102, 241, 0.12);
|
|
87
|
+
--close-btn-hover-bg: #3a2020;
|
|
88
|
+
--close-btn-hover-color: #ff8a8a;
|
|
59
89
|
}
|
|
60
90
|
|
|
61
91
|
* {
|
|
@@ -107,7 +137,6 @@ body {
|
|
|
107
137
|
|
|
108
138
|
/* Header - Drag Region */
|
|
109
139
|
.drag-region {
|
|
110
|
-
app-region: no-drag;
|
|
111
140
|
-webkit-app-region: no-drag;
|
|
112
141
|
min-height: 34px;
|
|
113
142
|
padding: 0 8px;
|
|
@@ -124,7 +153,6 @@ body {
|
|
|
124
153
|
}
|
|
125
154
|
|
|
126
155
|
.header-content {
|
|
127
|
-
app-region: drag;
|
|
128
156
|
-webkit-app-region: drag;
|
|
129
157
|
display: flex;
|
|
130
158
|
align-items: center;
|
|
@@ -134,7 +162,6 @@ body {
|
|
|
134
162
|
}
|
|
135
163
|
|
|
136
164
|
.titlebar-drag-space {
|
|
137
|
-
app-region: drag;
|
|
138
165
|
-webkit-app-region: drag;
|
|
139
166
|
align-self: stretch;
|
|
140
167
|
min-width: 0;
|
|
@@ -165,7 +192,6 @@ h1 {
|
|
|
165
192
|
.header-actions,
|
|
166
193
|
.header-utility,
|
|
167
194
|
.window-controls {
|
|
168
|
-
app-region: no-drag;
|
|
169
195
|
-webkit-app-region: no-drag;
|
|
170
196
|
display: flex;
|
|
171
197
|
align-items: center;
|
|
@@ -197,7 +223,6 @@ h1 {
|
|
|
197
223
|
.clear-btn,
|
|
198
224
|
.settings-btn {
|
|
199
225
|
-webkit-app-region: no-drag;
|
|
200
|
-
app-region: no-drag;
|
|
201
226
|
min-width: 0;
|
|
202
227
|
height: 28px;
|
|
203
228
|
border: 1px solid transparent;
|
|
@@ -231,7 +256,6 @@ h1 {
|
|
|
231
256
|
.maximize-btn,
|
|
232
257
|
.minimize-btn {
|
|
233
258
|
-webkit-app-region: no-drag;
|
|
234
|
-
app-region: no-drag;
|
|
235
259
|
background: transparent;
|
|
236
260
|
border: none;
|
|
237
261
|
color: var(--text-muted);
|
|
@@ -1270,8 +1294,8 @@ h1 {
|
|
|
1270
1294
|
.approval-card {
|
|
1271
1295
|
align-items: stretch;
|
|
1272
1296
|
flex-direction: column;
|
|
1273
|
-
background:
|
|
1274
|
-
border-color:
|
|
1297
|
+
background: transparent;
|
|
1298
|
+
border-color: transparent;
|
|
1275
1299
|
}
|
|
1276
1300
|
|
|
1277
1301
|
.approval-card[data-tier="dangerous"] {
|
|
@@ -2172,13 +2196,13 @@ input:checked + .slider:before {
|
|
|
2172
2196
|
}
|
|
2173
2197
|
|
|
2174
2198
|
.sidebar-chat-delete:hover {
|
|
2175
|
-
color:
|
|
2176
|
-
background:
|
|
2199
|
+
color: var(--hover-delete);
|
|
2200
|
+
background: var(--hover-delete-bg);
|
|
2177
2201
|
}
|
|
2178
2202
|
|
|
2179
2203
|
.sidebar-chat-edit:hover {
|
|
2180
|
-
color:
|
|
2181
|
-
background:
|
|
2204
|
+
color: var(--hover-edit);
|
|
2205
|
+
background: var(--hover-edit-bg);
|
|
2182
2206
|
}
|
|
2183
2207
|
|
|
2184
2208
|
.sidebar-chat-rename-input {
|
|
@@ -2270,49 +2294,49 @@ input:checked + .slider:before {
|
|
|
2270
2294
|
|
|
2271
2295
|
.mint-status-pill[data-state="listening"],
|
|
2272
2296
|
.model-activity-badge[data-state="listening"] {
|
|
2273
|
-
color:
|
|
2297
|
+
color: var(--status-listening);
|
|
2274
2298
|
}
|
|
2275
2299
|
|
|
2276
2300
|
.mint-status-pill[data-state="listening"] .mint-status-dot,
|
|
2277
2301
|
.model-activity-badge[data-state="listening"] .mint-status-dot {
|
|
2278
|
-
background:
|
|
2279
|
-
box-shadow: 0 0 0 3px
|
|
2302
|
+
background: var(--status-listening);
|
|
2303
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--status-listening) 16%, transparent);
|
|
2280
2304
|
animation: mintStatusPulse 1.2s ease-in-out infinite;
|
|
2281
2305
|
}
|
|
2282
2306
|
|
|
2283
2307
|
.mint-status-pill[data-state="thinking"],
|
|
2284
2308
|
.model-activity-badge[data-state="thinking"] {
|
|
2285
|
-
color:
|
|
2309
|
+
color: var(--status-thinking);
|
|
2286
2310
|
}
|
|
2287
2311
|
|
|
2288
2312
|
.mint-status-pill[data-state="thinking"] .mint-status-dot,
|
|
2289
2313
|
.model-activity-badge[data-state="thinking"] .mint-status-dot {
|
|
2290
|
-
background: var(--
|
|
2291
|
-
box-shadow: 0 0 0 3px color-mix(in srgb, var(--
|
|
2314
|
+
background: var(--status-thinking);
|
|
2315
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--status-thinking) 20%, transparent);
|
|
2292
2316
|
animation: mintStatusPulse 1s ease-in-out infinite;
|
|
2293
2317
|
}
|
|
2294
2318
|
|
|
2295
2319
|
.mint-status-pill[data-state="speaking"],
|
|
2296
2320
|
.model-activity-badge[data-state="speaking"] {
|
|
2297
|
-
color:
|
|
2321
|
+
color: var(--status-speaking);
|
|
2298
2322
|
}
|
|
2299
2323
|
|
|
2300
2324
|
.mint-status-pill[data-state="speaking"] .mint-status-dot,
|
|
2301
2325
|
.model-activity-badge[data-state="speaking"] .mint-status-dot {
|
|
2302
|
-
background:
|
|
2303
|
-
box-shadow: 0 0 0 3px
|
|
2326
|
+
background: var(--status-speaking);
|
|
2327
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--status-speaking) 16%, transparent);
|
|
2304
2328
|
animation: mintStatusPulse 0.9s ease-in-out infinite;
|
|
2305
2329
|
}
|
|
2306
2330
|
|
|
2307
2331
|
.mint-status-pill[data-state="error"],
|
|
2308
2332
|
.model-activity-badge[data-state="error"] {
|
|
2309
|
-
color:
|
|
2333
|
+
color: var(--status-error);
|
|
2310
2334
|
}
|
|
2311
2335
|
|
|
2312
2336
|
.mint-status-pill[data-state="error"] .mint-status-dot,
|
|
2313
2337
|
.model-activity-badge[data-state="error"] .mint-status-dot {
|
|
2314
|
-
background:
|
|
2315
|
-
box-shadow: 0 0 0 3px
|
|
2338
|
+
background: var(--status-error);
|
|
2339
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--status-error) 16%, transparent);
|
|
2316
2340
|
}
|
|
2317
2341
|
|
|
2318
2342
|
@keyframes mintStatusPulse {
|
|
@@ -3609,8 +3633,8 @@ input:checked + .slider:before {
|
|
|
3609
3633
|
}
|
|
3610
3634
|
|
|
3611
3635
|
.close-btn:hover {
|
|
3612
|
-
background:
|
|
3613
|
-
color:
|
|
3636
|
+
background: var(--close-btn-hover-bg);
|
|
3637
|
+
color: var(--close-btn-hover-color);
|
|
3614
3638
|
}
|
|
3615
3639
|
|
|
3616
3640
|
.assistant-workspace.layout-horizontal {
|
|
@@ -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,108 @@ 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
|
+
}
|
|
@@ -65,6 +65,29 @@ export interface PictureEntry {
|
|
|
65
65
|
thumbnailUrl?: string
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
export interface ImageGenRequest {
|
|
69
|
+
prompt: string
|
|
70
|
+
negativePrompt?: string
|
|
71
|
+
aspectRatio?: '1:1' | '16:9' | '9:16' | '4:3'
|
|
72
|
+
numImages?: number
|
|
73
|
+
model?: string
|
|
74
|
+
/** Which image generation provider to use. Falls back to config default when omitted. */
|
|
75
|
+
provider?: string
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface ImageGenProviders {
|
|
79
|
+
active: string
|
|
80
|
+
available: string[]
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface ImageGenResponse {
|
|
84
|
+
images: PictureEntry[]
|
|
85
|
+
model: string
|
|
86
|
+
provider: string
|
|
87
|
+
prompt: string
|
|
88
|
+
description?: string | null
|
|
89
|
+
}
|
|
90
|
+
|
|
68
91
|
export interface WorkspaceTreeEntry {
|
|
69
92
|
name: string
|
|
70
93
|
path: string
|
|
@@ -394,6 +417,106 @@ export async function listSavedPictures(): Promise<PictureEntry[]> {
|
|
|
394
417
|
return invoke<PictureEntry[]>('list_pictures')
|
|
395
418
|
}
|
|
396
419
|
|
|
420
|
+
export async function generateImages(
|
|
421
|
+
request: ImageGenRequest
|
|
422
|
+
): Promise<ImageGenResponse> {
|
|
423
|
+
if (typeof window === 'undefined' || !(window as any).__TAURI_INTERNALS__) {
|
|
424
|
+
const API_BASE = 'http://localhost:3000/api'
|
|
425
|
+
const res = await fetch(`${API_BASE}/image-generate`, {
|
|
426
|
+
method: 'POST',
|
|
427
|
+
headers: { 'Content-Type': 'application/json' },
|
|
428
|
+
body: JSON.stringify({
|
|
429
|
+
prompt: request.prompt,
|
|
430
|
+
negativePrompt: request.negativePrompt,
|
|
431
|
+
aspectRatio: request.aspectRatio ?? '1:1',
|
|
432
|
+
numImages: request.numImages ?? 1,
|
|
433
|
+
model: request.model,
|
|
434
|
+
provider: request.provider,
|
|
435
|
+
}),
|
|
436
|
+
})
|
|
437
|
+
if (!res.ok) {
|
|
438
|
+
const err = await res.json().catch(() => null)
|
|
439
|
+
throw new Error(err?.error || `Image generation failed: HTTP ${res.status}`)
|
|
440
|
+
}
|
|
441
|
+
const data = await res.json()
|
|
442
|
+
// Normalize image URLs for web mode
|
|
443
|
+
const images: PictureEntry[] = Array.isArray(data.images)
|
|
444
|
+
? data.images.map((pic: PictureEntry) => {
|
|
445
|
+
const pictureUrl = pic.url ? `http://localhost:3000${pic.url}` : pic.url
|
|
446
|
+
return { ...pic, url: pictureUrl, thumbnailUrl: pictureUrl }
|
|
447
|
+
})
|
|
448
|
+
: []
|
|
449
|
+
return { ...data, images }
|
|
450
|
+
}
|
|
451
|
+
// Desktop / Tauri mode
|
|
452
|
+
const { invoke } = await import('@tauri-apps/api/core')
|
|
453
|
+
return invoke<ImageGenResponse>('generate_images', { request })
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/** Fetch which image-generation providers are currently configured on the backend. */
|
|
457
|
+
export async function getImageGenProviders(): Promise<ImageGenProviders> {
|
|
458
|
+
if (typeof window === 'undefined' || !(window as any).__TAURI_INTERNALS__) {
|
|
459
|
+
const API_BASE = 'http://localhost:3000/api'
|
|
460
|
+
try {
|
|
461
|
+
const res = await fetch(`${API_BASE}/image-gen/providers`)
|
|
462
|
+
if (res.ok) return await res.json()
|
|
463
|
+
} catch (_) { /* ignore */ }
|
|
464
|
+
return { active: 'nanobanana', available: ['nanobanana'] }
|
|
465
|
+
}
|
|
466
|
+
// Desktop / Tauri: read config to know which keys are set
|
|
467
|
+
try {
|
|
468
|
+
const { invoke } = await import('@tauri-apps/api/core')
|
|
469
|
+
const config = await invoke<Record<string, string>>('get_config')
|
|
470
|
+
const available: string[] = []
|
|
471
|
+
if (config.api_key) available.push('nanobanana')
|
|
472
|
+
if (config.openai_api_key) available.push('dalle')
|
|
473
|
+
if (config.stability_api_key) available.push('stability')
|
|
474
|
+
if (config.ideogram_api_key) available.push('ideogram')
|
|
475
|
+
if (config.replicate_api_key) available.push('replicate')
|
|
476
|
+
if (available.length === 0) available.push('nanobanana')
|
|
477
|
+
const active = available.includes(config.image_gen_provider)
|
|
478
|
+
? config.image_gen_provider
|
|
479
|
+
: available[0]
|
|
480
|
+
return { active, available }
|
|
481
|
+
} catch (_) {
|
|
482
|
+
return { active: 'nanobanana', available: ['nanobanana'] }
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/** Updates the default image generation provider in the configuration. */
|
|
487
|
+
export async function setDefaultImageProvider(provider: string): Promise<boolean> {
|
|
488
|
+
if (typeof window === 'undefined' || !(window as any).__TAURI_INTERNALS__) {
|
|
489
|
+
const API_BASE = "http://localhost:3000/api";
|
|
490
|
+
try {
|
|
491
|
+
const getRes = await fetch(`${API_BASE}/config`)
|
|
492
|
+
if (!getRes.ok) return false
|
|
493
|
+
const config = await getRes.json()
|
|
494
|
+
config.image_gen_provider = provider
|
|
495
|
+
const saveRes = await fetch(`${API_BASE}/config`, {
|
|
496
|
+
method: 'POST',
|
|
497
|
+
headers: { 'Content-Type': 'application/json' },
|
|
498
|
+
body: JSON.stringify(config)
|
|
499
|
+
})
|
|
500
|
+
return saveRes.ok
|
|
501
|
+
} catch (_) {
|
|
502
|
+
return false
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// Desktop / Tauri
|
|
507
|
+
try {
|
|
508
|
+
const { invoke } = await import('@tauri-apps/api/core')
|
|
509
|
+
const config = await invoke<any>('get_config')
|
|
510
|
+
config.image_gen_provider = provider
|
|
511
|
+
await invoke('update_config', { config })
|
|
512
|
+
return true
|
|
513
|
+
} catch (_) {
|
|
514
|
+
return false
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
|
|
397
520
|
export async function getWorkspaceTree(path?: string | null): Promise<WorkspaceTreeEntry> {
|
|
398
521
|
if (typeof window === 'undefined' || !(window as any).__TAURI_INTERNALS__) {
|
|
399
522
|
return {
|