@pheem49/mint 1.7.1 → 1.8.1
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/.github/workflows/release.yml +1 -1
- package/Cargo.lock +34 -3
- package/Cargo.toml +2 -2
- package/README.md +40 -0
- package/Release_Note.md +95 -0
- package/assets/Mint_CLI.png +0 -0
- package/crates/mint-cli/Cargo.toml +1 -0
- package/crates/mint-cli/src/agent.rs +142 -48
- package/crates/mint-cli/src/main.rs +231 -22
- package/crates/mint-core/src/api_server.rs +71 -4
- package/crates/mint-core/src/browser.rs +401 -0
- package/crates/mint-core/src/chat.rs +79 -0
- package/crates/mint-core/src/config.rs +69 -1
- package/crates/mint-core/src/lib.rs +6 -1
- package/crates/mint-core/src/orchestration.rs +137 -1
- package/crates/mint-core/src/skills.rs +113 -4
- package/crates/mint-core/src/workflows.rs +9 -22
- package/package.json +2 -1
- package/src/renderer/src/App.tsx +1 -1
- package/src/renderer/src/components/ChatPanel.tsx +197 -47
- package/src/renderer/src/components/DashboardSidebar.tsx +71 -12
- package/src/renderer/src/components/ImageStudioPanel.tsx +18 -4
- package/src/renderer/src/components/MintDashboard.tsx +239 -7
- package/src/renderer/src/components/PicturesLibrary.tsx +1 -3
- package/src/renderer/src/components/Settings/AudioTab.tsx +97 -0
- package/src/renderer/src/components/Settings/AutomationTab.tsx +195 -0
- package/src/renderer/src/components/Settings/GeneralTab.tsx +950 -0
- package/src/renderer/src/components/Settings/MemoryTab.tsx +60 -0
- package/src/renderer/src/components/Settings/PluginsTab.tsx +632 -0
- package/src/renderer/src/components/Settings/ShortcutsTab.tsx +30 -0
- package/src/renderer/src/components/Settings/ThemeTab.tsx +129 -0
- package/src/renderer/src/components/SettingsWindow.tsx +175 -970
- package/src/renderer/src/components/WorkflowBuilderPanel.tsx +536 -0
- package/src/renderer/src/components/WorkflowsWindow.tsx +46 -0
- package/src/renderer/src/components/WorkspacePanel.tsx +66 -9
- package/src/renderer/src/css/image-studio.css +15 -4
- package/src/renderer/src/css/settings.css +75 -6
- package/src/renderer/src/css/styles.css +419 -49
- package/src/renderer/src/css/workflows.css +542 -0
- package/src/renderer/src/env.d.ts +2 -0
- package/src/renderer/src/index.css +13 -1
- package/src/renderer/src/tauri.ts +140 -2
- package/src/renderer/src-web/components/ChatPanel.tsx +190 -46
- package/src/renderer/src-web/components/DashboardSidebar.tsx +17 -1
- package/src/renderer/src-web/components/ImageStudioPanel.tsx +18 -4
- package/src/renderer/src-web/components/MintDashboard.tsx +197 -3
- package/src/renderer/src-web/components/PicturesLibrary.tsx +1 -3
- package/src/renderer/src-web/components/Settings/AudioTab.tsx +97 -0
- package/src/renderer/src-web/components/Settings/AutomationTab.tsx +196 -0
- package/src/renderer/src-web/components/Settings/GeneralTab.tsx +948 -0
- package/src/renderer/src-web/components/Settings/MemoryTab.tsx +60 -0
- package/src/renderer/src-web/components/Settings/PluginsTab.tsx +632 -0
- package/src/renderer/src-web/components/Settings/ShortcutsTab.tsx +30 -0
- package/src/renderer/src-web/components/Settings/ThemeTab.tsx +129 -0
- package/src/renderer/src-web/components/SettingsWindow.tsx +187 -976
- package/src/renderer/src-web/css/image-studio.css +15 -4
- package/src/renderer/src-web/css/settings.css +75 -6
- package/src/renderer/src-web/css/styles.css +394 -50
- package/src/renderer/src-web/env.d.ts +2 -0
- package/src/renderer/src-web/index.css +12 -1
- package/src/renderer/src-web/tauri.ts +60 -2
- package/src-tauri/src/browser.rs +1 -141
- package/src-tauri/src/headless.rs +3 -2
- package/src-tauri/src/lib.rs +195 -111
- package/src-tauri/src/workflows.rs +56 -4
- package/src-tauri/tauri.conf.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react'
|
|
2
|
-
import { getWorkspaceTree, type WorkspaceTreeEntry } from '../tauri'
|
|
1
|
+
import React, { useEffect, useState } from 'react'
|
|
2
|
+
import { getWorkspaceTree, type WorkspaceTreeEntry, createWorkspaceFile, createWorkspaceFolder, deleteWorkspaceItem } from '../tauri'
|
|
3
3
|
import folderIcon from 'material-icon-theme/icons/folder.svg?url'
|
|
4
4
|
import folderOpenIcon from 'material-icon-theme/icons/folder-open.svg?url'
|
|
5
5
|
import folderComponentsIcon from 'material-icon-theme/icons/folder-components.svg?url'
|
|
@@ -147,7 +147,7 @@ function materialFileIcon(name: string, fileExtension: string) {
|
|
|
147
147
|
return FILE_ICONS_BY_NAME[name.toLowerCase()] || FILE_ICONS_BY_EXTENSION[fileExtension] || documentIcon
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
function TreeNode({ entry, level }: { entry: WorkspaceTreeEntry; level: number; key?: string }) {
|
|
150
|
+
function TreeNode({ entry, level, onRefresh, workspacePath }: { entry: WorkspaceTreeEntry; level: number; onRefresh: () => void; workspacePath: string; key?: string }) {
|
|
151
151
|
const [open, setOpen] = useState(level < 1)
|
|
152
152
|
const isDirectory = entry.kind === 'directory'
|
|
153
153
|
const hasChildren = entry.children.length > 0
|
|
@@ -156,6 +156,20 @@ function TreeNode({ entry, level }: { entry: WorkspaceTreeEntry; level: number;
|
|
|
156
156
|
const materialIcon = isDirectory ? materialFolderIcon(entry.name, open) : materialFileIcon(entry.name, fileExtension)
|
|
157
157
|
const dragText = `@${entry.path}`
|
|
158
158
|
|
|
159
|
+
const handleContextMenu = async (event: React.MouseEvent) => {
|
|
160
|
+
event.preventDefault()
|
|
161
|
+
const confirmed = confirm(`Are you sure you want to delete "${entry.name}"?`)
|
|
162
|
+
if (!confirmed) return
|
|
163
|
+
|
|
164
|
+
try {
|
|
165
|
+
const absolutePath = `${workspacePath}/${entry.path}`
|
|
166
|
+
await deleteWorkspaceItem(absolutePath)
|
|
167
|
+
onRefresh()
|
|
168
|
+
} catch (err) {
|
|
169
|
+
alert(`Failed to delete item: ${err instanceof Error ? err.message : String(err)}`)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
159
173
|
return (
|
|
160
174
|
<div className="workspace-tree-node">
|
|
161
175
|
<button
|
|
@@ -163,6 +177,7 @@ function TreeNode({ entry, level }: { entry: WorkspaceTreeEntry; level: number;
|
|
|
163
177
|
className={`workspace-tree-row ${isDirectory ? 'is-directory' : 'is-file'}`}
|
|
164
178
|
style={{ paddingLeft: `${level * 16 + 8}px` }}
|
|
165
179
|
onClick={() => isDirectory && hasChildren && setOpen((current) => !current)}
|
|
180
|
+
onContextMenu={handleContextMenu}
|
|
166
181
|
title={entry.path}
|
|
167
182
|
draggable
|
|
168
183
|
onDragStart={(event) => {
|
|
@@ -186,7 +201,7 @@ function TreeNode({ entry, level }: { entry: WorkspaceTreeEntry; level: number;
|
|
|
186
201
|
{isDirectory && open && hasChildren && (
|
|
187
202
|
<div className="workspace-tree-children">
|
|
188
203
|
{entry.children.map((child) => (
|
|
189
|
-
<TreeNode key={child.path} entry={child} level={level + 1} />
|
|
204
|
+
<TreeNode key={child.path} entry={child} level={level + 1} onRefresh={onRefresh} workspacePath={workspacePath} />
|
|
190
205
|
))}
|
|
191
206
|
</div>
|
|
192
207
|
)}
|
|
@@ -217,11 +232,52 @@ export default function WorkspacePanel({ agentMode, sending, workspacePath, onEn
|
|
|
217
232
|
|
|
218
233
|
useEffect(() => {
|
|
219
234
|
refresh()
|
|
235
|
+
|
|
236
|
+
// Refresh when the window gains focus (e.g., switching back from VS Code)
|
|
237
|
+
const handleFocus = () => {
|
|
238
|
+
refresh()
|
|
239
|
+
}
|
|
240
|
+
window.addEventListener('focus', handleFocus)
|
|
241
|
+
|
|
242
|
+
// Poll every 15 seconds to catch edits/updates in real-time
|
|
243
|
+
const interval = setInterval(() => {
|
|
244
|
+
refresh()
|
|
245
|
+
}, 15000)
|
|
246
|
+
|
|
247
|
+
return () => {
|
|
248
|
+
window.removeEventListener('focus', handleFocus)
|
|
249
|
+
clearInterval(interval)
|
|
250
|
+
}
|
|
220
251
|
}, [workspacePath])
|
|
221
252
|
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
253
|
+
const handleCreateFile = async () => {
|
|
254
|
+
if (!workspacePath.trim()) return
|
|
255
|
+
const name = prompt('Enter name of new file:')
|
|
256
|
+
if (!name || !name.trim()) return
|
|
257
|
+
|
|
258
|
+
try {
|
|
259
|
+
setError('')
|
|
260
|
+
const fullPath = `${workspacePath}/${name.trim()}`
|
|
261
|
+
await createWorkspaceFile(fullPath)
|
|
262
|
+
await refresh()
|
|
263
|
+
} catch (err) {
|
|
264
|
+
setError(err instanceof Error ? err.message : String(err))
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const handleCreateFolder = async () => {
|
|
269
|
+
if (!workspacePath.trim()) return
|
|
270
|
+
const name = prompt('Enter name of new folder:')
|
|
271
|
+
if (!name || !name.trim()) return
|
|
272
|
+
|
|
273
|
+
try {
|
|
274
|
+
setError('')
|
|
275
|
+
const fullPath = `${workspacePath}/${name.trim()}`
|
|
276
|
+
await createWorkspaceFolder(fullPath)
|
|
277
|
+
await refresh()
|
|
278
|
+
} catch (err) {
|
|
279
|
+
setError(err instanceof Error ? err.message : String(err))
|
|
280
|
+
}
|
|
225
281
|
}
|
|
226
282
|
|
|
227
283
|
return (
|
|
@@ -237,7 +293,8 @@ export default function WorkspacePanel({ agentMode, sending, workspacePath, onEn
|
|
|
237
293
|
</header>
|
|
238
294
|
|
|
239
295
|
<div className="workspace-panel-actions">
|
|
240
|
-
<button type="button" onClick={
|
|
296
|
+
<button type="button" onClick={handleCreateFile} disabled={!workspacePath.trim()}>New File</button>
|
|
297
|
+
<button type="button" onClick={handleCreateFolder} disabled={!workspacePath.trim()}>New Folder</button>
|
|
241
298
|
<button type="button" onClick={refresh} disabled={!workspacePath.trim()}>Refresh</button>
|
|
242
299
|
</div>
|
|
243
300
|
|
|
@@ -255,7 +312,7 @@ export default function WorkspacePanel({ agentMode, sending, workspacePath, onEn
|
|
|
255
312
|
</div>
|
|
256
313
|
<div className="workspace-tree">
|
|
257
314
|
{tree.children.map((entry) => (
|
|
258
|
-
<TreeNode key={entry.path} entry={entry} level={0} />
|
|
315
|
+
<TreeNode key={entry.path} entry={entry} level={0} onRefresh={refresh} workspacePath={workspacePath} />
|
|
259
316
|
))}
|
|
260
317
|
</div>
|
|
261
318
|
</>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/* Root panel: overlays the main content area, aligned with sidebar */
|
|
6
6
|
.img-studio {
|
|
7
|
-
display:
|
|
7
|
+
display: flex;
|
|
8
8
|
position: absolute;
|
|
9
9
|
top: 0;
|
|
10
10
|
bottom: 0;
|
|
@@ -14,7 +14,10 @@
|
|
|
14
14
|
overflow: hidden;
|
|
15
15
|
background: var(--bg-gradient, radial-gradient(circle at top left, #064e3b, #111827 52%, #0b1020));
|
|
16
16
|
z-index: 10;
|
|
17
|
-
|
|
17
|
+
opacity: 0;
|
|
18
|
+
pointer-events: none;
|
|
19
|
+
transform: translateY(12px) scale(0.995);
|
|
20
|
+
transition: left 0.22s ease, opacity 0.22s cubic-bezier(0.4, 0, 0.2, 1), transform 0.22s cubic-bezier(0.4, 0, 0.2, 1);
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
/* Adjust left position when the sidebar is collapsed */
|
|
@@ -23,8 +26,10 @@
|
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
/* Only visible when view === 'imagine' */
|
|
26
|
-
.img-studio
|
|
27
|
-
|
|
29
|
+
.img-studio.is-visible {
|
|
30
|
+
opacity: 1;
|
|
31
|
+
pointer-events: auto;
|
|
32
|
+
transform: translateY(0) scale(1);
|
|
28
33
|
}
|
|
29
34
|
|
|
30
35
|
/* MintDashboard renders ImageStudioPanel always, use view prop to show/hide via :not class trick */
|
|
@@ -720,3 +725,9 @@
|
|
|
720
725
|
overflow-y: auto;
|
|
721
726
|
}
|
|
722
727
|
}
|
|
728
|
+
|
|
729
|
+
@media (max-width: 760px) {
|
|
730
|
+
.img-studio {
|
|
731
|
+
left: 0 !important;
|
|
732
|
+
}
|
|
733
|
+
}
|
|
@@ -546,7 +546,7 @@ input[type="color"] {
|
|
|
546
546
|
color: var(--text-main);
|
|
547
547
|
}
|
|
548
548
|
|
|
549
|
-
.toggle-switch {
|
|
549
|
+
.settings-toggle-switch {
|
|
550
550
|
position: relative;
|
|
551
551
|
display: inline-block;
|
|
552
552
|
width: 46px;
|
|
@@ -554,13 +554,13 @@ input[type="color"] {
|
|
|
554
554
|
height: 26px;
|
|
555
555
|
}
|
|
556
556
|
|
|
557
|
-
.toggle-switch input {
|
|
557
|
+
.settings-toggle-switch input {
|
|
558
558
|
width: 0;
|
|
559
559
|
height: 0;
|
|
560
560
|
opacity: 0;
|
|
561
561
|
}
|
|
562
562
|
|
|
563
|
-
.toggle-slider {
|
|
563
|
+
.settings-toggle-slider {
|
|
564
564
|
position: absolute;
|
|
565
565
|
inset: 0;
|
|
566
566
|
cursor: pointer;
|
|
@@ -570,7 +570,7 @@ input[type="color"] {
|
|
|
570
570
|
transition: background 0.18s, border-color 0.18s;
|
|
571
571
|
}
|
|
572
572
|
|
|
573
|
-
.toggle-slider::before {
|
|
573
|
+
.settings-toggle-slider::before {
|
|
574
574
|
position: absolute;
|
|
575
575
|
content: "";
|
|
576
576
|
width: 18px;
|
|
@@ -582,12 +582,12 @@ input[type="color"] {
|
|
|
582
582
|
transition: transform 0.18s, background 0.18s;
|
|
583
583
|
}
|
|
584
584
|
|
|
585
|
-
input:checked + .toggle-slider {
|
|
585
|
+
input:checked + .settings-toggle-slider {
|
|
586
586
|
background: var(--accent);
|
|
587
587
|
border-color: var(--accent);
|
|
588
588
|
}
|
|
589
589
|
|
|
590
|
-
input:checked + .toggle-slider::before {
|
|
590
|
+
input:checked + .settings-toggle-slider::before {
|
|
591
591
|
transform: translateX(20px);
|
|
592
592
|
background: #ffffff;
|
|
593
593
|
}
|
|
@@ -1064,4 +1064,73 @@ kbd {
|
|
|
1064
1064
|
align-items: flex-start;
|
|
1065
1065
|
}
|
|
1066
1066
|
|
|
1067
|
+
/* Provider Cards styling */
|
|
1068
|
+
.provider-cards-container {
|
|
1069
|
+
padding: 16px;
|
|
1070
|
+
display: flex;
|
|
1071
|
+
flex-direction: column;
|
|
1072
|
+
gap: 16px;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
.provider-card {
|
|
1076
|
+
border: 1px solid var(--border);
|
|
1077
|
+
border-radius: 12px;
|
|
1078
|
+
background: var(--surface-bg);
|
|
1079
|
+
padding: 16px;
|
|
1080
|
+
transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
.provider-card:hover {
|
|
1084
|
+
border-color: var(--border-strong);
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
.provider-card.active-provider {
|
|
1088
|
+
border-color: var(--accent);
|
|
1089
|
+
box-shadow: 0 0 0 1px var(--accent);
|
|
1090
|
+
background: color-mix(in srgb, var(--accent) 2%, var(--surface-bg));
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
.provider-card-header {
|
|
1094
|
+
display: flex;
|
|
1095
|
+
align-items: center;
|
|
1096
|
+
justify-content: space-between;
|
|
1097
|
+
margin-bottom: 12px;
|
|
1098
|
+
padding-bottom: 8px;
|
|
1099
|
+
border-bottom: 1px solid var(--border);
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
.provider-card-title {
|
|
1103
|
+
font-size: 0.92rem;
|
|
1104
|
+
font-weight: 600;
|
|
1105
|
+
color: var(--text-main);
|
|
1106
|
+
display: flex;
|
|
1107
|
+
align-items: center;
|
|
1108
|
+
gap: 8px;
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
.provider-active-badge {
|
|
1112
|
+
background: color-mix(in srgb, var(--accent) 15%, transparent);
|
|
1113
|
+
color: var(--accent-hover);
|
|
1114
|
+
border: 1px solid var(--accent);
|
|
1115
|
+
font-size: 0.7rem;
|
|
1116
|
+
font-weight: 600;
|
|
1117
|
+
padding: 2px 8px;
|
|
1118
|
+
border-radius: 20px;
|
|
1119
|
+
text-transform: uppercase;
|
|
1120
|
+
letter-spacing: 0.05em;
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
.provider-card-body {
|
|
1124
|
+
display: flex;
|
|
1125
|
+
flex-direction: column;
|
|
1126
|
+
gap: 12px;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
.provider-card-body .setting-row {
|
|
1130
|
+
border-top: none;
|
|
1131
|
+
padding: 6px 0;
|
|
1132
|
+
grid-template-columns: 180px 1fr;
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
|
|
1067
1136
|
|