@swarmclawai/swarmclaw 0.5.3 → 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 +53 -9
- package/bin/server-cmd.js +1 -0
- package/bin/swarmclaw.js +76 -16
- package/next.config.ts +11 -1
- package/package.json +5 -2
- package/scripts/postinstall.mjs +18 -0
- package/src/app/api/canvas/[sessionId]/route.ts +31 -0
- package/src/app/api/chatrooms/[id]/chat/route.ts +284 -0
- package/src/app/api/chatrooms/[id]/members/route.ts +82 -0
- package/src/app/api/chatrooms/[id]/pins/route.ts +39 -0
- package/src/app/api/chatrooms/[id]/reactions/route.ts +42 -0
- package/src/app/api/chatrooms/[id]/route.ts +84 -0
- package/src/app/api/chatrooms/route.ts +50 -0
- package/src/app/api/connectors/[id]/route.ts +1 -0
- package/src/app/api/connectors/route.ts +2 -1
- package/src/app/api/credentials/route.ts +2 -3
- package/src/app/api/files/open/route.ts +43 -0
- package/src/app/api/knowledge/[id]/route.ts +13 -2
- package/src/app/api/knowledge/route.ts +8 -1
- package/src/app/api/memory/route.ts +8 -0
- package/src/app/api/notifications/route.ts +4 -0
- package/src/app/api/orchestrator/run/route.ts +1 -1
- package/src/app/api/plugins/install/route.ts +2 -2
- package/src/app/api/search/route.ts +53 -1
- package/src/app/api/sessions/[id]/chat/route.ts +2 -0
- package/src/app/api/sessions/[id]/edit-resend/route.ts +1 -1
- package/src/app/api/sessions/[id]/fork/route.ts +1 -1
- 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/sessions/route.ts +3 -3
- package/src/app/api/settings/route.ts +9 -0
- package/src/app/api/setup/check-provider/route.ts +3 -16
- package/src/app/api/skills/[id]/route.ts +6 -0
- package/src/app/api/skills/route.ts +6 -0
- package/src/app/api/tasks/[id]/route.ts +12 -0
- package/src/app/api/tasks/bulk/route.ts +100 -0
- package/src/app/api/tasks/metrics/route.ts +101 -0
- package/src/app/api/tasks/route.ts +18 -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/api/webhooks/[id]/route.ts +15 -1
- package/src/app/globals.css +63 -15
- package/src/app/page.tsx +142 -13
- package/src/cli/index.js +40 -1
- package/src/cli/index.test.js +30 -0
- package/src/cli/spec.js +42 -0
- package/src/components/agents/agent-avatar.tsx +57 -10
- package/src/components/agents/agent-card.tsx +50 -17
- package/src/components/agents/agent-chat-list.tsx +148 -12
- package/src/components/agents/agent-list.tsx +50 -19
- package/src/components/agents/agent-sheet.tsx +120 -65
- 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/auth/access-key-gate.tsx +10 -3
- package/src/components/auth/setup-wizard.tsx +2 -2
- package/src/components/auth/user-picker.tsx +31 -3
- package/src/components/canvas/canvas-panel.tsx +96 -0
- package/src/components/chat/activity-moment.tsx +173 -0
- package/src/components/chat/chat-area.tsx +46 -22
- package/src/components/chat/chat-header.tsx +457 -286
- package/src/components/chat/chat-preview-panel.tsx +1 -2
- package/src/components/chat/chat-tool-toggles.tsx +1 -1
- package/src/components/chat/delegation-banner.tsx +371 -0
- package/src/components/chat/file-path-chip.tsx +146 -0
- package/src/components/chat/heartbeat-history-panel.tsx +269 -0
- package/src/components/chat/markdown-utils.ts +9 -0
- package/src/components/chat/message-bubble.tsx +356 -315
- package/src/components/chat/message-list.tsx +230 -8
- package/src/components/chat/streaming-bubble.tsx +104 -47
- package/src/components/chat/suggestions-bar.tsx +1 -1
- package/src/components/chat/thinking-indicator.tsx +72 -10
- package/src/components/chat/tool-call-bubble.tsx +111 -73
- package/src/components/chat/tool-request-banner.tsx +31 -7
- package/src/components/chat/transfer-agent-picker.tsx +63 -0
- package/src/components/chatrooms/agent-hover-card.tsx +124 -0
- package/src/components/chatrooms/chatroom-input.tsx +320 -0
- package/src/components/chatrooms/chatroom-list.tsx +130 -0
- package/src/components/chatrooms/chatroom-message.tsx +432 -0
- package/src/components/chatrooms/chatroom-sheet.tsx +215 -0
- package/src/components/chatrooms/chatroom-tool-request-banner.tsx +134 -0
- package/src/components/chatrooms/chatroom-typing-bar.tsx +88 -0
- package/src/components/chatrooms/chatroom-view.tsx +344 -0
- package/src/components/chatrooms/reaction-picker.tsx +273 -0
- package/src/components/connectors/connector-list.tsx +168 -90
- package/src/components/connectors/connector-sheet.tsx +95 -56
- package/src/components/home/home-view.tsx +501 -0
- package/src/components/input/chat-input.tsx +107 -43
- package/src/components/knowledge/knowledge-list.tsx +31 -1
- package/src/components/knowledge/knowledge-sheet.tsx +83 -2
- package/src/components/layout/app-layout.tsx +194 -97
- package/src/components/layout/update-banner.tsx +2 -2
- package/src/components/logs/log-list.tsx +2 -2
- package/src/components/mcp-servers/mcp-server-sheet.tsx +1 -1
- package/src/components/memory/memory-agent-list.tsx +143 -0
- package/src/components/memory/memory-browser.tsx +205 -0
- package/src/components/memory/memory-card.tsx +34 -7
- package/src/components/memory/memory-detail.tsx +359 -120
- package/src/components/memory/memory-sheet.tsx +157 -23
- package/src/components/plugins/plugin-list.tsx +1 -1
- package/src/components/plugins/plugin-sheet.tsx +1 -1
- package/src/components/projects/project-detail.tsx +509 -0
- package/src/components/projects/project-list.tsx +195 -59
- package/src/components/providers/provider-list.tsx +2 -2
- package/src/components/providers/provider-sheet.tsx +3 -3
- package/src/components/schedules/schedule-card.tsx +1 -1
- package/src/components/schedules/schedule-list.tsx +1 -1
- package/src/components/schedules/schedule-sheet.tsx +259 -126
- package/src/components/secrets/secret-sheet.tsx +47 -24
- package/src/components/secrets/secrets-list.tsx +18 -8
- package/src/components/sessions/new-session-sheet.tsx +33 -65
- package/src/components/sessions/session-card.tsx +45 -14
- package/src/components/sessions/session-list.tsx +35 -18
- package/src/components/settings/gateway-disconnect-overlay.tsx +80 -0
- package/src/components/shared/agent-picker-list.tsx +90 -0
- package/src/components/shared/agent-switch-dialog.tsx +156 -0
- package/src/components/shared/attachment-chip.tsx +165 -0
- package/src/components/shared/avatar.tsx +10 -1
- package/src/components/shared/chatroom-picker-list.tsx +61 -0
- package/src/components/shared/check-icon.tsx +12 -0
- package/src/components/shared/confirm-dialog.tsx +1 -1
- package/src/components/shared/connector-platform-icon.tsx +51 -4
- package/src/components/shared/empty-state.tsx +32 -0
- package/src/components/shared/file-preview.tsx +34 -0
- package/src/components/shared/form-styles.ts +2 -0
- package/src/components/shared/icon-button.tsx +16 -2
- package/src/components/shared/keyboard-shortcuts-dialog.tsx +116 -0
- package/src/components/shared/notification-center.tsx +44 -6
- package/src/components/shared/profile-sheet.tsx +115 -0
- package/src/components/shared/reply-quote.tsx +26 -0
- package/src/components/shared/search-dialog.tsx +31 -15
- package/src/components/shared/section-label.tsx +12 -0
- package/src/components/shared/settings/plugin-manager.tsx +1 -1
- 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-providers.tsx +1 -1
- package/src/components/shared/settings/section-secrets.tsx +1 -1
- package/src/components/shared/settings/section-storage.tsx +206 -0
- package/src/components/shared/settings/section-theme.tsx +95 -0
- package/src/components/shared/settings/section-user-preferences.tsx +57 -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 +182 -27
- package/src/components/shared/settings/settings-sheet.tsx +9 -73
- package/src/components/shared/settings/storage-browser.tsx +259 -0
- package/src/components/shared/sheet-footer.tsx +33 -0
- package/src/components/skills/skill-list.tsx +61 -30
- package/src/components/skills/skill-sheet.tsx +81 -2
- package/src/components/tasks/task-board.tsx +448 -26
- package/src/components/tasks/task-card.tsx +59 -9
- package/src/components/tasks/task-column.tsx +62 -3
- package/src/components/tasks/task-list.tsx +12 -4
- package/src/components/tasks/task-sheet.tsx +416 -74
- package/src/components/ui/hover-card.tsx +52 -0
- package/src/components/usage/metrics-dashboard.tsx +90 -6
- package/src/components/usage/usage-list.tsx +1 -1
- package/src/components/webhooks/webhook-sheet.tsx +1 -1
- package/src/hooks/use-continuous-speech.ts +10 -4
- package/src/hooks/use-view-router.ts +69 -19
- package/src/hooks/use-voice-conversation.ts +53 -10
- package/src/hooks/use-ws.ts +4 -2
- package/src/instrumentation.ts +15 -1
- package/src/lib/chat.ts +2 -0
- package/src/lib/memory.ts +3 -0
- 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 +75 -15
- package/src/lib/server/chatroom-helpers.ts +146 -0
- package/src/lib/server/connectors/manager.ts +229 -7
- package/src/lib/server/context-manager.ts +225 -13
- package/src/lib/server/create-notification.ts +14 -2
- package/src/lib/server/daemon-state.ts +157 -10
- package/src/lib/server/execution-log.ts +1 -0
- package/src/lib/server/heartbeat-service.ts +48 -6
- package/src/lib/server/heartbeat-wake.ts +110 -0
- package/src/lib/server/langgraph-checkpoint.ts +1 -0
- package/src/lib/server/main-agent-loop.ts +1 -1
- package/src/lib/server/memory-consolidation.ts +105 -0
- package/src/lib/server/memory-db.ts +183 -10
- package/src/lib/server/mime.ts +51 -0
- package/src/lib/server/openclaw-gateway.ts +9 -1
- 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/provider-health.ts +125 -0
- package/src/lib/server/queue.ts +56 -10
- package/src/lib/server/scheduler.ts +8 -0
- package/src/lib/server/session-run-manager.ts +4 -0
- package/src/lib/server/session-tools/canvas.ts +67 -0
- package/src/lib/server/session-tools/chatroom.ts +136 -0
- package/src/lib/server/session-tools/connector.ts +83 -9
- package/src/lib/server/session-tools/context-mgmt.ts +36 -18
- 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 +10 -0
- package/src/lib/server/session-tools/memory.ts +7 -1
- 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/storage.ts +53 -29
- package/src/lib/server/stream-agent-chat.ts +185 -57
- package/src/lib/server/system-events.ts +49 -0
- package/src/lib/server/task-mention.ts +41 -0
- package/src/lib/server/ws-hub.ts +11 -0
- package/src/lib/sessions.ts +10 -0
- package/src/lib/soul-library.ts +103 -0
- package/src/lib/soul-suggestions.ts +109 -0
- package/src/lib/task-dedupe.ts +26 -0
- package/src/lib/tasks.ts +4 -1
- package/src/lib/tool-definitions.ts +2 -0
- package/src/lib/tts.ts +2 -2
- package/src/lib/view-routes.ts +36 -1
- package/src/lib/ws-client.ts +14 -4
- package/src/stores/use-app-store.ts +41 -3
- package/src/stores/use-chat-store.ts +113 -5
- package/src/stores/use-chatroom-store.ts +276 -0
- package/src/types/index.ts +88 -4
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import { Component, useState, useEffect, useCallback } from 'react'
|
|
4
4
|
import type { ReactNode, ErrorInfo } from 'react'
|
|
5
|
-
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
|
|
6
5
|
import { useAppStore } from '@/stores/use-app-store'
|
|
7
6
|
import { useMediaQuery } from '@/hooks/use-media-query'
|
|
8
7
|
import { Avatar } from '@/components/shared/avatar'
|
|
@@ -12,9 +11,9 @@ import { AgentChatList } from '@/components/agents/agent-chat-list'
|
|
|
12
11
|
import { AgentSheet } from '@/components/agents/agent-sheet'
|
|
13
12
|
import { ScheduleList } from '@/components/schedules/schedule-list'
|
|
14
13
|
import { ScheduleSheet } from '@/components/schedules/schedule-sheet'
|
|
15
|
-
import {
|
|
14
|
+
import { MemoryAgentList } from '@/components/memory/memory-agent-list'
|
|
16
15
|
import { MemorySheet } from '@/components/memory/memory-sheet'
|
|
17
|
-
import {
|
|
16
|
+
import { MemoryBrowser } from '@/components/memory/memory-browser'
|
|
18
17
|
import { TaskList } from '@/components/tasks/task-list'
|
|
19
18
|
import { TaskSheet } from '@/components/tasks/task-sheet'
|
|
20
19
|
import { TaskBoard } from '@/components/tasks/task-board'
|
|
@@ -26,6 +25,10 @@ import { SkillList } from '@/components/skills/skill-list'
|
|
|
26
25
|
import { SkillSheet } from '@/components/skills/skill-sheet'
|
|
27
26
|
import { ConnectorList } from '@/components/connectors/connector-list'
|
|
28
27
|
import { ConnectorSheet } from '@/components/connectors/connector-sheet'
|
|
28
|
+
import { ChatroomList } from '@/components/chatrooms/chatroom-list'
|
|
29
|
+
import { ChatroomView } from '@/components/chatrooms/chatroom-view'
|
|
30
|
+
import { ChatroomSheet } from '@/components/chatrooms/chatroom-sheet'
|
|
31
|
+
import { useChatroomStore } from '@/stores/use-chatroom-store'
|
|
29
32
|
import { WebhookList } from '@/components/webhooks/webhook-list'
|
|
30
33
|
import { WebhookSheet } from '@/components/webhooks/webhook-sheet'
|
|
31
34
|
import { LogList } from '@/components/logs/log-list'
|
|
@@ -39,18 +42,27 @@ import { RunList } from '@/components/runs/run-list'
|
|
|
39
42
|
import { ActivityFeed } from '@/components/activity/activity-feed'
|
|
40
43
|
import { MetricsDashboard } from '@/components/usage/metrics-dashboard'
|
|
41
44
|
import { ProjectList } from '@/components/projects/project-list'
|
|
45
|
+
import { ProjectDetail } from '@/components/projects/project-detail'
|
|
42
46
|
import { ProjectSheet } from '@/components/projects/project-sheet'
|
|
43
47
|
import { SearchDialog } from '@/components/shared/search-dialog'
|
|
48
|
+
import { AgentSwitchDialog } from '@/components/shared/agent-switch-dialog'
|
|
49
|
+
import { KeyboardShortcutsDialog } from '@/components/shared/keyboard-shortcuts-dialog'
|
|
50
|
+
import { ProfileSheet } from '@/components/shared/profile-sheet'
|
|
51
|
+
import { HomeView } from '@/components/home/home-view'
|
|
44
52
|
import { NetworkBanner } from './network-banner'
|
|
45
53
|
import { UpdateBanner } from './update-banner'
|
|
46
54
|
import { MobileHeader } from './mobile-header'
|
|
47
55
|
import { DaemonIndicator } from './daemon-indicator'
|
|
48
56
|
import { NotificationCenter } from '@/components/shared/notification-center'
|
|
49
57
|
import { ChatArea } from '@/components/chat/chat-area'
|
|
58
|
+
import { CanvasPanel } from '@/components/canvas/canvas-panel'
|
|
50
59
|
import { Tooltip, TooltipTrigger, TooltipContent } from '@/components/ui/tooltip'
|
|
60
|
+
import { api } from '@/lib/api-client'
|
|
51
61
|
import type { AppView } from '@/types'
|
|
52
62
|
|
|
53
63
|
const RAIL_EXPANDED_KEY = 'sc_rail_expanded'
|
|
64
|
+
const STAR_NOTIFICATION_KEY = 'sc_star_notification_v1'
|
|
65
|
+
const GITHUB_REPO_URL = 'https://github.com/swarmclawai/swarmclaw'
|
|
54
66
|
|
|
55
67
|
export function AppLayout() {
|
|
56
68
|
const currentUser = useAppStore((s) => s.currentUser)
|
|
@@ -58,8 +70,6 @@ export function AppLayout() {
|
|
|
58
70
|
const currentSessionId = useAppStore((s) => s.currentSessionId)
|
|
59
71
|
const sidebarOpen = useAppStore((s) => s.sidebarOpen)
|
|
60
72
|
const setSidebarOpen = useAppStore((s) => s.setSidebarOpen)
|
|
61
|
-
const setUser = useAppStore((s) => s.setUser)
|
|
62
|
-
const setCurrentSession = useAppStore((s) => s.setCurrentSession)
|
|
63
73
|
const activeView = useAppStore((s) => s.activeView)
|
|
64
74
|
const setActiveView = useAppStore((s) => s.setActiveView)
|
|
65
75
|
const setAgentSheetOpen = useAppStore((s) => s.setAgentSheetOpen)
|
|
@@ -79,23 +89,26 @@ export function AppLayout() {
|
|
|
79
89
|
const hasSelectedSession = !!(currentSessionId && sessions[currentSessionId])
|
|
80
90
|
const pendingApprovalCount = Object.values(tasks).filter((t) => t.pendingApproval).length
|
|
81
91
|
|
|
92
|
+
const appSettings = useAppStore((s) => s.appSettings)
|
|
82
93
|
const [agentViewMode, setAgentViewMode] = useState<'chat' | 'config'>('chat')
|
|
83
|
-
const [
|
|
94
|
+
const [profileSheetOpen, setProfileSheetOpen] = useState(false)
|
|
95
|
+
const [canvasDismissedFor, setCanvasDismissedFor] = useState<string | null>(null)
|
|
84
96
|
|
|
85
97
|
const handleShortcutKey = useCallback((e: KeyboardEvent) => {
|
|
86
|
-
|
|
87
|
-
|
|
98
|
+
const mod = e.metaKey || e.ctrlKey
|
|
99
|
+
// Cmd+N / Ctrl+N — new chat
|
|
100
|
+
if (mod && !e.shiftKey && e.key.toLowerCase() === 'n') {
|
|
88
101
|
e.preventDefault()
|
|
89
|
-
|
|
102
|
+
const state = useAppStore.getState()
|
|
103
|
+
const allAgents = Object.values(state.agents).filter((a) => !a.trashedAt)
|
|
104
|
+
const target = allAgents.find((a) => a.id === 'default') || allAgents[0]
|
|
105
|
+
if (target) void state.setCurrentAgent(target.id)
|
|
90
106
|
return
|
|
91
107
|
}
|
|
92
|
-
//
|
|
93
|
-
if (
|
|
94
|
-
const tag = (e.target as HTMLElement)?.tagName?.toLowerCase()
|
|
95
|
-
const editable = (e.target as HTMLElement)?.isContentEditable
|
|
96
|
-
if (tag === 'input' || tag === 'textarea' || editable) return
|
|
108
|
+
// Cmd+Shift+T / Ctrl+Shift+T — jump to tasks
|
|
109
|
+
if (mod && e.shiftKey && e.key.toLowerCase() === 't') {
|
|
97
110
|
e.preventDefault()
|
|
98
|
-
|
|
111
|
+
useAppStore.getState().setActiveView('tasks')
|
|
99
112
|
}
|
|
100
113
|
}, [])
|
|
101
114
|
|
|
@@ -104,6 +117,31 @@ export function AppLayout() {
|
|
|
104
117
|
return () => window.removeEventListener('keydown', handleShortcutKey)
|
|
105
118
|
}, [handleShortcutKey])
|
|
106
119
|
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
if (typeof window === 'undefined') return
|
|
122
|
+
if (localStorage.getItem(STAR_NOTIFICATION_KEY)) return
|
|
123
|
+
localStorage.setItem(STAR_NOTIFICATION_KEY, '1')
|
|
124
|
+
void api('POST', '/notifications', {
|
|
125
|
+
type: 'info',
|
|
126
|
+
title: 'Enjoying SwarmClaw?',
|
|
127
|
+
message: 'If SwarmClaw helps your workflow, please star the GitHub repo to support the project.',
|
|
128
|
+
actionLabel: 'Star on GitHub',
|
|
129
|
+
actionUrl: GITHUB_REPO_URL,
|
|
130
|
+
entityType: 'support',
|
|
131
|
+
entityId: 'github-star',
|
|
132
|
+
}).then(() => {
|
|
133
|
+
void useAppStore.getState().loadNotifications()
|
|
134
|
+
}).catch(() => {})
|
|
135
|
+
}, [])
|
|
136
|
+
|
|
137
|
+
// Apply theme hue on mount/change
|
|
138
|
+
useEffect(() => {
|
|
139
|
+
const hue = appSettings.themeHue
|
|
140
|
+
if (hue) {
|
|
141
|
+
document.documentElement.style.setProperty('--neutral-tint', hue)
|
|
142
|
+
}
|
|
143
|
+
}, [appSettings.themeHue])
|
|
144
|
+
|
|
107
145
|
const [railExpanded, setRailExpanded] = useState(() => {
|
|
108
146
|
if (typeof window === 'undefined') return true
|
|
109
147
|
const stored = localStorage.getItem(RAIL_EXPANDED_KEY)
|
|
@@ -117,8 +155,7 @@ export function AppLayout() {
|
|
|
117
155
|
}
|
|
118
156
|
|
|
119
157
|
const handleSwitchUser = () => {
|
|
120
|
-
|
|
121
|
-
setCurrentSession(null)
|
|
158
|
+
setProfileSheetOpen(true)
|
|
122
159
|
}
|
|
123
160
|
|
|
124
161
|
const openNewSheet = () => {
|
|
@@ -129,6 +166,7 @@ export function AppLayout() {
|
|
|
129
166
|
else if (activeView === 'providers') setProviderSheetOpen(true)
|
|
130
167
|
else if (activeView === 'skills') setSkillSheetOpen(true)
|
|
131
168
|
else if (activeView === 'connectors') setConnectorSheetOpen(true)
|
|
169
|
+
else if (activeView === 'chatrooms') useChatroomStore.getState().setChatroomSheetOpen(true)
|
|
132
170
|
else if (activeView === 'webhooks') setWebhookSheetOpen(true)
|
|
133
171
|
else if (activeView === 'mcp_servers') setMcpServerSheetOpen(true)
|
|
134
172
|
else if (activeView === 'knowledge') setKnowledgeSheetOpen(true)
|
|
@@ -151,11 +189,18 @@ export function AppLayout() {
|
|
|
151
189
|
const agents = useAppStore((s) => s.agents)
|
|
152
190
|
const currentAgentId = useAppStore((s) => s.currentAgentId)
|
|
153
191
|
const setCurrentAgent = useAppStore((s) => s.setCurrentAgent)
|
|
192
|
+
const defaultAgentId = appSettings.defaultAgentId && agents[appSettings.defaultAgentId]
|
|
193
|
+
? appSettings.defaultAgentId
|
|
194
|
+
: Object.values(agents)[0]?.id || null
|
|
195
|
+
const isMainChat = activeView === 'agents' && currentAgentId === defaultAgentId
|
|
196
|
+
|
|
197
|
+
const currentSession = currentSessionId ? sessions[currentSessionId] : null
|
|
198
|
+
const hasCanvas = !!(currentSession?.canvasContent && canvasDismissedFor !== currentSessionId)
|
|
199
|
+
const canvasAgentName = currentSession?.agentId && agents[currentSession.agentId] ? agents[currentSession.agentId].name : undefined
|
|
200
|
+
|
|
154
201
|
const goToMainChat = async () => {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if (defaultAgent) {
|
|
158
|
-
await setCurrentAgent(defaultAgent.id)
|
|
202
|
+
if (defaultAgentId) {
|
|
203
|
+
await setCurrentAgent(defaultAgentId)
|
|
159
204
|
}
|
|
160
205
|
setActiveView('agents')
|
|
161
206
|
setSidebarOpen(false)
|
|
@@ -169,7 +214,7 @@ export function AppLayout() {
|
|
|
169
214
|
{/* Desktop: Navigation rail (expandable) */}
|
|
170
215
|
{isDesktop && (
|
|
171
216
|
<div
|
|
172
|
-
className="shrink-0 bg-raised border-r border-white/[0.04] flex flex-col py-4 transition-all duration-200 overflow-
|
|
217
|
+
className="shrink-0 bg-raised border-r border-white/[0.04] flex flex-col py-4 transition-all duration-200 overflow-visible"
|
|
173
218
|
style={{ width: railExpanded ? 180 : 60 }}
|
|
174
219
|
>
|
|
175
220
|
{/* Logo + collapse toggle */}
|
|
@@ -216,9 +261,9 @@ export function AppLayout() {
|
|
|
216
261
|
<button
|
|
217
262
|
onClick={goToMainChat}
|
|
218
263
|
className={`w-full flex items-center gap-2.5 px-3 py-2.5 rounded-[10px] text-[13px] font-600 cursor-pointer transition-all
|
|
219
|
-
${
|
|
220
|
-
? 'bg-
|
|
221
|
-
: 'bg-
|
|
264
|
+
${isMainChat
|
|
265
|
+
? 'bg-accent-bright/15 border border-[#6366F1]/25 text-accent-bright'
|
|
266
|
+
: 'bg-accent-bright/10 border border-[#6366F1]/20 text-accent-bright hover:bg-accent-bright/15'}`}
|
|
222
267
|
style={{ fontFamily: 'inherit' }}
|
|
223
268
|
>
|
|
224
269
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
@@ -231,7 +276,7 @@ export function AppLayout() {
|
|
|
231
276
|
<RailTooltip label="Main Chat" description="Your persistent assistant chat">
|
|
232
277
|
<button
|
|
233
278
|
onClick={goToMainChat}
|
|
234
|
-
className={`rail-btn self-center mb-2 ${
|
|
279
|
+
className={`rail-btn self-center mb-2 ${isMainChat ? 'active' : ''}`}
|
|
235
280
|
>
|
|
236
281
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
237
282
|
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
|
|
@@ -273,11 +318,22 @@ export function AppLayout() {
|
|
|
273
318
|
|
|
274
319
|
{/* Nav items */}
|
|
275
320
|
<div className={`flex flex-col gap-0.5 ${railExpanded ? 'px-3' : 'items-center'}`}>
|
|
321
|
+
<NavItem view="home" label="Home" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('home')}>
|
|
322
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
323
|
+
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" /><polyline points="9 22 9 12 15 12 15 22" />
|
|
324
|
+
</svg>
|
|
325
|
+
</NavItem>
|
|
276
326
|
<NavItem view="agents" label="Agents" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('agents')}>
|
|
277
327
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
278
328
|
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /><circle cx="12" cy="7" r="4" />
|
|
279
329
|
</svg>
|
|
280
330
|
</NavItem>
|
|
331
|
+
<NavItem view="chatrooms" label="Chatrooms" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('chatrooms')}>
|
|
332
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
333
|
+
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
|
|
334
|
+
<path d="M8 10h8" /><path d="M8 14h4" />
|
|
335
|
+
</svg>
|
|
336
|
+
</NavItem>
|
|
281
337
|
<NavItem view="projects" label="Projects" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('projects')}>
|
|
282
338
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
283
339
|
<path d="M2 20a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8l-7-7H4a2 2 0 0 0-2 2v17Z" /><path d="M14 2v7h7" />
|
|
@@ -395,42 +451,53 @@ export function AppLayout() {
|
|
|
395
451
|
</a>
|
|
396
452
|
</RailTooltip>
|
|
397
453
|
)}
|
|
398
|
-
{railExpanded && <DaemonIndicator />}
|
|
399
|
-
{railExpanded ? (
|
|
400
|
-
<div className="flex items-center gap-1 px-3 py-1">
|
|
401
|
-
<span className="text-[12px] font-500 text-text-3 flex-1">Alerts</span>
|
|
402
|
-
<NotificationCenter />
|
|
403
|
-
</div>
|
|
404
|
-
) : (
|
|
405
|
-
<RailTooltip label="Notifications" description="View system notifications">
|
|
406
|
-
<div className="rail-btn flex items-center justify-center">
|
|
407
|
-
<NotificationCenter />
|
|
408
|
-
</div>
|
|
409
|
-
</RailTooltip>
|
|
410
|
-
)}
|
|
411
454
|
{railExpanded ? (
|
|
412
|
-
<
|
|
413
|
-
|
|
455
|
+
<a
|
|
456
|
+
href={GITHUB_REPO_URL}
|
|
457
|
+
target="_blank"
|
|
458
|
+
rel="noopener noreferrer"
|
|
414
459
|
className="w-full flex items-center gap-2.5 px-3 py-2 rounded-[10px] text-[13px] font-500 cursor-pointer transition-all
|
|
415
|
-
bg-transparent text-text-3 hover:text-text hover:bg-white/[0.04]
|
|
460
|
+
bg-transparent text-text-3 hover:text-text hover:bg-white/[0.04] no-underline"
|
|
416
461
|
style={{ fontFamily: 'inherit' }}
|
|
417
462
|
>
|
|
418
463
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" className="shrink-0">
|
|
419
|
-
<
|
|
420
|
-
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
|
|
464
|
+
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" />
|
|
421
465
|
</svg>
|
|
422
|
-
|
|
423
|
-
|
|
466
|
+
Star on GitHub
|
|
467
|
+
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" className="ml-auto opacity-40">
|
|
468
|
+
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" /><polyline points="15 3 21 3 21 9" /><line x1="10" y1="14" x2="21" y2="3" />
|
|
469
|
+
</svg>
|
|
470
|
+
</a>
|
|
424
471
|
) : (
|
|
425
|
-
<RailTooltip label="
|
|
426
|
-
<
|
|
472
|
+
<RailTooltip label="Star on GitHub" description="Support SwarmClaw with a GitHub star">
|
|
473
|
+
<a
|
|
474
|
+
href={GITHUB_REPO_URL}
|
|
475
|
+
target="_blank"
|
|
476
|
+
rel="noopener noreferrer"
|
|
477
|
+
className="rail-btn"
|
|
478
|
+
>
|
|
427
479
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
428
|
-
<
|
|
429
|
-
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
|
|
480
|
+
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" />
|
|
430
481
|
</svg>
|
|
431
|
-
</
|
|
482
|
+
</a>
|
|
483
|
+
</RailTooltip>
|
|
484
|
+
)}
|
|
485
|
+
{railExpanded && <DaemonIndicator />}
|
|
486
|
+
{railExpanded ? (
|
|
487
|
+
<NotificationCenter variant="row" align="left" direction="up" />
|
|
488
|
+
) : (
|
|
489
|
+
<RailTooltip label="Notifications" description="View system notifications">
|
|
490
|
+
<div className="rail-btn flex items-center justify-center">
|
|
491
|
+
<NotificationCenter align="left" direction="up" />
|
|
492
|
+
</div>
|
|
432
493
|
</RailTooltip>
|
|
433
494
|
)}
|
|
495
|
+
<NavItem view="settings" label="Settings" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('settings')}>
|
|
496
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
497
|
+
<circle cx="12" cy="12" r="3" />
|
|
498
|
+
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
|
|
499
|
+
</svg>
|
|
500
|
+
</NavItem>
|
|
434
501
|
|
|
435
502
|
{railExpanded ? (
|
|
436
503
|
<button
|
|
@@ -439,13 +506,13 @@ export function AppLayout() {
|
|
|
439
506
|
bg-transparent hover:bg-white/[0.04] border-none"
|
|
440
507
|
style={{ fontFamily: 'inherit' }}
|
|
441
508
|
>
|
|
442
|
-
<Avatar user={currentUser!} size="sm" />
|
|
509
|
+
<Avatar user={currentUser!} size="sm" avatarSeed={appSettings.userAvatarSeed} />
|
|
443
510
|
<span className="text-[13px] font-500 text-text-2 capitalize truncate">{currentUser}</span>
|
|
444
511
|
</button>
|
|
445
512
|
) : (
|
|
446
|
-
<RailTooltip label="
|
|
513
|
+
<RailTooltip label="Profile" description="Edit your profile">
|
|
447
514
|
<button onClick={handleSwitchUser} className="mt-2 bg-transparent border-none cursor-pointer shrink-0">
|
|
448
|
-
<Avatar user={currentUser!} size="sm" />
|
|
515
|
+
<Avatar user={currentUser!} size="sm" avatarSeed={appSettings.userAvatarSeed} />
|
|
449
516
|
</button>
|
|
450
517
|
</RailTooltip>
|
|
451
518
|
)}
|
|
@@ -464,7 +531,7 @@ export function AppLayout() {
|
|
|
464
531
|
{activeView === 'logs' || activeView === 'usage' || activeView === 'runs' ? null : activeView === 'memory' ? (
|
|
465
532
|
<button
|
|
466
533
|
onClick={() => useAppStore.getState().setMemorySheetOpen(true)}
|
|
467
|
-
className="flex items-center gap-1.5 px-2.5 py-1.5 rounded-[8px] text-[11px] font-600 text-accent-bright bg-accent-soft hover:bg-
|
|
534
|
+
className="flex items-center gap-1.5 px-2.5 py-1.5 rounded-[8px] text-[11px] font-600 text-accent-bright bg-accent-soft hover:bg-accent-bright/15 transition-all cursor-pointer"
|
|
468
535
|
style={{ fontFamily: 'inherit' }}
|
|
469
536
|
>
|
|
470
537
|
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round">
|
|
@@ -475,7 +542,7 @@ export function AppLayout() {
|
|
|
475
542
|
) : (
|
|
476
543
|
<button
|
|
477
544
|
onClick={openNewSheet}
|
|
478
|
-
className="flex items-center gap-1.5 px-2.5 py-1.5 rounded-[8px] text-[11px] font-600 text-accent-bright bg-accent-soft hover:bg-
|
|
545
|
+
className="flex items-center gap-1.5 px-2.5 py-1.5 rounded-[8px] text-[11px] font-600 text-accent-bright bg-accent-soft hover:bg-accent-bright/15 transition-all cursor-pointer"
|
|
479
546
|
style={{ fontFamily: 'inherit' }}
|
|
480
547
|
>
|
|
481
548
|
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round">
|
|
@@ -505,7 +572,7 @@ export function AppLayout() {
|
|
|
505
572
|
</>
|
|
506
573
|
)}
|
|
507
574
|
{activeView === 'schedules' && <ScheduleList inSidebar />}
|
|
508
|
-
{activeView === 'memory' && <
|
|
575
|
+
{activeView === 'memory' && <MemoryAgentList />}
|
|
509
576
|
{activeView === 'tasks' && <TaskList inSidebar />}
|
|
510
577
|
{activeView === 'secrets' && <SecretsList inSidebar />}
|
|
511
578
|
{activeView === 'providers' && <ProviderList inSidebar />}
|
|
@@ -540,19 +607,19 @@ export function AppLayout() {
|
|
|
540
607
|
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z" /><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z" />
|
|
541
608
|
</svg>
|
|
542
609
|
</a>
|
|
543
|
-
<button onClick={() => handleNavClick('settings')} className=
|
|
610
|
+
<button onClick={() => handleNavClick('settings')} className={`rail-btn ${activeView === 'settings' ? 'active' : ''}`}>
|
|
544
611
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
545
612
|
<circle cx="12" cy="12" r="3" />
|
|
546
613
|
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
|
|
547
614
|
</svg>
|
|
548
615
|
</button>
|
|
549
616
|
<button onClick={handleSwitchUser} className="bg-transparent border-none cursor-pointer shrink-0">
|
|
550
|
-
<Avatar user={currentUser!} size="sm" />
|
|
617
|
+
<Avatar user={currentUser!} size="sm" avatarSeed={appSettings.userAvatarSeed} />
|
|
551
618
|
</button>
|
|
552
619
|
</div>
|
|
553
620
|
{/* View selector tabs */}
|
|
554
621
|
<div className="flex px-4 py-2 gap-1 shrink-0 flex-wrap">
|
|
555
|
-
{(['agents', 'schedules', 'memory', 'tasks', 'secrets', 'providers', 'skills', 'connectors', 'webhooks', 'mcp_servers', 'knowledge', 'plugins', 'usage', 'runs', 'logs'] as AppView[]).map((v) => (
|
|
622
|
+
{(['agents', 'chatrooms', 'schedules', 'memory', 'tasks', 'secrets', 'providers', 'skills', 'connectors', 'webhooks', 'mcp_servers', 'knowledge', 'plugins', 'usage', 'runs', 'logs'] as AppView[]).map((v) => (
|
|
556
623
|
<button
|
|
557
624
|
key={v}
|
|
558
625
|
onClick={() => setActiveView(v)}
|
|
@@ -573,7 +640,7 @@ export function AppLayout() {
|
|
|
573
640
|
setSidebarOpen(false)
|
|
574
641
|
openNewSheet()
|
|
575
642
|
}}
|
|
576
|
-
className="w-full py-3 rounded-[12px] border-none bg-
|
|
643
|
+
className="w-full py-3 rounded-[12px] border-none bg-accent-bright text-white text-[14px] font-600 cursor-pointer
|
|
577
644
|
hover:brightness-110 active:scale-[0.98] transition-all
|
|
578
645
|
shadow-[0_2px_12px_rgba(99,102,241,0.15)]"
|
|
579
646
|
style={{ fontFamily: 'inherit' }}
|
|
@@ -601,7 +668,7 @@ export function AppLayout() {
|
|
|
601
668
|
</>
|
|
602
669
|
)}
|
|
603
670
|
{activeView === 'schedules' && <ScheduleList inSidebar />}
|
|
604
|
-
{activeView === 'memory' && <
|
|
671
|
+
{activeView === 'memory' && <MemoryAgentList />}
|
|
605
672
|
{activeView === 'tasks' && <TaskList inSidebar />}
|
|
606
673
|
{activeView === 'secrets' && <SecretsList inSidebar />}
|
|
607
674
|
{activeView === 'providers' && <ProviderList inSidebar />}
|
|
@@ -611,7 +678,6 @@ export function AppLayout() {
|
|
|
611
678
|
{activeView === 'mcp_servers' && <McpServerList />}
|
|
612
679
|
{activeView === 'knowledge' && <KnowledgeList />}
|
|
613
680
|
{activeView === 'plugins' && <PluginList inSidebar />}
|
|
614
|
-
{activeView === 'projects' && <ProjectList />}
|
|
615
681
|
{activeView === 'runs' && <RunList />}
|
|
616
682
|
{activeView === 'logs' && <LogList />}
|
|
617
683
|
</div>
|
|
@@ -620,10 +686,23 @@ export function AppLayout() {
|
|
|
620
686
|
|
|
621
687
|
{/* Main content */}
|
|
622
688
|
<ErrorBoundary>
|
|
623
|
-
<div className="flex-1 flex flex-col h-full min-w-0 bg-bg">
|
|
689
|
+
<div className="flex-1 flex flex-col h-full min-h-0 min-w-0 bg-bg">
|
|
624
690
|
{!isDesktop && <MobileHeader />}
|
|
625
|
-
{activeView === '
|
|
626
|
-
<
|
|
691
|
+
{activeView === 'home' ? (
|
|
692
|
+
<HomeView />
|
|
693
|
+
) : activeView === 'agents' && hasSelectedSession ? (
|
|
694
|
+
<div className="flex-1 flex h-full min-h-0 min-w-0">
|
|
695
|
+
<div className="flex-1 min-h-0 min-w-0 overflow-hidden">
|
|
696
|
+
<ChatArea />
|
|
697
|
+
</div>
|
|
698
|
+
{hasCanvas && currentSessionId && (
|
|
699
|
+
<CanvasPanel
|
|
700
|
+
sessionId={currentSessionId}
|
|
701
|
+
agentName={canvasAgentName}
|
|
702
|
+
onClose={() => setCanvasDismissedFor(currentSessionId)}
|
|
703
|
+
/>
|
|
704
|
+
)}
|
|
705
|
+
</div>
|
|
627
706
|
) : activeView === 'agents' ? (
|
|
628
707
|
<div className="flex-1 flex flex-col">
|
|
629
708
|
{!isDesktop ? (
|
|
@@ -644,11 +723,38 @@ export function AppLayout() {
|
|
|
644
723
|
) : activeView === 'tasks' && isDesktop ? (
|
|
645
724
|
<TaskBoard />
|
|
646
725
|
) : activeView === 'memory' ? (
|
|
647
|
-
<
|
|
726
|
+
<MemoryBrowser />
|
|
648
727
|
) : activeView === 'activity' ? (
|
|
649
728
|
<ActivityFeed />
|
|
650
729
|
) : activeView === 'usage' ? (
|
|
651
730
|
<MetricsDashboard />
|
|
731
|
+
) : activeView === 'chatrooms' ? (
|
|
732
|
+
<div className="flex-1 flex h-full min-w-0">
|
|
733
|
+
<div className="w-[280px] shrink-0 border-r border-white/[0.06] flex flex-col">
|
|
734
|
+
<div className="flex items-center px-4 pt-4 pb-2 shrink-0">
|
|
735
|
+
<h2 className="font-display text-[14px] font-600 text-text-2 tracking-[-0.01em] flex-1">Chatrooms</h2>
|
|
736
|
+
<button
|
|
737
|
+
onClick={() => { useChatroomStore.getState().setEditingChatroomId(null); useChatroomStore.getState().setChatroomSheetOpen(true) }}
|
|
738
|
+
className="flex items-center gap-1 px-2 py-1 rounded-[6px] text-[11px] font-600 text-accent-bright bg-accent-soft hover:bg-accent-bright/15 transition-all cursor-pointer"
|
|
739
|
+
style={{ fontFamily: 'inherit' }}
|
|
740
|
+
>
|
|
741
|
+
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round">
|
|
742
|
+
<line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" />
|
|
743
|
+
</svg>
|
|
744
|
+
New
|
|
745
|
+
</button>
|
|
746
|
+
</div>
|
|
747
|
+
<ChatroomList />
|
|
748
|
+
</div>
|
|
749
|
+
<ChatroomView />
|
|
750
|
+
</div>
|
|
751
|
+
) : activeView === 'projects' ? (
|
|
752
|
+
<div className="flex-1 flex h-full min-w-0">
|
|
753
|
+
<div className="w-[280px] shrink-0 border-r border-white/[0.06] flex flex-col">
|
|
754
|
+
<ProjectList />
|
|
755
|
+
</div>
|
|
756
|
+
<ProjectDetail />
|
|
757
|
+
</div>
|
|
652
758
|
) : activeView === 'settings' ? (
|
|
653
759
|
<SettingsPage />
|
|
654
760
|
) : !sidebarOpen && FULL_WIDTH_VIEWS.has(activeView) ? (
|
|
@@ -660,13 +766,13 @@ export function AppLayout() {
|
|
|
660
766
|
{activeView !== 'runs' && activeView !== 'logs' && (
|
|
661
767
|
<button
|
|
662
768
|
onClick={openNewSheet}
|
|
663
|
-
className="flex items-center gap-1.5 px-2.5 py-1.5 rounded-[8px] text-[11px] font-600 text-accent-bright bg-accent-soft hover:bg-
|
|
769
|
+
className="flex items-center gap-1.5 px-2.5 py-1.5 rounded-[8px] text-[11px] font-600 text-accent-bright bg-accent-soft hover:bg-accent-bright/15 transition-all cursor-pointer"
|
|
664
770
|
style={{ fontFamily: 'inherit' }}
|
|
665
771
|
>
|
|
666
772
|
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round">
|
|
667
773
|
<line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" />
|
|
668
774
|
</svg>
|
|
669
|
-
{activeView === 'schedules' ? 'Schedule' : activeView === 'secrets' ? 'Secret' : activeView === 'providers' ? 'Provider' : activeView === 'skills' ? 'Skill' : activeView === 'connectors' ? 'Connector' : activeView === 'webhooks' ? 'Webhook' : activeView === 'mcp_servers' ? 'MCP Server' : activeView === 'knowledge' ? 'Knowledge' : activeView === 'plugins' ? 'Plugin' :
|
|
775
|
+
{activeView === 'schedules' ? 'Schedule' : activeView === 'secrets' ? 'Secret' : activeView === 'providers' ? 'Provider' : activeView === 'skills' ? 'Skill' : activeView === 'connectors' ? 'Connector' : activeView === 'webhooks' ? 'Webhook' : activeView === 'mcp_servers' ? 'MCP Server' : activeView === 'knowledge' ? 'Knowledge' : activeView === 'plugins' ? 'Plugin' : 'New'}
|
|
670
776
|
</button>
|
|
671
777
|
)}
|
|
672
778
|
</div>
|
|
@@ -679,7 +785,6 @@ export function AppLayout() {
|
|
|
679
785
|
{activeView === 'mcp_servers' && <McpServerList />}
|
|
680
786
|
{activeView === 'knowledge' && <KnowledgeList />}
|
|
681
787
|
{activeView === 'plugins' && <PluginList />}
|
|
682
|
-
{activeView === 'projects' && <ProjectList />}
|
|
683
788
|
{activeView === 'runs' && <RunList />}
|
|
684
789
|
{activeView === 'logs' && <LogList />}
|
|
685
790
|
</div>
|
|
@@ -690,6 +795,8 @@ export function AppLayout() {
|
|
|
690
795
|
</ErrorBoundary>
|
|
691
796
|
|
|
692
797
|
<SearchDialog />
|
|
798
|
+
<AgentSwitchDialog />
|
|
799
|
+
<KeyboardShortcutsDialog />
|
|
693
800
|
<AgentSheet />
|
|
694
801
|
<ScheduleSheet />
|
|
695
802
|
<MemorySheet />
|
|
@@ -698,32 +805,14 @@ export function AppLayout() {
|
|
|
698
805
|
<ProviderSheet />
|
|
699
806
|
<SkillSheet />
|
|
700
807
|
<ConnectorSheet />
|
|
808
|
+
<ChatroomSheet />
|
|
701
809
|
<WebhookSheet />
|
|
702
810
|
<McpServerSheet />
|
|
703
811
|
<KnowledgeSheet />
|
|
704
812
|
<PluginSheet />
|
|
705
813
|
<ProjectSheet />
|
|
814
|
+
<ProfileSheet open={profileSheetOpen} onClose={() => setProfileSheetOpen(false)} />
|
|
706
815
|
|
|
707
|
-
<Dialog open={shortcutsOpen} onOpenChange={setShortcutsOpen}>
|
|
708
|
-
<DialogContent className="sm:max-w-[380px] bg-raised border-white/[0.08]">
|
|
709
|
-
<DialogHeader>
|
|
710
|
-
<DialogTitle className="text-text">Keyboard Shortcuts</DialogTitle>
|
|
711
|
-
</DialogHeader>
|
|
712
|
-
<div className="space-y-3 py-2">
|
|
713
|
-
{([
|
|
714
|
-
['Enter', 'Send message'],
|
|
715
|
-
['Shift + Enter', 'New line'],
|
|
716
|
-
['Ctrl + F', 'Search in chat'],
|
|
717
|
-
['Ctrl + /', 'Show shortcuts'],
|
|
718
|
-
] as const).map(([keys, desc]) => (
|
|
719
|
-
<div key={keys} className="flex items-center justify-between">
|
|
720
|
-
<span className="text-[13px] text-text-2">{desc}</span>
|
|
721
|
-
<kbd className="px-2 py-1 rounded-[6px] bg-white/[0.06] border border-white/[0.08] text-[11px] font-mono text-text-3">{keys}</kbd>
|
|
722
|
-
</div>
|
|
723
|
-
))}
|
|
724
|
-
</div>
|
|
725
|
-
</DialogContent>
|
|
726
|
-
</Dialog>
|
|
727
816
|
</div>
|
|
728
817
|
)
|
|
729
818
|
}
|
|
@@ -762,7 +851,7 @@ class ErrorBoundary extends Component<{ children: ReactNode }, { hasError: boole
|
|
|
762
851
|
</p>
|
|
763
852
|
<button
|
|
764
853
|
onClick={() => window.location.reload()}
|
|
765
|
-
className="inline-flex items-center gap-2 px-6 py-3 rounded-[12px] border-none bg-
|
|
854
|
+
className="inline-flex items-center gap-2 px-6 py-3 rounded-[12px] border-none bg-accent-bright text-white text-[14px] font-600 cursor-pointer
|
|
766
855
|
hover:brightness-110 active:scale-[0.97] transition-all shadow-[0_4px_16px_rgba(99,102,241,0.2)]"
|
|
767
856
|
style={{ fontFamily: 'inherit' }}
|
|
768
857
|
>
|
|
@@ -782,7 +871,9 @@ class ErrorBoundary extends Component<{ children: ReactNode }, { hasError: boole
|
|
|
782
871
|
}
|
|
783
872
|
|
|
784
873
|
const VIEW_DESCRIPTIONS: Record<AppView, string> = {
|
|
874
|
+
home: 'Dashboard overview',
|
|
785
875
|
agents: 'Chat with & configure your AI agents',
|
|
876
|
+
chatrooms: 'Multi-agent collaborative chatrooms',
|
|
786
877
|
schedules: 'Automated task schedules',
|
|
787
878
|
memory: 'Long-term agent memory store',
|
|
788
879
|
tasks: 'Task board for orchestrator jobs',
|
|
@@ -803,12 +894,18 @@ const VIEW_DESCRIPTIONS: Record<AppView, string> = {
|
|
|
803
894
|
}
|
|
804
895
|
|
|
805
896
|
const FULL_WIDTH_VIEWS = new Set<AppView>([
|
|
806
|
-
'schedules', 'secrets', 'providers', 'skills',
|
|
897
|
+
'home', 'chatrooms', 'schedules', 'secrets', 'providers', 'skills',
|
|
807
898
|
'connectors', 'webhooks', 'mcp_servers', 'knowledge', 'plugins',
|
|
808
|
-
'usage', 'runs', 'logs', 'settings', '
|
|
899
|
+
'usage', 'runs', 'logs', 'settings', 'activity', 'projects',
|
|
809
900
|
])
|
|
810
901
|
|
|
811
|
-
const VIEW_EMPTY_STATES: Record<Exclude<AppView, 'agents'>, { icon: string; title: string; description: string; features: string[] }> = {
|
|
902
|
+
const VIEW_EMPTY_STATES: Record<Exclude<AppView, 'agents' | 'home'>, { icon: string; title: string; description: string; features: string[] }> = {
|
|
903
|
+
chatrooms: {
|
|
904
|
+
icon: 'message-square',
|
|
905
|
+
title: 'Chatrooms',
|
|
906
|
+
description: 'Multi-agent chatrooms for collaborative conversations. Add agents and use @mentions to trigger responses.',
|
|
907
|
+
features: ['Create chatrooms with multiple AI agents', 'Use @AgentName to trigger specific agents', '@all mentions trigger all agents sequentially', 'Agents can chain by mentioning each other'],
|
|
908
|
+
},
|
|
812
909
|
schedules: {
|
|
813
910
|
icon: 'clock',
|
|
814
911
|
title: 'Schedules',
|
|
@@ -914,8 +1011,8 @@ const VIEW_EMPTY_STATES: Record<Exclude<AppView, 'agents'>, { icon: string; titl
|
|
|
914
1011
|
}
|
|
915
1012
|
|
|
916
1013
|
function ViewEmptyState({ view }: { view: AppView }) {
|
|
917
|
-
if (view === 'agents') return null
|
|
918
|
-
const config = VIEW_EMPTY_STATES[view as Exclude<AppView, 'agents'>]
|
|
1014
|
+
if (view === 'agents' || view === 'home') return null
|
|
1015
|
+
const config = VIEW_EMPTY_STATES[view as Exclude<AppView, 'agents' | 'home'>]
|
|
919
1016
|
if (!config) return null
|
|
920
1017
|
|
|
921
1018
|
return (
|
|
@@ -1102,7 +1199,7 @@ function DesktopEmptyState({ userName }: { userName: string | null }) {
|
|
|
1102
1199
|
</p>
|
|
1103
1200
|
<button
|
|
1104
1201
|
onClick={() => setNewSessionOpen(true)}
|
|
1105
|
-
className="inline-flex items-center gap-2.5 px-12 py-4 rounded-[16px] border-none bg-
|
|
1202
|
+
className="inline-flex items-center gap-2.5 px-12 py-4 rounded-[16px] border-none bg-accent-bright text-white text-[16px] font-display font-600
|
|
1106
1203
|
cursor-pointer hover:brightness-110 active:scale-[0.97] transition-all duration-200
|
|
1107
1204
|
shadow-[0_6px_28px_rgba(99,102,241,0.3)]"
|
|
1108
1205
|
style={{ fontFamily: 'inherit' }}
|
|
@@ -63,7 +63,7 @@ export function UpdateBanner() {
|
|
|
63
63
|
if (dismissed === version.remoteSha && updateState === 'idle') return null
|
|
64
64
|
|
|
65
65
|
return (
|
|
66
|
-
<div className="px-4 py-1.5 border-b border-white/[0.04] text-[10px] flex items-center gap-2 shrink-0 bg-
|
|
66
|
+
<div className="px-4 py-1.5 border-b border-white/[0.04] text-[10px] flex items-center gap-2 shrink-0 bg-accent-bright/[0.04]">
|
|
67
67
|
{updateState === 'idle' && (
|
|
68
68
|
<>
|
|
69
69
|
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" className="text-accent-bright shrink-0">
|
|
@@ -74,7 +74,7 @@ export function UpdateBanner() {
|
|
|
74
74
|
</span>
|
|
75
75
|
<button
|
|
76
76
|
onClick={handleUpdate}
|
|
77
|
-
className="text-[10px] font-600 text-accent-bright hover:text-white bg-
|
|
77
|
+
className="text-[10px] font-600 text-accent-bright hover:text-white bg-accent-bright/20 hover:bg-accent-bright/30 px-2 py-0.5 rounded-[6px] border-none cursor-pointer transition-all shrink-0"
|
|
78
78
|
style={{ fontFamily: 'inherit' }}
|
|
79
79
|
>
|
|
80
80
|
Update
|
|
@@ -162,7 +162,7 @@ export function LogList() {
|
|
|
162
162
|
<button
|
|
163
163
|
key={i}
|
|
164
164
|
onClick={() => { setLevelFilter(f.levels); setSearch(f.search) }}
|
|
165
|
-
className="group flex items-center gap-1 px-2 py-1 rounded-[6px] text-[10px] font-600 cursor-pointer transition-all border-none bg-accent-soft text-accent-bright hover:bg-
|
|
165
|
+
className="group flex items-center gap-1 px-2 py-1 rounded-[6px] text-[10px] font-600 cursor-pointer transition-all border-none bg-accent-soft text-accent-bright hover:bg-accent-bright/15"
|
|
166
166
|
>
|
|
167
167
|
{f.name}
|
|
168
168
|
<span
|
|
@@ -337,7 +337,7 @@ export function LogList() {
|
|
|
337
337
|
<button
|
|
338
338
|
onClick={handleCreateTask}
|
|
339
339
|
disabled={creatingTask}
|
|
340
|
-
className="px-5 py-3 rounded-[14px] border-none bg-
|
|
340
|
+
className="px-5 py-3 rounded-[14px] border-none bg-accent-bright text-white text-[14px] font-600
|
|
341
341
|
cursor-pointer active:scale-[0.97] disabled:opacity-40 transition-all
|
|
342
342
|
shadow-[0_4px_20px_rgba(99,102,241,0.25)] hover:brightness-110 shrink-0"
|
|
343
343
|
style={{ fontFamily: 'inherit' }}
|