@swarmclawai/swarmclaw 0.6.3 → 0.6.6
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/README.md +5 -3
- package/package.json +5 -1
- package/src/app/api/chatrooms/[id]/chat/route.ts +41 -2
- package/src/app/api/chatrooms/[id]/route.ts +15 -1
- package/src/app/api/chatrooms/route.ts +15 -2
- package/src/app/api/schedules/[id]/run/route.ts +3 -0
- package/src/app/api/tasks/route.ts +24 -0
- package/src/app/api/wallets/[id]/approve/route.ts +62 -0
- package/src/app/api/wallets/[id]/balance-history/route.ts +18 -0
- package/src/app/api/wallets/[id]/route.ts +118 -0
- package/src/app/api/wallets/[id]/send/route.ts +118 -0
- package/src/app/api/wallets/[id]/transactions/route.ts +18 -0
- package/src/app/api/wallets/route.ts +74 -0
- package/src/app/globals.css +8 -0
- package/src/app/page.tsx +7 -3
- package/src/cli/index.js +15 -0
- package/src/cli/spec.js +14 -0
- package/src/components/agents/agent-avatar.tsx +15 -1
- package/src/components/agents/agent-card.tsx +1 -0
- package/src/components/agents/agent-chat-list.tsx +1 -1
- package/src/components/agents/agent-sheet.tsx +112 -26
- package/src/components/auth/access-key-gate.tsx +22 -11
- package/src/components/chat/chat-area.tsx +2 -2
- package/src/components/chat/chat-header.tsx +48 -19
- package/src/components/chat/chat-tool-toggles.tsx +1 -1
- package/src/components/chat/delegation-banner.test.ts +27 -0
- package/src/components/chat/delegation-banner.tsx +109 -23
- package/src/components/chat/message-bubble.tsx +14 -3
- package/src/components/chat/message-list.tsx +5 -4
- package/src/components/chat/streaming-bubble.tsx +3 -2
- package/src/components/chat/thinking-indicator.tsx +3 -2
- package/src/components/chat/tool-call-bubble.test.ts +28 -0
- package/src/components/chat/tool-call-bubble.tsx +13 -1
- package/src/components/chat/transfer-agent-picker.tsx +1 -1
- package/src/components/chatrooms/agent-hover-card.tsx +1 -1
- package/src/components/chatrooms/chatroom-input.tsx +7 -6
- package/src/components/chatrooms/chatroom-message.tsx +1 -1
- package/src/components/chatrooms/chatroom-sheet.tsx +1 -1
- package/src/components/chatrooms/chatroom-typing-bar.tsx +1 -1
- package/src/components/chatrooms/chatroom-view.tsx +1 -1
- package/src/components/connectors/connector-list.tsx +1 -1
- package/src/components/home/home-view.tsx +2 -1
- package/src/components/input/chat-input.tsx +5 -4
- package/src/components/knowledge/knowledge-list.tsx +1 -1
- package/src/components/knowledge/knowledge-sheet.tsx +1 -1
- package/src/components/layout/app-layout.tsx +23 -9
- package/src/components/logs/log-list.tsx +7 -7
- package/src/components/memory/memory-agent-list.tsx +1 -1
- package/src/components/memory/memory-browser.tsx +1 -0
- package/src/components/memory/memory-card.tsx +3 -2
- package/src/components/memory/memory-detail.tsx +3 -3
- package/src/components/memory/memory-sheet.tsx +2 -2
- package/src/components/projects/project-detail.tsx +4 -4
- package/src/components/secrets/secret-sheet.tsx +1 -1
- package/src/components/secrets/secrets-list.tsx +1 -1
- package/src/components/sessions/new-session-sheet.tsx +4 -3
- package/src/components/sessions/session-card.tsx +1 -1
- package/src/components/shared/agent-picker-list.tsx +1 -1
- package/src/components/shared/agent-switch-dialog.tsx +1 -1
- package/src/components/shared/settings/section-user-preferences.tsx +4 -4
- package/src/components/skills/skill-list.tsx +1 -1
- package/src/components/skills/skill-sheet.tsx +1 -1
- package/src/components/tasks/task-board.tsx +3 -3
- package/src/components/tasks/task-sheet.tsx +21 -1
- package/src/components/wallets/wallet-approval-dialog.tsx +99 -0
- package/src/components/wallets/wallet-panel.tsx +616 -0
- package/src/components/wallets/wallet-section.tsx +100 -0
- package/src/hooks/use-media-query.ts +30 -4
- package/src/lib/api-client.ts +6 -18
- package/src/lib/fetch-timeout.ts +17 -0
- package/src/lib/notification-sounds.ts +4 -4
- package/src/lib/safe-storage.ts +42 -0
- package/src/lib/server/agent-registry.ts +2 -2
- package/src/lib/server/chat-execution.ts +35 -3
- package/src/lib/server/chatroom-health.ts +60 -0
- package/src/lib/server/chatroom-helpers.test.ts +94 -0
- package/src/lib/server/chatroom-helpers.ts +64 -11
- package/src/lib/server/connectors/inbound-audio-transcription.test.ts +191 -0
- package/src/lib/server/connectors/inbound-audio-transcription.ts +261 -0
- package/src/lib/server/connectors/manager.ts +80 -2
- package/src/lib/server/connectors/whatsapp-text.test.ts +29 -0
- package/src/lib/server/connectors/whatsapp-text.ts +26 -0
- package/src/lib/server/connectors/whatsapp.ts +8 -5
- package/src/lib/server/orchestrator-lg.ts +12 -2
- package/src/lib/server/orchestrator.ts +6 -1
- package/src/lib/server/queue-followups.test.ts +224 -0
- package/src/lib/server/queue.ts +226 -24
- package/src/lib/server/scheduler.ts +3 -0
- package/src/lib/server/session-tools/chatroom.ts +11 -2
- package/src/lib/server/session-tools/context-mgmt.ts +2 -2
- package/src/lib/server/session-tools/index.ts +6 -2
- package/src/lib/server/session-tools/memory.ts +1 -1
- package/src/lib/server/session-tools/shell.ts +1 -1
- package/src/lib/server/session-tools/wallet.ts +124 -0
- package/src/lib/server/session-tools/web-output.test.ts +29 -0
- package/src/lib/server/session-tools/web-output.ts +16 -0
- package/src/lib/server/session-tools/web.ts +7 -3
- package/src/lib/server/solana.ts +122 -0
- package/src/lib/server/storage.ts +38 -0
- package/src/lib/server/stream-agent-chat.ts +126 -63
- package/src/lib/server/task-mention.test.ts +41 -0
- package/src/lib/server/task-mention.ts +3 -2
- package/src/lib/tool-definitions.ts +1 -0
- package/src/lib/view-routes.ts +6 -1
- package/src/stores/use-app-store.ts +17 -11
- package/src/types/index.ts +60 -1
|
@@ -5,6 +5,7 @@ import { AgentAvatar } from '@/components/agents/agent-avatar'
|
|
|
5
5
|
import { FilePreview } from '@/components/shared/file-preview'
|
|
6
6
|
import { useChatroomStore } from '@/stores/use-chatroom-store'
|
|
7
7
|
import { uploadImage } from '@/lib/upload'
|
|
8
|
+
import { safeStorageGet, safeStorageRemove, safeStorageSet } from '@/lib/safe-storage'
|
|
8
9
|
import type { Agent } from '@/types'
|
|
9
10
|
|
|
10
11
|
interface Props {
|
|
@@ -33,7 +34,7 @@ export function ChatroomInput({ agents, onSend, disabled }: Props) {
|
|
|
33
34
|
const draftTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
|
34
35
|
useEffect(() => {
|
|
35
36
|
if (!chatroomId) return
|
|
36
|
-
const draft =
|
|
37
|
+
const draft = safeStorageGet(`sc_draft_cr_${chatroomId}`)
|
|
37
38
|
setText(draft || '')
|
|
38
39
|
}, [chatroomId])
|
|
39
40
|
|
|
@@ -42,8 +43,8 @@ export function ChatroomInput({ agents, onSend, disabled }: Props) {
|
|
|
42
43
|
if (!chatroomId) return
|
|
43
44
|
if (draftTimerRef.current) clearTimeout(draftTimerRef.current)
|
|
44
45
|
draftTimerRef.current = setTimeout(() => {
|
|
45
|
-
if (text)
|
|
46
|
-
else
|
|
46
|
+
if (text) safeStorageSet(`sc_draft_cr_${chatroomId}`, text)
|
|
47
|
+
else safeStorageRemove(`sc_draft_cr_${chatroomId}`)
|
|
47
48
|
}, 300)
|
|
48
49
|
return () => { if (draftTimerRef.current) clearTimeout(draftTimerRef.current) }
|
|
49
50
|
}, [text, chatroomId])
|
|
@@ -167,7 +168,7 @@ export function ChatroomInput({ agents, onSend, disabled }: Props) {
|
|
|
167
168
|
if ((text.trim() || pendingFiles.length) && !disabled) {
|
|
168
169
|
onSend(text)
|
|
169
170
|
setText('')
|
|
170
|
-
if (chatroomId)
|
|
171
|
+
if (chatroomId) safeStorageRemove(`sc_draft_cr_${chatroomId}`)
|
|
171
172
|
setShowMentions(false)
|
|
172
173
|
}
|
|
173
174
|
}
|
|
@@ -202,7 +203,7 @@ export function ChatroomInput({ agents, onSend, disabled }: Props) {
|
|
|
202
203
|
selectedIndex === i + 1 ? 'bg-white/[0.08]' : 'hover:bg-white/[0.06]'
|
|
203
204
|
}`}
|
|
204
205
|
>
|
|
205
|
-
<AgentAvatar seed={agent.avatarSeed} name={agent.name} size={20} />
|
|
206
|
+
<AgentAvatar seed={agent.avatarSeed} avatarUrl={agent.avatarUrl} name={agent.name} size={20} />
|
|
206
207
|
<span className="text-[13px] text-text">{agent.name}</span>
|
|
207
208
|
</button>
|
|
208
209
|
))}
|
|
@@ -294,7 +295,7 @@ export function ChatroomInput({ agents, onSend, disabled }: Props) {
|
|
|
294
295
|
if ((text.trim() || pendingFiles.length) && !disabled) {
|
|
295
296
|
onSend(text)
|
|
296
297
|
setText('')
|
|
297
|
-
if (chatroomId)
|
|
298
|
+
if (chatroomId) safeStorageRemove(`sc_draft_cr_${chatroomId}`)
|
|
298
299
|
setShowMentions(false)
|
|
299
300
|
}
|
|
300
301
|
}}
|
|
@@ -172,7 +172,7 @@ export function ChatroomMessageBubble({ message, agents, onToggleReaction, onRep
|
|
|
172
172
|
className="bg-transparent border-none p-0 cursor-pointer transition-all duration-150 hover:scale-110 hover:-translate-y-0.5"
|
|
173
173
|
style={momentOverlay ? { animation: 'avatar-moment-pulse 0.6s ease' } : undefined}
|
|
174
174
|
>
|
|
175
|
-
<AgentAvatar seed={agent.avatarSeed || null} name={message.senderName} size={28} status={streamingAgentIds?.has(message.senderId) ? 'busy' : 'online'} />
|
|
175
|
+
<AgentAvatar seed={agent.avatarSeed || null} avatarUrl={agent.avatarUrl} name={message.senderName} size={28} status={streamingAgentIds?.has(message.senderId) ? 'busy' : 'online'} />
|
|
176
176
|
</button>
|
|
177
177
|
) : (
|
|
178
178
|
<div style={momentOverlay ? { animation: 'avatar-moment-pulse 0.6s ease' } : undefined}>
|
|
@@ -178,7 +178,7 @@ export function ChatroomSheet() {
|
|
|
178
178
|
selected ? 'bg-accent-soft/40' : 'hover:bg-white/[0.04]'
|
|
179
179
|
}`}
|
|
180
180
|
>
|
|
181
|
-
<AgentAvatar seed={agent.avatarSeed} name={agent.name} size={24} />
|
|
181
|
+
<AgentAvatar seed={agent.avatarSeed} avatarUrl={agent.avatarUrl} name={agent.name} size={24} />
|
|
182
182
|
<span className="text-[13px] text-text flex-1 truncate">{agent.name}</span>
|
|
183
183
|
{selected && (
|
|
184
184
|
<CheckIcon size={14} className="text-accent-bright shrink-0" />
|
|
@@ -63,7 +63,7 @@ export function ChatroomTypingBar({ streamingAgents }: Props) {
|
|
|
63
63
|
return (
|
|
64
64
|
<div key={agentId} className="flex gap-2.5 px-4 py-1.5" style={{ animation: 'msg-in 0.2s ease-out both' }}>
|
|
65
65
|
<div className="shrink-0 mt-0.5 w-7">
|
|
66
|
-
<AgentAvatar seed={agent?.avatarSeed || null} name={a.name} size={28} />
|
|
66
|
+
<AgentAvatar seed={agent?.avatarSeed || null} avatarUrl={agent?.avatarUrl} name={a.name} size={28} />
|
|
67
67
|
</div>
|
|
68
68
|
<div className="flex-1 min-w-0">
|
|
69
69
|
<div className="flex items-baseline gap-2 mb-0.5">
|
|
@@ -192,7 +192,7 @@ export function ChatroomView() {
|
|
|
192
192
|
onClick={() => navigateToAgent(agent.id)}
|
|
193
193
|
className="relative transition-all duration-200 hover:scale-110 hover:z-10 hover:-translate-y-0.5 cursor-pointer bg-transparent border-none p-0"
|
|
194
194
|
>
|
|
195
|
-
<AgentAvatar seed={agent.avatarSeed} name={agent.name} size={22} status={streamingAgents.has(agent.id) ? 'busy' : 'online'} />
|
|
195
|
+
<AgentAvatar seed={agent.avatarSeed} avatarUrl={agent.avatarUrl} name={agent.name} size={22} status={streamingAgents.has(agent.id) ? 'busy' : 'online'} />
|
|
196
196
|
</button>
|
|
197
197
|
</TooltipTrigger>
|
|
198
198
|
<TooltipContent side="bottom" sideOffset={6}>
|
|
@@ -206,7 +206,7 @@ export function ConnectorList({ inSidebar }: { inSidebar?: boolean }) {
|
|
|
206
206
|
</>
|
|
207
207
|
) : agent ? (
|
|
208
208
|
<>
|
|
209
|
-
<AgentAvatar seed={agent.avatarSeed || null} name={agent.name} size={24} />
|
|
209
|
+
<AgentAvatar seed={agent.avatarSeed || null} avatarUrl={agent.avatarUrl} name={agent.name} size={24} />
|
|
210
210
|
<div className="flex-1 min-w-0">
|
|
211
211
|
<span className="text-[12px] font-600 text-text-2 block truncate">{agent.name}</span>
|
|
212
212
|
<span className="text-[10px] text-text-3/60 block">{agent.provider}/{agent.model}</span>
|
|
@@ -353,7 +353,7 @@ export function HomeView() {
|
|
|
353
353
|
style={{ fontFamily: 'inherit' }}
|
|
354
354
|
>
|
|
355
355
|
<div className="relative">
|
|
356
|
-
<AgentAvatar seed={agent.avatarSeed} name={agent.name} size={36} />
|
|
356
|
+
<AgentAvatar seed={agent.avatarSeed} avatarUrl={agent.avatarUrl} name={agent.name} size={36} />
|
|
357
357
|
<div className={`absolute -bottom-0.5 -right-0.5 w-2.5 h-2.5 rounded-full border-2 border-surface ${
|
|
358
358
|
isTyping ? 'bg-accent-bright animate-pulse'
|
|
359
359
|
: isOnline ? 'bg-emerald-400 shadow-[0_0_6px_rgba(52,211,153,0.4)]'
|
|
@@ -414,6 +414,7 @@ export function HomeView() {
|
|
|
414
414
|
>
|
|
415
415
|
<AgentAvatar
|
|
416
416
|
seed={agent?.avatarSeed}
|
|
417
|
+
avatarUrl={agent?.avatarUrl}
|
|
417
418
|
name={displayName}
|
|
418
419
|
size={28}
|
|
419
420
|
/>
|
|
@@ -8,6 +8,7 @@ import { useAutoResize } from '@/hooks/use-auto-resize'
|
|
|
8
8
|
import { useSpeechRecognition } from '@/hooks/use-speech-recognition'
|
|
9
9
|
import { FilePreview } from '@/components/shared/file-preview'
|
|
10
10
|
import { Tooltip, TooltipTrigger, TooltipContent } from '@/components/ui/tooltip'
|
|
11
|
+
import { safeStorageGet, safeStorageRemove, safeStorageSet } from '@/lib/safe-storage'
|
|
11
12
|
|
|
12
13
|
interface Props {
|
|
13
14
|
streaming: boolean
|
|
@@ -36,7 +37,7 @@ export function ChatInput({ streaming, onSend, onStop }: Props) {
|
|
|
36
37
|
const draftTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
|
37
38
|
useEffect(() => {
|
|
38
39
|
if (!sessionId) return
|
|
39
|
-
const draft =
|
|
40
|
+
const draft = safeStorageGet(`sc_draft_${sessionId}`)
|
|
40
41
|
setValue(draft || '')
|
|
41
42
|
}, [sessionId])
|
|
42
43
|
|
|
@@ -45,8 +46,8 @@ export function ChatInput({ streaming, onSend, onStop }: Props) {
|
|
|
45
46
|
if (!sessionId) return
|
|
46
47
|
if (draftTimerRef.current) clearTimeout(draftTimerRef.current)
|
|
47
48
|
draftTimerRef.current = setTimeout(() => {
|
|
48
|
-
if (value)
|
|
49
|
-
else
|
|
49
|
+
if (value) safeStorageSet(`sc_draft_${sessionId}`, value)
|
|
50
|
+
else safeStorageRemove(`sc_draft_${sessionId}`)
|
|
50
51
|
}, 300)
|
|
51
52
|
return () => { if (draftTimerRef.current) clearTimeout(draftTimerRef.current) }
|
|
52
53
|
}, [value, sessionId])
|
|
@@ -65,7 +66,7 @@ export function ChatInput({ streaming, onSend, onStop }: Props) {
|
|
|
65
66
|
}
|
|
66
67
|
onSend(text || 'See attached file(s).')
|
|
67
68
|
setValue('')
|
|
68
|
-
if (sessionId)
|
|
69
|
+
if (sessionId) safeStorageRemove(`sc_draft_${sessionId}`)
|
|
69
70
|
if (textareaRef.current) {
|
|
70
71
|
textareaRef.current.style.height = 'auto'
|
|
71
72
|
}
|
|
@@ -183,7 +183,7 @@ export function KnowledgeList() {
|
|
|
183
183
|
<div className="flex items-center gap-1.5">
|
|
184
184
|
<div className="flex items-center -space-x-1.5">
|
|
185
185
|
{scopedAgents.slice(0, 5).map((agent) => (
|
|
186
|
-
<AgentAvatar key={agent.id} seed={agent.avatarSeed} name={agent.name} size={16} className="ring-1 ring-surface" />
|
|
186
|
+
<AgentAvatar key={agent.id} seed={agent.avatarSeed} avatarUrl={agent.avatarUrl} name={agent.name} size={16} className="ring-1 ring-surface" />
|
|
187
187
|
))}
|
|
188
188
|
</div>
|
|
189
189
|
{scopedAgents.length > 5 && (
|
|
@@ -360,7 +360,7 @@ export function KnowledgeSheet() {
|
|
|
360
360
|
}`}
|
|
361
361
|
style={{ fontFamily: 'inherit' }}
|
|
362
362
|
>
|
|
363
|
-
<AgentAvatar seed={agent.avatarSeed} name={agent.name} size={24} />
|
|
363
|
+
<AgentAvatar seed={agent.avatarSeed} avatarUrl={agent.avatarUrl} name={agent.name} size={24} />
|
|
364
364
|
<span className="text-[13px] text-text flex-1 truncate">{agent.name}</span>
|
|
365
365
|
{selected && (
|
|
366
366
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" className="text-accent-bright shrink-0">
|
|
@@ -41,6 +41,7 @@ import { PluginSheet } from '@/components/plugins/plugin-sheet'
|
|
|
41
41
|
import { RunList } from '@/components/runs/run-list'
|
|
42
42
|
import { ActivityFeed } from '@/components/activity/activity-feed'
|
|
43
43
|
import { MetricsDashboard } from '@/components/usage/metrics-dashboard'
|
|
44
|
+
import { WalletPanel } from '@/components/wallets/wallet-panel'
|
|
44
45
|
import { ProjectList } from '@/components/projects/project-list'
|
|
45
46
|
import { ProjectDetail } from '@/components/projects/project-detail'
|
|
46
47
|
import { ProjectSheet } from '@/components/projects/project-sheet'
|
|
@@ -58,6 +59,7 @@ import { ChatArea } from '@/components/chat/chat-area'
|
|
|
58
59
|
import { CanvasPanel } from '@/components/canvas/canvas-panel'
|
|
59
60
|
import { Tooltip, TooltipTrigger, TooltipContent } from '@/components/ui/tooltip'
|
|
60
61
|
import { api } from '@/lib/api-client'
|
|
62
|
+
import { safeStorageGet, safeStorageSet } from '@/lib/safe-storage'
|
|
61
63
|
import type { AppView } from '@/types'
|
|
62
64
|
|
|
63
65
|
const RAIL_EXPANDED_KEY = 'sc_rail_expanded'
|
|
@@ -118,9 +120,8 @@ export function AppLayout() {
|
|
|
118
120
|
}, [handleShortcutKey])
|
|
119
121
|
|
|
120
122
|
useEffect(() => {
|
|
121
|
-
if (
|
|
122
|
-
|
|
123
|
-
localStorage.setItem(STAR_NOTIFICATION_KEY, '1')
|
|
123
|
+
if (safeStorageGet(STAR_NOTIFICATION_KEY)) return
|
|
124
|
+
safeStorageSet(STAR_NOTIFICATION_KEY, '1')
|
|
124
125
|
void api('POST', '/notifications', {
|
|
125
126
|
type: 'info',
|
|
126
127
|
title: 'Enjoying SwarmClaw?',
|
|
@@ -143,15 +144,14 @@ export function AppLayout() {
|
|
|
143
144
|
}, [appSettings.themeHue])
|
|
144
145
|
|
|
145
146
|
const [railExpanded, setRailExpanded] = useState(() => {
|
|
146
|
-
|
|
147
|
-
const stored = localStorage.getItem(RAIL_EXPANDED_KEY)
|
|
147
|
+
const stored = safeStorageGet(RAIL_EXPANDED_KEY)
|
|
148
148
|
return stored === null ? true : stored === 'true'
|
|
149
149
|
})
|
|
150
150
|
|
|
151
151
|
const toggleRail = () => {
|
|
152
152
|
const next = !railExpanded
|
|
153
153
|
setRailExpanded(next)
|
|
154
|
-
|
|
154
|
+
safeStorageSet(RAIL_EXPANDED_KEY, String(next))
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
const handleSwitchUser = () => {
|
|
@@ -399,6 +399,11 @@ export function AppLayout() {
|
|
|
399
399
|
<line x1="18" y1="20" x2="18" y2="10" /><line x1="12" y1="20" x2="12" y2="4" /><line x1="6" y1="20" x2="6" y2="14" />
|
|
400
400
|
</svg>
|
|
401
401
|
</NavItem>
|
|
402
|
+
<NavItem view="wallets" label="Wallets" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('wallets')}>
|
|
403
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
404
|
+
<rect x="2" y="6" width="20" height="14" rx="2" /><path d="M22 10H18a2 2 0 0 0 0 4h4" /><path d="M6 6V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v2" />
|
|
405
|
+
</svg>
|
|
406
|
+
</NavItem>
|
|
402
407
|
<NavItem view="runs" label="Runs" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('runs')}>
|
|
403
408
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
404
409
|
<polyline points="22 12 18 12 15 21 9 3 6 12 2 12" />
|
|
@@ -520,8 +525,8 @@ export function AppLayout() {
|
|
|
520
525
|
</div>
|
|
521
526
|
)}
|
|
522
527
|
|
|
523
|
-
{/* Desktop: Side panel */}
|
|
524
|
-
{isDesktop && sidebarOpen && (
|
|
528
|
+
{/* Desktop: Side panel (wallets has its own built-in sidebar) */}
|
|
529
|
+
{isDesktop && sidebarOpen && activeView !== 'wallets' && (
|
|
525
530
|
<div
|
|
526
531
|
className="w-[280px] shrink-0 bg-raised border-r border-white/[0.04] flex flex-col h-full"
|
|
527
532
|
style={{ animation: 'panel-in 0.2s cubic-bezier(0.16, 1, 0.3, 1)' }}
|
|
@@ -728,6 +733,8 @@ export function AppLayout() {
|
|
|
728
733
|
<ActivityFeed />
|
|
729
734
|
) : activeView === 'usage' ? (
|
|
730
735
|
<MetricsDashboard />
|
|
736
|
+
) : activeView === 'wallets' ? (
|
|
737
|
+
<WalletPanel />
|
|
731
738
|
) : activeView === 'chatrooms' ? (
|
|
732
739
|
<div className="flex-1 flex h-full min-w-0">
|
|
733
740
|
<div className="w-[280px] shrink-0 border-r border-white/[0.06] flex flex-col">
|
|
@@ -887,6 +894,7 @@ const VIEW_DESCRIPTIONS: Record<AppView, string> = {
|
|
|
887
894
|
logs: 'Application logs & error tracking',
|
|
888
895
|
plugins: 'Extend agent capabilities with custom plugins',
|
|
889
896
|
usage: 'Usage metrics, cost tracking & agent performance',
|
|
897
|
+
wallets: 'Agent crypto wallets — hold funds, send SOL, manage spending',
|
|
890
898
|
runs: 'Live run monitoring & history',
|
|
891
899
|
settings: 'Manage providers, API keys & orchestrator engine',
|
|
892
900
|
projects: 'Group agents, tasks & schedules into projects',
|
|
@@ -896,7 +904,7 @@ const VIEW_DESCRIPTIONS: Record<AppView, string> = {
|
|
|
896
904
|
const FULL_WIDTH_VIEWS = new Set<AppView>([
|
|
897
905
|
'home', 'chatrooms', 'schedules', 'secrets', 'providers', 'skills',
|
|
898
906
|
'connectors', 'webhooks', 'mcp_servers', 'knowledge', 'plugins',
|
|
899
|
-
'usage', 'runs', 'logs', 'settings', 'activity', 'projects',
|
|
907
|
+
'usage', 'wallets', 'runs', 'logs', 'settings', 'activity', 'projects',
|
|
900
908
|
])
|
|
901
909
|
|
|
902
910
|
const VIEW_EMPTY_STATES: Record<Exclude<AppView, 'agents' | 'home'>, { icon: string; title: string; description: string; features: string[] }> = {
|
|
@@ -1008,6 +1016,12 @@ const VIEW_EMPTY_STATES: Record<Exclude<AppView, 'agents' | 'home'>, { icon: str
|
|
|
1008
1016
|
description: 'Audit trail of all entity mutations across the system.',
|
|
1009
1017
|
features: ['Track agent, task, and connector changes', 'Filter by entity type and action', 'Real-time updates via WebSocket', 'Relative timestamps'],
|
|
1010
1018
|
},
|
|
1019
|
+
wallets: {
|
|
1020
|
+
icon: 'wallet',
|
|
1021
|
+
title: 'Wallets',
|
|
1022
|
+
description: 'Agent crypto wallets for autonomous financial operations on Solana.',
|
|
1023
|
+
features: ['Create Solana wallets for agents', 'Per-transaction and daily spending limits', 'User approval for transactions', 'Balance tracking and transaction history'],
|
|
1024
|
+
},
|
|
1011
1025
|
}
|
|
1012
1026
|
|
|
1013
1027
|
function ViewEmptyState({ view }: { view: AppView }) {
|
|
@@ -5,6 +5,7 @@ import { api } from '@/lib/api-client'
|
|
|
5
5
|
import { useWs } from '@/hooks/use-ws'
|
|
6
6
|
import { useAppStore } from '@/stores/use-app-store'
|
|
7
7
|
import { BottomSheet } from '@/components/shared/bottom-sheet'
|
|
8
|
+
import { safeStorageGetJson, safeStorageSet } from '@/lib/safe-storage'
|
|
8
9
|
|
|
9
10
|
interface LogEntry {
|
|
10
11
|
time: string
|
|
@@ -38,10 +39,9 @@ export function LogList() {
|
|
|
38
39
|
const [selected, setSelected] = useState<LogEntry | null>(null)
|
|
39
40
|
const [creatingTask, setCreatingTask] = useState(false)
|
|
40
41
|
const [taskAgentId, setTaskAgentId] = useState('')
|
|
41
|
-
const [savedFilters, setSavedFilters] = useState<Array<{ name: string; levels: string[]; search: string }>>(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
})
|
|
42
|
+
const [savedFilters, setSavedFilters] = useState<Array<{ name: string; levels: string[]; search: string }>>(
|
|
43
|
+
() => safeStorageGetJson<Array<{ name: string; levels: string[]; search: string }>>('sc_log_filters', []),
|
|
44
|
+
)
|
|
45
45
|
const scrollRef = useRef<HTMLDivElement>(null)
|
|
46
46
|
|
|
47
47
|
const agents = useAppStore((s) => s.agents)
|
|
@@ -169,7 +169,7 @@ export function LogList() {
|
|
|
169
169
|
onClick={(e) => {
|
|
170
170
|
e.stopPropagation()
|
|
171
171
|
const next = savedFilters.filter((_, j) => j !== i)
|
|
172
|
-
|
|
172
|
+
safeStorageSet('sc_log_filters', JSON.stringify(next))
|
|
173
173
|
setSavedFilters(next)
|
|
174
174
|
}}
|
|
175
175
|
className="text-accent-bright/50 hover:text-red-400 ml-0.5"
|
|
@@ -232,9 +232,9 @@ export function LogList() {
|
|
|
232
232
|
const name = prompt('Filter name:')
|
|
233
233
|
if (!name?.trim()) return
|
|
234
234
|
const filter = { name: name.trim(), levels: levelFilter, search }
|
|
235
|
-
const existing =
|
|
235
|
+
const existing = safeStorageGetJson<Array<{ name: string; levels: string[]; search: string }>>('sc_log_filters', [])
|
|
236
236
|
existing.push(filter)
|
|
237
|
-
|
|
237
|
+
safeStorageSet('sc_log_filters', JSON.stringify(existing))
|
|
238
238
|
setSavedFilters(existing)
|
|
239
239
|
}}
|
|
240
240
|
className="px-2 py-1 rounded-[6px] text-[10px] font-600 cursor-pointer transition-all border-none bg-white/[0.04] text-text-3 hover:text-accent-bright hover:bg-accent-soft"
|
|
@@ -120,7 +120,7 @@ export function MemoryAgentList() {
|
|
|
120
120
|
{isActive && (
|
|
121
121
|
<div className="absolute left-0 top-2 bottom-2 w-[2.5px] rounded-full bg-accent-bright" />
|
|
122
122
|
)}
|
|
123
|
-
<AgentAvatar seed={agent.avatarSeed || null} name={agent.name} size={28} />
|
|
123
|
+
<AgentAvatar seed={agent.avatarSeed || null} avatarUrl={agent.avatarUrl} name={agent.name} size={28} />
|
|
124
124
|
<span className={`text-[13px] font-600 flex-1 truncate ${isActive ? 'text-accent-bright' : 'text-text-2'}`}>
|
|
125
125
|
{agent.name}
|
|
126
126
|
</span>
|
|
@@ -163,6 +163,7 @@ export function MemoryBrowser() {
|
|
|
163
163
|
active={e.id === selectedMemoryId}
|
|
164
164
|
agentName={showAgent ? (agent?.name || null) : undefined}
|
|
165
165
|
agentAvatarSeed={showAgent ? (agent?.avatarSeed || null) : undefined}
|
|
166
|
+
agentAvatarUrl={showAgent ? (agent?.avatarUrl || null) : undefined}
|
|
166
167
|
onClick={() => setSelectedMemoryId(e.id)}
|
|
167
168
|
/>
|
|
168
169
|
)
|
|
@@ -17,10 +17,11 @@ interface Props {
|
|
|
17
17
|
active?: boolean
|
|
18
18
|
agentName?: string | null
|
|
19
19
|
agentAvatarSeed?: string | null
|
|
20
|
+
agentAvatarUrl?: string | null
|
|
20
21
|
onClick: () => void
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
export function MemoryCard({ entry, active, agentName, agentAvatarSeed, onClick }: Props) {
|
|
24
|
+
export function MemoryCard({ entry, active, agentName, agentAvatarSeed, agentAvatarUrl, onClick }: Props) {
|
|
24
25
|
return (
|
|
25
26
|
<div
|
|
26
27
|
onClick={onClick}
|
|
@@ -73,7 +74,7 @@ export function MemoryCard({ entry, active, agentName, agentAvatarSeed, onClick
|
|
|
73
74
|
)}
|
|
74
75
|
{agentName ? (
|
|
75
76
|
<div className="flex items-center gap-1.5 mt-1.5">
|
|
76
|
-
<AgentAvatar seed={agentAvatarSeed || null} name={agentName} size={16} />
|
|
77
|
+
<AgentAvatar seed={agentAvatarSeed || null} avatarUrl={agentAvatarUrl} name={agentName} size={16} />
|
|
77
78
|
<span className="text-[10px] text-text-3/60 truncate">{agentName}</span>
|
|
78
79
|
</div>
|
|
79
80
|
) : !entry.agentId ? (
|
|
@@ -329,7 +329,7 @@ export function MemoryDetail() {
|
|
|
329
329
|
: 'bg-white/[0.02] border-white/[0.06] text-text-3 hover:text-text-2 hover:bg-white/[0.04]'}`}
|
|
330
330
|
style={{ fontFamily: 'inherit' }}
|
|
331
331
|
>
|
|
332
|
-
<AgentAvatar seed={agent.avatarSeed || null} name={agent.name} size={16} />
|
|
332
|
+
<AgentAvatar seed={agent.avatarSeed || null} avatarUrl={agent.avatarUrl} name={agent.name} size={16} />
|
|
333
333
|
<span className="truncate max-w-[100px]">{agent.name}</span>
|
|
334
334
|
</button>
|
|
335
335
|
))}
|
|
@@ -360,7 +360,7 @@ export function MemoryDetail() {
|
|
|
360
360
|
: 'bg-white/[0.02] border-white/[0.06] text-text-3 hover:text-text-2 hover:bg-white/[0.04]'}`}
|
|
361
361
|
style={{ fontFamily: 'inherit' }}
|
|
362
362
|
>
|
|
363
|
-
<AgentAvatar seed={agent.avatarSeed || null} name={agent.name} size={16} />
|
|
363
|
+
<AgentAvatar seed={agent.avatarSeed || null} avatarUrl={agent.avatarUrl} name={agent.name} size={16} />
|
|
364
364
|
<span className="truncate max-w-[100px]">{agent.name}</span>
|
|
365
365
|
</button>
|
|
366
366
|
)
|
|
@@ -406,7 +406,7 @@ export function MemoryDetail() {
|
|
|
406
406
|
const a = agents[aid]
|
|
407
407
|
return (
|
|
408
408
|
<span key={aid} className="flex items-center gap-1.5 px-2.5 py-1 rounded-[8px] bg-white/[0.03] text-[11px] text-text-3">
|
|
409
|
-
<AgentAvatar seed={a?.avatarSeed || null} name={a?.name || aid} size={16} />
|
|
409
|
+
<AgentAvatar seed={a?.avatarSeed || null} avatarUrl={a?.avatarUrl} name={a?.name || aid} size={16} />
|
|
410
410
|
{a?.name || aid}
|
|
411
411
|
</span>
|
|
412
412
|
)
|
|
@@ -104,7 +104,7 @@ export function MemorySheet() {
|
|
|
104
104
|
: 'bg-white/[0.02] border-white/[0.06] text-text-3 hover:text-text-2 hover:bg-white/[0.04]'}`}
|
|
105
105
|
style={{ fontFamily: 'inherit' }}
|
|
106
106
|
>
|
|
107
|
-
<AgentAvatar seed={agent.avatarSeed || null} name={agent.name} size={20} />
|
|
107
|
+
<AgentAvatar seed={agent.avatarSeed || null} avatarUrl={agent.avatarUrl} name={agent.name} size={20} />
|
|
108
108
|
<span className="truncate max-w-[120px]">{agent.name}</span>
|
|
109
109
|
</button>
|
|
110
110
|
))}
|
|
@@ -140,7 +140,7 @@ export function MemorySheet() {
|
|
|
140
140
|
: 'bg-white/[0.02] border-white/[0.06] text-text-3 hover:text-text-2 hover:bg-white/[0.04]'}`}
|
|
141
141
|
style={{ fontFamily: 'inherit' }}
|
|
142
142
|
>
|
|
143
|
-
<AgentAvatar seed={agent.avatarSeed || null} name={agent.name} size={20} />
|
|
143
|
+
<AgentAvatar seed={agent.avatarSeed || null} avatarUrl={agent.avatarUrl} name={agent.name} size={20} />
|
|
144
144
|
<span className="truncate max-w-[120px]">{agent.name}</span>
|
|
145
145
|
</button>
|
|
146
146
|
)
|
|
@@ -68,7 +68,7 @@ function AssignAgentPicker({ projectId, onClose }: { projectId: string; onClose:
|
|
|
68
68
|
className="w-full flex items-center gap-2.5 px-3 py-2 rounded-[8px] text-left hover:bg-white/[0.06] transition-colors cursor-pointer bg-transparent border-none"
|
|
69
69
|
style={{ fontFamily: 'inherit' }}
|
|
70
70
|
>
|
|
71
|
-
<AgentAvatar seed={a.avatarSeed} name={a.name} size={22} />
|
|
71
|
+
<AgentAvatar seed={a.avatarSeed} avatarUrl={a.avatarUrl} name={a.name} size={22} />
|
|
72
72
|
<div className="min-w-0 flex-1">
|
|
73
73
|
<div className="text-[12px] text-text truncate">{a.name}</div>
|
|
74
74
|
<div className="text-[10px] text-text-3/40 truncate">{a.model || a.provider}</div>
|
|
@@ -312,7 +312,7 @@ export function ProjectDetail() {
|
|
|
312
312
|
className="flex items-center gap-3 flex-1 min-w-0 cursor-pointer bg-transparent border-none text-left p-0"
|
|
313
313
|
style={{ fontFamily: 'inherit' }}
|
|
314
314
|
>
|
|
315
|
-
<AgentAvatar seed={agent.avatarSeed} name={agent.name} size={28} />
|
|
315
|
+
<AgentAvatar seed={agent.avatarSeed} avatarUrl={agent.avatarUrl} name={agent.name} size={28} />
|
|
316
316
|
<div className="min-w-0 flex-1">
|
|
317
317
|
<div className="text-[13px] font-600 text-text truncate">{agent.name}</div>
|
|
318
318
|
<div className="text-[11px] text-text-3/50 truncate">{agent.model || agent.provider}</div>
|
|
@@ -381,7 +381,7 @@ export function ProjectDetail() {
|
|
|
381
381
|
<span className="text-[13px] text-text truncate flex-1">{task.title}</span>
|
|
382
382
|
{agent && (
|
|
383
383
|
<span className="shrink-0 flex items-center gap-1.5 text-[11px] text-text-3/40">
|
|
384
|
-
<AgentAvatar seed={agent.avatarSeed} name={agent.name} size={16} />
|
|
384
|
+
<AgentAvatar seed={agent.avatarSeed} avatarUrl={agent.avatarUrl} name={agent.name} size={16} />
|
|
385
385
|
{agent.name}
|
|
386
386
|
</span>
|
|
387
387
|
)}
|
|
@@ -448,7 +448,7 @@ export function ProjectDetail() {
|
|
|
448
448
|
</span>
|
|
449
449
|
{agent && (
|
|
450
450
|
<span className="shrink-0 flex items-center gap-1.5 text-[11px] text-text-3/40">
|
|
451
|
-
<AgentAvatar seed={agent.avatarSeed} name={agent.name} size={16} />
|
|
451
|
+
<AgentAvatar seed={agent.avatarSeed} avatarUrl={agent.avatarUrl} name={agent.name} size={16} />
|
|
452
452
|
</span>
|
|
453
453
|
)}
|
|
454
454
|
{schedule.nextRunAt && (
|
|
@@ -161,7 +161,7 @@ export function SecretSheet() {
|
|
|
161
161
|
}`}
|
|
162
162
|
style={{ fontFamily: 'inherit' }}
|
|
163
163
|
>
|
|
164
|
-
<AgentAvatar seed={agent.avatarSeed} name={agent.name} size={24} />
|
|
164
|
+
<AgentAvatar seed={agent.avatarSeed} avatarUrl={agent.avatarUrl} name={agent.name} size={24} />
|
|
165
165
|
<span className="text-[13px] text-text flex-1 truncate">{agent.name}</span>
|
|
166
166
|
{selected && (
|
|
167
167
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" className="text-accent-bright shrink-0">
|
|
@@ -102,7 +102,7 @@ export function SecretsList({ inSidebar }: Props) {
|
|
|
102
102
|
<div className="flex items-center gap-1.5 mt-1.5 pl-[22px]">
|
|
103
103
|
<div className="flex items-center -space-x-1.5">
|
|
104
104
|
{scopedAgents.slice(0, 5).map((agent) => (
|
|
105
|
-
<AgentAvatar key={agent.id} seed={agent.avatarSeed} name={agent.name} size={16} className="ring-1 ring-surface" />
|
|
105
|
+
<AgentAvatar key={agent.id} seed={agent.avatarSeed} avatarUrl={agent.avatarUrl} name={agent.name} size={16} className="ring-1 ring-surface" />
|
|
106
106
|
))}
|
|
107
107
|
</div>
|
|
108
108
|
{scopedAgents.length > 5 && (
|
|
@@ -13,6 +13,7 @@ import { SheetFooter } from '@/components/shared/sheet-footer'
|
|
|
13
13
|
import { inputClass } from '@/components/shared/form-styles'
|
|
14
14
|
import type { ProviderType, SessionTool } from '@/types'
|
|
15
15
|
import { SectionLabel } from '@/components/shared/section-label'
|
|
16
|
+
import { safeStorageGet, safeStorageRemove, safeStorageSet } from '@/lib/safe-storage'
|
|
16
17
|
|
|
17
18
|
export function NewSessionSheet() {
|
|
18
19
|
const open = useAppStore((s) => s.newSessionOpen)
|
|
@@ -64,7 +65,7 @@ export function NewSessionSheet() {
|
|
|
64
65
|
setOllamaMode('local')
|
|
65
66
|
// Auto-select last used agent, or default agent if no history
|
|
66
67
|
const agentsList = Object.values(agents)
|
|
67
|
-
const lastAgentId =
|
|
68
|
+
const lastAgentId = safeStorageGet('swarmclaw-last-agent')
|
|
68
69
|
const lastAgent = lastAgentId ? agentsList.find((a) => a.id === lastAgentId) : null
|
|
69
70
|
const defaultAgent = lastAgent || agentsList.find((a) => a.id === 'default') || agentsList[0]
|
|
70
71
|
if (defaultAgent) {
|
|
@@ -153,9 +154,9 @@ export function NewSessionSheet() {
|
|
|
153
154
|
)
|
|
154
155
|
// Remember agent selection for next time
|
|
155
156
|
if (selectedAgentId) {
|
|
156
|
-
|
|
157
|
+
safeStorageSet('swarmclaw-last-agent', selectedAgentId)
|
|
157
158
|
} else {
|
|
158
|
-
|
|
159
|
+
safeStorageRemove('swarmclaw-last-agent')
|
|
159
160
|
}
|
|
160
161
|
updateSessionInStore(s)
|
|
161
162
|
setCurrentSession(s.id)
|
|
@@ -86,7 +86,7 @@ export function SessionCard({ session, active, onClick }: Props) {
|
|
|
86
86
|
<div className="flex items-center gap-2.5">
|
|
87
87
|
{agent && (
|
|
88
88
|
<div className="relative shrink-0">
|
|
89
|
-
<AgentAvatar seed={agent.avatarSeed} name={agent.name} size={24} />
|
|
89
|
+
<AgentAvatar seed={agent.avatarSeed} avatarUrl={agent.avatarUrl} name={agent.name} size={24} />
|
|
90
90
|
{(heartbeatEnabled || session.active) && (
|
|
91
91
|
<span className="absolute -bottom-0.5 -right-0.5 w-2 h-2 rounded-full bg-emerald-400 ring-2 ring-[#0f0f1a]" />
|
|
92
92
|
)}
|
|
@@ -72,7 +72,7 @@ export function AgentPickerList({
|
|
|
72
72
|
{active && (
|
|
73
73
|
<div className="absolute left-0 top-2 bottom-2 w-[2.5px] rounded-full bg-accent-bright" />
|
|
74
74
|
)}
|
|
75
|
-
<AgentAvatar seed={a.avatarSeed || null} name={a.name} size={28} />
|
|
75
|
+
<AgentAvatar seed={a.avatarSeed || null} avatarUrl={a.avatarUrl} name={a.name} size={28} />
|
|
76
76
|
<span className={`text-[13px] font-600 flex-1 truncate ${active ? 'text-accent-bright' : 'text-text-2'}`}>
|
|
77
77
|
{a.name}
|
|
78
78
|
</span>
|
|
@@ -115,7 +115,7 @@ export function AgentSwitchDialog() {
|
|
|
115
115
|
${idx === selectedIdx ? 'bg-white/[0.06]' : 'hover:bg-white/[0.04]'}`}
|
|
116
116
|
style={{ fontFamily: 'inherit' }}
|
|
117
117
|
>
|
|
118
|
-
<AgentAvatar seed={agent.avatarSeed} name={agent.name} size={28} />
|
|
118
|
+
<AgentAvatar seed={agent.avatarSeed} avatarUrl={agent.avatarUrl} name={agent.name} size={28} />
|
|
119
119
|
<div className="flex-1 min-w-0">
|
|
120
120
|
<div className="flex items-center gap-2">
|
|
121
121
|
<span className="text-[13px] font-500 text-text truncate">{agent.name}</span>
|
|
@@ -35,11 +35,11 @@ export function UserPreferencesSection({ appSettings, patchSettings, inputClass
|
|
|
35
35
|
</div>
|
|
36
36
|
<button
|
|
37
37
|
type="button"
|
|
38
|
-
onClick={() => patchSettings({ suggestionsEnabled: appSettings.suggestionsEnabled
|
|
39
|
-
className={`relative w-9 h-5 rounded-full transition-colors ${appSettings.suggestionsEnabled
|
|
38
|
+
onClick={() => patchSettings({ suggestionsEnabled: !appSettings.suggestionsEnabled })}
|
|
39
|
+
className={`relative w-9 h-5 rounded-full transition-colors ${appSettings.suggestionsEnabled ? 'bg-accent-bright' : 'bg-white/[0.10]'}`}
|
|
40
40
|
style={{ fontFamily: 'inherit' }}
|
|
41
41
|
>
|
|
42
|
-
<span className={`absolute top-0.5 left-0.5 w-4 h-4 rounded-full bg-white transition-transform ${appSettings.suggestionsEnabled
|
|
42
|
+
<span className={`absolute top-0.5 left-0.5 w-4 h-4 rounded-full bg-white transition-transform ${appSettings.suggestionsEnabled ? 'translate-x-4' : ''}`} />
|
|
43
43
|
</button>
|
|
44
44
|
</div>
|
|
45
45
|
|
|
@@ -70,7 +70,7 @@ export function UserPreferencesSection({ appSettings, patchSettings, inputClass
|
|
|
70
70
|
: 'bg-transparent border-white/[0.06] text-text-3 hover:bg-white/[0.03]'}`}
|
|
71
71
|
style={{ fontFamily: 'inherit' }}
|
|
72
72
|
>
|
|
73
|
-
<AgentAvatar seed={agent.avatarSeed || null} name={agent.name} size={18} />
|
|
73
|
+
<AgentAvatar seed={agent.avatarSeed || null} avatarUrl={agent.avatarUrl} name={agent.name} size={18} />
|
|
74
74
|
{agent.name}
|
|
75
75
|
</button>
|
|
76
76
|
))}
|
|
@@ -309,7 +309,7 @@ export function SkillList({ inSidebar }: { inSidebar?: boolean }) {
|
|
|
309
309
|
<div className="flex items-center gap-1.5 mt-1.5">
|
|
310
310
|
<div className="flex items-center -space-x-1.5">
|
|
311
311
|
{scopedAgents.slice(0, 5).map((agent) => (
|
|
312
|
-
<AgentAvatar key={agent.id} seed={agent.avatarSeed} name={agent.name} size={16} className="ring-1 ring-surface" />
|
|
312
|
+
<AgentAvatar key={agent.id} seed={agent.avatarSeed} avatarUrl={agent.avatarUrl} name={agent.name} size={16} className="ring-1 ring-surface" />
|
|
313
313
|
))}
|
|
314
314
|
</div>
|
|
315
315
|
{scopedAgents.length > 5 && (
|
|
@@ -255,7 +255,7 @@ export function SkillSheet() {
|
|
|
255
255
|
}`}
|
|
256
256
|
style={{ fontFamily: 'inherit' }}
|
|
257
257
|
>
|
|
258
|
-
<AgentAvatar seed={agent.avatarSeed} name={agent.name} size={24} />
|
|
258
|
+
<AgentAvatar seed={agent.avatarSeed} avatarUrl={agent.avatarUrl} name={agent.name} size={24} />
|
|
259
259
|
<span className="text-[13px] text-text flex-1 truncate">{agent.name}</span>
|
|
260
260
|
{selected && (
|
|
261
261
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" className="text-accent-bright shrink-0">
|
|
@@ -264,7 +264,7 @@ export function TaskBoard() {
|
|
|
264
264
|
>
|
|
265
265
|
{filterAgentId && agents[filterAgentId] ? (
|
|
266
266
|
<>
|
|
267
|
-
<AgentAvatar seed={agents[filterAgentId].avatarSeed || null} name={agents[filterAgentId].name} size={18} />
|
|
267
|
+
<AgentAvatar seed={agents[filterAgentId].avatarSeed || null} avatarUrl={agents[filterAgentId].avatarUrl} name={agents[filterAgentId].name} size={18} />
|
|
268
268
|
{agents[filterAgentId].name}
|
|
269
269
|
</>
|
|
270
270
|
) : 'All Agents'}
|
|
@@ -290,7 +290,7 @@ export function TaskBoard() {
|
|
|
290
290
|
${filterAgentId === a.id ? 'bg-white/[0.06] text-text' : 'bg-transparent text-text-3 hover:bg-white/[0.04]'}`}
|
|
291
291
|
style={{ fontFamily: 'inherit' }}
|
|
292
292
|
>
|
|
293
|
-
<AgentAvatar seed={a.avatarSeed || null} name={a.name} size={20} />
|
|
293
|
+
<AgentAvatar seed={a.avatarSeed || null} avatarUrl={a.avatarUrl} name={a.name} size={20} />
|
|
294
294
|
{a.name}
|
|
295
295
|
</button>
|
|
296
296
|
))}
|
|
@@ -480,7 +480,7 @@ export function TaskBoard() {
|
|
|
480
480
|
className="w-full flex items-center gap-2 px-3 py-2 text-[12px] font-600 cursor-pointer border-none text-left bg-transparent text-text-3 hover:bg-white/[0.06] hover:text-text transition-colors"
|
|
481
481
|
style={{ fontFamily: 'inherit' }}
|
|
482
482
|
>
|
|
483
|
-
<AgentAvatar seed={a.avatarSeed || null} name={a.name} size={16} />
|
|
483
|
+
<AgentAvatar seed={a.avatarSeed || null} avatarUrl={a.avatarUrl} name={a.name} size={16} />
|
|
484
484
|
{a.name}
|
|
485
485
|
</button>
|
|
486
486
|
))}
|