@swarmclawai/swarmclaw 0.7.1 → 0.7.3
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 +155 -150
- package/package.json +1 -1
- package/src/app/api/agents/[id]/route.ts +26 -0
- package/src/app/api/agents/[id]/thread/route.ts +37 -9
- package/src/app/api/agents/route.ts +13 -2
- package/src/app/api/auth/route.ts +76 -7
- package/src/app/api/chatrooms/[id]/chat/route.ts +7 -2
- package/src/app/api/{sessions → chats}/[id]/browser/route.ts +5 -1
- package/src/app/api/{sessions → chats}/[id]/chat/route.ts +7 -3
- package/src/app/api/{sessions → chats}/[id]/checkpoints/route.ts +1 -1
- package/src/app/api/chats/[id]/main-loop/route.ts +13 -0
- package/src/app/api/{sessions → chats}/[id]/messages/route.ts +19 -13
- package/src/app/api/{sessions → chats}/[id]/restore/route.ts +1 -1
- package/src/app/api/{sessions → chats}/[id]/route.ts +22 -52
- package/src/app/api/{sessions → chats}/[id]/stop/route.ts +6 -1
- package/src/app/api/{sessions → chats}/route.ts +21 -7
- package/src/app/api/connectors/[id]/doctor/route.ts +26 -0
- package/src/app/api/connectors/doctor/route.ts +13 -0
- package/src/app/api/files/open/route.ts +16 -14
- package/src/app/api/memory/maintenance/route.ts +11 -1
- package/src/app/api/openclaw/agent-files/route.ts +27 -4
- package/src/app/api/openclaw/skills/route.ts +11 -3
- package/src/app/api/plugins/dependencies/route.ts +24 -0
- package/src/app/api/plugins/install/route.ts +15 -92
- package/src/app/api/plugins/route.ts +6 -26
- package/src/app/api/plugins/settings/route.ts +40 -0
- package/src/app/api/plugins/ui/route.ts +1 -0
- package/src/app/api/settings/route.ts +49 -7
- package/src/app/api/tasks/[id]/route.ts +15 -6
- package/src/app/api/tasks/bulk/route.ts +2 -2
- package/src/app/api/tasks/route.ts +9 -4
- package/src/app/api/usage/route.ts +30 -0
- package/src/app/api/webhooks/[id]/route.ts +8 -1
- package/src/app/page.tsx +9 -2
- package/src/cli/index.js +39 -33
- package/src/cli/index.ts +43 -49
- package/src/cli/spec.js +29 -27
- package/src/components/agents/agent-card.tsx +16 -13
- package/src/components/agents/agent-chat-list.tsx +104 -4
- package/src/components/agents/agent-list.tsx +54 -22
- package/src/components/agents/agent-sheet.tsx +209 -18
- package/src/components/agents/cron-job-form.tsx +3 -3
- package/src/components/agents/inspector-panel.tsx +110 -50
- package/src/components/auth/access-key-gate.tsx +36 -97
- package/src/components/auth/setup-wizard.tsx +5 -38
- package/src/components/chat/chat-area.tsx +39 -27
- package/src/components/{sessions/session-card.tsx → chat/chat-card.tsx} +7 -23
- package/src/components/chat/chat-header.tsx +299 -314
- package/src/components/{sessions/session-list.tsx → chat/chat-list.tsx} +11 -14
- package/src/components/chat/chat-tool-toggles.tsx +26 -17
- package/src/components/chat/checkpoint-timeline.tsx +4 -4
- package/src/components/chat/message-bubble.tsx +4 -1
- package/src/components/chat/message-list.tsx +5 -3
- package/src/components/chat/session-debug-panel.tsx +1 -1
- package/src/components/chat/tool-request-banner.tsx +3 -3
- package/src/components/chatrooms/agent-hover-card.tsx +3 -3
- package/src/components/chatrooms/chatroom-tool-request-banner.tsx +2 -2
- package/src/components/chatrooms/chatroom-view.tsx +347 -205
- package/src/components/connectors/connector-list.tsx +265 -127
- package/src/components/connectors/connector-sheet.tsx +218 -1
- package/src/components/home/home-view.tsx +129 -5
- package/src/components/layout/app-layout.tsx +392 -182
- package/src/components/layout/mobile-header.tsx +26 -8
- package/src/components/plugins/plugin-list.tsx +487 -254
- package/src/components/plugins/plugin-sheet.tsx +236 -13
- package/src/components/projects/project-detail.tsx +183 -0
- package/src/components/settings/gateway-connection-panel.tsx +1 -1
- package/src/components/shared/agent-picker-list.tsx +2 -2
- package/src/components/shared/command-palette.tsx +111 -25
- package/src/components/shared/settings/plugin-manager.tsx +20 -4
- package/src/components/shared/settings/section-capability-policy.tsx +105 -0
- package/src/components/shared/settings/section-heartbeat.tsx +78 -1
- package/src/components/shared/settings/section-orchestrator.tsx +3 -3
- package/src/components/shared/settings/section-providers.tsx +1 -1
- package/src/components/shared/settings/section-runtime-loop.tsx +5 -5
- package/src/components/shared/settings/section-secrets.tsx +6 -6
- package/src/components/shared/settings/section-user-preferences.tsx +1 -1
- package/src/components/shared/settings/section-voice.tsx +5 -1
- package/src/components/shared/settings/section-web-search.tsx +10 -2
- package/src/components/shared/settings/settings-page.tsx +244 -56
- package/src/components/tasks/approvals-panel.tsx +205 -18
- package/src/components/tasks/task-board.tsx +242 -46
- package/src/components/usage/metrics-dashboard.tsx +147 -1
- package/src/components/wallets/wallet-panel.tsx +17 -5
- package/src/components/webhooks/webhook-sheet.tsx +8 -8
- package/src/lib/auth.ts +17 -0
- package/src/lib/chat-streaming-state.test.ts +108 -0
- package/src/lib/chat-streaming-state.ts +108 -0
- package/src/lib/chat.ts +1 -1
- package/src/lib/{sessions.ts → chats.ts} +28 -18
- package/src/lib/openclaw-agent-id.test.ts +14 -0
- package/src/lib/openclaw-agent-id.ts +31 -0
- package/src/lib/providers/claude-cli.ts +1 -1
- package/src/lib/server/agent-assignment.test.ts +112 -0
- package/src/lib/server/agent-assignment.ts +169 -0
- package/src/lib/server/approval-connector-notify.test.ts +253 -0
- package/src/lib/server/approvals-auto-approve.test.ts +205 -0
- package/src/lib/server/approvals.ts +483 -75
- package/src/lib/server/autonomy-runtime.test.ts +341 -0
- package/src/lib/server/browser-state.test.ts +118 -0
- package/src/lib/server/browser-state.ts +123 -0
- package/src/lib/server/build-llm.test.ts +36 -0
- package/src/lib/server/build-llm.ts +11 -4
- package/src/lib/server/builtin-plugins.ts +34 -0
- package/src/lib/server/capability-router.ts +10 -8
- package/src/lib/server/chat-execution-heartbeat.test.ts +40 -0
- package/src/lib/server/chat-execution-tool-events.test.ts +134 -0
- package/src/lib/server/chat-execution.ts +285 -165
- package/src/lib/server/chatroom-health.test.ts +26 -0
- package/src/lib/server/chatroom-health.ts +2 -3
- package/src/lib/server/chatroom-helpers.test.ts +67 -2
- package/src/lib/server/chatroom-helpers.ts +48 -8
- package/src/lib/server/connectors/discord.ts +175 -11
- package/src/lib/server/connectors/doctor.test.ts +80 -0
- package/src/lib/server/connectors/doctor.ts +116 -0
- package/src/lib/server/connectors/manager.ts +948 -112
- package/src/lib/server/connectors/policy.test.ts +222 -0
- package/src/lib/server/connectors/policy.ts +452 -0
- package/src/lib/server/connectors/slack.ts +188 -9
- package/src/lib/server/connectors/telegram.ts +65 -15
- package/src/lib/server/connectors/thread-context.test.ts +44 -0
- package/src/lib/server/connectors/thread-context.ts +72 -0
- package/src/lib/server/connectors/types.ts +41 -11
- package/src/lib/server/cost.ts +34 -1
- package/src/lib/server/daemon-state.ts +61 -3
- package/src/lib/server/data-dir.ts +13 -0
- package/src/lib/server/delegation-jobs.test.ts +140 -0
- package/src/lib/server/delegation-jobs.ts +248 -0
- package/src/lib/server/document-utils.test.ts +47 -0
- package/src/lib/server/document-utils.ts +397 -0
- package/src/lib/server/heartbeat-service.ts +14 -40
- package/src/lib/server/heartbeat-source.test.ts +22 -0
- package/src/lib/server/heartbeat-source.ts +7 -0
- package/src/lib/server/identity-continuity.test.ts +77 -0
- package/src/lib/server/identity-continuity.ts +127 -0
- package/src/lib/server/mailbox-utils.ts +347 -0
- package/src/lib/server/main-agent-loop.ts +28 -1103
- package/src/lib/server/memory-db.ts +4 -6
- package/src/lib/server/memory-tiers.ts +40 -0
- package/src/lib/server/openclaw-agent-resolver.test.ts +70 -0
- package/src/lib/server/openclaw-agent-resolver.ts +128 -0
- package/src/lib/server/openclaw-exec-config.ts +5 -6
- package/src/lib/server/openclaw-skills-normalize.test.ts +56 -0
- package/src/lib/server/openclaw-skills-normalize.ts +136 -0
- package/src/lib/server/openclaw-sync.ts +3 -2
- package/src/lib/server/orchestrator-lg.ts +20 -9
- package/src/lib/server/orchestrator.ts +7 -7
- package/src/lib/server/playwright-proxy.mjs +27 -3
- package/src/lib/server/plugins.test.ts +207 -0
- package/src/lib/server/plugins.ts +927 -66
- package/src/lib/server/provider-health.ts +38 -6
- package/src/lib/server/queue.ts +13 -28
- package/src/lib/server/scheduler.ts +2 -0
- package/src/lib/server/session-archive-memory.test.ts +85 -0
- package/src/lib/server/session-archive-memory.ts +230 -0
- package/src/lib/server/session-mailbox.ts +8 -18
- package/src/lib/server/session-reset-policy.test.ts +99 -0
- package/src/lib/server/session-reset-policy.ts +311 -0
- package/src/lib/server/session-run-manager.ts +33 -82
- package/src/lib/server/session-tools/autonomy-tools.test.ts +105 -0
- package/src/lib/server/session-tools/calendar.ts +366 -0
- package/src/lib/server/session-tools/canvas.ts +1 -1
- package/src/lib/server/session-tools/chatroom.ts +4 -2
- package/src/lib/server/session-tools/connector.ts +114 -10
- package/src/lib/server/session-tools/context.ts +21 -5
- package/src/lib/server/session-tools/crawl.ts +447 -0
- package/src/lib/server/session-tools/crud.ts +74 -28
- package/src/lib/server/session-tools/delegate-fallback.test.ts +219 -0
- package/src/lib/server/session-tools/delegate.ts +497 -24
- package/src/lib/server/session-tools/discovery.ts +24 -6
- package/src/lib/server/session-tools/document.ts +283 -0
- package/src/lib/server/session-tools/edit_file.ts +4 -2
- package/src/lib/server/session-tools/email.ts +320 -0
- package/src/lib/server/session-tools/extract.ts +137 -0
- package/src/lib/server/session-tools/file-normalize.test.ts +93 -0
- package/src/lib/server/session-tools/file-send.test.ts +84 -1
- package/src/lib/server/session-tools/file.ts +241 -25
- package/src/lib/server/session-tools/git.ts +1 -1
- package/src/lib/server/session-tools/http.ts +1 -1
- package/src/lib/server/session-tools/human-loop.ts +227 -0
- package/src/lib/server/session-tools/image-gen.ts +380 -0
- package/src/lib/server/session-tools/index.ts +130 -50
- package/src/lib/server/session-tools/mailbox.ts +276 -0
- package/src/lib/server/session-tools/memory.ts +172 -3
- package/src/lib/server/session-tools/monitor.ts +151 -8
- package/src/lib/server/session-tools/normalize-tool-args.ts +17 -14
- package/src/lib/server/session-tools/openclaw-nodes.ts +1 -1
- package/src/lib/server/session-tools/openclaw-workspace.ts +1 -1
- package/src/lib/server/session-tools/platform-normalize.test.ts +142 -0
- package/src/lib/server/session-tools/platform.ts +148 -7
- package/src/lib/server/session-tools/plugin-creator.ts +89 -26
- package/src/lib/server/session-tools/primitive-tools.test.ts +257 -0
- package/src/lib/server/session-tools/replicate.ts +301 -0
- package/src/lib/server/session-tools/sample-ui.ts +1 -1
- package/src/lib/server/session-tools/sandbox.ts +4 -2
- package/src/lib/server/session-tools/schedule.ts +24 -12
- package/src/lib/server/session-tools/session-info.ts +43 -7
- package/src/lib/server/session-tools/session-tools-wiring.test.ts +31 -17
- package/src/lib/server/session-tools/shell.ts +5 -2
- package/src/lib/server/session-tools/subagent.ts +194 -28
- package/src/lib/server/session-tools/table.ts +587 -0
- package/src/lib/server/session-tools/wallet.ts +42 -12
- package/src/lib/server/session-tools/web-browser-config.test.ts +39 -0
- package/src/lib/server/session-tools/web.ts +926 -91
- package/src/lib/server/storage.ts +255 -16
- package/src/lib/server/stream-agent-chat.ts +116 -268
- package/src/lib/server/structured-extract.test.ts +72 -0
- package/src/lib/server/structured-extract.ts +373 -0
- package/src/lib/server/task-mention.test.ts +16 -2
- package/src/lib/server/task-mention.ts +61 -10
- package/src/lib/server/tool-aliases.ts +66 -18
- package/src/lib/server/tool-capability-policy.test.ts +9 -9
- package/src/lib/server/tool-capability-policy.ts +38 -27
- package/src/lib/server/tool-retry.ts +2 -0
- package/src/lib/server/watch-jobs.test.ts +173 -0
- package/src/lib/server/watch-jobs.ts +532 -0
- package/src/lib/server/ws-hub.ts +5 -3
- package/src/lib/tool-definitions.ts +4 -0
- package/src/lib/validation/schemas.test.ts +26 -0
- package/src/lib/validation/schemas.ts +10 -1
- package/src/lib/ws-client.ts +14 -12
- package/src/proxy.ts +5 -5
- package/src/stores/use-app-store.ts +5 -11
- package/src/stores/use-chat-store.ts +38 -9
- package/src/types/index.ts +352 -47
- package/src/app/api/sessions/[id]/main-loop/route.ts +0 -94
- package/src/components/sessions/new-session-sheet.tsx +0 -253
- package/src/lib/server/main-session.ts +0 -24
- package/src/lib/server/session-run-manager.test.ts +0 -23
- /package/src/app/api/{sessions → chats}/[id]/clear/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/deploy/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/devserver/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/edit-resend/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/fork/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/mailbox/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/retry/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/heartbeat/route.ts +0 -0
|
@@ -9,6 +9,7 @@ import { Avatar } from '@/components/shared/avatar'
|
|
|
9
9
|
import { SettingsPage } from '@/components/shared/settings/settings-page'
|
|
10
10
|
import { AgentList } from '@/components/agents/agent-list'
|
|
11
11
|
import { AgentChatList } from '@/components/agents/agent-chat-list'
|
|
12
|
+
import { AgentAvatar } from '@/components/agents/agent-avatar'
|
|
12
13
|
import { AgentSheet } from '@/components/agents/agent-sheet'
|
|
13
14
|
import { ScheduleList } from '@/components/schedules/schedule-list'
|
|
14
15
|
import { ScheduleSheet } from '@/components/schedules/schedule-sheet'
|
|
@@ -71,6 +72,46 @@ const RAIL_EXPANDED_KEY = 'sc_rail_expanded'
|
|
|
71
72
|
const STAR_NOTIFICATION_KEY = 'sc_star_notification_v1'
|
|
72
73
|
const GITHUB_REPO_URL = 'https://github.com/swarmclawai/swarmclaw'
|
|
73
74
|
|
|
75
|
+
const VIEW_LABELS: Record<AppView, string> = {
|
|
76
|
+
home: 'Home',
|
|
77
|
+
agents: 'Agents',
|
|
78
|
+
chatrooms: 'Chatrooms',
|
|
79
|
+
schedules: 'Schedules',
|
|
80
|
+
memory: 'Memory',
|
|
81
|
+
tasks: 'Tasks',
|
|
82
|
+
approvals: 'Approvals',
|
|
83
|
+
secrets: 'Secrets',
|
|
84
|
+
providers: 'Providers',
|
|
85
|
+
skills: 'Skills',
|
|
86
|
+
connectors: 'Connectors',
|
|
87
|
+
webhooks: 'Webhooks',
|
|
88
|
+
mcp_servers: 'MCP Servers',
|
|
89
|
+
knowledge: 'Knowledge',
|
|
90
|
+
logs: 'Logs',
|
|
91
|
+
plugins: 'Plugins',
|
|
92
|
+
usage: 'Usage',
|
|
93
|
+
wallets: 'Wallets',
|
|
94
|
+
runs: 'Runs',
|
|
95
|
+
settings: 'Settings',
|
|
96
|
+
projects: 'Projects',
|
|
97
|
+
activity: 'Activity',
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const CREATE_LABELS: Partial<Record<AppView, string>> = {
|
|
101
|
+
agents: 'Agent',
|
|
102
|
+
schedules: 'Schedule',
|
|
103
|
+
tasks: 'Task',
|
|
104
|
+
secrets: 'Secret',
|
|
105
|
+
providers: 'Provider',
|
|
106
|
+
skills: 'Skill',
|
|
107
|
+
connectors: 'Connector',
|
|
108
|
+
webhooks: 'Webhook',
|
|
109
|
+
mcp_servers: 'MCP Server',
|
|
110
|
+
knowledge: 'Knowledge Entry',
|
|
111
|
+
plugins: 'Plugin',
|
|
112
|
+
projects: 'Project',
|
|
113
|
+
}
|
|
114
|
+
|
|
74
115
|
export function AppLayout() {
|
|
75
116
|
const currentUser = useAppStore((s) => s.currentUser)
|
|
76
117
|
const sessions = useAppStore((s) => s.sessions)
|
|
@@ -92,6 +133,8 @@ export function AppLayout() {
|
|
|
92
133
|
const setPluginSheetOpen = useAppStore((s) => s.setPluginSheetOpen)
|
|
93
134
|
const setProjectSheetOpen = useAppStore((s) => s.setProjectSheetOpen)
|
|
94
135
|
const tasks = useAppStore((s) => s.tasks)
|
|
136
|
+
const plugins = useAppStore((s) => s.plugins)
|
|
137
|
+
const loadPlugins = useAppStore((s) => s.loadPlugins)
|
|
95
138
|
const approvals = useAppStore((s) => s.approvals)
|
|
96
139
|
const loadApprovals = useAppStore((s) => s.loadApprovals)
|
|
97
140
|
const execApprovals = useApprovalStore((s) => s.approvals)
|
|
@@ -131,13 +174,15 @@ export function AppLayout() {
|
|
|
131
174
|
|
|
132
175
|
const handleShortcutKey = useCallback((e: KeyboardEvent) => {
|
|
133
176
|
const mod = e.metaKey || e.ctrlKey
|
|
134
|
-
// Cmd+N / Ctrl+N —
|
|
177
|
+
// Cmd+N / Ctrl+N — jump to the default agent shortcut
|
|
135
178
|
if (mod && !e.shiftKey && e.key.toLowerCase() === 'n') {
|
|
136
179
|
e.preventDefault()
|
|
137
180
|
const state = useAppStore.getState()
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
181
|
+
const defaultAgentId = state.appSettings.defaultAgentId && state.agents[state.appSettings.defaultAgentId]
|
|
182
|
+
? state.appSettings.defaultAgentId
|
|
183
|
+
: Object.values(state.agents)[0]?.id || null
|
|
184
|
+
if (defaultAgentId) void state.setCurrentAgent(defaultAgentId)
|
|
185
|
+
else state.setActiveView('agents')
|
|
141
186
|
return
|
|
142
187
|
}
|
|
143
188
|
// Cmd+Shift+T / Ctrl+Shift+T — jump to tasks
|
|
@@ -178,11 +223,27 @@ export function AppLayout() {
|
|
|
178
223
|
|
|
179
224
|
const [pluginSidebarItems, setPluginSidebarItems] = useState<Array<{ id: string; label: string; href: string }>>([])
|
|
180
225
|
|
|
181
|
-
|
|
226
|
+
const refreshPluginState = useCallback(() => {
|
|
182
227
|
api<Array<{ id: string; label: string; href: string }>>('GET', '/plugins/ui?type=sidebar').then(items => {
|
|
183
228
|
if (Array.isArray(items)) setPluginSidebarItems(items)
|
|
184
229
|
}).catch(() => {})
|
|
185
|
-
|
|
230
|
+
void loadPlugins()
|
|
231
|
+
}, [loadPlugins])
|
|
232
|
+
|
|
233
|
+
useEffect(() => { refreshPluginState() }, [refreshPluginState])
|
|
234
|
+
|
|
235
|
+
useWs('plugins', refreshPluginState)
|
|
236
|
+
|
|
237
|
+
const isViewEnabled = useCallback((view: AppView) => {
|
|
238
|
+
if (view === 'chatrooms') return plugins['chatroom']?.enabled !== false
|
|
239
|
+
if (view === 'schedules') return plugins['schedule']?.enabled !== false
|
|
240
|
+
if (view === 'memory') return plugins['memory']?.enabled !== false
|
|
241
|
+
if (view === 'connectors') return plugins['connectors']?.enabled !== false
|
|
242
|
+
if (view === 'webhooks') return plugins['http']?.enabled !== false
|
|
243
|
+
if (view === 'wallets') return plugins['wallet']?.enabled !== false
|
|
244
|
+
if (view === 'logs') return plugins['monitor']?.enabled !== false
|
|
245
|
+
return true
|
|
246
|
+
}, [plugins])
|
|
186
247
|
|
|
187
248
|
const [railExpanded, setRailExpanded] = useState(() => {
|
|
188
249
|
const stored = safeStorageGet(RAIL_EXPANDED_KEY)
|
|
@@ -230,10 +291,11 @@ export function AppLayout() {
|
|
|
230
291
|
const agents = useAppStore((s) => s.agents)
|
|
231
292
|
const currentAgentId = useAppStore((s) => s.currentAgentId)
|
|
232
293
|
const setCurrentAgent = useAppStore((s) => s.setCurrentAgent)
|
|
233
|
-
const
|
|
234
|
-
? appSettings.defaultAgentId
|
|
235
|
-
: Object.values(agents)[0]
|
|
236
|
-
const
|
|
294
|
+
const defaultAgent = appSettings.defaultAgentId && agents[appSettings.defaultAgentId]
|
|
295
|
+
? agents[appSettings.defaultAgentId]
|
|
296
|
+
: Object.values(agents)[0] || null
|
|
297
|
+
const defaultAgentId = defaultAgent?.id || null
|
|
298
|
+
const isDefaultChat = activeView === 'agents' && currentAgentId === defaultAgentId
|
|
237
299
|
|
|
238
300
|
const swipeHandlers = useSwipe({
|
|
239
301
|
onSwipe: (dir) => {
|
|
@@ -248,9 +310,11 @@ export function AppLayout() {
|
|
|
248
310
|
const hasCanvas = !!(currentSession?.canvasContent && canvasDismissedFor !== currentSessionId)
|
|
249
311
|
const canvasAgentName = currentSession?.agentId && agents[currentSession.agentId] ? agents[currentSession.agentId].name : undefined
|
|
250
312
|
|
|
251
|
-
const
|
|
313
|
+
const goToDefaultChat = async () => {
|
|
252
314
|
if (defaultAgentId) {
|
|
253
315
|
await setCurrentAgent(defaultAgentId)
|
|
316
|
+
} else {
|
|
317
|
+
setActiveView('agents')
|
|
254
318
|
}
|
|
255
319
|
setActiveView('agents')
|
|
256
320
|
setSidebarOpen(false)
|
|
@@ -310,32 +374,60 @@ export function AppLayout() {
|
|
|
310
374
|
</div>
|
|
311
375
|
)}
|
|
312
376
|
|
|
313
|
-
{/*
|
|
377
|
+
{/* Default agent shortcut */}
|
|
314
378
|
{railExpanded ? (
|
|
315
|
-
<div className="px-3 mb-2">
|
|
379
|
+
<div className="px-3 mb-2.5">
|
|
316
380
|
<button
|
|
317
|
-
onClick={
|
|
318
|
-
className={`w-full flex items-center gap-
|
|
319
|
-
${
|
|
381
|
+
onClick={goToDefaultChat}
|
|
382
|
+
className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-[12px] text-[13px] font-600 cursor-pointer transition-all text-left
|
|
383
|
+
${isDefaultChat
|
|
320
384
|
? 'bg-accent-bright/15 border border-[#6366F1]/25 text-accent-bright'
|
|
321
385
|
: 'bg-accent-bright/10 border border-[#6366F1]/20 text-accent-bright hover:bg-accent-bright/15'}`}
|
|
322
386
|
style={{ fontFamily: 'inherit' }}
|
|
323
387
|
>
|
|
324
|
-
|
|
325
|
-
<
|
|
326
|
-
|
|
327
|
-
|
|
388
|
+
{defaultAgent ? (
|
|
389
|
+
<AgentAvatar
|
|
390
|
+
seed={defaultAgent.avatarSeed || null}
|
|
391
|
+
avatarUrl={defaultAgent.avatarUrl}
|
|
392
|
+
name={defaultAgent.name}
|
|
393
|
+
size={28}
|
|
394
|
+
/>
|
|
395
|
+
) : (
|
|
396
|
+
<div className="w-7 h-7 rounded-full bg-accent-bright/15 flex items-center justify-center shrink-0">
|
|
397
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
398
|
+
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
|
|
399
|
+
</svg>
|
|
400
|
+
</div>
|
|
401
|
+
)}
|
|
402
|
+
<div className="min-w-0">
|
|
403
|
+
<div className="truncate">{defaultAgent?.name || 'Choose Agent'}</div>
|
|
404
|
+
<div className="text-[10px] font-500 text-accent-bright/75 mt-0.5">
|
|
405
|
+
{defaultAgent ? 'Default shortcut' : 'Pick an agent to open its thread'}
|
|
406
|
+
</div>
|
|
407
|
+
</div>
|
|
328
408
|
</button>
|
|
329
409
|
</div>
|
|
330
410
|
) : (
|
|
331
|
-
<RailTooltip
|
|
411
|
+
<RailTooltip
|
|
412
|
+
label={defaultAgent?.name || 'Choose Agent'}
|
|
413
|
+
description={defaultAgent ? 'Open your default agent shortcut chat' : 'Choose an agent thread'}
|
|
414
|
+
>
|
|
332
415
|
<button
|
|
333
|
-
onClick={
|
|
334
|
-
className={`rail-btn self-center mb-2 ${
|
|
416
|
+
onClick={goToDefaultChat}
|
|
417
|
+
className={`rail-btn self-center mb-2 ${isDefaultChat ? 'active' : ''}`}
|
|
335
418
|
>
|
|
336
|
-
|
|
337
|
-
<
|
|
338
|
-
|
|
419
|
+
{defaultAgent ? (
|
|
420
|
+
<AgentAvatar
|
|
421
|
+
seed={defaultAgent.avatarSeed || null}
|
|
422
|
+
avatarUrl={defaultAgent.avatarUrl}
|
|
423
|
+
name={defaultAgent.name}
|
|
424
|
+
size={20}
|
|
425
|
+
/>
|
|
426
|
+
) : (
|
|
427
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
428
|
+
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
|
|
429
|
+
</svg>
|
|
430
|
+
)}
|
|
339
431
|
</button>
|
|
340
432
|
</RailTooltip>
|
|
341
433
|
)}
|
|
@@ -373,114 +465,159 @@ export function AppLayout() {
|
|
|
373
465
|
|
|
374
466
|
<div className="flex-1 min-h-0 flex flex-col overflow-y-auto overscroll-contain touch-pan-y">
|
|
375
467
|
{/* Nav items */}
|
|
376
|
-
<div className={`flex flex-col gap-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
</
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
<
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
<
|
|
482
|
-
|
|
483
|
-
|
|
468
|
+
<div className={`flex flex-col gap-3 ${railExpanded ? 'px-3' : 'items-center'}`}>
|
|
469
|
+
<div className={`flex flex-col gap-0.5 ${railExpanded ? '' : 'items-center'}`}>
|
|
470
|
+
{railExpanded ? (
|
|
471
|
+
<div className="px-3 pb-1 text-[10px] font-700 uppercase tracking-[0.12em] text-text-3/45">Workspace</div>
|
|
472
|
+
) : (
|
|
473
|
+
<div className="my-1 h-px w-6 bg-white/[0.06]" />
|
|
474
|
+
)}
|
|
475
|
+
<NavItem view="home" label="Home" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('home')}>
|
|
476
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
477
|
+
<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" />
|
|
478
|
+
</svg>
|
|
479
|
+
</NavItem>
|
|
480
|
+
<NavItem view="agents" label="Agents" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('agents')}>
|
|
481
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
482
|
+
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /><circle cx="12" cy="7" r="4" />
|
|
483
|
+
</svg>
|
|
484
|
+
</NavItem>
|
|
485
|
+
{isViewEnabled('chatrooms') && (
|
|
486
|
+
<NavItem view="chatrooms" label="Chatrooms" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('chatrooms')}>
|
|
487
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
488
|
+
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
|
|
489
|
+
<path d="M8 10h8" /><path d="M8 14h4" />
|
|
490
|
+
</svg>
|
|
491
|
+
</NavItem>
|
|
492
|
+
)}
|
|
493
|
+
<NavItem view="projects" label="Projects" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('projects')}>
|
|
494
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
495
|
+
<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" />
|
|
496
|
+
</svg>
|
|
497
|
+
</NavItem>
|
|
498
|
+
</div>
|
|
499
|
+
|
|
500
|
+
<div className={`flex flex-col gap-0.5 ${railExpanded ? '' : 'items-center'}`}>
|
|
501
|
+
{railExpanded ? (
|
|
502
|
+
<div className="px-3 pb-1 text-[10px] font-700 uppercase tracking-[0.12em] text-text-3/45">Execution</div>
|
|
503
|
+
) : (
|
|
504
|
+
<div className="my-1 h-px w-6 bg-white/[0.06]" />
|
|
505
|
+
)}
|
|
506
|
+
<NavItem view="tasks" label="Tasks" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('tasks')} badge={pendingApprovalCount}>
|
|
507
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
508
|
+
<path d="M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2" /><rect x="9" y="3" width="6" height="4" rx="1" /><path d="M9 14l2 2 4-4" />
|
|
509
|
+
</svg>
|
|
510
|
+
</NavItem>
|
|
511
|
+
<NavItem view="approvals" label="Approvals" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('approvals')} badge={pendingApprovalCount}>
|
|
512
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
513
|
+
<path d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z"/>
|
|
514
|
+
<path d="m9 12 2 2 4-4"/>
|
|
515
|
+
</svg>
|
|
516
|
+
</NavItem>
|
|
517
|
+
{isViewEnabled('schedules') && (
|
|
518
|
+
<NavItem view="schedules" label="Schedules" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('schedules')}>
|
|
519
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
520
|
+
<circle cx="12" cy="12" r="10" /><polyline points="12 6 12 12 16 14" />
|
|
521
|
+
</svg>
|
|
522
|
+
</NavItem>
|
|
523
|
+
)}
|
|
524
|
+
{isViewEnabled('memory') && (
|
|
525
|
+
<NavItem view="memory" label="Memory" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('memory')}>
|
|
526
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
527
|
+
<ellipse cx="12" cy="5" rx="9" ry="3" /><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3" /><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5" />
|
|
528
|
+
</svg>
|
|
529
|
+
</NavItem>
|
|
530
|
+
)}
|
|
531
|
+
<NavItem view="runs" label="Runs" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('runs')}>
|
|
532
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
533
|
+
<polyline points="22 12 18 12 15 21 9 3 6 12 2 12" />
|
|
534
|
+
</svg>
|
|
535
|
+
</NavItem>
|
|
536
|
+
</div>
|
|
537
|
+
|
|
538
|
+
<div className={`flex flex-col gap-0.5 ${railExpanded ? '' : 'items-center'}`}>
|
|
539
|
+
{railExpanded ? (
|
|
540
|
+
<div className="px-3 pb-1 text-[10px] font-700 uppercase tracking-[0.12em] text-text-3/45">Knowledge</div>
|
|
541
|
+
) : (
|
|
542
|
+
<div className="my-1 h-px w-6 bg-white/[0.06]" />
|
|
543
|
+
)}
|
|
544
|
+
<NavItem view="knowledge" label="Knowledge" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('knowledge')}>
|
|
545
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
546
|
+
<circle cx="12" cy="12" r="10" /><line x1="2" y1="12" x2="22" y2="12" /><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" />
|
|
547
|
+
</svg>
|
|
548
|
+
</NavItem>
|
|
549
|
+
<NavItem view="skills" label="Skills" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('skills')}>
|
|
550
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
551
|
+
<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" />
|
|
552
|
+
</svg>
|
|
553
|
+
</NavItem>
|
|
554
|
+
{isViewEnabled('connectors') && (
|
|
555
|
+
<NavItem view="connectors" label="Connectors" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('connectors')}>
|
|
556
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
557
|
+
<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" />
|
|
558
|
+
</svg>
|
|
559
|
+
</NavItem>
|
|
560
|
+
)}
|
|
561
|
+
{isViewEnabled('webhooks') && (
|
|
562
|
+
<NavItem view="webhooks" label="Webhooks" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('webhooks')}>
|
|
563
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
564
|
+
<path d="M22 12h-4l-3 7L9 5l-3 7H2" />
|
|
565
|
+
</svg>
|
|
566
|
+
</NavItem>
|
|
567
|
+
)}
|
|
568
|
+
<NavItem view="mcp_servers" label="MCP Servers" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('mcp_servers')}>
|
|
569
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
570
|
+
<rect x="2" y="2" width="20" height="8" rx="2" /><rect x="2" y="14" width="20" height="8" rx="2" /><line x1="6" y1="6" x2="6.01" y2="6" /><line x1="6" y1="18" x2="6.01" y2="18" />
|
|
571
|
+
</svg>
|
|
572
|
+
</NavItem>
|
|
573
|
+
<NavItem view="plugins" label="Plugins" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('plugins')}>
|
|
574
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
575
|
+
<path d="M12 2v4m0 12v4M2 12h4m12 0h4" /><circle cx="12" cy="12" r="4" /><path d="M8 8L5.5 5.5M16 8l2.5-2.5M8 16l-2.5 2.5M16 16l2.5 2.5" />
|
|
576
|
+
</svg>
|
|
577
|
+
</NavItem>
|
|
578
|
+
</div>
|
|
579
|
+
|
|
580
|
+
<div className={`flex flex-col gap-0.5 ${railExpanded ? '' : 'items-center'}`}>
|
|
581
|
+
{railExpanded ? (
|
|
582
|
+
<div className="px-3 pb-1 text-[10px] font-700 uppercase tracking-[0.12em] text-text-3/45">System</div>
|
|
583
|
+
) : (
|
|
584
|
+
<div className="my-1 h-px w-6 bg-white/[0.06]" />
|
|
585
|
+
)}
|
|
586
|
+
<NavItem view="secrets" label="Secrets" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('secrets')}>
|
|
587
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
588
|
+
<rect x="3" y="11" width="18" height="11" rx="2" ry="2" /><path d="M7 11V7a5 5 0 0 1 10 0v4" />
|
|
589
|
+
</svg>
|
|
590
|
+
</NavItem>
|
|
591
|
+
<NavItem view="providers" label="Providers" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('providers')}>
|
|
592
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
593
|
+
<path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z" />
|
|
594
|
+
</svg>
|
|
595
|
+
</NavItem>
|
|
596
|
+
<NavItem view="usage" label="Usage" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('usage')}>
|
|
597
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
598
|
+
<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" />
|
|
599
|
+
</svg>
|
|
600
|
+
</NavItem>
|
|
601
|
+
<NavItem view="activity" label="Activity" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('activity')}>
|
|
602
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
603
|
+
<path d="M12 8v4l3 3" /><circle cx="12" cy="12" r="10" />
|
|
604
|
+
</svg>
|
|
605
|
+
</NavItem>
|
|
606
|
+
{isViewEnabled('wallets') && (
|
|
607
|
+
<NavItem view="wallets" label="Wallets" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('wallets')}>
|
|
608
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
609
|
+
<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" />
|
|
610
|
+
</svg>
|
|
611
|
+
</NavItem>
|
|
612
|
+
)}
|
|
613
|
+
{isViewEnabled('logs') && (
|
|
614
|
+
<NavItem view="logs" label="Logs" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('logs')}>
|
|
615
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
616
|
+
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" /><polyline points="14 2 14 8 20 8" /><line x1="16" y1="13" x2="8" y2="13" /><line x1="16" y1="17" x2="8" y2="17" /><polyline points="10 9 9 9 8 9" />
|
|
617
|
+
</svg>
|
|
618
|
+
</NavItem>
|
|
619
|
+
)}
|
|
620
|
+
</div>
|
|
484
621
|
</div>
|
|
485
622
|
|
|
486
623
|
<div className="flex-1" />
|
|
@@ -595,7 +732,7 @@ export function AppLayout() {
|
|
|
595
732
|
style={{ animation: 'panel-in 0.3s var(--ease-spring)' }}
|
|
596
733
|
>
|
|
597
734
|
<div className="flex items-center px-5 pt-5 pb-3 shrink-0">
|
|
598
|
-
<h2 className="font-display text-[14px] font-600 text-text-2 tracking-[-0.01em]
|
|
735
|
+
<h2 className="font-display text-[14px] font-600 text-text-2 tracking-[-0.01em] flex-1">{VIEW_LABELS[activeView]}</h2>
|
|
599
736
|
{activeView === 'logs' || activeView === 'usage' || activeView === 'runs' ? null : activeView === 'memory' ? (
|
|
600
737
|
<button
|
|
601
738
|
onClick={() => useAppStore.getState().setMemorySheetOpen(true)}
|
|
@@ -617,7 +754,7 @@ export function AppLayout() {
|
|
|
617
754
|
<line x1="12" y1="5" x2="12" y2="19" />
|
|
618
755
|
<line x1="5" y1="12" x2="19" y2="12" />
|
|
619
756
|
</svg>
|
|
620
|
-
{activeView
|
|
757
|
+
{CREATE_LABELS[activeView] || 'New'}
|
|
621
758
|
</button>
|
|
622
759
|
)}
|
|
623
760
|
</div>
|
|
@@ -685,32 +822,89 @@ export function AppLayout() {
|
|
|
685
822
|
<Avatar user={currentUser!} size="sm" avatarSeed={appSettings.userAvatarSeed} />
|
|
686
823
|
</button>
|
|
687
824
|
</div>
|
|
688
|
-
{
|
|
689
|
-
|
|
690
|
-
{(['agents', 'chatrooms', 'schedules', 'memory', 'tasks', 'secrets', 'providers', 'skills', 'connectors', 'webhooks', 'mcp_servers', 'knowledge', 'plugins', 'usage', 'runs', 'logs'] as AppView[]).map((v) => (
|
|
691
|
-
<button
|
|
692
|
-
key={v}
|
|
693
|
-
onClick={() => setActiveView(v)}
|
|
694
|
-
className={`py-2 px-2.5 rounded-[10px] text-[11px] font-600 capitalize cursor-pointer transition-all
|
|
695
|
-
${activeView === v
|
|
696
|
-
? 'bg-accent-soft text-accent-bright'
|
|
697
|
-
: 'bg-transparent text-text-3 hover:text-text-2'}`}
|
|
698
|
-
style={{ fontFamily: 'inherit' }}
|
|
699
|
-
>
|
|
700
|
-
{v}
|
|
701
|
-
</button>
|
|
702
|
-
))}
|
|
703
|
-
{/* Dynamic Plugin Items */}
|
|
704
|
-
{pluginSidebarItems.map((item) => (
|
|
825
|
+
{defaultAgent && (
|
|
826
|
+
<div className="px-4 pt-1 pb-3 shrink-0">
|
|
705
827
|
<button
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
828
|
+
onClick={goToDefaultChat}
|
|
829
|
+
className={`w-full flex items-center gap-3 rounded-[14px] border px-4 py-3 text-left transition-all cursor-pointer ${
|
|
830
|
+
isDefaultChat
|
|
831
|
+
? 'bg-accent-soft border-accent-bright/25 text-accent-bright'
|
|
832
|
+
: 'bg-accent-soft/50 border-accent-bright/15 text-accent-bright hover:bg-accent-soft/65'
|
|
833
|
+
}`}
|
|
709
834
|
style={{ fontFamily: 'inherit' }}
|
|
710
835
|
>
|
|
711
|
-
|
|
836
|
+
<AgentAvatar
|
|
837
|
+
seed={defaultAgent.avatarSeed || null}
|
|
838
|
+
avatarUrl={defaultAgent.avatarUrl}
|
|
839
|
+
name={defaultAgent.name}
|
|
840
|
+
size={32}
|
|
841
|
+
/>
|
|
842
|
+
<div className="min-w-0">
|
|
843
|
+
<div className="text-[13px] font-700 truncate">{defaultAgent.name}</div>
|
|
844
|
+
<div className="text-[11px] text-accent-bright/70">Default shortcut</div>
|
|
845
|
+
</div>
|
|
712
846
|
</button>
|
|
713
|
-
|
|
847
|
+
</div>
|
|
848
|
+
)}
|
|
849
|
+
<div className="px-4 pb-3 shrink-0 max-h-[260px] overflow-y-auto">
|
|
850
|
+
<div className="space-y-4">
|
|
851
|
+
{([
|
|
852
|
+
{ label: 'Workspace', views: ['agents', 'chatrooms', 'projects'] as AppView[] },
|
|
853
|
+
{ label: 'Execution', views: ['tasks', 'approvals', 'schedules', 'memory', 'runs'] as AppView[] },
|
|
854
|
+
{ label: 'Knowledge', views: ['knowledge', 'skills', 'connectors', 'webhooks', 'mcp_servers', 'plugins'] as AppView[] },
|
|
855
|
+
{ label: 'System', views: ['secrets', 'providers', 'usage', 'logs'] as AppView[] },
|
|
856
|
+
]).map((section) => {
|
|
857
|
+
const visibleViews = section.views.filter((view) => isViewEnabled(view))
|
|
858
|
+
if (!visibleViews.length) return null
|
|
859
|
+
return (
|
|
860
|
+
<div key={section.label}>
|
|
861
|
+
<div className="px-1 pb-2 text-[10px] font-700 uppercase tracking-[0.12em] text-text-3/45">
|
|
862
|
+
{section.label}
|
|
863
|
+
</div>
|
|
864
|
+
<div className="grid grid-cols-2 gap-2">
|
|
865
|
+
{visibleViews.map((view) => (
|
|
866
|
+
<button
|
|
867
|
+
key={view}
|
|
868
|
+
onClick={() => {
|
|
869
|
+
setActiveView(view)
|
|
870
|
+
if (FULL_WIDTH_VIEWS.has(view)) setSidebarOpen(false)
|
|
871
|
+
}}
|
|
872
|
+
className={`rounded-[12px] border px-3 py-2.5 text-left transition-all cursor-pointer ${
|
|
873
|
+
activeView === view
|
|
874
|
+
? 'bg-accent-soft border-accent-bright/20 text-accent-bright'
|
|
875
|
+
: 'bg-transparent border-white/[0.06] text-text-3 hover:text-text hover:bg-white/[0.04]'
|
|
876
|
+
}`}
|
|
877
|
+
style={{ fontFamily: 'inherit' }}
|
|
878
|
+
>
|
|
879
|
+
<div className="text-[12px] font-600">{VIEW_LABELS[view]}</div>
|
|
880
|
+
<div className="text-[10px] text-current/60 mt-1">{VIEW_DESCRIPTIONS[view]}</div>
|
|
881
|
+
</button>
|
|
882
|
+
))}
|
|
883
|
+
</div>
|
|
884
|
+
</div>
|
|
885
|
+
)
|
|
886
|
+
})}
|
|
887
|
+
{pluginSidebarItems.length > 0 && (
|
|
888
|
+
<div>
|
|
889
|
+
<div className="px-1 pb-2 text-[10px] font-700 uppercase tracking-[0.12em] text-text-3/45">
|
|
890
|
+
Extensions
|
|
891
|
+
</div>
|
|
892
|
+
<div className="grid grid-cols-2 gap-2">
|
|
893
|
+
{pluginSidebarItems.map((item) => (
|
|
894
|
+
<button
|
|
895
|
+
key={item.id}
|
|
896
|
+
onClick={() => window.open(item.href, '_blank')}
|
|
897
|
+
className="rounded-[12px] border border-emerald-400/10 bg-emerald-500/[0.05] px-3 py-2.5 text-left text-emerald-400/85 hover:text-emerald-300 transition-colors cursor-pointer"
|
|
898
|
+
style={{ fontFamily: 'inherit' }}
|
|
899
|
+
>
|
|
900
|
+
<div className="text-[12px] font-600">{item.label}</div>
|
|
901
|
+
<div className="text-[10px] text-emerald-300/60 mt-1">Open plugin view</div>
|
|
902
|
+
</button>
|
|
903
|
+
))}
|
|
904
|
+
</div>
|
|
905
|
+
</div>
|
|
906
|
+
)}
|
|
907
|
+
</div>
|
|
714
908
|
</div>
|
|
715
909
|
{activeView !== 'logs' && activeView !== 'usage' && activeView !== 'runs' && activeView !== 'settings' && (
|
|
716
910
|
<div className="px-4 py-2.5 shrink-0">
|
|
@@ -724,7 +918,7 @@ export function AppLayout() {
|
|
|
724
918
|
shadow-[0_2px_12px_rgba(99,102,241,0.15)]"
|
|
725
919
|
style={{ fontFamily: 'inherit' }}
|
|
726
920
|
>
|
|
727
|
-
+ New {activeView
|
|
921
|
+
+ New {CREATE_LABELS[activeView] || 'Entry'}
|
|
728
922
|
</button>
|
|
729
923
|
</div>
|
|
730
924
|
)}
|
|
@@ -790,11 +984,27 @@ export function AppLayout() {
|
|
|
790
984
|
<div className="flex-1 flex items-center justify-center px-8">
|
|
791
985
|
<div className="text-center max-w-[420px]">
|
|
792
986
|
<h2 className="font-display text-[24px] font-700 text-text mb-2 tracking-[-0.02em]">
|
|
793
|
-
|
|
987
|
+
Open a Chat
|
|
794
988
|
</h2>
|
|
795
989
|
<p className="text-[14px] text-text-3">
|
|
796
|
-
Choose
|
|
990
|
+
Choose a chat from the sidebar, or jump straight into your default agent shortcut.
|
|
797
991
|
</p>
|
|
992
|
+
<div className="mt-5 flex items-center justify-center gap-3">
|
|
993
|
+
<button
|
|
994
|
+
onClick={defaultAgent ? goToDefaultChat : () => setAgentSheetOpen(true)}
|
|
995
|
+
className="inline-flex items-center gap-2 px-4 py-2.5 rounded-[12px] border-none bg-accent-bright text-white text-[13px] font-600 cursor-pointer hover:brightness-110 transition-all"
|
|
996
|
+
style={{ fontFamily: 'inherit' }}
|
|
997
|
+
>
|
|
998
|
+
{defaultAgent ? `Open ${defaultAgent.name}` : 'Create Agent'}
|
|
999
|
+
</button>
|
|
1000
|
+
<button
|
|
1001
|
+
onClick={() => setAgentSheetOpen(true)}
|
|
1002
|
+
className="inline-flex items-center gap-2 px-4 py-2.5 rounded-[12px] border border-white/[0.08] bg-transparent text-[13px] font-600 text-text-2 cursor-pointer hover:bg-white/[0.04] transition-all"
|
|
1003
|
+
style={{ fontFamily: 'inherit' }}
|
|
1004
|
+
>
|
|
1005
|
+
Create Agent
|
|
1006
|
+
</button>
|
|
1007
|
+
</div>
|
|
798
1008
|
</div>
|
|
799
1009
|
</div>
|
|
800
1010
|
)}
|
|
@@ -844,7 +1054,7 @@ export function AppLayout() {
|
|
|
844
1054
|
<div className="flex-1 flex flex-col h-full">
|
|
845
1055
|
<div className="flex items-center px-6 pt-5 pb-3 shrink-0">
|
|
846
1056
|
<h2 className="font-display text-[14px] font-600 text-text-2 tracking-[-0.01em] capitalize flex-1">
|
|
847
|
-
{activeView
|
|
1057
|
+
{VIEW_LABELS[activeView]}
|
|
848
1058
|
</h2>
|
|
849
1059
|
{activeView !== 'runs' && activeView !== 'logs' && (
|
|
850
1060
|
<button
|
|
@@ -855,7 +1065,7 @@ export function AppLayout() {
|
|
|
855
1065
|
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round">
|
|
856
1066
|
<line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" />
|
|
857
1067
|
</svg>
|
|
858
|
-
{activeView
|
|
1068
|
+
{CREATE_LABELS[activeView] || 'New'}
|
|
859
1069
|
</button>
|
|
860
1070
|
)}
|
|
861
1071
|
</div>
|
|
@@ -960,9 +1170,9 @@ const VIEW_DESCRIPTIONS: Record<AppView, string> = {
|
|
|
960
1170
|
chatrooms: 'Multi-agent collaborative chatrooms',
|
|
961
1171
|
schedules: 'Automated task schedules',
|
|
962
1172
|
memory: 'Long-term agent memory store',
|
|
963
|
-
tasks: 'Task board for
|
|
1173
|
+
tasks: 'Task board for agent work and queued runs',
|
|
964
1174
|
approvals: 'Pending tool execution approvals',
|
|
965
|
-
secrets: 'API keys
|
|
1175
|
+
secrets: 'API keys, tokens, and encrypted credentials',
|
|
966
1176
|
providers: 'LLM providers & custom endpoints',
|
|
967
1177
|
skills: 'Reusable instruction sets for agents',
|
|
968
1178
|
connectors: 'Chat platform bridges (Discord, Slack, etc.)',
|
|
@@ -974,7 +1184,7 @@ const VIEW_DESCRIPTIONS: Record<AppView, string> = {
|
|
|
974
1184
|
usage: 'Usage metrics, cost tracking & agent performance',
|
|
975
1185
|
wallets: 'Agent crypto wallets — hold funds, send SOL, manage spending',
|
|
976
1186
|
runs: 'Live run monitoring & history',
|
|
977
|
-
settings: 'Manage providers,
|
|
1187
|
+
settings: 'Manage defaults, providers, secrets, and automation settings',
|
|
978
1188
|
projects: 'Group agents, tasks & schedules into projects',
|
|
979
1189
|
activity: 'Audit trail of all entity mutations',
|
|
980
1190
|
}
|
|
@@ -995,26 +1205,26 @@ const VIEW_EMPTY_STATES: Record<Exclude<AppView, 'agents' | 'home'>, { icon: str
|
|
|
995
1205
|
schedules: {
|
|
996
1206
|
icon: 'clock',
|
|
997
1207
|
title: 'Schedules',
|
|
998
|
-
description: 'Automate recurring
|
|
999
|
-
features: ['Set up cron expressions for precise timing', 'Run
|
|
1208
|
+
description: 'Automate recurring work with cron, interval, or one-time schedules that launch agent tasks.',
|
|
1209
|
+
features: ['Set up cron expressions for precise timing', 'Run agents automatically on intervals', 'Schedule one-time future tasks', 'View execution history and results'],
|
|
1000
1210
|
},
|
|
1001
1211
|
memory: {
|
|
1002
1212
|
icon: 'database',
|
|
1003
1213
|
title: 'Memory',
|
|
1004
|
-
description: 'Long-term memory store for AI agents
|
|
1214
|
+
description: 'Long-term memory store for AI agents so they can retain useful context across conversations.',
|
|
1005
1215
|
features: ['Agents store findings and learnings automatically', 'Full-text search across all stored memories', 'Organized by categories and agents', 'Persists across conversations for continuity'],
|
|
1006
1216
|
},
|
|
1007
1217
|
tasks: {
|
|
1008
1218
|
icon: 'clipboard',
|
|
1009
1219
|
title: 'Task Board',
|
|
1010
|
-
description: 'A
|
|
1011
|
-
features: ['Kanban columns: Backlog, Queued, Running, Completed, Failed', 'Assign tasks to specific
|
|
1220
|
+
description: 'A kanban board for managing agent work. Create tasks, assign them to agents, and track progress.',
|
|
1221
|
+
features: ['Kanban columns: Backlog, Queued, Running, Completed, Failed', 'Assign tasks to specific agents', 'Track retries, results, and logs', 'Review status without leaving the board'],
|
|
1012
1222
|
},
|
|
1013
1223
|
secrets: {
|
|
1014
1224
|
icon: 'lock',
|
|
1015
1225
|
title: 'Secrets',
|
|
1016
|
-
description: 'Manage API keys and credentials that
|
|
1017
|
-
features: ['Store keys for external services (Gmail, APIs, etc.)', 'Scope secrets globally or to specific
|
|
1226
|
+
description: 'Manage API keys and credentials that agents and integrations can access securely.',
|
|
1227
|
+
features: ['Store keys for external services (Gmail, APIs, etc.)', 'Scope secrets globally or to specific agents', 'Encrypted at rest with AES-256-GCM', 'Agents retrieve secrets through approved tools'],
|
|
1018
1228
|
},
|
|
1019
1229
|
providers: {
|
|
1020
1230
|
icon: 'zap',
|
|
@@ -1037,8 +1247,8 @@ const VIEW_EMPTY_STATES: Record<Exclude<AppView, 'agents' | 'home'>, { icon: str
|
|
|
1037
1247
|
webhooks: {
|
|
1038
1248
|
icon: 'webhook',
|
|
1039
1249
|
title: 'Webhooks',
|
|
1040
|
-
description: 'Receive external events over HTTP and
|
|
1041
|
-
features: ['Create secure inbound webhook endpoints', 'Filter events by type or source', 'Route each webhook to a specific
|
|
1250
|
+
description: 'Receive external events over HTTP and route them into agent-driven workflows automatically.',
|
|
1251
|
+
features: ['Create secure inbound webhook endpoints', 'Filter events by type or source', 'Route each webhook to a specific agent', 'Use x-webhook-secret for request authentication'],
|
|
1042
1252
|
},
|
|
1043
1253
|
mcp_servers: {
|
|
1044
1254
|
icon: 'server',
|
|
@@ -1049,7 +1259,7 @@ const VIEW_EMPTY_STATES: Record<Exclude<AppView, 'agents' | 'home'>, { icon: str
|
|
|
1049
1259
|
knowledge: {
|
|
1050
1260
|
icon: 'globe',
|
|
1051
1261
|
title: 'Knowledge Base',
|
|
1052
|
-
description: 'A shared knowledge graph accessible by all agents
|
|
1262
|
+
description: 'A shared knowledge graph accessible by all agents for cross-workspace information sharing.',
|
|
1053
1263
|
features: ['Create tagged knowledge entries', 'Agents can store and search knowledge via tools', 'Full-text and vector search', 'Provenance tracking per entry'],
|
|
1054
1264
|
},
|
|
1055
1265
|
logs: {
|
|
@@ -1079,8 +1289,8 @@ const VIEW_EMPTY_STATES: Record<Exclude<AppView, 'agents' | 'home'>, { icon: str
|
|
|
1079
1289
|
settings: {
|
|
1080
1290
|
icon: 'settings',
|
|
1081
1291
|
title: 'Settings',
|
|
1082
|
-
description: 'Manage providers,
|
|
1083
|
-
features: ['
|
|
1292
|
+
description: 'Manage app defaults, providers, encrypted secrets, and automation settings.',
|
|
1293
|
+
features: ['Choose your default agent shortcut', 'Configure LLM providers and credentials', 'Tune heartbeat and autonomy settings', 'Set up voice, embeddings, and search'],
|
|
1084
1294
|
},
|
|
1085
1295
|
projects: {
|
|
1086
1296
|
icon: 'folder',
|
|
@@ -1262,7 +1472,7 @@ function RailTooltip({ label, description, children }: { label: string; descript
|
|
|
1262
1472
|
}
|
|
1263
1473
|
|
|
1264
1474
|
function DesktopEmptyState({ userName }: { userName: string | null }) {
|
|
1265
|
-
const
|
|
1475
|
+
const setAgentSheetOpen = useAppStore((s) => s.setAgentSheetOpen)
|
|
1266
1476
|
|
|
1267
1477
|
return (
|
|
1268
1478
|
<div className="flex-1 flex flex-col items-center justify-center px-8 pb-20 relative overflow-hidden">
|
|
@@ -1293,10 +1503,10 @@ function DesktopEmptyState({ userName }: { userName: string | null }) {
|
|
|
1293
1503
|
<span className="text-text-2">What would you like to do?</span>
|
|
1294
1504
|
</h1>
|
|
1295
1505
|
<p className="text-[15px] text-text-3 mb-12">
|
|
1296
|
-
Create
|
|
1506
|
+
Create an agent, then keep working in its persistent thread
|
|
1297
1507
|
</p>
|
|
1298
1508
|
<button
|
|
1299
|
-
onClick={() =>
|
|
1509
|
+
onClick={() => setAgentSheetOpen(true)}
|
|
1300
1510
|
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
|
|
1301
1511
|
cursor-pointer hover:brightness-110 active:scale-[0.97] transition-all duration-200
|
|
1302
1512
|
shadow-[0_6px_28px_rgba(99,102,241,0.3)]"
|
|
@@ -1306,7 +1516,7 @@ function DesktopEmptyState({ userName }: { userName: string | null }) {
|
|
|
1306
1516
|
<line x1="12" y1="5" x2="12" y2="19" />
|
|
1307
1517
|
<line x1="5" y1="12" x2="19" y2="12" />
|
|
1308
1518
|
</svg>
|
|
1309
|
-
New
|
|
1519
|
+
New Agent
|
|
1310
1520
|
</button>
|
|
1311
1521
|
</div>
|
|
1312
1522
|
</div>
|