@swarmclawai/swarmclaw 0.7.2 → 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 +81 -22
- package/package.json +1 -1
- package/src/app/api/agents/[id]/route.ts +26 -0
- package/src/app/api/agents/[id]/thread/route.ts +36 -7
- package/src/app/api/agents/route.ts +12 -1
- package/src/app/api/auth/route.ts +76 -7
- package/src/app/api/chatrooms/[id]/chat/route.ts +7 -2
- package/src/app/api/chats/[id]/browser/route.ts +5 -1
- package/src/app/api/chats/[id]/chat/route.ts +7 -3
- package/src/app/api/chats/[id]/main-loop/route.ts +7 -88
- package/src/app/api/chats/[id]/messages/route.ts +19 -13
- package/src/app/api/chats/[id]/route.ts +18 -0
- package/src/app/api/chats/[id]/stop/route.ts +6 -1
- package/src/app/api/chats/route.ts +16 -0
- 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 +3 -26
- package/src/app/api/plugins/settings/route.ts +17 -12
- 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/webhooks/[id]/route.ts +8 -1
- package/src/app/page.tsx +9 -2
- package/src/cli/index.js +4 -0
- package/src/cli/index.ts +3 -10
- package/src/components/agents/agent-card.tsx +15 -12
- package/src/components/agents/agent-chat-list.tsx +101 -1
- package/src/components/agents/agent-list.tsx +46 -9
- package/src/components/agents/agent-sheet.tsx +207 -16
- package/src/components/agents/inspector-panel.tsx +108 -48
- package/src/components/auth/access-key-gate.tsx +36 -97
- package/src/components/chat/chat-area.tsx +29 -13
- package/src/components/chat/chat-card.tsx +4 -20
- package/src/components/chat/chat-header.tsx +255 -353
- package/src/components/chat/chat-list.tsx +7 -9
- package/src/components/chat/checkpoint-timeline.tsx +1 -1
- package/src/components/chat/message-list.tsx +3 -1
- 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 +217 -0
- package/src/components/home/home-view.tsx +128 -4
- package/src/components/layout/app-layout.tsx +383 -194
- package/src/components/layout/mobile-header.tsx +26 -8
- package/src/components/plugins/plugin-list.tsx +15 -3
- package/src/components/plugins/plugin-sheet.tsx +118 -9
- package/src/components/projects/project-detail.tsx +183 -0
- package/src/components/shared/agent-picker-list.tsx +2 -2
- package/src/components/shared/command-palette.tsx +111 -24
- 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 +77 -0
- package/src/components/shared/settings/section-orchestrator.tsx +3 -3
- 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 +245 -46
- 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 +74 -1
- package/src/components/wallets/wallet-panel.tsx +17 -5
- package/src/components/webhooks/webhook-sheet.tsx +7 -7
- 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/openclaw-agent-id.test.ts +14 -0
- package/src/lib/openclaw-agent-id.ts +31 -0
- 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/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 +250 -61
- 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 +45 -5
- 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 +946 -110
- 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/daemon-state.ts +59 -1
- 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 +13 -39
- 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 +27 -967
- 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 +17 -6
- package/src/lib/server/orchestrator.ts +2 -2
- package/src/lib/server/playwright-proxy.mjs +27 -3
- package/src/lib/server/plugins.test.ts +207 -0
- package/src/lib/server/plugins.ts +822 -69
- package/src/lib/server/provider-health.ts +33 -3
- package/src/lib/server/queue.ts +3 -20
- 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 -80
- package/src/lib/server/session-tools/autonomy-tools.test.ts +105 -0
- package/src/lib/server/session-tools/calendar.ts +2 -12
- package/src/lib/server/session-tools/connector.ts +109 -8
- package/src/lib/server/session-tools/context.ts +14 -2
- package/src/lib/server/session-tools/crawl.ts +447 -0
- package/src/lib/server/session-tools/crud.ts +70 -32
- package/src/lib/server/session-tools/delegate-fallback.test.ts +219 -0
- package/src/lib/server/session-tools/delegate.ts +406 -20
- package/src/lib/server/session-tools/discovery.ts +22 -4
- package/src/lib/server/session-tools/document.ts +283 -0
- package/src/lib/server/session-tools/email.ts +1 -3
- 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 +237 -24
- package/src/lib/server/session-tools/human-loop.ts +227 -0
- package/src/lib/server/session-tools/image-gen.ts +1 -3
- package/src/lib/server/session-tools/index.ts +56 -1
- package/src/lib/server/session-tools/mailbox.ts +276 -0
- package/src/lib/server/session-tools/memory.ts +35 -3
- package/src/lib/server/session-tools/monitor.ts +150 -7
- package/src/lib/server/session-tools/normalize-tool-args.ts +17 -14
- package/src/lib/server/session-tools/platform-normalize.test.ts +142 -0
- package/src/lib/server/session-tools/platform.ts +142 -4
- package/src/lib/server/session-tools/plugin-creator.ts +86 -23
- package/src/lib/server/session-tools/primitive-tools.test.ts +257 -0
- package/src/lib/server/session-tools/replicate.ts +1 -3
- package/src/lib/server/session-tools/schedule.ts +20 -10
- package/src/lib/server/session-tools/session-info.ts +36 -3
- package/src/lib/server/session-tools/session-tools-wiring.test.ts +31 -17
- package/src/lib/server/session-tools/subagent.ts +193 -27
- package/src/lib/server/session-tools/table.ts +587 -0
- package/src/lib/server/session-tools/wallet.ts +13 -10
- package/src/lib/server/session-tools/web-browser-config.test.ts +39 -0
- package/src/lib/server/session-tools/web.ts +896 -100
- package/src/lib/server/storage.ts +226 -7
- package/src/lib/server/stream-agent-chat.ts +46 -21
- 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 +44 -7
- package/src/lib/server/tool-capability-policy.ts +6 -0
- 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/validation/schemas.test.ts +26 -0
- package/src/lib/validation/schemas.ts +7 -0
- package/src/lib/ws-client.ts +14 -12
- package/src/proxy.ts +5 -5
- package/src/stores/use-app-store.ts +0 -6
- package/src/stores/use-chat-store.ts +31 -2
- package/src/types/index.ts +287 -44
- package/src/components/chat/new-chat-sheet.tsx +0 -253
- package/src/lib/server/main-session.ts +0 -17
- package/src/lib/server/session-run-manager.test.ts +0 -26
|
@@ -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)
|
|
@@ -133,13 +174,15 @@ export function AppLayout() {
|
|
|
133
174
|
|
|
134
175
|
const handleShortcutKey = useCallback((e: KeyboardEvent) => {
|
|
135
176
|
const mod = e.metaKey || e.ctrlKey
|
|
136
|
-
// Cmd+N / Ctrl+N —
|
|
177
|
+
// Cmd+N / Ctrl+N — jump to the default agent shortcut
|
|
137
178
|
if (mod && !e.shiftKey && e.key.toLowerCase() === 'n') {
|
|
138
179
|
e.preventDefault()
|
|
139
180
|
const state = useAppStore.getState()
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
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')
|
|
143
186
|
return
|
|
144
187
|
}
|
|
145
188
|
// Cmd+Shift+T / Ctrl+Shift+T — jump to tasks
|
|
@@ -191,6 +234,17 @@ export function AppLayout() {
|
|
|
191
234
|
|
|
192
235
|
useWs('plugins', refreshPluginState)
|
|
193
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])
|
|
247
|
+
|
|
194
248
|
const [railExpanded, setRailExpanded] = useState(() => {
|
|
195
249
|
const stored = safeStorageGet(RAIL_EXPANDED_KEY)
|
|
196
250
|
return stored === null ? true : stored === 'true'
|
|
@@ -237,10 +291,11 @@ export function AppLayout() {
|
|
|
237
291
|
const agents = useAppStore((s) => s.agents)
|
|
238
292
|
const currentAgentId = useAppStore((s) => s.currentAgentId)
|
|
239
293
|
const setCurrentAgent = useAppStore((s) => s.setCurrentAgent)
|
|
240
|
-
const
|
|
241
|
-
? appSettings.defaultAgentId
|
|
242
|
-
: Object.values(agents)[0]
|
|
243
|
-
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
|
|
244
299
|
|
|
245
300
|
const swipeHandlers = useSwipe({
|
|
246
301
|
onSwipe: (dir) => {
|
|
@@ -255,9 +310,11 @@ export function AppLayout() {
|
|
|
255
310
|
const hasCanvas = !!(currentSession?.canvasContent && canvasDismissedFor !== currentSessionId)
|
|
256
311
|
const canvasAgentName = currentSession?.agentId && agents[currentSession.agentId] ? agents[currentSession.agentId].name : undefined
|
|
257
312
|
|
|
258
|
-
const
|
|
313
|
+
const goToDefaultChat = async () => {
|
|
259
314
|
if (defaultAgentId) {
|
|
260
315
|
await setCurrentAgent(defaultAgentId)
|
|
316
|
+
} else {
|
|
317
|
+
setActiveView('agents')
|
|
261
318
|
}
|
|
262
319
|
setActiveView('agents')
|
|
263
320
|
setSidebarOpen(false)
|
|
@@ -317,32 +374,60 @@ export function AppLayout() {
|
|
|
317
374
|
</div>
|
|
318
375
|
)}
|
|
319
376
|
|
|
320
|
-
{/*
|
|
377
|
+
{/* Default agent shortcut */}
|
|
321
378
|
{railExpanded ? (
|
|
322
|
-
<div className="px-3 mb-2">
|
|
379
|
+
<div className="px-3 mb-2.5">
|
|
323
380
|
<button
|
|
324
|
-
onClick={
|
|
325
|
-
className={`w-full flex items-center gap-
|
|
326
|
-
${
|
|
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
|
|
327
384
|
? 'bg-accent-bright/15 border border-[#6366F1]/25 text-accent-bright'
|
|
328
385
|
: 'bg-accent-bright/10 border border-[#6366F1]/20 text-accent-bright hover:bg-accent-bright/15'}`}
|
|
329
386
|
style={{ fontFamily: 'inherit' }}
|
|
330
387
|
>
|
|
331
|
-
|
|
332
|
-
<
|
|
333
|
-
|
|
334
|
-
|
|
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>
|
|
335
408
|
</button>
|
|
336
409
|
</div>
|
|
337
410
|
) : (
|
|
338
|
-
<RailTooltip
|
|
411
|
+
<RailTooltip
|
|
412
|
+
label={defaultAgent?.name || 'Choose Agent'}
|
|
413
|
+
description={defaultAgent ? 'Open your default agent shortcut chat' : 'Choose an agent thread'}
|
|
414
|
+
>
|
|
339
415
|
<button
|
|
340
|
-
onClick={
|
|
341
|
-
className={`rail-btn self-center mb-2 ${
|
|
416
|
+
onClick={goToDefaultChat}
|
|
417
|
+
className={`rail-btn self-center mb-2 ${isDefaultChat ? 'active' : ''}`}
|
|
342
418
|
>
|
|
343
|
-
|
|
344
|
-
<
|
|
345
|
-
|
|
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
|
+
)}
|
|
346
431
|
</button>
|
|
347
432
|
</RailTooltip>
|
|
348
433
|
)}
|
|
@@ -380,128 +465,159 @@ export function AppLayout() {
|
|
|
380
465
|
|
|
381
466
|
<div className="flex-1 min-h-0 flex flex-col overflow-y-auto overscroll-contain touch-pan-y">
|
|
382
467
|
{/* Nav items */}
|
|
383
|
-
<div className={`flex flex-col gap-
|
|
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
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
<
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
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>
|
|
505
621
|
</div>
|
|
506
622
|
|
|
507
623
|
<div className="flex-1" />
|
|
@@ -616,7 +732,7 @@ export function AppLayout() {
|
|
|
616
732
|
style={{ animation: 'panel-in 0.3s var(--ease-spring)' }}
|
|
617
733
|
>
|
|
618
734
|
<div className="flex items-center px-5 pt-5 pb-3 shrink-0">
|
|
619
|
-
<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>
|
|
620
736
|
{activeView === 'logs' || activeView === 'usage' || activeView === 'runs' ? null : activeView === 'memory' ? (
|
|
621
737
|
<button
|
|
622
738
|
onClick={() => useAppStore.getState().setMemorySheetOpen(true)}
|
|
@@ -638,7 +754,7 @@ export function AppLayout() {
|
|
|
638
754
|
<line x1="12" y1="5" x2="12" y2="19" />
|
|
639
755
|
<line x1="5" y1="12" x2="19" y2="12" />
|
|
640
756
|
</svg>
|
|
641
|
-
{activeView
|
|
757
|
+
{CREATE_LABELS[activeView] || 'New'}
|
|
642
758
|
</button>
|
|
643
759
|
)}
|
|
644
760
|
</div>
|
|
@@ -706,32 +822,89 @@ export function AppLayout() {
|
|
|
706
822
|
<Avatar user={currentUser!} size="sm" avatarSeed={appSettings.userAvatarSeed} />
|
|
707
823
|
</button>
|
|
708
824
|
</div>
|
|
709
|
-
{
|
|
710
|
-
|
|
711
|
-
{(['agents', 'chatrooms', 'schedules', 'memory', 'tasks', 'secrets', 'providers', 'skills', 'connectors', 'webhooks', 'mcp_servers', 'knowledge', 'plugins', 'usage', 'runs', 'logs'] as AppView[]).map((v) => (
|
|
712
|
-
<button
|
|
713
|
-
key={v}
|
|
714
|
-
onClick={() => setActiveView(v)}
|
|
715
|
-
className={`py-2 px-2.5 rounded-[10px] text-[11px] font-600 capitalize cursor-pointer transition-all
|
|
716
|
-
${activeView === v
|
|
717
|
-
? 'bg-accent-soft text-accent-bright'
|
|
718
|
-
: 'bg-transparent text-text-3 hover:text-text-2'}`}
|
|
719
|
-
style={{ fontFamily: 'inherit' }}
|
|
720
|
-
>
|
|
721
|
-
{v}
|
|
722
|
-
</button>
|
|
723
|
-
))}
|
|
724
|
-
{/* Dynamic Plugin Items */}
|
|
725
|
-
{pluginSidebarItems.map((item) => (
|
|
825
|
+
{defaultAgent && (
|
|
826
|
+
<div className="px-4 pt-1 pb-3 shrink-0">
|
|
726
827
|
<button
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
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
|
+
}`}
|
|
730
834
|
style={{ fontFamily: 'inherit' }}
|
|
731
835
|
>
|
|
732
|
-
|
|
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>
|
|
733
846
|
</button>
|
|
734
|
-
|
|
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>
|
|
735
908
|
</div>
|
|
736
909
|
{activeView !== 'logs' && activeView !== 'usage' && activeView !== 'runs' && activeView !== 'settings' && (
|
|
737
910
|
<div className="px-4 py-2.5 shrink-0">
|
|
@@ -745,7 +918,7 @@ export function AppLayout() {
|
|
|
745
918
|
shadow-[0_2px_12px_rgba(99,102,241,0.15)]"
|
|
746
919
|
style={{ fontFamily: 'inherit' }}
|
|
747
920
|
>
|
|
748
|
-
+ New {activeView
|
|
921
|
+
+ New {CREATE_LABELS[activeView] || 'Entry'}
|
|
749
922
|
</button>
|
|
750
923
|
</div>
|
|
751
924
|
)}
|
|
@@ -811,11 +984,27 @@ export function AppLayout() {
|
|
|
811
984
|
<div className="flex-1 flex items-center justify-center px-8">
|
|
812
985
|
<div className="text-center max-w-[420px]">
|
|
813
986
|
<h2 className="font-display text-[24px] font-700 text-text mb-2 tracking-[-0.02em]">
|
|
814
|
-
|
|
987
|
+
Open a Chat
|
|
815
988
|
</h2>
|
|
816
989
|
<p className="text-[14px] text-text-3">
|
|
817
|
-
Choose
|
|
990
|
+
Choose a chat from the sidebar, or jump straight into your default agent shortcut.
|
|
818
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>
|
|
819
1008
|
</div>
|
|
820
1009
|
</div>
|
|
821
1010
|
)}
|
|
@@ -865,7 +1054,7 @@ export function AppLayout() {
|
|
|
865
1054
|
<div className="flex-1 flex flex-col h-full">
|
|
866
1055
|
<div className="flex items-center px-6 pt-5 pb-3 shrink-0">
|
|
867
1056
|
<h2 className="font-display text-[14px] font-600 text-text-2 tracking-[-0.01em] capitalize flex-1">
|
|
868
|
-
{activeView
|
|
1057
|
+
{VIEW_LABELS[activeView]}
|
|
869
1058
|
</h2>
|
|
870
1059
|
{activeView !== 'runs' && activeView !== 'logs' && (
|
|
871
1060
|
<button
|
|
@@ -876,7 +1065,7 @@ export function AppLayout() {
|
|
|
876
1065
|
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round">
|
|
877
1066
|
<line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" />
|
|
878
1067
|
</svg>
|
|
879
|
-
{activeView
|
|
1068
|
+
{CREATE_LABELS[activeView] || 'New'}
|
|
880
1069
|
</button>
|
|
881
1070
|
)}
|
|
882
1071
|
</div>
|
|
@@ -981,9 +1170,9 @@ const VIEW_DESCRIPTIONS: Record<AppView, string> = {
|
|
|
981
1170
|
chatrooms: 'Multi-agent collaborative chatrooms',
|
|
982
1171
|
schedules: 'Automated task schedules',
|
|
983
1172
|
memory: 'Long-term agent memory store',
|
|
984
|
-
tasks: 'Task board for
|
|
1173
|
+
tasks: 'Task board for agent work and queued runs',
|
|
985
1174
|
approvals: 'Pending tool execution approvals',
|
|
986
|
-
secrets: 'API keys
|
|
1175
|
+
secrets: 'API keys, tokens, and encrypted credentials',
|
|
987
1176
|
providers: 'LLM providers & custom endpoints',
|
|
988
1177
|
skills: 'Reusable instruction sets for agents',
|
|
989
1178
|
connectors: 'Chat platform bridges (Discord, Slack, etc.)',
|
|
@@ -995,7 +1184,7 @@ const VIEW_DESCRIPTIONS: Record<AppView, string> = {
|
|
|
995
1184
|
usage: 'Usage metrics, cost tracking & agent performance',
|
|
996
1185
|
wallets: 'Agent crypto wallets — hold funds, send SOL, manage spending',
|
|
997
1186
|
runs: 'Live run monitoring & history',
|
|
998
|
-
settings: 'Manage providers,
|
|
1187
|
+
settings: 'Manage defaults, providers, secrets, and automation settings',
|
|
999
1188
|
projects: 'Group agents, tasks & schedules into projects',
|
|
1000
1189
|
activity: 'Audit trail of all entity mutations',
|
|
1001
1190
|
}
|
|
@@ -1016,26 +1205,26 @@ const VIEW_EMPTY_STATES: Record<Exclude<AppView, 'agents' | 'home'>, { icon: str
|
|
|
1016
1205
|
schedules: {
|
|
1017
1206
|
icon: 'clock',
|
|
1018
1207
|
title: 'Schedules',
|
|
1019
|
-
description: 'Automate recurring
|
|
1020
|
-
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'],
|
|
1021
1210
|
},
|
|
1022
1211
|
memory: {
|
|
1023
1212
|
icon: 'database',
|
|
1024
1213
|
title: 'Memory',
|
|
1025
|
-
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.',
|
|
1026
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'],
|
|
1027
1216
|
},
|
|
1028
1217
|
tasks: {
|
|
1029
1218
|
icon: 'clipboard',
|
|
1030
1219
|
title: 'Task Board',
|
|
1031
|
-
description: 'A
|
|
1032
|
-
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'],
|
|
1033
1222
|
},
|
|
1034
1223
|
secrets: {
|
|
1035
1224
|
icon: 'lock',
|
|
1036
1225
|
title: 'Secrets',
|
|
1037
|
-
description: 'Manage API keys and credentials that
|
|
1038
|
-
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'],
|
|
1039
1228
|
},
|
|
1040
1229
|
providers: {
|
|
1041
1230
|
icon: 'zap',
|
|
@@ -1058,8 +1247,8 @@ const VIEW_EMPTY_STATES: Record<Exclude<AppView, 'agents' | 'home'>, { icon: str
|
|
|
1058
1247
|
webhooks: {
|
|
1059
1248
|
icon: 'webhook',
|
|
1060
1249
|
title: 'Webhooks',
|
|
1061
|
-
description: 'Receive external events over HTTP and
|
|
1062
|
-
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'],
|
|
1063
1252
|
},
|
|
1064
1253
|
mcp_servers: {
|
|
1065
1254
|
icon: 'server',
|
|
@@ -1070,7 +1259,7 @@ const VIEW_EMPTY_STATES: Record<Exclude<AppView, 'agents' | 'home'>, { icon: str
|
|
|
1070
1259
|
knowledge: {
|
|
1071
1260
|
icon: 'globe',
|
|
1072
1261
|
title: 'Knowledge Base',
|
|
1073
|
-
description: 'A shared knowledge graph accessible by all agents
|
|
1262
|
+
description: 'A shared knowledge graph accessible by all agents for cross-workspace information sharing.',
|
|
1074
1263
|
features: ['Create tagged knowledge entries', 'Agents can store and search knowledge via tools', 'Full-text and vector search', 'Provenance tracking per entry'],
|
|
1075
1264
|
},
|
|
1076
1265
|
logs: {
|
|
@@ -1100,8 +1289,8 @@ const VIEW_EMPTY_STATES: Record<Exclude<AppView, 'agents' | 'home'>, { icon: str
|
|
|
1100
1289
|
settings: {
|
|
1101
1290
|
icon: 'settings',
|
|
1102
1291
|
title: 'Settings',
|
|
1103
|
-
description: 'Manage providers,
|
|
1104
|
-
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'],
|
|
1105
1294
|
},
|
|
1106
1295
|
projects: {
|
|
1107
1296
|
icon: 'folder',
|
|
@@ -1283,7 +1472,7 @@ function RailTooltip({ label, description, children }: { label: string; descript
|
|
|
1283
1472
|
}
|
|
1284
1473
|
|
|
1285
1474
|
function DesktopEmptyState({ userName }: { userName: string | null }) {
|
|
1286
|
-
const
|
|
1475
|
+
const setAgentSheetOpen = useAppStore((s) => s.setAgentSheetOpen)
|
|
1287
1476
|
|
|
1288
1477
|
return (
|
|
1289
1478
|
<div className="flex-1 flex flex-col items-center justify-center px-8 pb-20 relative overflow-hidden">
|
|
@@ -1314,10 +1503,10 @@ function DesktopEmptyState({ userName }: { userName: string | null }) {
|
|
|
1314
1503
|
<span className="text-text-2">What would you like to do?</span>
|
|
1315
1504
|
</h1>
|
|
1316
1505
|
<p className="text-[15px] text-text-3 mb-12">
|
|
1317
|
-
Create
|
|
1506
|
+
Create an agent, then keep working in its persistent thread
|
|
1318
1507
|
</p>
|
|
1319
1508
|
<button
|
|
1320
|
-
onClick={() =>
|
|
1509
|
+
onClick={() => setAgentSheetOpen(true)}
|
|
1321
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
|
|
1322
1511
|
cursor-pointer hover:brightness-110 active:scale-[0.97] transition-all duration-200
|
|
1323
1512
|
shadow-[0_6px_28px_rgba(99,102,241,0.3)]"
|
|
@@ -1327,7 +1516,7 @@ function DesktopEmptyState({ userName }: { userName: string | null }) {
|
|
|
1327
1516
|
<line x1="12" y1="5" x2="12" y2="19" />
|
|
1328
1517
|
<line x1="5" y1="12" x2="19" y2="12" />
|
|
1329
1518
|
</svg>
|
|
1330
|
-
New
|
|
1519
|
+
New Agent
|
|
1331
1520
|
</button>
|
|
1332
1521
|
</div>
|
|
1333
1522
|
</div>
|