@swarmclawai/swarmclaw 0.7.1 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -139
- package/package.json +1 -1
- package/src/app/api/agents/[id]/thread/route.ts +1 -2
- package/src/app/api/agents/route.ts +1 -1
- package/src/app/api/{sessions → chats}/[id]/checkpoints/route.ts +1 -1
- package/src/app/api/{sessions → chats}/[id]/main-loop/route.ts +2 -2
- package/src/app/api/{sessions → chats}/[id]/restore/route.ts +1 -1
- package/src/app/api/{sessions → chats}/[id]/route.ts +4 -52
- package/src/app/api/{sessions → chats}/route.ts +5 -7
- package/src/app/api/plugins/route.ts +3 -0
- package/src/app/api/plugins/settings/route.ts +35 -0
- package/src/app/api/usage/route.ts +30 -0
- package/src/cli/index.js +35 -33
- package/src/cli/index.ts +40 -39
- package/src/cli/spec.js +29 -27
- package/src/components/agents/agent-card.tsx +1 -1
- package/src/components/agents/agent-chat-list.tsx +3 -3
- package/src/components/agents/agent-list.tsx +8 -13
- package/src/components/agents/agent-sheet.tsx +2 -2
- package/src/components/agents/cron-job-form.tsx +3 -3
- package/src/components/agents/inspector-panel.tsx +2 -2
- package/src/components/auth/setup-wizard.tsx +5 -38
- package/src/components/chat/chat-area.tsx +10 -14
- package/src/components/{sessions/session-card.tsx → chat/chat-card.tsx} +3 -3
- package/src/components/chat/chat-header.tsx +156 -73
- package/src/components/{sessions/session-list.tsx → chat/chat-list.tsx} +4 -5
- 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 +2 -2
- package/src/components/{sessions/new-session-sheet.tsx → chat/new-chat-sheet.tsx} +6 -6
- 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/connectors/connector-sheet.tsx +1 -1
- package/src/components/home/home-view.tsx +1 -1
- package/src/components/layout/app-layout.tsx +23 -2
- package/src/components/plugins/plugin-list.tsx +475 -254
- package/src/components/plugins/plugin-sheet.tsx +124 -10
- package/src/components/settings/gateway-connection-panel.tsx +1 -1
- package/src/components/shared/command-palette.tsx +0 -1
- package/src/components/shared/settings/section-heartbeat.tsx +1 -1
- package/src/components/shared/settings/section-providers.tsx +1 -1
- package/src/components/shared/settings/settings-page.tsx +1 -12
- package/src/components/usage/metrics-dashboard.tsx +73 -0
- package/src/components/webhooks/webhook-sheet.tsx +1 -1
- package/src/lib/chat.ts +1 -1
- package/src/lib/{sessions.ts → chats.ts} +28 -18
- package/src/lib/providers/claude-cli.ts +1 -1
- package/src/lib/server/approvals.ts +4 -4
- package/src/lib/server/capability-router.ts +10 -8
- package/src/lib/server/chat-execution.ts +36 -105
- package/src/lib/server/chatroom-helpers.ts +3 -3
- package/src/lib/server/connectors/manager.ts +4 -4
- package/src/lib/server/cost.ts +34 -1
- package/src/lib/server/daemon-state.ts +2 -2
- package/src/lib/server/heartbeat-service.ts +1 -1
- package/src/lib/server/main-agent-loop.ts +25 -160
- package/src/lib/server/main-session.ts +6 -13
- package/src/lib/server/orchestrator-lg.ts +3 -3
- package/src/lib/server/orchestrator.ts +5 -5
- package/src/lib/server/plugins.ts +112 -4
- package/src/lib/server/provider-health.ts +5 -3
- package/src/lib/server/queue.ts +12 -10
- package/src/lib/server/session-run-manager.test.ts +9 -6
- package/src/lib/server/session-run-manager.ts +1 -3
- package/src/lib/server/session-tools/calendar.ts +376 -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 +5 -2
- package/src/lib/server/session-tools/context.ts +7 -3
- package/src/lib/server/session-tools/crud.ts +14 -6
- package/src/lib/server/session-tools/delegate.ts +95 -8
- package/src/lib/server/session-tools/discovery.ts +2 -2
- package/src/lib/server/session-tools/edit_file.ts +4 -2
- package/src/lib/server/session-tools/email.ts +322 -0
- package/src/lib/server/session-tools/file.ts +5 -2
- 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/image-gen.ts +382 -0
- package/src/lib/server/session-tools/index.ts +74 -49
- package/src/lib/server/session-tools/memory.ts +139 -2
- package/src/lib/server/session-tools/monitor.ts +1 -1
- 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.ts +6 -3
- package/src/lib/server/session-tools/plugin-creator.ts +3 -3
- package/src/lib/server/session-tools/replicate.ts +303 -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 +4 -2
- package/src/lib/server/session-tools/session-info.ts +7 -4
- package/src/lib/server/session-tools/shell.ts +5 -2
- package/src/lib/server/session-tools/subagent.ts +2 -2
- package/src/lib/server/session-tools/wallet.ts +29 -2
- package/src/lib/server/session-tools/web.ts +44 -5
- package/src/lib/server/storage.ts +29 -9
- package/src/lib/server/stream-agent-chat.ts +72 -249
- package/src/lib/server/tool-aliases.ts +26 -15
- package/src/lib/server/tool-capability-policy.test.ts +9 -9
- package/src/lib/server/tool-capability-policy.ts +32 -27
- package/src/lib/tool-definitions.ts +4 -0
- package/src/lib/validation/schemas.ts +3 -1
- package/src/stores/use-app-store.ts +5 -5
- package/src/stores/use-chat-store.ts +7 -7
- package/src/types/index.ts +65 -3
- /package/src/app/api/{sessions → chats}/[id]/browser/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/chat/route.ts +0 -0
- /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]/messages/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/retry/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/stop/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/heartbeat/route.ts +0 -0
|
@@ -26,7 +26,7 @@ export function CheckpointTimeline({ sessionId }: Props) {
|
|
|
26
26
|
const load = async () => {
|
|
27
27
|
setLoading(true)
|
|
28
28
|
try {
|
|
29
|
-
const data = await api<Checkpoint[]>('GET', `/
|
|
29
|
+
const data = await api<Checkpoint[]>('GET', `/chats/${sessionId}/checkpoints`)
|
|
30
30
|
setCheckpoints(data)
|
|
31
31
|
} catch (err) {
|
|
32
32
|
console.error('Failed to load checkpoints', err)
|
|
@@ -45,7 +45,7 @@ export function CheckpointTimeline({ sessionId }: Props) {
|
|
|
45
45
|
|
|
46
46
|
setRestoringId(checkpoint.checkpointId)
|
|
47
47
|
try {
|
|
48
|
-
await api('POST', `/
|
|
48
|
+
await api('POST', `/chats/${sessionId}/restore`, {
|
|
49
49
|
checkpointId: checkpoint.checkpointId,
|
|
50
50
|
timestamp: checkpoint.createdAt
|
|
51
51
|
})
|
|
@@ -67,8 +67,8 @@ export function CheckpointTimeline({ sessionId }: Props) {
|
|
|
67
67
|
if (checkpoints.length === 0) {
|
|
68
68
|
return (
|
|
69
69
|
<div className="p-8 text-center">
|
|
70
|
-
<p className="text-text-3 text-[13px]">No checkpoints found for this
|
|
71
|
-
<p className="text-[11px] text-text-3/50 mt-1">Only LangGraph-orchestrated
|
|
70
|
+
<p className="text-text-3 text-[13px]">No checkpoints found for this chat.</p>
|
|
71
|
+
<p className="text-[11px] text-text-3/50 mt-1">Only LangGraph-orchestrated chats support time travel.</p>
|
|
72
72
|
</div>
|
|
73
73
|
)
|
|
74
74
|
}
|
|
@@ -243,7 +243,10 @@ export const MessageBubble = memo(function MessageBubble({ message, assistantNam
|
|
|
243
243
|
const delegationSource = !isUser && message.kind === 'system' ? parseDelegationSource(message.text || '') : null
|
|
244
244
|
// Detect task completion system messages (delegated or direct)
|
|
245
245
|
const taskCompletion = !isUser && message.kind === 'system' ? parseTaskCompletion(message.text || '') : null
|
|
246
|
-
const
|
|
246
|
+
const rawDisplayText = delegationSource ? delegationSource.rest : message.text
|
|
247
|
+
const displayText = rawDisplayText
|
|
248
|
+
? rawDisplayText.split('\n').filter((l) => !/\[(MAIN_LOOP_META|MAIN_LOOP_PLAN|MAIN_LOOP_REVIEW|AGENT_HEARTBEAT_META)\]/.test(l)).join('\n').trim()
|
|
249
|
+
: ''
|
|
247
250
|
|
|
248
251
|
const handleCopy = useCallback(() => {
|
|
249
252
|
void copyTextToClipboard(message.text).then((copiedText) => {
|
|
@@ -129,7 +129,7 @@ export function MessageList({ messages, streaming, connectorFilter = null }: Pro
|
|
|
129
129
|
if (!msg) return
|
|
130
130
|
const next = !msg.bookmarked
|
|
131
131
|
try {
|
|
132
|
-
await api('PUT', `/
|
|
132
|
+
await api('PUT', `/chats/${sessionId}/messages`, { messageIndex: index, bookmarked: next })
|
|
133
133
|
const updated = [...messages]
|
|
134
134
|
updated[index] = { ...updated[index], bookmarked: next }
|
|
135
135
|
setMessages(updated)
|
|
@@ -469,7 +469,7 @@ export function MessageList({ messages, streaming, connectorFilter = null }: Pro
|
|
|
469
469
|
type="button"
|
|
470
470
|
onClick={async () => {
|
|
471
471
|
try {
|
|
472
|
-
await api('DELETE', `/
|
|
472
|
+
await api('DELETE', `/chats/${sessionId}/messages`, { messageIndex: originalIndex })
|
|
473
473
|
setMessages(messages.filter((_: Message, idx: number) => idx !== originalIndex))
|
|
474
474
|
} catch { /* best-effort */ }
|
|
475
475
|
}}
|
|
@@ -17,7 +17,7 @@ interface Props {
|
|
|
17
17
|
onClose: () => void
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export function
|
|
20
|
+
export function NewChatSheet({ open, onClose }: Props) {
|
|
21
21
|
const router = useRouter()
|
|
22
22
|
const agents = useAppStore((s) => s.agents)
|
|
23
23
|
const loadSessions = useAppStore((s) => s.loadSessions)
|
|
@@ -47,7 +47,7 @@ export function NewSessionSheet({ open, onClose }: Props) {
|
|
|
47
47
|
const id = genId(8)
|
|
48
48
|
const now = Date.now()
|
|
49
49
|
|
|
50
|
-
const agentTools = agent?.
|
|
50
|
+
const agentTools = agent?.plugins || (selectedTools.length ? selectedTools : undefined)
|
|
51
51
|
|
|
52
52
|
const session = {
|
|
53
53
|
id,
|
|
@@ -56,7 +56,7 @@ export function NewSessionSheet({ open, onClose }: Props) {
|
|
|
56
56
|
model: agent ? agent.model : model,
|
|
57
57
|
apiEndpoint: agent ? agent.apiEndpoint : (endpoint || undefined),
|
|
58
58
|
credentialId: agent ? agent.credentialId : undefined,
|
|
59
|
-
|
|
59
|
+
plugins: agentTools || undefined,
|
|
60
60
|
messages: [],
|
|
61
61
|
createdAt: now,
|
|
62
62
|
updatedAt: now,
|
|
@@ -64,7 +64,7 @@ export function NewSessionSheet({ open, onClose }: Props) {
|
|
|
64
64
|
agentId: selectedAgentId || undefined,
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
await api('POST', '/
|
|
67
|
+
await api('POST', '/chats', session)
|
|
68
68
|
await loadSessions()
|
|
69
69
|
router.push(`/chat?session=${id}`)
|
|
70
70
|
onClose()
|
|
@@ -223,10 +223,10 @@ export function NewSessionSheet({ open, onClose }: Props) {
|
|
|
223
223
|
Using <span className="text-text-2 font-600">{agents[selectedAgentId].provider}</span>
|
|
224
224
|
{' / '}
|
|
225
225
|
<span className="text-text-2 font-600">{agents[selectedAgentId].model}</span>
|
|
226
|
-
{agents[selectedAgentId].
|
|
226
|
+
{agents[selectedAgentId].plugins?.length ? (
|
|
227
227
|
<>
|
|
228
228
|
{' + '}
|
|
229
|
-
{agents[selectedAgentId].
|
|
229
|
+
{agents[selectedAgentId].plugins!.map((tool, i) => (
|
|
230
230
|
<span key={tool}>
|
|
231
231
|
{i > 0 && ', '}
|
|
232
232
|
<span className="text-sky-400/70 font-600 cursor-help" title={TOOL_DESCRIPTIONS[tool] || tool}>
|
|
@@ -209,7 +209,7 @@ export function SessionDebugPanel({ messages, open, onClose }: Props) {
|
|
|
209
209
|
{currentSessionId ? (
|
|
210
210
|
<CheckpointTimeline sessionId={currentSessionId} />
|
|
211
211
|
) : (
|
|
212
|
-
<div className="p-12 text-center text-text-3">No active
|
|
212
|
+
<div className="p-12 text-center text-text-3">No active chat</div>
|
|
213
213
|
)}
|
|
214
214
|
</div>
|
|
215
215
|
)}
|
|
@@ -62,13 +62,13 @@ export function ToolRequestBanner({ text, toolOutputs = [] }: Props) {
|
|
|
62
62
|
|
|
63
63
|
const handleGrant = async (toolId: string) => {
|
|
64
64
|
if (!sid || !session) return
|
|
65
|
-
const currentTools: string[] = session.
|
|
65
|
+
const currentTools: string[] = session.plugins || []
|
|
66
66
|
if (currentTools.includes(toolId)) {
|
|
67
67
|
setGranted((prev) => new Set(prev).add(toolId))
|
|
68
68
|
return
|
|
69
69
|
}
|
|
70
70
|
const updated = [...currentTools, toolId]
|
|
71
|
-
await api('PUT', `/
|
|
71
|
+
await api('PUT', `/chats/${sid}`, { plugins: updated })
|
|
72
72
|
await loadSessions()
|
|
73
73
|
const newGranted = new Set(granted).add(toolId)
|
|
74
74
|
setGranted(newGranted)
|
|
@@ -108,7 +108,7 @@ export function ToolRequestBanner({ text, toolOutputs = [] }: Props) {
|
|
|
108
108
|
return (
|
|
109
109
|
<div className="max-w-[85%] md:max-w-[72%] flex flex-col gap-2 mt-2">
|
|
110
110
|
{pluginRequests.map(({ pluginId, reason }) => {
|
|
111
|
-
const isGranted = granted.has(pluginId) || (session?.
|
|
111
|
+
const isGranted = granted.has(pluginId) || (session?.plugins || []).includes(pluginId)
|
|
112
112
|
const isDenied = denied.has(pluginId)
|
|
113
113
|
const label = TOOL_LABELS[pluginId] || pluginId
|
|
114
114
|
return (
|
|
@@ -19,7 +19,7 @@ const ALL_TOOL_IDS = [...AVAILABLE_TOOLS, ...PLATFORM_TOOLS].map((t) => t.id)
|
|
|
19
19
|
export function AgentHoverCard({ agent, children, status }: Props) {
|
|
20
20
|
const [showAll, setShowAll] = useState(false)
|
|
21
21
|
const [busy, setBusy] = useState(false)
|
|
22
|
-
const tools = agent.
|
|
22
|
+
const tools = agent.plugins ?? []
|
|
23
23
|
|
|
24
24
|
const displayTools = showAll ? ALL_TOOL_IDS : tools
|
|
25
25
|
|
|
@@ -27,11 +27,11 @@ export function AgentHoverCard({ agent, children, status }: Props) {
|
|
|
27
27
|
if (busy) return
|
|
28
28
|
setBusy(true)
|
|
29
29
|
try {
|
|
30
|
-
const current = agent.
|
|
30
|
+
const current = agent.plugins || []
|
|
31
31
|
const updated = current.includes(toolId)
|
|
32
32
|
? current.filter((t) => t !== toolId)
|
|
33
33
|
: [...current, toolId]
|
|
34
|
-
await api('PUT', `/agents/${agent.id}`, {
|
|
34
|
+
await api('PUT', `/agents/${agent.id}`, { plugins: updated })
|
|
35
35
|
useAppStore.getState().loadAgents()
|
|
36
36
|
} finally {
|
|
37
37
|
setBusy(false)
|
|
@@ -44,7 +44,7 @@ export function ChatroomToolRequestBanner({ agentId, agentName, text, toolOutput
|
|
|
44
44
|
if (toolRequests.length === 0) return null
|
|
45
45
|
|
|
46
46
|
const agent = agents[agentId]
|
|
47
|
-
const agentTools: string[] = agent?.
|
|
47
|
+
const agentTools: string[] = agent?.plugins || []
|
|
48
48
|
|
|
49
49
|
const handleGrant = async (toolId: string) => {
|
|
50
50
|
if (agentTools.includes(toolId)) {
|
|
@@ -52,7 +52,7 @@ export function ChatroomToolRequestBanner({ agentId, agentName, text, toolOutput
|
|
|
52
52
|
return
|
|
53
53
|
}
|
|
54
54
|
const updated = [...agentTools, toolId]
|
|
55
|
-
await api('PUT', `/agents/${agentId}`, {
|
|
55
|
+
await api('PUT', `/agents/${agentId}`, { plugins: updated })
|
|
56
56
|
await loadAgents()
|
|
57
57
|
const newGranted = new Set(granted).add(toolId)
|
|
58
58
|
setGranted(newGranted)
|
|
@@ -121,7 +121,7 @@ const PLATFORMS: {
|
|
|
121
121
|
tokenHelp: 'Required when your OpenClaw gateway is auth-protected',
|
|
122
122
|
configFields: [
|
|
123
123
|
{ key: 'wsUrl', label: 'WebSocket URL', placeholder: 'ws://localhost:18789', help: 'OpenClaw gateway WebSocket endpoint (root URL, not /ws)' },
|
|
124
|
-
{ key: 'sessionKey', label: 'Chat Key Filter', placeholder: 'main', help: 'Optional. If set, only inbound events for this OpenClaw
|
|
124
|
+
{ key: 'sessionKey', label: 'Chat Key Filter', placeholder: 'main', help: 'Optional. If set, only inbound events for this OpenClaw chat are processed.' },
|
|
125
125
|
{ key: 'nodeId', label: 'Client Label', placeholder: 'swarmclaw', help: 'Optional display label shown in OpenClaw presence metadata.' },
|
|
126
126
|
{ key: 'role', label: 'Gateway Role', placeholder: 'operator', help: 'Optional role claim for connect handshake. Default is operator.' },
|
|
127
127
|
{ key: 'scopes', label: 'Scopes (CSV)', placeholder: 'operator.read,operator.write', help: 'Optional comma-separated scopes for OpenClaw connect.' },
|
|
@@ -379,7 +379,7 @@ export function HomeView() {
|
|
|
379
379
|
<div className="flex gap-3 overflow-x-auto pb-2">
|
|
380
380
|
{pinnedAgents.map((agent) => {
|
|
381
381
|
const threadSession = agent.threadSessionId ? sessions[agent.threadSessionId] as Session | undefined : undefined
|
|
382
|
-
const heartbeatOn = agent.heartbeatEnabled === true && (agent.
|
|
382
|
+
const heartbeatOn = agent.heartbeatEnabled === true && (agent.plugins?.length ?? 0) > 0
|
|
383
383
|
const recentlyActive = (threadSession?.lastActiveAt ?? 0) > Date.now() - 30 * 60 * 1000
|
|
384
384
|
const isOnline = runningAgentIds.has(agent.id) || (threadSession?.active ?? false) || heartbeatOn || recentlyActive
|
|
385
385
|
const isTyping = streamingSessionId === agent.threadSessionId
|
|
@@ -92,6 +92,8 @@ export function AppLayout() {
|
|
|
92
92
|
const setPluginSheetOpen = useAppStore((s) => s.setPluginSheetOpen)
|
|
93
93
|
const setProjectSheetOpen = useAppStore((s) => s.setProjectSheetOpen)
|
|
94
94
|
const tasks = useAppStore((s) => s.tasks)
|
|
95
|
+
const plugins = useAppStore((s) => s.plugins)
|
|
96
|
+
const loadPlugins = useAppStore((s) => s.loadPlugins)
|
|
95
97
|
const approvals = useAppStore((s) => s.approvals)
|
|
96
98
|
const loadApprovals = useAppStore((s) => s.loadApprovals)
|
|
97
99
|
const execApprovals = useApprovalStore((s) => s.approvals)
|
|
@@ -178,11 +180,16 @@ export function AppLayout() {
|
|
|
178
180
|
|
|
179
181
|
const [pluginSidebarItems, setPluginSidebarItems] = useState<Array<{ id: string; label: string; href: string }>>([])
|
|
180
182
|
|
|
181
|
-
|
|
183
|
+
const refreshPluginState = useCallback(() => {
|
|
182
184
|
api<Array<{ id: string; label: string; href: string }>>('GET', '/plugins/ui?type=sidebar').then(items => {
|
|
183
185
|
if (Array.isArray(items)) setPluginSidebarItems(items)
|
|
184
186
|
}).catch(() => {})
|
|
185
|
-
|
|
187
|
+
void loadPlugins()
|
|
188
|
+
}, [loadPlugins])
|
|
189
|
+
|
|
190
|
+
useEffect(() => { refreshPluginState() }, [refreshPluginState])
|
|
191
|
+
|
|
192
|
+
useWs('plugins', refreshPluginState)
|
|
186
193
|
|
|
187
194
|
const [railExpanded, setRailExpanded] = useState(() => {
|
|
188
195
|
const stored = safeStorageGet(RAIL_EXPANDED_KEY)
|
|
@@ -384,27 +391,33 @@ export function AppLayout() {
|
|
|
384
391
|
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /><circle cx="12" cy="7" r="4" />
|
|
385
392
|
</svg>
|
|
386
393
|
</NavItem>
|
|
394
|
+
{plugins['chatroom']?.enabled !== false && (
|
|
387
395
|
<NavItem view="chatrooms" label="Chatrooms" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('chatrooms')}>
|
|
388
396
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
389
397
|
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
|
|
390
398
|
<path d="M8 10h8" /><path d="M8 14h4" />
|
|
391
399
|
</svg>
|
|
392
400
|
</NavItem>
|
|
401
|
+
)}
|
|
393
402
|
<NavItem view="projects" label="Projects" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('projects')}>
|
|
394
403
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
395
404
|
<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" />
|
|
396
405
|
</svg>
|
|
397
406
|
</NavItem>
|
|
407
|
+
{plugins['schedule']?.enabled !== false && (
|
|
398
408
|
<NavItem view="schedules" label="Schedules" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('schedules')}>
|
|
399
409
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
400
410
|
<circle cx="12" cy="12" r="10" /><polyline points="12 6 12 12 16 14" />
|
|
401
411
|
</svg>
|
|
402
412
|
</NavItem>
|
|
413
|
+
)}
|
|
414
|
+
{plugins['memory']?.enabled !== false && (
|
|
403
415
|
<NavItem view="memory" label="Memory" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('memory')}>
|
|
404
416
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
405
417
|
<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" />
|
|
406
418
|
</svg>
|
|
407
419
|
</NavItem>
|
|
420
|
+
)}
|
|
408
421
|
<NavItem view="tasks" label="Tasks" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('tasks')} badge={pendingApprovalCount}>
|
|
409
422
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
410
423
|
<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" />
|
|
@@ -431,16 +444,20 @@ export function AppLayout() {
|
|
|
431
444
|
<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" />
|
|
432
445
|
</svg>
|
|
433
446
|
</NavItem>
|
|
447
|
+
{plugins['connectors']?.enabled !== false && (
|
|
434
448
|
<NavItem view="connectors" label="Connectors" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('connectors')}>
|
|
435
449
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
436
450
|
<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" />
|
|
437
451
|
</svg>
|
|
438
452
|
</NavItem>
|
|
453
|
+
)}
|
|
454
|
+
{plugins['http']?.enabled !== false && (
|
|
439
455
|
<NavItem view="webhooks" label="Webhooks" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('webhooks')}>
|
|
440
456
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
441
457
|
<path d="M22 12h-4l-3 7L9 5l-3 7H2" />
|
|
442
458
|
</svg>
|
|
443
459
|
</NavItem>
|
|
460
|
+
)}
|
|
444
461
|
<NavItem view="mcp_servers" label="MCP" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('mcp_servers')}>
|
|
445
462
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
446
463
|
<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" />
|
|
@@ -461,11 +478,13 @@ export function AppLayout() {
|
|
|
461
478
|
<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" />
|
|
462
479
|
</svg>
|
|
463
480
|
</NavItem>
|
|
481
|
+
{plugins['wallet']?.enabled !== false && (
|
|
464
482
|
<NavItem view="wallets" label="Wallets" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('wallets')}>
|
|
465
483
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
466
484
|
<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" />
|
|
467
485
|
</svg>
|
|
468
486
|
</NavItem>
|
|
487
|
+
)}
|
|
469
488
|
<NavItem view="runs" label="Runs" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('runs')}>
|
|
470
489
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
471
490
|
<polyline points="22 12 18 12 15 21 9 3 6 12 2 12" />
|
|
@@ -476,11 +495,13 @@ export function AppLayout() {
|
|
|
476
495
|
<path d="M12 8v4l3 3" /><circle cx="12" cy="12" r="10" />
|
|
477
496
|
</svg>
|
|
478
497
|
</NavItem>
|
|
498
|
+
{plugins['monitor']?.enabled !== false && (
|
|
479
499
|
<NavItem view="logs" label="Logs" expanded={railExpanded} active={activeView} sidebarOpen={sidebarOpen} onClick={() => handleNavClick('logs')}>
|
|
480
500
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
481
501
|
<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" />
|
|
482
502
|
</svg>
|
|
483
503
|
</NavItem>
|
|
504
|
+
)}
|
|
484
505
|
</div>
|
|
485
506
|
|
|
486
507
|
<div className="flex-1" />
|