@pheem49/mint 1.6.4 → 1.7.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/Cargo.toml +1 -1
- package/bin/mint +0 -0
- package/crates/mint-cli/src/agent.rs +42 -14
- package/crates/mint-cli/src/main.rs +412 -2
- package/crates/mint-cli/src/setup.rs +173 -32
- package/crates/mint-core/src/api_server.rs +35 -0
- package/crates/mint-core/src/config.rs +2 -2
- 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 +35 -0
- package/crates/mint-core/tests/memory_persistence.rs +28 -0
- package/package.json +12 -2
- package/src/renderer/src/agentProgress.ts +39 -0
- package/src/renderer/src/components/ChatPanel.tsx +308 -34
- package/src/renderer/src/components/DashboardSidebar.tsx +3 -3
- package/src/renderer/src/components/MintDashboard.tsx +71 -27
- package/src/renderer/src/components/ModelPanel.tsx +2 -2
- package/src/renderer/src/components/PicturesLibrary.tsx +5 -1
- package/src/renderer/src/components/SpotlightWindow.tsx +8 -8
- package/src/renderer/src/components/WorkspacePanel.tsx +1 -1
- package/src/renderer/src/css/styles.css +195 -17
- package/src/renderer/src/index.css +46 -0
- package/src/renderer/src/tauri.ts +25 -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 +309 -35
- package/src/renderer/src-web/components/DashboardSidebar.tsx +1 -1
- package/src/renderer/src-web/components/MintDashboard.tsx +53 -16
- package/src/renderer/src-web/components/PicturesLibrary.tsx +5 -1
- package/src/renderer/src-web/css/styles.css +242 -18
- package/src/renderer/src-web/index.css +46 -0
- package/src/renderer/src-web/tauri.ts +25 -0
- package/src-tauri/src/lib.rs +16 -0
- package/src-tauri/tauri.conf.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ChangeEvent, type FormEvent, useEffect, useRef, useState } from 'react'
|
|
2
|
+
import { mergeActivitySnapshots, trimAgentProgress } from '../agentProgress'
|
|
2
3
|
import {
|
|
3
4
|
clearChatHistory,
|
|
4
5
|
deleteChatSession,
|
|
@@ -7,6 +8,7 @@ import {
|
|
|
7
8
|
getRuntimeStatus,
|
|
8
9
|
listChatSessions,
|
|
9
10
|
listSavedPictures,
|
|
11
|
+
saveInteractionAgentActivity,
|
|
10
12
|
streamChatMessage,
|
|
11
13
|
submitToolApproval,
|
|
12
14
|
listen,
|
|
@@ -57,7 +59,7 @@ function activeConversationId() {
|
|
|
57
59
|
const MOCK_WELCOME_INTERACTION = {
|
|
58
60
|
id: -1,
|
|
59
61
|
userText: '',
|
|
60
|
-
aiText:
|
|
62
|
+
aiText: `Hi there! I'm Mint, your AI assistant! 🎯✨ I'm here and ready to help you with whatever you need. I've been organizing some background data to make things smoother for you. 💖\n\nBut the moment you start chatting with me, I'll put everything aside and focus on you! Is there something I can help you with today, or would you like to chat about something special? Let's do this! 🚀💪`,
|
|
61
63
|
provider: 'gemini',
|
|
62
64
|
model: 'gemini-3-flash-preview',
|
|
63
65
|
createdAt: new Date().toISOString(),
|
|
@@ -212,8 +214,11 @@ export default function MintDashboard() {
|
|
|
212
214
|
const [sendingImageCount, setSendingImageCount] = useState(0)
|
|
213
215
|
const [streamedReply, setStreamedReply] = useState('')
|
|
214
216
|
const [streamedResponse, setStreamedResponse] = useState<ChatResponse | null>(null)
|
|
217
|
+
const [streamingConversationId, setStreamingConversationId] = useState<string | null>(null)
|
|
215
218
|
const [agentProgress, setAgentProgress] = useState<AgentProgress[]>([])
|
|
216
219
|
const [agentActivitySnapshots, setAgentActivitySnapshots] = useState<Record<string, AgentProgress[]>>({})
|
|
220
|
+
const [thinkingExpanded, setThinkingExpanded] = useState<Record<string, boolean>>({})
|
|
221
|
+
const liveThinkingOpenRef = useRef(true)
|
|
217
222
|
const [imageAttachments, setImageAttachments] = useState<Array<{ dataUri: string; name: string; previewDataUri?: string }>>([])
|
|
218
223
|
const [documentAttachment, setDocumentAttachment] = useState<DocumentAttachment | null>(null)
|
|
219
224
|
const [pendingApproval, setPendingApproval] = useState<any | null>(null)
|
|
@@ -232,7 +237,9 @@ export default function MintDashboard() {
|
|
|
232
237
|
|
|
233
238
|
async function refreshHistory() {
|
|
234
239
|
const history = await getRecentInteractions(50, conversationId)
|
|
235
|
-
|
|
240
|
+
const reversed = history.reverse()
|
|
241
|
+
setInteractions(reversed)
|
|
242
|
+
setAgentActivitySnapshots((current) => mergeActivitySnapshots(current, reversed))
|
|
236
243
|
}
|
|
237
244
|
|
|
238
245
|
async function refreshChatSessions(nextActiveId = conversationId) {
|
|
@@ -347,12 +354,15 @@ export default function MintDashboard() {
|
|
|
347
354
|
const outgoingImage = outgoingImages.map((img) => img.dataUri).join(' ')
|
|
348
355
|
const outgoingImageCount = outgoingImages.length
|
|
349
356
|
setSending(true)
|
|
357
|
+
setStreamingConversationId(conversationId)
|
|
350
358
|
setSendingMessage(promptText)
|
|
351
359
|
setSendingImageCount(outgoingImageCount)
|
|
352
360
|
setError('')
|
|
353
361
|
setStreamedReply('')
|
|
354
362
|
setStreamedResponse(null)
|
|
355
363
|
setAgentProgress([])
|
|
364
|
+
liveThinkingOpenRef.current = true
|
|
365
|
+
setThinkingExpanded((current) => ({ ...current, live: true }))
|
|
356
366
|
const progressSnapshot: AgentProgress[] = []
|
|
357
367
|
if (options.clearComposer) {
|
|
358
368
|
setMessage('')
|
|
@@ -369,7 +379,7 @@ export default function MintDashboard() {
|
|
|
369
379
|
options.systemInstruction ?? '',
|
|
370
380
|
(progress) => {
|
|
371
381
|
progressSnapshot.push(progress)
|
|
372
|
-
setAgentProgress((current) => [...current, progress]
|
|
382
|
+
setAgentProgress((current) => trimAgentProgress([...current, progress]))
|
|
373
383
|
},
|
|
374
384
|
outgoingDocument,
|
|
375
385
|
null,
|
|
@@ -377,18 +387,33 @@ export default function MintDashboard() {
|
|
|
377
387
|
)
|
|
378
388
|
setStreamedResponse(response)
|
|
379
389
|
const history = (await getRecentInteractions(50, conversationId)).reverse()
|
|
390
|
+
let enrichedHistory = history
|
|
380
391
|
if (progressSnapshot.length > 0) {
|
|
381
392
|
const newestInteraction = [...history]
|
|
382
393
|
.reverse()
|
|
383
394
|
.find((interaction) => interaction.aiText === response.text || interaction.userText === promptText) ?? history[history.length - 1]
|
|
384
395
|
if (newestInteraction?.id != null) {
|
|
396
|
+
const interactionKey = String(newestInteraction.id)
|
|
397
|
+
enrichedHistory = history.map((interaction) =>
|
|
398
|
+
interaction.id === newestInteraction.id
|
|
399
|
+
? { ...interaction, agentActivity: progressSnapshot }
|
|
400
|
+
: interaction,
|
|
401
|
+
)
|
|
385
402
|
setAgentActivitySnapshots((current) => ({
|
|
386
403
|
...current,
|
|
387
|
-
[
|
|
404
|
+
[interactionKey]: progressSnapshot.slice(),
|
|
388
405
|
}))
|
|
406
|
+
if (liveThinkingOpenRef.current) {
|
|
407
|
+
setThinkingExpanded((current) => ({
|
|
408
|
+
...current,
|
|
409
|
+
[interactionKey]: true,
|
|
410
|
+
}))
|
|
411
|
+
}
|
|
412
|
+
await saveInteractionAgentActivity(newestInteraction.id, progressSnapshot)
|
|
389
413
|
}
|
|
390
414
|
}
|
|
391
|
-
setInteractions(
|
|
415
|
+
setInteractions(enrichedHistory)
|
|
416
|
+
setAgentActivitySnapshots((current) => mergeActivitySnapshots(current, enrichedHistory))
|
|
392
417
|
await refreshChatSessions()
|
|
393
418
|
await refreshPictures()
|
|
394
419
|
setStreamedReply('')
|
|
@@ -397,6 +422,7 @@ export default function MintDashboard() {
|
|
|
397
422
|
setError(errorMessage(reason))
|
|
398
423
|
} finally {
|
|
399
424
|
setSending(false)
|
|
425
|
+
setStreamingConversationId(null)
|
|
400
426
|
setSendingMessage('')
|
|
401
427
|
setSendingImageCount(0)
|
|
402
428
|
}
|
|
@@ -418,7 +444,7 @@ export default function MintDashboard() {
|
|
|
418
444
|
}
|
|
419
445
|
|
|
420
446
|
async function sendVoiceMessage(transcript: string, audioDataUri?: string | null) {
|
|
421
|
-
const promptText = transcript.trim() || '
|
|
447
|
+
const promptText = transcript.trim() || 'Voice message'
|
|
422
448
|
if (!promptText || sending) return
|
|
423
449
|
await sendPrompt(promptText, {
|
|
424
450
|
audioDataUri,
|
|
@@ -568,6 +594,11 @@ export default function MintDashboard() {
|
|
|
568
594
|
}
|
|
569
595
|
}
|
|
570
596
|
|
|
597
|
+
function handleThinkingExpandedChange(key: string, open: boolean) {
|
|
598
|
+
if (key === 'live') liveThinkingOpenRef.current = open
|
|
599
|
+
setThinkingExpanded((current) => ({ ...current, [key]: open }))
|
|
600
|
+
}
|
|
601
|
+
|
|
571
602
|
async function selectConversation(id: string) {
|
|
572
603
|
if (id === conversationId) {
|
|
573
604
|
changeView('chat')
|
|
@@ -583,7 +614,9 @@ export default function MintDashboard() {
|
|
|
583
614
|
setDocumentAttachment(null)
|
|
584
615
|
setAgentProgress([])
|
|
585
616
|
const history = await getRecentInteractions(50, id)
|
|
586
|
-
|
|
617
|
+
const reversed = history.reverse()
|
|
618
|
+
setInteractions(reversed)
|
|
619
|
+
setAgentActivitySnapshots((current) => mergeActivitySnapshots(current, reversed))
|
|
587
620
|
}
|
|
588
621
|
|
|
589
622
|
async function deleteConversation(id: string) {
|
|
@@ -604,7 +637,9 @@ export default function MintDashboard() {
|
|
|
604
637
|
setConversationId(nextActive)
|
|
605
638
|
setAgentProgress([])
|
|
606
639
|
const history = await getRecentInteractions(50, nextActive)
|
|
607
|
-
|
|
640
|
+
const reversed = history.reverse()
|
|
641
|
+
setInteractions(reversed)
|
|
642
|
+
setAgentActivitySnapshots((current) => mergeActivitySnapshots(current, reversed))
|
|
608
643
|
}
|
|
609
644
|
|
|
610
645
|
await refreshChatSessions(nextActive)
|
|
@@ -707,17 +742,19 @@ export default function MintDashboard() {
|
|
|
707
742
|
<main className="assistant-workspace model-hidden">
|
|
708
743
|
<ChatPanel
|
|
709
744
|
interactions={interactions}
|
|
710
|
-
sending={sending}
|
|
711
|
-
sendingMessage={sendingMessage}
|
|
712
|
-
sendingImageCount={sendingImageCount}
|
|
713
|
-
streamedReply={streamedReply}
|
|
714
|
-
streamedResponse={streamedResponse}
|
|
715
|
-
agentProgress={agentProgress}
|
|
745
|
+
sending={sending && streamingConversationId === conversationId}
|
|
746
|
+
sendingMessage={streamingConversationId === conversationId ? sendingMessage : ''}
|
|
747
|
+
sendingImageCount={streamingConversationId === conversationId ? sendingImageCount : 0}
|
|
748
|
+
streamedReply={streamingConversationId === conversationId ? streamedReply : ''}
|
|
749
|
+
streamedResponse={streamingConversationId === conversationId ? streamedResponse : null}
|
|
750
|
+
agentProgress={streamingConversationId === conversationId ? agentProgress : []}
|
|
716
751
|
agentActivitySnapshots={agentActivitySnapshots}
|
|
752
|
+
thinkingExpanded={thinkingExpanded}
|
|
753
|
+
onThinkingExpandedChange={handleThinkingExpandedChange}
|
|
717
754
|
message={message}
|
|
718
755
|
imageAttachments={imageAttachments}
|
|
719
756
|
documentName={documentAttachment?.filename ?? ''}
|
|
720
|
-
pendingApproval={pendingApproval}
|
|
757
|
+
pendingApproval={streamingConversationId === conversationId ? pendingApproval : null}
|
|
721
758
|
smartContext={smartContext}
|
|
722
759
|
agentMode={agentMode}
|
|
723
760
|
status={status}
|
|
@@ -745,7 +782,7 @@ export default function MintDashboard() {
|
|
|
745
782
|
onToggleMobileSidebar={() => setMobileSidebarOpen(!mobileSidebarOpen)}
|
|
746
783
|
/>
|
|
747
784
|
</main>
|
|
748
|
-
<PicturesLibrary view={view} pictures={pictures} onSetView={changeView} />
|
|
785
|
+
<PicturesLibrary view={view} pictures={pictures} onSetView={changeView} onRefreshPictures={refreshPictures} />
|
|
749
786
|
<ImageStudioPanel
|
|
750
787
|
view={view}
|
|
751
788
|
onRefreshPictures={refreshPictures}
|
|
@@ -10,9 +10,10 @@ interface PicturesLibraryProps {
|
|
|
10
10
|
view: DashboardView
|
|
11
11
|
pictures: PictureEntry[]
|
|
12
12
|
onSetView: (view: DashboardView) => void
|
|
13
|
+
onRefreshPictures?: () => Promise<void>
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
export default function PicturesLibrary({ view, pictures, onSetView }: PicturesLibraryProps) {
|
|
16
|
+
export default function PicturesLibrary({ view, pictures, onSetView, onRefreshPictures }: PicturesLibraryProps) {
|
|
16
17
|
const [visibleCount, setVisibleCount] = useState(INITIAL_VISIBLE_PICTURES)
|
|
17
18
|
const visiblePictures = useMemo(
|
|
18
19
|
() => pictures.slice(0, visibleCount),
|
|
@@ -46,6 +47,9 @@ export default function PicturesLibrary({ view, pictures, onSetView }: PicturesL
|
|
|
46
47
|
<div><span className="pictures-kicker">Gallery</span><h2>Saved Pictures</h2></div>
|
|
47
48
|
<div className="pictures-header-actions">
|
|
48
49
|
<button className="pictures-close-btn" onClick={() => onSetView('chat')}>Close Gallery</button>
|
|
50
|
+
<button type="button" className="picture-refresh-btn" title="Refresh" onClick={() => onRefreshPictures?.()}>
|
|
51
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/><path d="M3.51 9a9 9 0 0 1 14.13-3.36L23 10"/><path d="M20.49 15a9 9 0 0 1-14.13 3.36L1 14"/></svg>
|
|
52
|
+
</button>
|
|
49
53
|
</div>
|
|
50
54
|
</header>
|
|
51
55
|
{pictures.length === 0 ? (
|
|
@@ -406,7 +406,27 @@ h1 {
|
|
|
406
406
|
.interaction-guide-btn.active {
|
|
407
407
|
background: rgba(34, 211, 238, 0.22);
|
|
408
408
|
border-color: rgba(34, 211, 238, 0.34);
|
|
409
|
-
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
.picture-refresh-btn {
|
|
412
|
+
height: 28px;
|
|
413
|
+
min-width: 0;
|
|
414
|
+
padding: 0 8px;
|
|
415
|
+
display: inline-flex;
|
|
416
|
+
align-items: center;
|
|
417
|
+
justify-content: center;
|
|
418
|
+
gap: 8px;
|
|
419
|
+
border-radius: 6px;
|
|
420
|
+
background: transparent;
|
|
421
|
+
color: var(--text-muted);
|
|
422
|
+
border: 1px solid transparent;
|
|
423
|
+
cursor: pointer;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.picture-refresh-btn:hover {
|
|
427
|
+
background: color-mix(in srgb, var(--accent) 10%, transparent);
|
|
428
|
+
border-color: color-mix(in srgb, var(--accent) 16%, transparent);
|
|
429
|
+
color: var(--accent);
|
|
410
430
|
}
|
|
411
431
|
|
|
412
432
|
.maximize-btn:hover {
|
|
@@ -829,6 +849,41 @@ h1 {
|
|
|
829
849
|
transform: scaleX(1.2);
|
|
830
850
|
}
|
|
831
851
|
|
|
852
|
+
/* Settings modal overlay (web) */
|
|
853
|
+
.settings-modal-overlay {
|
|
854
|
+
position: fixed;
|
|
855
|
+
inset: 0;
|
|
856
|
+
display: flex;
|
|
857
|
+
align-items: center;
|
|
858
|
+
justify-content: center;
|
|
859
|
+
background: rgba(0,0,0,0.45);
|
|
860
|
+
z-index: 80;
|
|
861
|
+
padding: 24px;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
.settings-modal {
|
|
865
|
+
width: min(920px, 96vw);
|
|
866
|
+
max-height: 92vh;
|
|
867
|
+
overflow: hidden;
|
|
868
|
+
border-radius: 12px;
|
|
869
|
+
box-shadow: 0 30px 80px rgba(0,0,0,0.6);
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
/* When rendered inside modal, make settings-container adapt to modal size */
|
|
873
|
+
.settings-modal .settings-container {
|
|
874
|
+
height: auto !important;
|
|
875
|
+
width: 100% !important;
|
|
876
|
+
max-height: 92vh !important;
|
|
877
|
+
overflow: hidden !important;
|
|
878
|
+
border-radius: 12px !important;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
/* Make settings content scroll internally */
|
|
882
|
+
.settings-modal .settings-content {
|
|
883
|
+
max-height: calc(92vh - 160px);
|
|
884
|
+
overflow-y: auto;
|
|
885
|
+
}
|
|
886
|
+
|
|
832
887
|
@keyframes modelFloat {
|
|
833
888
|
0%,
|
|
834
889
|
100% {
|
|
@@ -841,8 +896,9 @@ h1 {
|
|
|
841
896
|
}
|
|
842
897
|
|
|
843
898
|
.conversation-panel {
|
|
844
|
-
|
|
845
|
-
|
|
899
|
+
/* Make conversation panel wider by default */
|
|
900
|
+
flex: 0 1 720px;
|
|
901
|
+
min-width: 600px;
|
|
846
902
|
display: flex;
|
|
847
903
|
flex-direction: column;
|
|
848
904
|
min-height: 0;
|
|
@@ -889,7 +945,7 @@ h1 {
|
|
|
889
945
|
|
|
890
946
|
.message {
|
|
891
947
|
display: flex;
|
|
892
|
-
max-width:
|
|
948
|
+
max-width: 95%;
|
|
893
949
|
animation: messagePopIn 0.5s cubic-bezier(0.2, 0.9, 0.3, 1.2) forwards;
|
|
894
950
|
opacity: 0;
|
|
895
951
|
transform: translateY(15px) scale(0.95);
|
|
@@ -897,6 +953,21 @@ h1 {
|
|
|
897
953
|
transition: all 0.3s ease;
|
|
898
954
|
}
|
|
899
955
|
|
|
956
|
+
/* Allow selecting text inside the main chat and settings areas despite global user-select:none */
|
|
957
|
+
.chat-container,
|
|
958
|
+
.chat-container *,
|
|
959
|
+
.message-bubble,
|
|
960
|
+
.message-bubble *,
|
|
961
|
+
.bubble-wrapper,
|
|
962
|
+
.bubble-wrapper *,
|
|
963
|
+
.settings-content,
|
|
964
|
+
.settings-content * {
|
|
965
|
+
-webkit-user-select: text !important;
|
|
966
|
+
-moz-user-select: text !important;
|
|
967
|
+
-ms-user-select: text !important;
|
|
968
|
+
user-select: text !important;
|
|
969
|
+
}
|
|
970
|
+
|
|
900
971
|
.bubble-wrapper {
|
|
901
972
|
display: flex;
|
|
902
973
|
flex-direction: column;
|
|
@@ -1078,24 +1149,26 @@ h1 {
|
|
|
1078
1149
|
}
|
|
1079
1150
|
|
|
1080
1151
|
.ai-message .message-bubble {
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
border
|
|
1086
|
-
border-
|
|
1087
|
-
|
|
1088
|
-
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.1);
|
|
1152
|
+
/* Render AI replies without a framed bubble — plain inline text */
|
|
1153
|
+
background: transparent;
|
|
1154
|
+
backdrop-filter: none;
|
|
1155
|
+
-webkit-backdrop-filter: none;
|
|
1156
|
+
border: none;
|
|
1157
|
+
border-radius: 0;
|
|
1158
|
+
box-shadow: none;
|
|
1089
1159
|
color: var(--text-main);
|
|
1160
|
+
padding: 0; /* keep spacing handled by wrapper */
|
|
1090
1161
|
}
|
|
1091
1162
|
|
|
1092
1163
|
.message.ai-message.thinking-message .message-bubble {
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1164
|
+
/* Keep thinking state unframed too */
|
|
1165
|
+
background: transparent !important;
|
|
1166
|
+
border: none !important;
|
|
1167
|
+
box-shadow: none !important;
|
|
1096
1168
|
color: var(--text-muted) !important;
|
|
1097
1169
|
backdrop-filter: none !important;
|
|
1098
1170
|
-webkit-backdrop-filter: none !important;
|
|
1171
|
+
padding: 0 !important;
|
|
1099
1172
|
}
|
|
1100
1173
|
|
|
1101
1174
|
|
|
@@ -1714,6 +1787,146 @@ h1 {
|
|
|
1714
1787
|
line-height: 1;
|
|
1715
1788
|
}
|
|
1716
1789
|
|
|
1790
|
+
/* ── Thinking Block ─────────────────────────────────────── */
|
|
1791
|
+
.thinking-block {
|
|
1792
|
+
margin-bottom: 6px;
|
|
1793
|
+
border-radius: 8px;
|
|
1794
|
+
border: 1px solid rgba(148, 163, 184, 0.18);
|
|
1795
|
+
background: rgba(148, 163, 184, 0.04);
|
|
1796
|
+
overflow: hidden;
|
|
1797
|
+
animation: agent-activity-slide-up-fade 0.25s cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
.thinking-block-header {
|
|
1801
|
+
display: flex;
|
|
1802
|
+
align-items: center;
|
|
1803
|
+
gap: 7px;
|
|
1804
|
+
width: 100%;
|
|
1805
|
+
padding: 6px 10px;
|
|
1806
|
+
background: transparent;
|
|
1807
|
+
border: 0;
|
|
1808
|
+
color: #94a3b8;
|
|
1809
|
+
font-size: 0.76rem;
|
|
1810
|
+
font-weight: 500;
|
|
1811
|
+
cursor: pointer;
|
|
1812
|
+
text-align: left;
|
|
1813
|
+
transition: background 0.15s ease, color 0.15s ease;
|
|
1814
|
+
user-select: none;
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
.thinking-block-header:hover {
|
|
1818
|
+
background: rgba(148, 163, 184, 0.08);
|
|
1819
|
+
color: #cbd5e1;
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
.thinking-block-label {
|
|
1823
|
+
flex: 1;
|
|
1824
|
+
min-width: 0;
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1827
|
+
.thinking-block-live-dot {
|
|
1828
|
+
width: 6px;
|
|
1829
|
+
height: 6px;
|
|
1830
|
+
border-radius: 50%;
|
|
1831
|
+
background: #94a3b8;
|
|
1832
|
+
flex-shrink: 0;
|
|
1833
|
+
animation: thinkingDotPulse 1.4s ease-in-out infinite;
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
@keyframes thinkingDotPulse {
|
|
1837
|
+
0%, 100% {
|
|
1838
|
+
opacity: 0.4;
|
|
1839
|
+
transform: scale(0.85);
|
|
1840
|
+
}
|
|
1841
|
+
50% {
|
|
1842
|
+
opacity: 1;
|
|
1843
|
+
transform: scale(1.1);
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
.thinking-block-chevron {
|
|
1848
|
+
color: rgba(148, 163, 184, 0.6);
|
|
1849
|
+
flex-shrink: 0;
|
|
1850
|
+
display: inline-flex;
|
|
1851
|
+
align-items: center;
|
|
1852
|
+
transition: transform 0.2s ease;
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1855
|
+
.thinking-block-chevron.is-open {
|
|
1856
|
+
transform: rotate(90deg);
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1859
|
+
.thinking-block-body {
|
|
1860
|
+
border-top: 1px solid rgba(148, 163, 184, 0.12);
|
|
1861
|
+
animation: thinkingBodyIn 0.18s ease;
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
@keyframes thinkingBodyIn {
|
|
1865
|
+
from {
|
|
1866
|
+
opacity: 0;
|
|
1867
|
+
transform: translateY(-4px);
|
|
1868
|
+
}
|
|
1869
|
+
to {
|
|
1870
|
+
opacity: 1;
|
|
1871
|
+
transform: translateY(0);
|
|
1872
|
+
}
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1875
|
+
.thinking-block-content {
|
|
1876
|
+
padding: 8px 12px 10px;
|
|
1877
|
+
font-size: 0.76rem;
|
|
1878
|
+
line-height: 1.6;
|
|
1879
|
+
color: #64748b;
|
|
1880
|
+
white-space: pre-wrap;
|
|
1881
|
+
max-height: 260px;
|
|
1882
|
+
overflow-y: auto;
|
|
1883
|
+
user-select: text;
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
.thinking-block-step + .thinking-block-step {
|
|
1887
|
+
margin-top: 10px;
|
|
1888
|
+
padding-top: 10px;
|
|
1889
|
+
border-top: 1px dashed rgba(148, 163, 184, 0.16);
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1892
|
+
.thinking-block-step-label {
|
|
1893
|
+
font-size: 0.68rem;
|
|
1894
|
+
font-weight: 600;
|
|
1895
|
+
letter-spacing: 0.02em;
|
|
1896
|
+
color: #94a3b8;
|
|
1897
|
+
margin-bottom: 4px;
|
|
1898
|
+
font-style: normal;
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1901
|
+
.thinking-block-step-body {
|
|
1902
|
+
font-style: italic;
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
.thinking-block-empty-state {
|
|
1906
|
+
padding: 6px 10px;
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
.thinking-block-empty {
|
|
1910
|
+
display: block;
|
|
1911
|
+
font-size: 0.74rem;
|
|
1912
|
+
line-height: 1.5;
|
|
1913
|
+
color: #64748b;
|
|
1914
|
+
font-style: italic;
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1917
|
+
.thinking-block-content::-webkit-scrollbar {
|
|
1918
|
+
width: 3px;
|
|
1919
|
+
}
|
|
1920
|
+
|
|
1921
|
+
.thinking-block-content::-webkit-scrollbar-track {
|
|
1922
|
+
background: transparent;
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
.thinking-block-content::-webkit-scrollbar-thumb {
|
|
1926
|
+
background: rgba(148, 163, 184, 0.22);
|
|
1927
|
+
border-radius: 2px;
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1717
1930
|
/* Smart Context Toggle */
|
|
1718
1931
|
.smart-context-bar {
|
|
1719
1932
|
display: flex;
|
|
@@ -2896,13 +3109,15 @@ input:checked + .slider:before {
|
|
|
2896
3109
|
|
|
2897
3110
|
.ai-message .message-bubble,
|
|
2898
3111
|
.typing-indicator {
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
border
|
|
3112
|
+
/* Keep AI messages unframed here as well */
|
|
3113
|
+
background: transparent;
|
|
3114
|
+
border: none;
|
|
3115
|
+
border-radius: 0;
|
|
2902
3116
|
color: var(--text-main);
|
|
2903
3117
|
backdrop-filter: none;
|
|
2904
3118
|
-webkit-backdrop-filter: none;
|
|
2905
3119
|
box-shadow: none;
|
|
3120
|
+
padding: 0; /* spacing handled by wrapper */
|
|
2906
3121
|
}
|
|
2907
3122
|
|
|
2908
3123
|
.user-message .message-bubble {
|
|
@@ -2917,6 +3132,15 @@ input:checked + .slider:before {
|
|
|
2917
3132
|
color: var(--accent-hover);
|
|
2918
3133
|
}
|
|
2919
3134
|
|
|
3135
|
+
/* Force AI replies to render as plain inline text (no bubble/frame). */
|
|
3136
|
+
.message.ai-message .message-bubble {
|
|
3137
|
+
background: transparent !important;
|
|
3138
|
+
border: none !important;
|
|
3139
|
+
box-shadow: none !important;
|
|
3140
|
+
border-radius: 0 !important;
|
|
3141
|
+
padding: 0 !important;
|
|
3142
|
+
}
|
|
3143
|
+
|
|
2920
3144
|
.input-area {
|
|
2921
3145
|
flex: 0 0 auto;
|
|
2922
3146
|
padding: 0;
|
|
@@ -483,3 +483,49 @@ button {
|
|
|
483
483
|
font-family: 'Fira Code', 'Courier New', Courier, monospace;
|
|
484
484
|
font-size: 0.9em;
|
|
485
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 {
|
|
@@ -292,6 +293,30 @@ export async function getRecentInteractions(limit = 50, chatId?: string | null):
|
|
|
292
293
|
return invoke<InteractionMemory[]>('get_recent_interactions', { limit, chatId })
|
|
293
294
|
}
|
|
294
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
|
+
|
|
295
320
|
export async function listChatSessions(): Promise<ChatSession[]> {
|
|
296
321
|
if (typeof window === 'undefined' || !isTauriRuntime()) {
|
|
297
322
|
const API_BASE = getApiBase();
|
package/src-tauri/src/lib.rs
CHANGED
|
@@ -547,6 +547,21 @@ async fn stream_chat_message(
|
|
|
547
547
|
})
|
|
548
548
|
}
|
|
549
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 = serde_json::to_string(&activity).map_err(|error| error.to_string())?;
|
|
556
|
+
MemoryStore::open_default()
|
|
557
|
+
.and_then(|memory| {
|
|
558
|
+
memory
|
|
559
|
+
.set_interaction_agent_activity_json(interaction_id, &activity_json)
|
|
560
|
+
.map(|_| ())
|
|
561
|
+
})
|
|
562
|
+
.map_err(|error| error.to_string())
|
|
563
|
+
}
|
|
564
|
+
|
|
550
565
|
#[tauri::command]
|
|
551
566
|
fn get_recent_interactions(
|
|
552
567
|
limit: Option<usize>,
|
|
@@ -1032,6 +1047,7 @@ pub fn run() {
|
|
|
1032
1047
|
stream_chat_message,
|
|
1033
1048
|
submit_tool_approval,
|
|
1034
1049
|
get_recent_interactions,
|
|
1050
|
+
save_interaction_agent_activity,
|
|
1035
1051
|
list_chat_sessions,
|
|
1036
1052
|
delete_chat_session,
|
|
1037
1053
|
rename_chat_session,
|