@swarmclawai/swarmclaw 0.5.2 → 0.6.0
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 +42 -7
- package/bin/swarmclaw.js +76 -16
- package/next.config.ts +11 -1
- package/package.json +4 -2
- package/public/screenshots/agents.png +0 -0
- package/public/screenshots/dashboard.png +0 -0
- package/public/screenshots/providers.png +0 -0
- package/public/screenshots/tasks.png +0 -0
- package/scripts/postinstall.mjs +18 -0
- package/src/app/api/chatrooms/[id]/chat/route.ts +410 -0
- package/src/app/api/chatrooms/[id]/members/route.ts +82 -0
- package/src/app/api/chatrooms/[id]/pins/route.ts +39 -0
- package/src/app/api/chatrooms/[id]/reactions/route.ts +42 -0
- package/src/app/api/chatrooms/[id]/route.ts +84 -0
- package/src/app/api/chatrooms/route.ts +50 -0
- package/src/app/api/credentials/route.ts +2 -3
- package/src/app/api/knowledge/[id]/route.ts +13 -2
- package/src/app/api/knowledge/route.ts +8 -1
- package/src/app/api/memory/route.ts +8 -0
- package/src/app/api/notifications/[id]/route.ts +27 -0
- package/src/app/api/notifications/route.ts +68 -0
- package/src/app/api/orchestrator/run/route.ts +1 -1
- package/src/app/api/plugins/install/route.ts +2 -2
- package/src/app/api/search/route.ts +155 -0
- package/src/app/api/sessions/[id]/chat/route.ts +2 -0
- package/src/app/api/sessions/[id]/edit-resend/route.ts +1 -1
- package/src/app/api/sessions/[id]/fork/route.ts +1 -1
- package/src/app/api/sessions/route.ts +3 -3
- package/src/app/api/settings/route.ts +9 -0
- package/src/app/api/setup/check-provider/route.ts +3 -16
- package/src/app/api/skills/[id]/route.ts +6 -0
- package/src/app/api/skills/route.ts +6 -0
- package/src/app/api/tasks/[id]/route.ts +20 -0
- package/src/app/api/tasks/bulk/route.ts +100 -0
- package/src/app/api/tasks/route.ts +1 -0
- package/src/app/api/usage/route.ts +45 -0
- package/src/app/api/webhooks/[id]/route.ts +15 -1
- package/src/app/globals.css +58 -15
- package/src/app/page.tsx +142 -13
- package/src/cli/index.js +42 -0
- package/src/cli/index.test.js +30 -0
- package/src/cli/spec.js +32 -0
- package/src/components/agents/agent-avatar.tsx +57 -10
- package/src/components/agents/agent-card.tsx +48 -15
- package/src/components/agents/agent-chat-list.tsx +123 -10
- package/src/components/agents/agent-list.tsx +50 -19
- package/src/components/agents/agent-sheet.tsx +56 -63
- package/src/components/auth/access-key-gate.tsx +10 -3
- package/src/components/auth/setup-wizard.tsx +2 -2
- package/src/components/auth/user-picker.tsx +31 -3
- package/src/components/chat/activity-moment.tsx +169 -0
- package/src/components/chat/chat-header.tsx +2 -0
- package/src/components/chat/chat-tool-toggles.tsx +1 -1
- package/src/components/chat/file-path-chip.tsx +125 -0
- package/src/components/chat/markdown-utils.ts +9 -0
- package/src/components/chat/message-bubble.tsx +46 -295
- package/src/components/chat/message-list.tsx +50 -1
- package/src/components/chat/streaming-bubble.tsx +36 -46
- package/src/components/chat/suggestions-bar.tsx +1 -1
- package/src/components/chat/thinking-indicator.tsx +72 -10
- package/src/components/chat/tool-call-bubble.tsx +66 -70
- package/src/components/chat/tool-request-banner.tsx +31 -7
- package/src/components/chat/transfer-agent-picker.tsx +63 -0
- package/src/components/chatrooms/agent-hover-card.tsx +124 -0
- package/src/components/chatrooms/chatroom-input.tsx +320 -0
- package/src/components/chatrooms/chatroom-list.tsx +123 -0
- package/src/components/chatrooms/chatroom-message.tsx +427 -0
- package/src/components/chatrooms/chatroom-sheet.tsx +215 -0
- package/src/components/chatrooms/chatroom-tool-request-banner.tsx +134 -0
- package/src/components/chatrooms/chatroom-typing-bar.tsx +88 -0
- package/src/components/chatrooms/chatroom-view.tsx +344 -0
- package/src/components/chatrooms/reaction-picker.tsx +273 -0
- package/src/components/connectors/connector-sheet.tsx +34 -47
- package/src/components/home/home-view.tsx +501 -0
- package/src/components/input/chat-input.tsx +79 -41
- package/src/components/knowledge/knowledge-list.tsx +31 -1
- package/src/components/knowledge/knowledge-sheet.tsx +83 -2
- package/src/components/layout/app-layout.tsx +209 -83
- package/src/components/layout/mobile-header.tsx +2 -0
- package/src/components/layout/update-banner.tsx +2 -2
- package/src/components/logs/log-list.tsx +2 -2
- package/src/components/mcp-servers/mcp-server-sheet.tsx +1 -1
- package/src/components/memory/memory-agent-list.tsx +143 -0
- package/src/components/memory/memory-browser.tsx +205 -0
- package/src/components/memory/memory-card.tsx +34 -7
- package/src/components/memory/memory-detail.tsx +359 -120
- package/src/components/memory/memory-sheet.tsx +157 -23
- package/src/components/plugins/plugin-list.tsx +1 -1
- package/src/components/plugins/plugin-sheet.tsx +1 -1
- package/src/components/projects/project-detail.tsx +509 -0
- package/src/components/projects/project-list.tsx +195 -59
- package/src/components/providers/provider-list.tsx +2 -2
- package/src/components/providers/provider-sheet.tsx +3 -3
- package/src/components/schedules/schedule-card.tsx +3 -2
- package/src/components/schedules/schedule-list.tsx +1 -1
- package/src/components/schedules/schedule-sheet.tsx +25 -25
- package/src/components/secrets/secret-sheet.tsx +47 -24
- package/src/components/secrets/secrets-list.tsx +18 -8
- package/src/components/sessions/new-session-sheet.tsx +33 -65
- package/src/components/sessions/session-card.tsx +45 -14
- package/src/components/sessions/session-list.tsx +35 -18
- package/src/components/shared/agent-picker-list.tsx +90 -0
- package/src/components/shared/agent-switch-dialog.tsx +156 -0
- package/src/components/shared/attachment-chip.tsx +165 -0
- package/src/components/shared/avatar.tsx +10 -1
- package/src/components/shared/check-icon.tsx +12 -0
- package/src/components/shared/confirm-dialog.tsx +1 -1
- package/src/components/shared/empty-state.tsx +32 -0
- package/src/components/shared/file-preview.tsx +34 -0
- package/src/components/shared/form-styles.ts +2 -0
- package/src/components/shared/keyboard-shortcuts-dialog.tsx +116 -0
- package/src/components/shared/notification-center.tsx +223 -0
- package/src/components/shared/profile-sheet.tsx +115 -0
- package/src/components/shared/reply-quote.tsx +26 -0
- package/src/components/shared/search-dialog.tsx +296 -0
- package/src/components/shared/section-label.tsx +12 -0
- package/src/components/shared/settings/plugin-manager.tsx +1 -1
- package/src/components/shared/settings/section-providers.tsx +1 -1
- package/src/components/shared/settings/section-secrets.tsx +1 -1
- package/src/components/shared/settings/section-theme.tsx +95 -0
- package/src/components/shared/settings/section-user-preferences.tsx +39 -0
- package/src/components/shared/settings/settings-page.tsx +180 -27
- package/src/components/shared/settings/settings-sheet.tsx +9 -73
- package/src/components/shared/sheet-footer.tsx +33 -0
- package/src/components/skills/skill-list.tsx +61 -30
- package/src/components/skills/skill-sheet.tsx +81 -2
- package/src/components/tasks/task-board.tsx +448 -26
- package/src/components/tasks/task-card.tsx +46 -9
- package/src/components/tasks/task-column.tsx +62 -3
- package/src/components/tasks/task-list.tsx +12 -4
- package/src/components/tasks/task-sheet.tsx +89 -72
- package/src/components/ui/hover-card.tsx +52 -0
- package/src/components/usage/metrics-dashboard.tsx +78 -0
- package/src/components/usage/usage-list.tsx +1 -1
- package/src/components/webhooks/webhook-sheet.tsx +1 -1
- package/src/hooks/use-view-router.ts +69 -19
- package/src/instrumentation.ts +15 -1
- package/src/lib/chat.ts +2 -0
- package/src/lib/cron-human.ts +114 -0
- package/src/lib/memory.ts +3 -0
- package/src/lib/server/chat-execution.ts +24 -4
- package/src/lib/server/connectors/manager.ts +11 -0
- package/src/lib/server/context-manager.ts +225 -13
- package/src/lib/server/create-notification.ts +42 -0
- package/src/lib/server/daemon-state.ts +165 -10
- package/src/lib/server/execution-log.ts +1 -0
- package/src/lib/server/heartbeat-service.ts +40 -5
- package/src/lib/server/heartbeat-wake.ts +110 -0
- package/src/lib/server/langgraph-checkpoint.ts +1 -0
- package/src/lib/server/memory-consolidation.ts +92 -0
- package/src/lib/server/memory-db.ts +51 -6
- package/src/lib/server/openclaw-gateway.ts +9 -1
- package/src/lib/server/provider-health.ts +125 -0
- package/src/lib/server/queue.ts +5 -4
- package/src/lib/server/scheduler.ts +8 -0
- package/src/lib/server/session-run-manager.ts +4 -0
- package/src/lib/server/session-tools/chatroom.ts +136 -0
- package/src/lib/server/session-tools/context-mgmt.ts +36 -18
- package/src/lib/server/session-tools/index.ts +2 -0
- package/src/lib/server/session-tools/memory.ts +6 -1
- package/src/lib/server/storage.ts +80 -29
- package/src/lib/server/stream-agent-chat.ts +153 -47
- package/src/lib/server/system-events.ts +49 -0
- package/src/lib/server/ws-hub.ts +11 -0
- package/src/lib/soul-suggestions.ts +109 -0
- package/src/lib/tasks.ts +4 -1
- package/src/lib/view-routes.ts +36 -1
- package/src/lib/ws-client.ts +14 -4
- package/src/proxy.ts +79 -2
- package/src/stores/use-app-store.ts +94 -3
- package/src/stores/use-chat-store.ts +48 -3
- package/src/stores/use-chatroom-store.ts +276 -0
- package/src/types/index.ts +69 -2
|
@@ -4,6 +4,7 @@ import { useEffect, useState, useCallback } from 'react'
|
|
|
4
4
|
import { useAppStore } from '@/stores/use-app-store'
|
|
5
5
|
import { api } from '@/lib/api-client'
|
|
6
6
|
import { Badge } from '@/components/ui/badge'
|
|
7
|
+
import { AgentAvatar } from '@/components/agents/agent-avatar'
|
|
7
8
|
import { ClawHubBrowser } from './clawhub-browser'
|
|
8
9
|
import { toast } from 'sonner'
|
|
9
10
|
|
|
@@ -27,6 +28,8 @@ interface SearchResponse {
|
|
|
27
28
|
export function SkillList({ inSidebar }: { inSidebar?: boolean }) {
|
|
28
29
|
const skills = useAppStore((s) => s.skills)
|
|
29
30
|
const loadSkills = useAppStore((s) => s.loadSkills)
|
|
31
|
+
const agents = useAppStore((s) => s.agents)
|
|
32
|
+
const loadAgents = useAppStore((s) => s.loadAgents)
|
|
30
33
|
const setSkillSheetOpen = useAppStore((s) => s.setSkillSheetOpen)
|
|
31
34
|
const setEditingSkillId = useAppStore((s) => s.setEditingSkillId)
|
|
32
35
|
const activeProjectFilter = useAppStore((s) => s.activeProjectFilter)
|
|
@@ -45,6 +48,8 @@ export function SkillList({ inSidebar }: { inSidebar?: boolean }) {
|
|
|
45
48
|
|
|
46
49
|
useEffect(() => {
|
|
47
50
|
loadSkills()
|
|
51
|
+
loadAgents()
|
|
52
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
48
53
|
}, [])
|
|
49
54
|
|
|
50
55
|
const skillList = Object.values(skills).filter((s) => !activeProjectFilter || s.projectId === activeProjectFilter)
|
|
@@ -258,37 +263,63 @@ export function SkillList({ inSidebar }: { inSidebar?: boolean }) {
|
|
|
258
263
|
</div>
|
|
259
264
|
) : (
|
|
260
265
|
<div className={inSidebar ? 'space-y-2' : 'grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-3'}>
|
|
261
|
-
{skillList.map((skill) =>
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
266
|
+
{skillList.map((skill) => {
|
|
267
|
+
const skillScope = skill.scope || 'global'
|
|
268
|
+
const skillAgentIds = skill.agentIds || []
|
|
269
|
+
const scopeLabel = skillScope === 'global' ? 'Global' : `${skillAgentIds.length} agent(s)`
|
|
270
|
+
const scopedAgents = skillScope === 'agent'
|
|
271
|
+
? skillAgentIds.map((id) => agents[id]).filter(Boolean)
|
|
272
|
+
: []
|
|
273
|
+
return (
|
|
274
|
+
<button
|
|
275
|
+
key={skill.id}
|
|
276
|
+
onClick={() => handleEdit(skill.id)}
|
|
277
|
+
className="w-full text-left p-4 rounded-[14px] border border-white/[0.06] bg-surface hover:bg-surface-2 transition-all cursor-pointer"
|
|
278
|
+
>
|
|
279
|
+
<div className="flex items-center justify-between mb-1">
|
|
280
|
+
<span className="font-display text-[14px] font-600 text-text truncate">{skill.name}</span>
|
|
281
|
+
<div className="flex items-center gap-2 shrink-0 ml-2">
|
|
282
|
+
<span className="text-[10px] font-mono text-text-3/50">{skill.filename}</span>
|
|
283
|
+
{!inSidebar && (
|
|
284
|
+
<button
|
|
285
|
+
onClick={(e) => handleDelete(e, skill.id)}
|
|
286
|
+
className="text-text-3/40 hover:text-red-400 transition-colors p-0.5"
|
|
287
|
+
title="Delete"
|
|
288
|
+
>
|
|
289
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
290
|
+
<path d="M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
|
|
291
|
+
</svg>
|
|
292
|
+
</button>
|
|
293
|
+
)}
|
|
294
|
+
</div>
|
|
282
295
|
</div>
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
296
|
+
{skill.description && (
|
|
297
|
+
<p className="text-[12px] text-text-3/60 line-clamp-2">{skill.description}</p>
|
|
298
|
+
)}
|
|
299
|
+
<div className="flex items-center gap-2 mt-1.5">
|
|
300
|
+
<span className="text-[11px] text-text-3/70">{skill.content.length} chars</span>
|
|
301
|
+
<span className="text-[11px] text-text-3/60">·</span>
|
|
302
|
+
<span className={`text-[10px] font-600 ${
|
|
303
|
+
skillScope === 'global' ? 'text-emerald-400' : 'text-amber-400'
|
|
304
|
+
}`}>
|
|
305
|
+
{scopeLabel}
|
|
306
|
+
</span>
|
|
307
|
+
</div>
|
|
308
|
+
{scopedAgents.length > 0 && (
|
|
309
|
+
<div className="flex items-center gap-1.5 mt-1.5">
|
|
310
|
+
<div className="flex items-center -space-x-1.5">
|
|
311
|
+
{scopedAgents.slice(0, 5).map((agent) => (
|
|
312
|
+
<AgentAvatar key={agent.id} seed={agent.avatarSeed} name={agent.name} size={16} className="ring-1 ring-surface" />
|
|
313
|
+
))}
|
|
314
|
+
</div>
|
|
315
|
+
{scopedAgents.length > 5 && (
|
|
316
|
+
<span className="text-[10px] font-600 text-text-3/60 ml-0.5">+{scopedAgents.length - 5}</span>
|
|
317
|
+
)}
|
|
318
|
+
</div>
|
|
319
|
+
)}
|
|
320
|
+
</button>
|
|
321
|
+
)
|
|
322
|
+
})}
|
|
292
323
|
</div>
|
|
293
324
|
)
|
|
294
325
|
)}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { useEffect, useState, useRef } from 'react'
|
|
4
4
|
import { useAppStore } from '@/stores/use-app-store'
|
|
5
5
|
import { BottomSheet } from '@/components/shared/bottom-sheet'
|
|
6
|
+
import { AgentAvatar } from '@/components/agents/agent-avatar'
|
|
6
7
|
import { api } from '@/lib/api-client'
|
|
7
8
|
|
|
8
9
|
export function SkillSheet() {
|
|
@@ -12,18 +13,23 @@ export function SkillSheet() {
|
|
|
12
13
|
const setEditingId = useAppStore((s) => s.setEditingSkillId)
|
|
13
14
|
const skills = useAppStore((s) => s.skills)
|
|
14
15
|
const loadSkills = useAppStore((s) => s.loadSkills)
|
|
16
|
+
const agents = useAppStore((s) => s.agents)
|
|
17
|
+
const loadAgents = useAppStore((s) => s.loadAgents)
|
|
15
18
|
const fileRef = useRef<HTMLInputElement>(null)
|
|
16
19
|
|
|
17
20
|
const [name, setName] = useState('')
|
|
18
21
|
const [filename, setFilename] = useState('')
|
|
19
22
|
const [description, setDescription] = useState('')
|
|
20
23
|
const [content, setContent] = useState('')
|
|
24
|
+
const [scope, setScope] = useState<'global' | 'agent'>('global')
|
|
25
|
+
const [agentIds, setAgentIds] = useState<string[]>([])
|
|
21
26
|
const [importUrl, setImportUrl] = useState('')
|
|
22
27
|
const [importingUrl, setImportingUrl] = useState(false)
|
|
23
28
|
const [importError, setImportError] = useState('')
|
|
24
29
|
const [importNotice, setImportNotice] = useState('')
|
|
25
30
|
|
|
26
31
|
const editing = editingId ? skills[editingId] : null
|
|
32
|
+
const agentList = Object.values(agents)
|
|
27
33
|
|
|
28
34
|
const handleImportFromUrl = async () => {
|
|
29
35
|
if (!importUrl.trim()) return
|
|
@@ -48,6 +54,11 @@ export function SkillSheet() {
|
|
|
48
54
|
}
|
|
49
55
|
}
|
|
50
56
|
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (open) loadAgents()
|
|
59
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
60
|
+
}, [open])
|
|
61
|
+
|
|
51
62
|
useEffect(() => {
|
|
52
63
|
if (open) {
|
|
53
64
|
setImportUrl('')
|
|
@@ -59,11 +70,15 @@ export function SkillSheet() {
|
|
|
59
70
|
setFilename(editing.filename)
|
|
60
71
|
setDescription(editing.description || '')
|
|
61
72
|
setContent(editing.content)
|
|
73
|
+
setScope(editing.scope || 'global')
|
|
74
|
+
setAgentIds(editing.agentIds || [])
|
|
62
75
|
} else {
|
|
63
76
|
setName('')
|
|
64
77
|
setFilename('')
|
|
65
78
|
setDescription('')
|
|
66
79
|
setContent('')
|
|
80
|
+
setScope('global')
|
|
81
|
+
setAgentIds([])
|
|
67
82
|
}
|
|
68
83
|
}
|
|
69
84
|
}, [open, editingId])
|
|
@@ -87,12 +102,24 @@ export function SkillSheet() {
|
|
|
87
102
|
e.target.value = ''
|
|
88
103
|
}
|
|
89
104
|
|
|
105
|
+
const toggleAgent = (id: string) => {
|
|
106
|
+
setAgentIds((prev) => prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id])
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const scopeHelperText = scope === 'global'
|
|
110
|
+
? 'This skill will be accessible to all agents'
|
|
111
|
+
: agentIds.length === 0
|
|
112
|
+
? 'Select which agents can access this skill'
|
|
113
|
+
: `${agentIds.length} agent(s) selected`
|
|
114
|
+
|
|
90
115
|
const handleSave = async () => {
|
|
91
116
|
const data = {
|
|
92
117
|
name: name.trim() || 'Unnamed Skill',
|
|
93
118
|
filename: filename.trim() || `${name.trim().toLowerCase().replace(/\s+/g, '-')}.md`,
|
|
94
119
|
description,
|
|
95
120
|
content,
|
|
121
|
+
scope,
|
|
122
|
+
agentIds: scope === 'agent' ? agentIds : [],
|
|
96
123
|
}
|
|
97
124
|
if (editing) {
|
|
98
125
|
await api('PUT', `/skills/${editing.id}`, data)
|
|
@@ -155,7 +182,7 @@ export function SkillSheet() {
|
|
|
155
182
|
<button
|
|
156
183
|
onClick={handleImportFromUrl}
|
|
157
184
|
disabled={importingUrl || !importUrl.trim()}
|
|
158
|
-
className="px-4 py-3 rounded-[12px] border-none bg-
|
|
185
|
+
className="px-4 py-3 rounded-[12px] border-none bg-accent-bright text-white text-[13px] font-600 cursor-pointer disabled:opacity-30 transition-all hover:brightness-110"
|
|
159
186
|
style={{ fontFamily: 'inherit' }}
|
|
160
187
|
>
|
|
161
188
|
{importingUrl ? 'Importing...' : 'Import'}
|
|
@@ -191,6 +218,58 @@ export function SkillSheet() {
|
|
|
191
218
|
<p className="text-[11px] text-text-3/70 mt-2">{content.length} characters</p>
|
|
192
219
|
</div>
|
|
193
220
|
|
|
221
|
+
<div className="mb-8">
|
|
222
|
+
<label className="block font-display text-[12px] font-600 text-text-2 uppercase tracking-[0.08em] mb-3">Scope</label>
|
|
223
|
+
<div className="flex p-1 rounded-[12px] bg-bg border border-white/[0.06]">
|
|
224
|
+
{(['global', 'agent'] as const).map((s) => (
|
|
225
|
+
<button
|
|
226
|
+
key={s}
|
|
227
|
+
onClick={() => setScope(s)}
|
|
228
|
+
className={`flex-1 py-2.5 rounded-[10px] text-center cursor-pointer transition-all text-[13px] font-600 border-none ${
|
|
229
|
+
scope === s ? 'bg-accent-soft text-accent-bright' : 'bg-transparent text-text-3 hover:text-text-2'
|
|
230
|
+
}`}
|
|
231
|
+
style={{ fontFamily: 'inherit' }}
|
|
232
|
+
>
|
|
233
|
+
{s === 'global' ? 'Global' : 'Specific'}
|
|
234
|
+
</button>
|
|
235
|
+
))}
|
|
236
|
+
</div>
|
|
237
|
+
<p className="text-[11px] text-text-3/60 mt-1.5 pl-1">{scopeHelperText}</p>
|
|
238
|
+
</div>
|
|
239
|
+
|
|
240
|
+
{scope === 'agent' && (
|
|
241
|
+
<div className="mb-8">
|
|
242
|
+
<label className="block font-display text-[12px] font-600 text-text-2 uppercase tracking-[0.08em] mb-3">Agents</label>
|
|
243
|
+
<div className="max-h-[240px] overflow-y-auto rounded-[12px] border border-white/[0.06] bg-white/[0.03]">
|
|
244
|
+
{agentList.length === 0 ? (
|
|
245
|
+
<p className="p-3 text-[12px] text-text-3">No agents available</p>
|
|
246
|
+
) : (
|
|
247
|
+
agentList.map((agent) => {
|
|
248
|
+
const selected = agentIds.includes(agent.id)
|
|
249
|
+
return (
|
|
250
|
+
<button
|
|
251
|
+
key={agent.id}
|
|
252
|
+
onClick={() => toggleAgent(agent.id)}
|
|
253
|
+
className={`w-full flex items-center gap-2.5 px-3 py-2 text-left transition-all cursor-pointer ${
|
|
254
|
+
selected ? 'bg-accent-soft/40' : 'hover:bg-white/[0.04]'
|
|
255
|
+
}`}
|
|
256
|
+
style={{ fontFamily: 'inherit' }}
|
|
257
|
+
>
|
|
258
|
+
<AgentAvatar seed={agent.avatarSeed} name={agent.name} size={24} />
|
|
259
|
+
<span className="text-[13px] text-text flex-1 truncate">{agent.name}</span>
|
|
260
|
+
{selected && (
|
|
261
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" className="text-accent-bright shrink-0">
|
|
262
|
+
<polyline points="20 6 9 17 4 12" />
|
|
263
|
+
</svg>
|
|
264
|
+
)}
|
|
265
|
+
</button>
|
|
266
|
+
)
|
|
267
|
+
})
|
|
268
|
+
)}
|
|
269
|
+
</div>
|
|
270
|
+
</div>
|
|
271
|
+
)}
|
|
272
|
+
|
|
194
273
|
<div className="flex gap-3 pt-2 border-t border-white/[0.04]">
|
|
195
274
|
{editing && (
|
|
196
275
|
<button onClick={handleDelete} className="py-3.5 px-6 rounded-[14px] border border-red-500/20 bg-transparent text-red-400 text-[15px] font-600 cursor-pointer hover:bg-red-500/10 transition-all" style={{ fontFamily: 'inherit' }}>
|
|
@@ -200,7 +279,7 @@ export function SkillSheet() {
|
|
|
200
279
|
<button onClick={onClose} className="flex-1 py-3.5 rounded-[14px] border border-white/[0.08] bg-transparent text-text-2 text-[15px] font-600 cursor-pointer hover:bg-surface-2 transition-all" style={{ fontFamily: 'inherit' }}>
|
|
201
280
|
Cancel
|
|
202
281
|
</button>
|
|
203
|
-
<button onClick={handleSave} disabled={!name.trim() || !content.trim()} className="flex-1 py-3.5 rounded-[14px] border-none bg-
|
|
282
|
+
<button onClick={handleSave} disabled={!name.trim() || !content.trim()} className="flex-1 py-3.5 rounded-[14px] border-none bg-accent-bright text-white text-[15px] font-600 cursor-pointer active:scale-[0.97] disabled:opacity-30 transition-all shadow-[0_4px_20px_rgba(99,102,241,0.25)] hover:brightness-110" style={{ fontFamily: 'inherit' }}>
|
|
204
283
|
{editing ? 'Save' : 'Create'}
|
|
205
284
|
</button>
|
|
206
285
|
</div>
|