@swarmclawai/swarmclaw 0.6.0 → 0.6.2
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 +15 -2
- package/bin/server-cmd.js +1 -0
- package/package.json +2 -1
- package/src/app/api/canvas/[sessionId]/route.ts +31 -0
- package/src/app/api/chatrooms/[id]/chat/route.ts +10 -136
- package/src/app/api/connectors/[id]/route.ts +1 -0
- package/src/app/api/connectors/route.ts +2 -1
- package/src/app/api/files/open/route.ts +43 -0
- package/src/app/api/search/route.ts +9 -7
- package/src/app/api/sessions/[id]/messages/route.ts +70 -2
- package/src/app/api/sessions/[id]/route.ts +4 -0
- package/src/app/api/tasks/metrics/route.ts +101 -0
- package/src/app/api/tasks/route.ts +17 -2
- package/src/app/api/tts/route.ts +3 -2
- package/src/app/api/tts/stream/route.ts +3 -2
- package/src/app/api/uploads/[filename]/route.ts +19 -34
- package/src/app/api/uploads/route.ts +94 -0
- package/src/app/globals.css +5 -0
- package/src/cli/index.js +16 -1
- package/src/cli/spec.js +26 -0
- package/src/components/agents/agent-card.tsx +3 -3
- package/src/components/agents/agent-chat-list.tsx +29 -6
- package/src/components/agents/agent-sheet.tsx +66 -4
- package/src/components/agents/inspector-panel.tsx +81 -6
- package/src/components/agents/openclaw-skills-panel.tsx +32 -3
- package/src/components/agents/personality-builder.tsx +42 -14
- package/src/components/agents/soul-library-picker.tsx +89 -0
- package/src/components/canvas/canvas-panel.tsx +96 -0
- package/src/components/chat/activity-moment.tsx +8 -4
- package/src/components/chat/chat-area.tsx +46 -22
- package/src/components/chat/chat-header.tsx +455 -286
- package/src/components/chat/chat-preview-panel.tsx +1 -2
- package/src/components/chat/delegation-banner.tsx +371 -0
- package/src/components/chat/file-path-chip.tsx +23 -2
- package/src/components/chat/heartbeat-history-panel.tsx +269 -0
- package/src/components/chat/message-bubble.tsx +315 -25
- package/src/components/chat/message-list.tsx +180 -7
- package/src/components/chat/streaming-bubble.tsx +68 -1
- package/src/components/chat/tool-call-bubble.tsx +45 -3
- package/src/components/chat/transfer-agent-picker.tsx +1 -1
- package/src/components/chatrooms/chatroom-list.tsx +8 -1
- package/src/components/chatrooms/chatroom-message.tsx +8 -3
- package/src/components/chatrooms/chatroom-view.tsx +3 -3
- package/src/components/connectors/connector-list.tsx +168 -90
- package/src/components/connectors/connector-sheet.tsx +68 -16
- package/src/components/home/home-view.tsx +1 -1
- package/src/components/input/chat-input.tsx +28 -2
- package/src/components/layout/app-layout.tsx +19 -2
- package/src/components/projects/project-detail.tsx +1 -1
- package/src/components/schedules/schedule-sheet.tsx +260 -127
- package/src/components/settings/gateway-disconnect-overlay.tsx +80 -0
- package/src/components/shared/agent-switch-dialog.tsx +1 -1
- package/src/components/shared/chatroom-picker-list.tsx +61 -0
- package/src/components/shared/connector-platform-icon.tsx +51 -4
- package/src/components/shared/icon-button.tsx +16 -2
- package/src/components/shared/keyboard-shortcuts-dialog.tsx +1 -1
- package/src/components/shared/search-dialog.tsx +17 -10
- package/src/components/shared/settings/section-embedding.tsx +48 -13
- package/src/components/shared/settings/section-orchestrator.tsx +46 -15
- package/src/components/shared/settings/section-storage.tsx +206 -0
- package/src/components/shared/settings/section-user-preferences.tsx +18 -0
- package/src/components/shared/settings/section-voice.tsx +42 -21
- package/src/components/shared/settings/section-web-search.tsx +30 -6
- package/src/components/shared/settings/settings-page.tsx +3 -1
- package/src/components/shared/settings/storage-browser.tsx +259 -0
- package/src/components/tasks/task-card.tsx +14 -1
- package/src/components/tasks/task-sheet.tsx +328 -3
- package/src/components/usage/metrics-dashboard.tsx +90 -6
- package/src/hooks/use-continuous-speech.ts +10 -4
- package/src/hooks/use-voice-conversation.ts +53 -10
- package/src/hooks/use-ws.ts +4 -2
- package/src/lib/providers/anthropic.ts +13 -7
- package/src/lib/providers/index.ts +1 -0
- package/src/lib/providers/openai.ts +13 -7
- package/src/lib/server/chat-execution.ts +51 -11
- package/src/lib/server/chatroom-helpers.ts +146 -0
- package/src/lib/server/connectors/manager.ts +218 -7
- package/src/lib/server/heartbeat-service.ts +8 -1
- package/src/lib/server/main-agent-loop.ts +1 -1
- package/src/lib/server/memory-consolidation.ts +15 -2
- package/src/lib/server/memory-db.ts +134 -6
- package/src/lib/server/mime.ts +51 -0
- package/src/lib/server/openclaw-gateway.ts +2 -2
- package/src/lib/server/orchestrator-lg.ts +2 -0
- package/src/lib/server/orchestrator.ts +5 -2
- package/src/lib/server/playwright-proxy.mjs +2 -3
- package/src/lib/server/prompt-runtime-context.ts +53 -0
- package/src/lib/server/queue.ts +52 -7
- package/src/lib/server/session-tools/canvas.ts +67 -0
- package/src/lib/server/session-tools/connector.ts +83 -9
- package/src/lib/server/session-tools/crud.ts +21 -0
- package/src/lib/server/session-tools/delegate.ts +68 -4
- package/src/lib/server/session-tools/git.ts +71 -0
- package/src/lib/server/session-tools/http.ts +57 -0
- package/src/lib/server/session-tools/index.ts +8 -0
- package/src/lib/server/session-tools/memory.ts +1 -0
- package/src/lib/server/session-tools/search-providers.ts +16 -8
- package/src/lib/server/session-tools/subagent.ts +106 -0
- package/src/lib/server/session-tools/web.ts +115 -4
- package/src/lib/server/stream-agent-chat.ts +32 -10
- package/src/lib/server/task-mention.ts +41 -0
- package/src/lib/sessions.ts +10 -0
- package/src/lib/soul-library.ts +103 -0
- package/src/lib/task-dedupe.ts +26 -0
- package/src/lib/tool-definitions.ts +2 -0
- package/src/lib/tts.ts +2 -2
- package/src/stores/use-app-store.ts +5 -1
- package/src/stores/use-chat-store.ts +65 -2
- package/src/types/index.ts +32 -2
|
@@ -4,7 +4,7 @@ import { useEffect, useCallback, useState, useRef } from 'react'
|
|
|
4
4
|
import { useAppStore } from '@/stores/use-app-store'
|
|
5
5
|
import { useWs } from '@/hooks/use-ws'
|
|
6
6
|
import { useChatStore } from '@/stores/use-chat-store'
|
|
7
|
-
import { fetchMessages, clearMessages, deleteSession, devServer, checkBrowser, stopBrowser } from '@/lib/sessions'
|
|
7
|
+
import { fetchMessages, fetchMessagesPaginated, clearMessages, deleteSession, devServer, checkBrowser, stopBrowser } from '@/lib/sessions'
|
|
8
8
|
import { uploadImage } from '@/lib/upload'
|
|
9
9
|
import { deleteAgent } from '@/lib/agents'
|
|
10
10
|
import { useMediaQuery } from '@/hooks/use-media-query'
|
|
@@ -17,6 +17,7 @@ import { useVoiceConversation } from '@/hooks/use-voice-conversation'
|
|
|
17
17
|
import { ChatInput } from '@/components/input/chat-input'
|
|
18
18
|
import { ChatPreviewPanel } from './chat-preview-panel'
|
|
19
19
|
import { InspectorPanel } from '@/components/agents/inspector-panel'
|
|
20
|
+
import { HeartbeatHistoryPanel } from './heartbeat-history-panel'
|
|
20
21
|
import { Dropdown, DropdownItem } from '@/components/shared/dropdown'
|
|
21
22
|
import { ConfirmDialog } from '@/components/shared/confirm-dialog'
|
|
22
23
|
import { speak } from '@/lib/tts'
|
|
@@ -47,6 +48,8 @@ export function ChatArea() {
|
|
|
47
48
|
const setEditingAgentId = useAppStore((s) => s.setEditingAgentId)
|
|
48
49
|
const setAgentSheetOpen = useAppStore((s) => s.setAgentSheetOpen)
|
|
49
50
|
const inspectorOpen = useAppStore((s) => s.inspectorOpen)
|
|
51
|
+
const sidebarOpen = useAppStore((s) => s.sidebarOpen)
|
|
52
|
+
const setSidebarOpen = useAppStore((s) => s.setSidebarOpen)
|
|
50
53
|
const currentAgent = session?.agentId ? agents[session.agentId] ?? null : null
|
|
51
54
|
|
|
52
55
|
const voice = useVoiceConversation()
|
|
@@ -60,6 +63,8 @@ export function ChatArea() {
|
|
|
60
63
|
const [confirmClear, setConfirmClear] = useState(false)
|
|
61
64
|
const [confirmDeleteAgent, setConfirmDeleteAgent] = useState(false)
|
|
62
65
|
const [browserActive, setBrowserActive] = useState(false)
|
|
66
|
+
const [heartbeatHistoryOpen, setHeartbeatHistoryOpen] = useState(false)
|
|
67
|
+
const [messagesLoading, setMessagesLoading] = useState(true)
|
|
63
68
|
const [isDragging, setIsDragging] = useState(false)
|
|
64
69
|
const dragCounter = useRef(0)
|
|
65
70
|
const setPendingImage = useChatStore((s) => s.setPendingImage)
|
|
@@ -69,13 +74,19 @@ export function ChatArea() {
|
|
|
69
74
|
const chatState = useChatStore.getState()
|
|
70
75
|
const preserveLocalStream = chatState.streaming && chatState.streamingSessionId === sessionId
|
|
71
76
|
// Clear stale state from the previous session, but keep active local stream state for this session.
|
|
77
|
+
setMessagesLoading(true)
|
|
72
78
|
setMessages([])
|
|
73
79
|
if (!preserveLocalStream) {
|
|
74
80
|
useChatStore.setState({ streaming: false, streamingSessionId: null, streamText: '', toolEvents: [] })
|
|
75
81
|
}
|
|
76
|
-
|
|
82
|
+
fetchMessagesPaginated(sessionId, 100).then((data) => {
|
|
83
|
+
setMessages(data.messages)
|
|
84
|
+
useChatStore.setState({ hasMoreMessages: data.hasMore, totalMessages: data.total })
|
|
85
|
+
}).catch((err) => {
|
|
77
86
|
console.error('Failed to load messages:', err)
|
|
78
87
|
setMessages(session?.messages || [])
|
|
88
|
+
}).finally(() => {
|
|
89
|
+
setMessagesLoading(false)
|
|
79
90
|
})
|
|
80
91
|
// If server reports session is still active, show streaming state
|
|
81
92
|
if (session?.active) {
|
|
@@ -125,12 +136,13 @@ export function ChatArea() {
|
|
|
125
136
|
return !isHeartbeat && !!m.text?.trim()
|
|
126
137
|
})
|
|
127
138
|
if (latestAssistant?.text) {
|
|
128
|
-
void speak(latestAssistant.text)
|
|
139
|
+
void speak(latestAssistant.text, currentAgent?.elevenLabsVoiceId)
|
|
129
140
|
}
|
|
130
141
|
}
|
|
131
142
|
}
|
|
132
143
|
if (isServerActiveRef.current) await loadSessions()
|
|
133
144
|
} catch (err) { console.error('Failed to refresh messages:', err) }
|
|
145
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
134
146
|
}, [sessionId])
|
|
135
147
|
|
|
136
148
|
// Subscribe to WS messages for this session — always subscribe when session exists,
|
|
@@ -198,10 +210,6 @@ export function ChatArea() {
|
|
|
198
210
|
setCurrentSession(null)
|
|
199
211
|
}, [sessionId])
|
|
200
212
|
|
|
201
|
-
const handleBack = useCallback(() => {
|
|
202
|
-
setCurrentSession(null)
|
|
203
|
-
}, [])
|
|
204
|
-
|
|
205
213
|
const handlePrompt = useCallback((text: string) => {
|
|
206
214
|
sendMessage(text)
|
|
207
215
|
}, [sendMessage])
|
|
@@ -244,7 +252,7 @@ export function ChatArea() {
|
|
|
244
252
|
|
|
245
253
|
const streamingForThisSession = streaming && (!streamingSessionId || streamingSessionId === session.id)
|
|
246
254
|
const isMainChat = session.name === '__main__'
|
|
247
|
-
const isEmpty = !messages.length && !streamingForThisSession
|
|
255
|
+
const isEmpty = !messages.length && !streamingForThisSession && !messagesLoading
|
|
248
256
|
|
|
249
257
|
return (
|
|
250
258
|
<div className="flex-1 flex h-full min-h-0 min-w-0">
|
|
@@ -261,12 +269,14 @@ export function ChatArea() {
|
|
|
261
269
|
streaming={streamingForThisSession}
|
|
262
270
|
onStop={stopStreaming}
|
|
263
271
|
onMenuToggle={() => setMenuOpen(!menuOpen)}
|
|
264
|
-
onBack={
|
|
272
|
+
onBack={sidebarOpen ? () => setSidebarOpen(false) : undefined}
|
|
265
273
|
browserActive={browserActive}
|
|
266
274
|
onStopBrowser={handleStopBrowser}
|
|
267
275
|
voiceActive={voice.active}
|
|
268
276
|
voiceSupported={voice.supported}
|
|
269
277
|
onVoiceToggle={handleVoiceToggle}
|
|
278
|
+
heartbeatHistoryOpen={heartbeatHistoryOpen}
|
|
279
|
+
onToggleHeartbeatHistory={() => setHeartbeatHistoryOpen((v) => !v)}
|
|
270
280
|
/>
|
|
271
281
|
)}
|
|
272
282
|
{!isDesktop && (
|
|
@@ -285,7 +295,17 @@ export function ChatArea() {
|
|
|
285
295
|
)}
|
|
286
296
|
<DevServerBar status={devServerStatus} onStop={handleStopDevServer} />
|
|
287
297
|
|
|
288
|
-
{
|
|
298
|
+
{messagesLoading && !messages.length ? (
|
|
299
|
+
<div className="flex-1 flex items-center justify-center">
|
|
300
|
+
<div className="flex flex-col items-center gap-3" style={{ animation: 'fade-in 0.2s ease' }}>
|
|
301
|
+
<div className="relative w-10 h-10">
|
|
302
|
+
<div className="absolute inset-0 rounded-full border-2 border-white/[0.06]" />
|
|
303
|
+
<div className="absolute inset-0 rounded-full border-2 border-transparent border-t-accent-bright animate-spin" />
|
|
304
|
+
</div>
|
|
305
|
+
<span className="text-[13px] text-text-3/50 font-500">Loading messages...</span>
|
|
306
|
+
</div>
|
|
307
|
+
</div>
|
|
308
|
+
) : isEmpty ? (
|
|
289
309
|
<div className="flex-1 flex flex-col items-center justify-center px-6 pb-4 relative">
|
|
290
310
|
{/* Atmospheric background glow */}
|
|
291
311
|
<div className="absolute inset-0 pointer-events-none overflow-hidden">
|
|
@@ -361,19 +381,9 @@ export function ChatArea() {
|
|
|
361
381
|
/>
|
|
362
382
|
|
|
363
383
|
<Dropdown open={menuOpen} onClose={() => setMenuOpen(false)}>
|
|
364
|
-
{session.agentId && agents[session.agentId] && (
|
|
365
|
-
<DropdownItem onClick={() => { setMenuOpen(false); setEditingAgentId(session.agentId!); setAgentSheetOpen(true) }}>
|
|
366
|
-
Edit Agent
|
|
367
|
-
</DropdownItem>
|
|
368
|
-
)}
|
|
369
384
|
<DropdownItem onClick={() => { setMenuOpen(false); setConfirmClear(true) }}>
|
|
370
385
|
Clear History
|
|
371
386
|
</DropdownItem>
|
|
372
|
-
{session.agentId && agents[session.agentId] && !isMainChat && (
|
|
373
|
-
<DropdownItem danger onClick={() => { setMenuOpen(false); setConfirmDeleteAgent(true) }}>
|
|
374
|
-
Delete Agent
|
|
375
|
-
</DropdownItem>
|
|
376
|
-
)}
|
|
377
387
|
{!isMainChat && (
|
|
378
388
|
<DropdownItem danger onClick={() => { setMenuOpen(false); setConfirmDelete(true) }}>
|
|
379
389
|
Delete Chat
|
|
@@ -432,7 +442,21 @@ export function ChatArea() {
|
|
|
432
442
|
<ChatPreviewPanel content={previewContent} onClose={() => setPreviewContent(null)} />
|
|
433
443
|
)}
|
|
434
444
|
{isDesktop && inspectorOpen && currentAgent && (
|
|
435
|
-
<InspectorPanel
|
|
445
|
+
<InspectorPanel
|
|
446
|
+
agent={currentAgent}
|
|
447
|
+
onEditAgent={() => { setEditingAgentId(session.agentId!); setAgentSheetOpen(true) }}
|
|
448
|
+
onClearHistory={() => setConfirmClear(true)}
|
|
449
|
+
onDeleteAgent={!isMainChat ? () => setConfirmDeleteAgent(true) : undefined}
|
|
450
|
+
onDeleteChat={!isMainChat ? () => setConfirmDelete(true) : undefined}
|
|
451
|
+
isMainChat={isMainChat}
|
|
452
|
+
/>
|
|
453
|
+
)}
|
|
454
|
+
{isDesktop && heartbeatHistoryOpen && currentAgent?.heartbeatEnabled && (
|
|
455
|
+
<HeartbeatHistoryPanel
|
|
456
|
+
messages={messages}
|
|
457
|
+
agentHeartbeatGoal={currentAgent.heartbeatGoal ?? undefined}
|
|
458
|
+
onClose={() => setHeartbeatHistoryOpen(false)}
|
|
459
|
+
/>
|
|
436
460
|
)}
|
|
437
461
|
</div>
|
|
438
462
|
)
|
|
@@ -442,7 +466,7 @@ function PromptIcon({ type }: { type: string }) {
|
|
|
442
466
|
const cls = "w-5 h-5"
|
|
443
467
|
switch (type) {
|
|
444
468
|
case 'book':
|
|
445
|
-
return <svg className={cls} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" style={{ color: '
|
|
469
|
+
return <svg className={cls} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" style={{ color: 'var(--color-accent-bright)' }}><rect x="3" y="3" width="7" height="7" rx="1" /><rect x="14" y="3" width="7" height="7" rx="1" /><rect x="3" y="14" width="7" height="7" rx="1" /><rect x="14" y="14" width="7" height="7" rx="1" /></svg>
|
|
446
470
|
case 'link':
|
|
447
471
|
return <svg className={cls} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" style={{ color: '#F472B6' }}><path d="M15 7h3a5 5 0 0 1 5 5 5 5 0 0 1-5 5h-3m-6 0H6a5 5 0 0 1-5-5 5 5 0 0 1 5-5h3" /><line x1="8" y1="12" x2="16" y2="12" /></svg>
|
|
448
472
|
case 'bot':
|