@swarmclawai/swarmclaw 1.2.4 → 1.2.5
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 +14 -0
- package/bin/daemon-cmd.js +169 -0
- package/bin/server-cmd.js +3 -0
- package/bin/swarmclaw.js +11 -0
- package/package.json +17 -16
- package/src/app/api/agents/[id]/clone/route.ts +3 -32
- package/src/app/api/agents/[id]/route.ts +6 -158
- package/src/app/api/agents/[id]/status/route.ts +2 -3
- package/src/app/api/agents/[id]/thread/route.ts +4 -17
- package/src/app/api/agents/bulk/route.ts +5 -47
- package/src/app/api/agents/route.ts +5 -119
- package/src/app/api/agents/trash/route.ts +13 -24
- package/src/app/api/auth/route.ts +3 -9
- package/src/app/api/autonomy/estop/route.ts +5 -5
- package/src/app/api/chatrooms/[id]/chat/route.ts +11 -5
- package/src/app/api/chatrooms/[id]/route.ts +23 -2
- package/src/app/api/chatrooms/route.ts +13 -2
- package/src/app/api/chats/[id]/clear/route.ts +2 -13
- package/src/app/api/chats/[id]/deploy/route.ts +2 -3
- package/src/app/api/chats/[id]/edit-resend/route.ts +7 -13
- package/src/app/api/chats/[id]/mailbox/route.ts +6 -8
- package/src/app/api/chats/[id]/queue/route.ts +17 -64
- package/src/app/api/chats/[id]/retry/route.ts +4 -22
- package/src/app/api/chats/[id]/route.ts +10 -138
- package/src/app/api/chats/heartbeat/route.ts +2 -1
- package/src/app/api/chats/migrate-messages/route.ts +7 -0
- package/src/app/api/chats/route.ts +13 -134
- package/src/app/api/connectors/[id]/access/route.ts +12 -229
- package/src/app/api/connectors/[id]/doctor/route.ts +1 -1
- package/src/app/api/connectors/[id]/health/route.ts +12 -39
- package/src/app/api/connectors/[id]/route.ts +14 -122
- package/src/app/api/connectors/[id]/webhook/route.ts +1 -1
- package/src/app/api/connectors/doctor/route.ts +1 -1
- package/src/app/api/connectors/route.ts +12 -70
- package/src/app/api/credentials/[id]/route.ts +2 -4
- package/src/app/api/credentials/route.ts +10 -19
- package/src/app/api/daemon/health-check/route.ts +3 -4
- package/src/app/api/daemon/route.ts +10 -8
- package/src/app/api/documents/route.ts +11 -10
- package/src/app/api/external-agents/route.ts +3 -3
- package/src/app/api/gateways/[id]/health/route.ts +2 -3
- package/src/app/api/gateways/[id]/route.ts +7 -122
- package/src/app/api/gateways/route.ts +3 -103
- package/src/app/api/mcp-servers/[id]/tools/route.ts +5 -5
- package/src/app/api/openclaw/dashboard-url/route.ts +8 -16
- package/src/app/api/openclaw/directory/route.ts +2 -2
- package/src/app/api/openclaw/history/route.ts +3 -5
- package/src/app/api/providers/[id]/route.test.ts +49 -0
- package/src/app/api/providers/ollama/route.ts +6 -5
- package/src/app/api/schedules/[id]/route.ts +14 -108
- package/src/app/api/schedules/[id]/run/route.ts +6 -67
- package/src/app/api/schedules/route.ts +9 -51
- package/src/app/api/settings/route.ts +4 -3
- package/src/app/api/setup/check-provider/route.ts +15 -1
- package/src/app/api/setup/openclaw-device/route.ts +2 -2
- package/src/app/api/system/status/route.ts +2 -2
- package/src/app/api/tasks/[id]/route.ts +16 -202
- package/src/app/api/tasks/bulk/route.ts +5 -86
- package/src/app/api/tasks/metrics/route.ts +2 -1
- package/src/app/api/tasks/route.ts +11 -171
- package/src/app/api/upload/route.ts +1 -1
- package/src/app/api/uploads/[filename]/route.ts +1 -1
- package/src/app/api/uploads/route.ts +1 -1
- package/src/app/api/webhooks/[id]/history/route.ts +2 -2
- package/src/app/layout.tsx +9 -6
- package/src/app/protocols/page.tsx +71 -89
- package/src/app/tasks/page.tsx +32 -32
- package/src/cli/index.js +1 -0
- package/src/cli/spec.js +1 -0
- package/src/components/agents/agent-sheet.tsx +5 -5
- package/src/components/auth/setup-wizard/index.tsx +4 -4
- package/src/components/auth/setup-wizard/step-agents.tsx +1 -1
- package/src/components/auth/setup-wizard/step-connect.tsx +1 -1
- package/src/components/auth/setup-wizard/utils.ts +1 -1
- package/src/components/chatrooms/chatroom-sheet.tsx +16 -276
- package/src/components/connectors/connector-list.tsx +26 -40
- package/src/components/connectors/connector-sheet.tsx +95 -149
- package/src/components/gateways/gateway-sheet.tsx +61 -110
- package/src/components/layout/live-query-sync.tsx +121 -0
- package/src/components/protocols/structured-session-launcher.tsx +24 -45
- package/src/components/providers/app-query-provider.tsx +17 -0
- package/src/components/providers/provider-list.tsx +60 -61
- package/src/components/providers/provider-sheet.tsx +74 -56
- package/src/components/skills/skill-list.tsx +5 -18
- package/src/components/skills/skill-sheet.tsx +21 -20
- package/src/components/skills/skills-workspace.tsx +48 -87
- package/src/components/tasks/task-card.tsx +20 -13
- package/src/components/tasks/task-column.tsx +22 -7
- package/src/components/tasks/task-list.tsx +8 -11
- package/src/components/tasks/task-sheet.tsx +111 -103
- package/src/features/agents/queries.ts +20 -0
- package/src/features/chatrooms/queries.ts +20 -0
- package/src/features/chats/queries.ts +27 -0
- package/src/features/connectors/queries.ts +145 -0
- package/src/features/credentials/queries.ts +37 -0
- package/src/features/extensions/queries.ts +26 -0
- package/src/features/external-agents/queries.ts +36 -0
- package/src/features/gateways/queries.ts +274 -0
- package/src/features/missions/queries.ts +23 -0
- package/src/features/projects/queries.ts +20 -0
- package/src/features/protocols/queries.ts +149 -0
- package/src/features/providers/queries.ts +142 -0
- package/src/features/settings/queries.ts +20 -0
- package/src/features/skills/queries.ts +182 -0
- package/src/features/tasks/queries.ts +189 -0
- package/src/hooks/use-ws.ts +3 -2
- package/src/lib/app/api-client.ts +2 -2
- package/src/lib/query/client.ts +17 -0
- package/src/lib/server/agents/agent-runtime-config.ts +1 -1
- package/src/lib/server/agents/agent-service.ts +429 -0
- package/src/lib/server/agents/agent-thread-session.ts +6 -5
- package/src/lib/server/agents/autonomy-contract.ts +1 -4
- package/src/lib/server/agents/delegation-advisory.test.ts +206 -0
- package/src/lib/server/agents/delegation-advisory.ts +251 -0
- package/src/lib/server/agents/main-agent-loop.ts +98 -40
- package/src/lib/server/agents/subagent-runtime.ts +12 -0
- package/src/lib/server/autonomy/supervisor-reflection.test.ts +20 -1
- package/src/lib/server/autonomy/supervisor-reflection.ts +39 -19
- package/src/lib/server/build-llm.ts +7 -15
- package/src/lib/server/capability-router.test.ts +70 -1
- package/src/lib/server/capability-router.ts +24 -99
- package/src/lib/server/chat-execution/chat-execution-utils.ts +0 -15
- package/src/lib/server/chat-execution/chat-streaming-utils.ts +2 -4
- package/src/lib/server/chat-execution/chat-turn-finalization.ts +77 -12
- package/src/lib/server/chat-execution/chat-turn-partial-persistence.ts +4 -4
- package/src/lib/server/chat-execution/chat-turn-preflight.ts +2 -2
- package/src/lib/server/chat-execution/chat-turn-preparation.ts +41 -17
- package/src/lib/server/chat-execution/chat-turn-stream-execution.ts +4 -2
- package/src/lib/server/chat-execution/chat-turn-tool-routing.test.ts +45 -0
- package/src/lib/server/chat-execution/chat-turn-tool-routing.ts +48 -17
- package/src/lib/server/chat-execution/continuation-evaluator.ts +4 -1
- package/src/lib/server/chat-execution/direct-memory-intent.test.ts +9 -0
- package/src/lib/server/chat-execution/direct-memory-intent.ts +12 -2
- package/src/lib/server/chat-execution/message-classifier.test.ts +35 -23
- package/src/lib/server/chat-execution/message-classifier.ts +74 -32
- package/src/lib/server/chat-execution/prompt-builder.test.ts +29 -0
- package/src/lib/server/chat-execution/prompt-builder.ts +37 -2
- package/src/lib/server/chat-execution/prompt-sections.test.ts +56 -0
- package/src/lib/server/chat-execution/prompt-sections.ts +193 -0
- package/src/lib/server/chat-execution/stream-agent-chat.ts +63 -7
- package/src/lib/server/chat-execution/stream-continuation.test.ts +36 -0
- package/src/lib/server/chat-execution/stream-continuation.ts +28 -13
- package/src/lib/server/chatrooms/chatroom-agent-signals.ts +26 -18
- package/src/lib/server/chatrooms/chatroom-helpers.ts +19 -18
- package/src/lib/server/chatrooms/chatroom-repository.ts +16 -0
- package/src/lib/server/chatrooms/chatroom-routing.test.ts +96 -0
- package/src/lib/server/chatrooms/chatroom-routing.ts +207 -53
- package/src/lib/server/chatrooms/mailbox-utils.ts +4 -2
- package/src/lib/server/chatrooms/session-mailbox.ts +50 -40
- package/src/lib/server/chats/chat-session-service.ts +410 -0
- package/src/lib/server/connectors/access.ts +1 -1
- package/src/lib/server/connectors/commands.ts +7 -6
- package/src/lib/server/connectors/connector-inbound.ts +14 -7
- package/src/lib/server/connectors/connector-outbound.ts +16 -11
- package/src/lib/server/connectors/connector-service.ts +453 -0
- package/src/lib/server/connectors/delivery.ts +17 -12
- package/src/lib/server/connectors/inbound-audio-transcription.ts +5 -14
- package/src/lib/server/connectors/media.ts +1 -1
- package/src/lib/server/connectors/response-media.ts +1 -1
- package/src/lib/server/connectors/session-consolidation.ts +11 -7
- package/src/lib/server/connectors/session.ts +9 -7
- package/src/lib/server/connectors/voice-note.ts +2 -1
- package/src/lib/server/context-manager.ts +20 -1
- package/src/lib/server/cost.ts +2 -3
- package/src/lib/server/credentials/credential-repository.ts +43 -4
- package/src/lib/server/credentials/credential-service.ts +112 -0
- package/src/lib/server/daemon/admin-metadata.ts +64 -0
- package/src/lib/server/daemon/controller.ts +577 -0
- package/src/lib/server/daemon/daemon-runtime.ts +352 -0
- package/src/lib/server/daemon/daemon-status-repository.ts +63 -0
- package/src/lib/server/daemon/types.ts +101 -0
- package/src/lib/server/embeddings.ts +3 -9
- package/src/lib/server/eval/agent-regression.ts +3 -2
- package/src/lib/server/eval/runner.ts +2 -2
- package/src/lib/server/execution-brief.test.ts +167 -0
- package/src/lib/server/execution-brief.ts +295 -0
- package/src/lib/server/execution-engine/chat-turn.ts +9 -0
- package/src/lib/server/execution-engine/import-boundary.test.ts +44 -0
- package/src/lib/server/execution-engine/index.ts +35 -0
- package/src/lib/server/execution-engine/task-attempt.ts +303 -0
- package/src/lib/server/execution-engine/types.ts +33 -0
- package/src/lib/server/gateways/gateway-profile-repository.ts +47 -3
- package/src/lib/server/gateways/gateway-profile-service.ts +200 -0
- package/src/lib/server/memory/session-archive-memory.ts +12 -10
- package/src/lib/server/messages/message-repository.ts +330 -0
- package/src/lib/server/missions/mission-service/core.ts +8 -6
- package/src/lib/server/openclaw/agent-resolver.ts +2 -3
- package/src/lib/server/openclaw/doctor.ts +1 -1
- package/src/lib/server/openclaw/gateway.test.ts +10 -1
- package/src/lib/server/openclaw/gateway.ts +5 -14
- package/src/lib/server/openclaw/health.ts +3 -11
- package/src/lib/server/openclaw/sync.ts +8 -6
- package/src/lib/server/persistence/storage-context.ts +3 -0
- package/src/lib/server/protocols/protocol-agent-turn.ts +25 -17
- package/src/lib/server/protocols/protocol-normalization.ts +1 -1
- package/src/lib/server/protocols/protocol-queries.ts +13 -7
- package/src/lib/server/protocols/protocol-run-lifecycle.ts +16 -20
- package/src/lib/server/protocols/protocol-run-repository.ts +81 -0
- package/src/lib/server/protocols/protocol-step-processors.ts +23 -31
- package/src/lib/server/protocols/protocol-swarm.ts +8 -8
- package/src/lib/server/protocols/protocol-template-repository.ts +42 -0
- package/src/lib/server/protocols/protocol-templates.ts +4 -2
- package/src/lib/server/protocols/protocol-types.ts +10 -7
- package/src/lib/server/provider-endpoint.ts +7 -12
- package/src/lib/server/provider-model-discovery.ts +2 -11
- package/src/lib/server/query-expansion.ts +5 -6
- package/src/lib/server/run-context.test.ts +365 -0
- package/src/lib/server/run-context.ts +367 -0
- package/src/lib/server/runtime/heartbeat-service.ts +7 -5
- package/src/lib/server/runtime/queue/core.ts +61 -190
- package/src/lib/server/runtime/run-ledger.ts +8 -0
- package/src/lib/server/runtime/session-run-manager/drain.ts +2 -2
- package/src/lib/server/runtime/session-run-manager/enqueue.ts +6 -0
- package/src/lib/server/runtime/session-run-manager/state.ts +4 -0
- package/src/lib/server/schedules/schedule-route-service.ts +230 -0
- package/src/lib/server/service-result.ts +16 -0
- package/src/lib/server/session-note.ts +2 -3
- package/src/lib/server/session-reset-policy.ts +4 -3
- package/src/lib/server/session-tools/connector.ts +9 -6
- package/src/lib/server/session-tools/context-mgmt.ts +58 -9
- package/src/lib/server/session-tools/crud.ts +162 -10
- package/src/lib/server/session-tools/delegate.ts +1 -1
- package/src/lib/server/session-tools/manage-tasks.test.ts +152 -0
- package/src/lib/server/session-tools/memory.ts +6 -4
- package/src/lib/server/session-tools/session-info.test.ts +56 -0
- package/src/lib/server/session-tools/session-info.ts +119 -12
- package/src/lib/server/session-tools/skill-runtime.ts +3 -1
- package/src/lib/server/session-tools/skills.ts +15 -15
- package/src/lib/server/session-tools/subagent.test.ts +115 -1
- package/src/lib/server/session-tools/subagent.ts +125 -7
- package/src/lib/server/session-tools/team-context.ts +4 -3
- package/src/lib/server/session-tools/wallet.ts +0 -58
- package/src/lib/server/sessions/session-lineage.ts +55 -0
- package/src/lib/server/sessions/session-repository.ts +2 -2
- package/src/lib/server/skills/learned-skills.ts +24 -23
- package/src/lib/server/skills/runtime-skill-resolver.ts +2 -1
- package/src/lib/server/skills/skill-repository.ts +136 -13
- package/src/lib/server/skills/skill-suggestions.ts +25 -28
- package/src/lib/server/storage-normalization.test.ts +44 -267
- package/src/lib/server/storage-normalization.ts +75 -0
- package/src/lib/server/storage.ts +19 -0
- package/src/lib/server/structured-extract.ts +3 -14
- package/src/lib/server/tasks/task-followups.ts +16 -11
- package/src/lib/server/tasks/task-result.test.ts +25 -29
- package/src/lib/server/tasks/task-result.ts +5 -9
- package/src/lib/server/tasks/task-route-service.ts +449 -0
- package/src/lib/server/text-normalization.ts +41 -0
- package/src/lib/server/tool-planning.ts +6 -42
- package/src/lib/server/upload-path.ts +5 -0
- package/src/lib/server/working-state/extraction.ts +614 -0
- package/src/lib/server/working-state/normalization.ts +866 -0
- package/src/lib/server/working-state/prompt.ts +60 -0
- package/src/lib/server/working-state/repository.ts +38 -0
- package/src/lib/server/working-state/service.test.ts +253 -0
- package/src/lib/server/working-state/service.ts +293 -0
- package/src/lib/validation/schemas.ts +1 -0
- package/src/lib/ws-client.ts +3 -3
- package/src/stores/slices/task-slice.ts +1 -4
- package/src/stores/use-chatroom-store.ts +2 -2
- package/src/types/index.ts +277 -12
|
@@ -6,10 +6,8 @@ import ReactMarkdown from 'react-markdown'
|
|
|
6
6
|
import rehypeHighlight from 'rehype-highlight'
|
|
7
7
|
import remarkGfm from 'remark-gfm'
|
|
8
8
|
import { toast } from 'sonner'
|
|
9
|
-
import { api } from '@/lib/app/api-client'
|
|
10
9
|
import { dedup } from '@/lib/shared-utils'
|
|
11
10
|
import { useMountedRef } from '@/hooks/use-mounted-ref'
|
|
12
|
-
import { useWs } from '@/hooks/use-ws'
|
|
13
11
|
import { useAppStore } from '@/stores/use-app-store'
|
|
14
12
|
import { AgentAvatar } from '@/components/agents/agent-avatar'
|
|
15
13
|
import { CodeBlock } from '@/components/chat/code-block'
|
|
@@ -18,51 +16,54 @@ import type {
|
|
|
18
16
|
Agent,
|
|
19
17
|
ClawHubSkill,
|
|
20
18
|
Skill,
|
|
21
|
-
SkillCommandDispatch,
|
|
22
|
-
SkillInvocationConfig,
|
|
23
19
|
SkillSuggestion,
|
|
24
20
|
} from '@/types'
|
|
21
|
+
import { useAgentsQuery } from '@/features/agents/queries'
|
|
22
|
+
import {
|
|
23
|
+
useApproveSkillSuggestionMutation,
|
|
24
|
+
useClawHubPreviewMutation,
|
|
25
|
+
useClawHubSearchMutation,
|
|
26
|
+
useDeleteSkillMutation,
|
|
27
|
+
useGenerateSkillSuggestionMutation,
|
|
28
|
+
useInstallClawHubSkillMutation,
|
|
29
|
+
useRejectSkillSuggestionMutation,
|
|
30
|
+
useSkillsQuery,
|
|
31
|
+
useSkillSuggestionsQuery,
|
|
32
|
+
type ClawHubPreview,
|
|
33
|
+
} from '@/features/skills/queries'
|
|
25
34
|
|
|
26
35
|
type SkillScopeFilter = 'all' | 'global' | 'agent'
|
|
27
36
|
type SkillSort = 'updated' | 'name'
|
|
28
37
|
type HubSort = 'popular' | 'name' | 'updated'
|
|
29
38
|
|
|
30
|
-
interface ClawHubSearchResponse {
|
|
31
|
-
skills: ClawHubSkill[]
|
|
32
|
-
total: number
|
|
33
|
-
page: number
|
|
34
|
-
nextCursor?: string | null
|
|
35
|
-
error?: string
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
type ClawHubPreview = Partial<Skill> & {
|
|
39
|
-
name: string
|
|
40
|
-
content: string
|
|
41
|
-
description?: string
|
|
42
|
-
invocation?: SkillInvocationConfig | null
|
|
43
|
-
commandDispatch?: SkillCommandDispatch | null
|
|
44
|
-
}
|
|
45
|
-
|
|
46
39
|
const HUB_PAGE_SIZE = 18
|
|
47
40
|
|
|
48
41
|
export function SkillsWorkspace() {
|
|
49
42
|
const router = useRouter()
|
|
50
43
|
const searchParams = useSearchParams()
|
|
51
44
|
const mountedRef = useMountedRef()
|
|
52
|
-
|
|
53
|
-
const skills =
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
const
|
|
45
|
+
const skillsQuery = useSkillsQuery()
|
|
46
|
+
const skills = useMemo(() => skillsQuery.data ?? {}, [skillsQuery.data])
|
|
47
|
+
const agentsQuery = useAgentsQuery()
|
|
48
|
+
const suggestionsQuery = useSkillSuggestionsQuery()
|
|
49
|
+
const generateSuggestionMutation = useGenerateSkillSuggestionMutation()
|
|
50
|
+
const approveSuggestionMutation = useApproveSkillSuggestionMutation()
|
|
51
|
+
const rejectSuggestionMutation = useRejectSkillSuggestionMutation()
|
|
52
|
+
const clawHubSearchMutation = useClawHubSearchMutation()
|
|
53
|
+
const clawHubPreviewMutation = useClawHubPreviewMutation()
|
|
54
|
+
const installClawHubSkillMutation = useInstallClawHubSkillMutation()
|
|
55
|
+
const deleteSkillMutation = useDeleteSkillMutation()
|
|
57
56
|
const currentAgentId = useAppStore((s) => s.currentAgentId)
|
|
58
57
|
const activeProjectFilter = useAppStore((s) => s.activeProjectFilter)
|
|
59
58
|
const setSkillSheetOpen = useAppStore((s) => s.setSkillSheetOpen)
|
|
60
59
|
const setEditingSkillId = useAppStore((s) => s.setEditingSkillId)
|
|
61
60
|
|
|
61
|
+
const suggestions = suggestionsQuery.data ?? []
|
|
62
|
+
const agents = agentsQuery.data ?? {}
|
|
63
|
+
|
|
62
64
|
const activeTab = searchParams.get('tab') === 'clawhub' ? 'clawhub' : 'skills'
|
|
63
65
|
const selectedSkillId = activeTab === 'skills' ? searchParams.get('skill') : null
|
|
64
66
|
|
|
65
|
-
const [ready, setReady] = useState(false)
|
|
66
67
|
const [libraryQuery, setLibraryQuery] = useState('')
|
|
67
68
|
const [libraryScope, setLibraryScope] = useState<SkillScopeFilter>('all')
|
|
68
69
|
const [librarySort, setLibrarySort] = useState<SkillSort>('updated')
|
|
@@ -70,8 +71,6 @@ export function SkillsWorkspace() {
|
|
|
70
71
|
const [deleteTarget, setDeleteTarget] = useState<Skill | null>(null)
|
|
71
72
|
const [deletingSkillId, setDeletingSkillId] = useState<string | null>(null)
|
|
72
73
|
|
|
73
|
-
const [suggestions, setSuggestions] = useState<SkillSuggestion[]>([])
|
|
74
|
-
const [suggestionsLoading, setSuggestionsLoading] = useState(false)
|
|
75
74
|
const [suggestionActionId, setSuggestionActionId] = useState<string | null>(null)
|
|
76
75
|
const [generatingSuggestion, setGeneratingSuggestion] = useState(false)
|
|
77
76
|
|
|
@@ -93,16 +92,6 @@ export function SkillsWorkspace() {
|
|
|
93
92
|
const [installingHubId, setInstallingHubId] = useState<string | null>(null)
|
|
94
93
|
const hubSearchRequestIdRef = useRef(0)
|
|
95
94
|
|
|
96
|
-
useEffect(() => {
|
|
97
|
-
let active = true
|
|
98
|
-
void Promise.all([loadSkills(), loadAgents()]).finally(() => {
|
|
99
|
-
if (active && mountedRef.current) setReady(true)
|
|
100
|
-
})
|
|
101
|
-
return () => {
|
|
102
|
-
active = false
|
|
103
|
-
}
|
|
104
|
-
}, [loadAgents, loadSkills, mountedRef])
|
|
105
|
-
|
|
106
95
|
useEffect(() => {
|
|
107
96
|
if (activeTab !== 'clawhub') {
|
|
108
97
|
setSelectedHubSkill(null)
|
|
@@ -110,8 +99,6 @@ export function SkillsWorkspace() {
|
|
|
110
99
|
}
|
|
111
100
|
}, [activeTab])
|
|
112
101
|
|
|
113
|
-
useWs('skills', () => { void loadSkills() })
|
|
114
|
-
|
|
115
102
|
const skillList = useMemo(() => {
|
|
116
103
|
return Object.values(skills).filter((skill) => !activeProjectFilter || skill.projectId === activeProjectFilter)
|
|
117
104
|
}, [activeProjectFilter, skills])
|
|
@@ -141,26 +128,6 @@ export function SkillsWorkspace() {
|
|
|
141
128
|
setSkillSheetOpen(true)
|
|
142
129
|
}, [setEditingSkillId, setSkillSheetOpen])
|
|
143
130
|
|
|
144
|
-
const loadSuggestions = useCallback(async () => {
|
|
145
|
-
setSuggestionsLoading(true)
|
|
146
|
-
try {
|
|
147
|
-
const result = await api<SkillSuggestion[]>('GET', '/skill-suggestions')
|
|
148
|
-
if (!mountedRef.current) return
|
|
149
|
-
setSuggestions(Array.isArray(result) ? result : [])
|
|
150
|
-
} catch (err) {
|
|
151
|
-
if (!mountedRef.current) return
|
|
152
|
-
toast.error(err instanceof Error ? err.message : 'Failed to load skill suggestions')
|
|
153
|
-
} finally {
|
|
154
|
-
if (mountedRef.current) setSuggestionsLoading(false)
|
|
155
|
-
}
|
|
156
|
-
}, [mountedRef])
|
|
157
|
-
|
|
158
|
-
useEffect(() => {
|
|
159
|
-
void loadSuggestions()
|
|
160
|
-
}, [loadSuggestions])
|
|
161
|
-
|
|
162
|
-
useWs('skill_suggestions', () => { void loadSuggestions() })
|
|
163
|
-
|
|
164
131
|
const handleGenerateSuggestion = useCallback(async () => {
|
|
165
132
|
if (!currentSessionId) {
|
|
166
133
|
toast.error('Open a chat first so SwarmClaw has a session to learn from.')
|
|
@@ -168,41 +135,38 @@ export function SkillsWorkspace() {
|
|
|
168
135
|
}
|
|
169
136
|
setGeneratingSuggestion(true)
|
|
170
137
|
try {
|
|
171
|
-
await
|
|
138
|
+
await generateSuggestionMutation.mutateAsync(currentSessionId)
|
|
172
139
|
toast.success('Drafted a skill suggestion from the current conversation.')
|
|
173
|
-
await loadSuggestions()
|
|
174
140
|
} catch (err) {
|
|
175
141
|
toast.error(err instanceof Error ? err.message : 'Failed to generate a skill suggestion')
|
|
176
142
|
} finally {
|
|
177
143
|
if (mountedRef.current) setGeneratingSuggestion(false)
|
|
178
144
|
}
|
|
179
|
-
}, [currentSessionId,
|
|
145
|
+
}, [currentSessionId, generateSuggestionMutation, mountedRef])
|
|
180
146
|
|
|
181
147
|
const handleApproveSuggestion = useCallback(async (id: string) => {
|
|
182
148
|
setSuggestionActionId(id)
|
|
183
149
|
try {
|
|
184
|
-
await
|
|
150
|
+
await approveSuggestionMutation.mutateAsync(id)
|
|
185
151
|
toast.success('Skill suggestion approved and saved.')
|
|
186
|
-
await Promise.all([loadSuggestions(), loadSkills()])
|
|
187
152
|
} catch (err) {
|
|
188
153
|
toast.error(err instanceof Error ? err.message : 'Failed to approve the skill suggestion')
|
|
189
154
|
} finally {
|
|
190
155
|
if (mountedRef.current) setSuggestionActionId(null)
|
|
191
156
|
}
|
|
192
|
-
}, [
|
|
157
|
+
}, [approveSuggestionMutation, mountedRef])
|
|
193
158
|
|
|
194
159
|
const handleRejectSuggestion = useCallback(async (id: string) => {
|
|
195
160
|
setSuggestionActionId(id)
|
|
196
161
|
try {
|
|
197
|
-
await
|
|
162
|
+
await rejectSuggestionMutation.mutateAsync(id)
|
|
198
163
|
toast.success('Skill suggestion dismissed.')
|
|
199
|
-
await loadSuggestions()
|
|
200
164
|
} catch (err) {
|
|
201
165
|
toast.error(err instanceof Error ? err.message : 'Failed to dismiss the skill suggestion')
|
|
202
166
|
} finally {
|
|
203
167
|
if (mountedRef.current) setSuggestionActionId(null)
|
|
204
168
|
}
|
|
205
|
-
}, [
|
|
169
|
+
}, [mountedRef, rejectSuggestionMutation])
|
|
206
170
|
|
|
207
171
|
const searchHub = useCallback(async (query: string, page: number, append = false, cursor?: string | null) => {
|
|
208
172
|
const requestId = hubSearchRequestIdRef.current + 1
|
|
@@ -211,13 +175,12 @@ export function SkillsWorkspace() {
|
|
|
211
175
|
setHubError(null)
|
|
212
176
|
|
|
213
177
|
try {
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
page
|
|
217
|
-
limit:
|
|
178
|
+
const response = await clawHubSearchMutation.mutateAsync({
|
|
179
|
+
query,
|
|
180
|
+
page,
|
|
181
|
+
limit: HUB_PAGE_SIZE,
|
|
182
|
+
cursor,
|
|
218
183
|
})
|
|
219
|
-
if (cursor) params.set('cursor', cursor)
|
|
220
|
-
const response = await api<ClawHubSearchResponse>('GET', `/clawhub/search?${params.toString()}`)
|
|
221
184
|
if (!mountedRef.current || requestId !== hubSearchRequestIdRef.current) return
|
|
222
185
|
|
|
223
186
|
if (response.error) setHubError(response.error)
|
|
@@ -233,7 +196,7 @@ export function SkillsWorkspace() {
|
|
|
233
196
|
} finally {
|
|
234
197
|
if (mountedRef.current && requestId === hubSearchRequestIdRef.current) setHubLoading(false)
|
|
235
198
|
}
|
|
236
|
-
}, [mountedRef])
|
|
199
|
+
}, [clawHubSearchMutation, mountedRef])
|
|
237
200
|
|
|
238
201
|
useEffect(() => {
|
|
239
202
|
if (activeTab !== 'clawhub' || selectedHubSkill) return
|
|
@@ -252,7 +215,7 @@ export function SkillsWorkspace() {
|
|
|
252
215
|
setHubPreviewLoadingId(selectedHubSkill.id)
|
|
253
216
|
setHubPreviewError(null)
|
|
254
217
|
|
|
255
|
-
void
|
|
218
|
+
void clawHubPreviewMutation.mutateAsync({
|
|
256
219
|
name: selectedHubSkill.name,
|
|
257
220
|
description: selectedHubSkill.description,
|
|
258
221
|
author: selectedHubSkill.author,
|
|
@@ -271,7 +234,7 @@ export function SkillsWorkspace() {
|
|
|
271
234
|
return () => {
|
|
272
235
|
active = false
|
|
273
236
|
}
|
|
274
|
-
}, [hubPreviewCache, mountedRef, selectedHubSkill])
|
|
237
|
+
}, [clawHubPreviewMutation, hubPreviewCache, mountedRef, selectedHubSkill])
|
|
275
238
|
|
|
276
239
|
const installedHubIds = useMemo(() => {
|
|
277
240
|
const ids = new Set<string>()
|
|
@@ -335,7 +298,7 @@ export function SkillsWorkspace() {
|
|
|
335
298
|
const handleInstallHubSkill = useCallback(async (skill: ClawHubSkill) => {
|
|
336
299
|
setInstallingHubId(skill.id)
|
|
337
300
|
try {
|
|
338
|
-
await
|
|
301
|
+
await installClawHubSkillMutation.mutateAsync({
|
|
339
302
|
name: skill.name,
|
|
340
303
|
description: skill.description,
|
|
341
304
|
url: skill.url,
|
|
@@ -344,21 +307,19 @@ export function SkillsWorkspace() {
|
|
|
344
307
|
content: hubPreviewCache[skill.id]?.content,
|
|
345
308
|
})
|
|
346
309
|
toast.success(`Installed "${skill.name}"`)
|
|
347
|
-
await loadSkills()
|
|
348
310
|
} catch (err) {
|
|
349
311
|
toast.error(err instanceof Error ? err.message : 'Install failed')
|
|
350
312
|
} finally {
|
|
351
313
|
if (mountedRef.current) setInstallingHubId(null)
|
|
352
314
|
}
|
|
353
|
-
}, [hubPreviewCache,
|
|
315
|
+
}, [hubPreviewCache, installClawHubSkillMutation, mountedRef])
|
|
354
316
|
|
|
355
317
|
const confirmDeleteSkill = useCallback(async () => {
|
|
356
318
|
if (!deleteTarget) return
|
|
357
319
|
setDeletingSkillId(deleteTarget.id)
|
|
358
320
|
try {
|
|
359
|
-
await
|
|
321
|
+
await deleteSkillMutation.mutateAsync(deleteTarget.id)
|
|
360
322
|
toast.success('Skill deleted')
|
|
361
|
-
await loadSkills()
|
|
362
323
|
if (selectedSkillId === deleteTarget.id) {
|
|
363
324
|
setPageState({ skill: null }, 'replace')
|
|
364
325
|
}
|
|
@@ -368,9 +329,9 @@ export function SkillsWorkspace() {
|
|
|
368
329
|
} finally {
|
|
369
330
|
if (mountedRef.current) setDeletingSkillId(null)
|
|
370
331
|
}
|
|
371
|
-
}, [
|
|
332
|
+
}, [deleteSkillMutation, deleteTarget, mountedRef, selectedSkillId, setPageState])
|
|
372
333
|
|
|
373
|
-
if (
|
|
334
|
+
if (skillsQuery.isPending || agentsQuery.isPending) {
|
|
374
335
|
return (
|
|
375
336
|
<div className="flex-1 flex items-center justify-center px-6">
|
|
376
337
|
<div className="flex items-center gap-3 text-[13px] text-text-3/65">
|
|
@@ -573,10 +534,10 @@ export function SkillsWorkspace() {
|
|
|
573
534
|
</div>
|
|
574
535
|
)}
|
|
575
536
|
|
|
576
|
-
{(
|
|
537
|
+
{(suggestionsQuery.isPending || draftCount > 0) ? (
|
|
577
538
|
<SuggestionsPanel
|
|
578
539
|
suggestions={suggestions}
|
|
579
|
-
loading={
|
|
540
|
+
loading={suggestionsQuery.isPending}
|
|
580
541
|
busyId={suggestionActionId}
|
|
581
542
|
onApprove={handleApproveSuggestion}
|
|
582
543
|
onReject={handleRejectSuggestion}
|
|
@@ -4,30 +4,40 @@ import { useState, useCallback, useEffect } from 'react'
|
|
|
4
4
|
import { useRouter } from 'next/navigation'
|
|
5
5
|
import { useAppStore } from '@/stores/use-app-store'
|
|
6
6
|
import { getMissionPath, useNavigate } from '@/lib/app/navigation'
|
|
7
|
-
import {
|
|
7
|
+
import { useUpdateTaskMutation } from '@/features/tasks/queries'
|
|
8
8
|
import { ConfirmDialog } from '@/components/shared/confirm-dialog'
|
|
9
9
|
import { AgentAvatar } from '@/components/agents/agent-avatar'
|
|
10
10
|
import { timeAgo } from '@/lib/time-format'
|
|
11
11
|
import { InfoChip } from '@/components/ui/info-chip'
|
|
12
|
-
import type { BoardTask } from '@/types'
|
|
12
|
+
import type { Agent, BoardTask, Project } from '@/types'
|
|
13
13
|
|
|
14
14
|
interface TaskCardProps {
|
|
15
15
|
task: BoardTask
|
|
16
|
+
agents: Record<string, Agent>
|
|
17
|
+
projects: Record<string, Project>
|
|
18
|
+
tasksById: Record<string, BoardTask>
|
|
16
19
|
selectionMode?: boolean
|
|
17
20
|
selected?: boolean
|
|
18
21
|
onToggleSelect?: (id: string) => void
|
|
19
22
|
index?: number
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
export function TaskCard({
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
export function TaskCard({
|
|
26
|
+
task,
|
|
27
|
+
agents,
|
|
28
|
+
projects,
|
|
29
|
+
tasksById,
|
|
30
|
+
selectionMode,
|
|
31
|
+
selected,
|
|
32
|
+
onToggleSelect,
|
|
33
|
+
index = 0,
|
|
34
|
+
}: TaskCardProps) {
|
|
25
35
|
const setEditingTaskId = useAppStore((s) => s.setEditingTaskId)
|
|
26
36
|
const setTaskSheetOpen = useAppStore((s) => s.setTaskSheetOpen)
|
|
27
|
-
const loadTasks = useAppStore((s) => s.loadTasks)
|
|
28
37
|
const setCurrentAgent = useAppStore((s) => s.setCurrentAgent)
|
|
29
38
|
const navigateTo = useNavigate()
|
|
30
39
|
const router = useRouter()
|
|
40
|
+
const updateTaskMutation = useUpdateTaskMutation()
|
|
31
41
|
const [dragging, setDragging] = useState(false)
|
|
32
42
|
const [confirmArchive, setConfirmArchive] = useState(false)
|
|
33
43
|
const [allowDrag, setAllowDrag] = useState(false)
|
|
@@ -48,7 +58,6 @@ export function TaskCard({ task, selectionMode, selected, onToggleSelect, index
|
|
|
48
58
|
}
|
|
49
59
|
}, [])
|
|
50
60
|
|
|
51
|
-
const tasks = useAppStore((s) => s.tasks)
|
|
52
61
|
const agent = agents[task.agentId]
|
|
53
62
|
const project = task.projectId ? projects[task.projectId] : null
|
|
54
63
|
const creatorAgent = task.createdByAgentId ? agents[task.createdByAgentId] : null
|
|
@@ -78,14 +87,12 @@ export function TaskCard({ task, selectionMode, selected, onToggleSelect, index
|
|
|
78
87
|
|
|
79
88
|
const handleQueue = async (e: React.MouseEvent) => {
|
|
80
89
|
e.stopPropagation()
|
|
81
|
-
await
|
|
82
|
-
await loadTasks()
|
|
90
|
+
await updateTaskMutation.mutateAsync({ id: task.id, patch: { status: 'queued' } })
|
|
83
91
|
}
|
|
84
92
|
|
|
85
93
|
const handleArchive = async (e: React.MouseEvent) => {
|
|
86
94
|
e.stopPropagation()
|
|
87
|
-
await
|
|
88
|
-
await loadTasks()
|
|
95
|
+
await updateTaskMutation.mutateAsync({ id: task.id, patch: { status: 'archived' } })
|
|
89
96
|
}
|
|
90
97
|
|
|
91
98
|
const handleViewSession = (e: React.MouseEvent) => {
|
|
@@ -147,7 +154,7 @@ export function TaskCard({ task, selectionMode, selected, onToggleSelect, index
|
|
|
147
154
|
)}
|
|
148
155
|
{isBlocked && (
|
|
149
156
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" className="text-rose-400 shrink-0 mt-0.5">
|
|
150
|
-
<title>{`Blocked by: ${(task.blockedBy || []).map((bid) =>
|
|
157
|
+
<title>{`Blocked by: ${(task.blockedBy || []).map((bid) => tasksById[bid]?.title || bid).join(', ')}`}</title>
|
|
151
158
|
<rect x="3" y="11" width="18" height="11" rx="2" /><path d="M7 11V7a5 5 0 0 1 10 0v4" />
|
|
152
159
|
</svg>
|
|
153
160
|
)}
|
|
@@ -325,7 +332,7 @@ export function TaskCard({ task, selectionMode, selected, onToggleSelect, index
|
|
|
325
332
|
{Array.isArray(task.blocks) && task.blocks.length > 0 && (
|
|
326
333
|
<span
|
|
327
334
|
className="px-1.5 py-0.5 rounded-[5px] bg-amber-500/10 text-amber-400 text-[10px] font-600"
|
|
328
|
-
title={`Blocks: ${task.blocks.map((bid) =>
|
|
335
|
+
title={`Blocks: ${task.blocks.map((bid) => tasksById[bid]?.title || bid).join(', ')}`}
|
|
329
336
|
>
|
|
330
337
|
blocks {task.blocks.length}
|
|
331
338
|
</span>
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import { useState, useCallback } from 'react'
|
|
4
4
|
import { TaskCard } from './task-card'
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import type { BoardTask, BoardTaskStatus } from '@/types'
|
|
5
|
+
import { useCreateTaskMutation } from '@/features/tasks/queries'
|
|
6
|
+
import type { Agent, BoardTask, BoardTaskStatus, Project } from '@/types'
|
|
8
7
|
|
|
9
8
|
const COLUMN_CONFIG: Record<BoardTaskStatus, { label: string; color: string; dot: string }> = {
|
|
10
9
|
backlog: { label: 'Backlog', color: 'text-text-3', dot: 'bg-white/20' },
|
|
@@ -20,6 +19,9 @@ const COLUMN_CONFIG: Record<BoardTaskStatus, { label: string; color: string; dot
|
|
|
20
19
|
interface Props {
|
|
21
20
|
status: BoardTaskStatus
|
|
22
21
|
tasks: BoardTask[]
|
|
22
|
+
agents: Record<string, Agent>
|
|
23
|
+
projects: Record<string, Project>
|
|
24
|
+
tasksById: Record<string, BoardTask>
|
|
23
25
|
onDrop: (taskId: string, newStatus: BoardTaskStatus) => void
|
|
24
26
|
selectionMode?: boolean
|
|
25
27
|
selectedIds?: Set<string>
|
|
@@ -27,12 +29,23 @@ interface Props {
|
|
|
27
29
|
onSelectAll?: () => void
|
|
28
30
|
}
|
|
29
31
|
|
|
30
|
-
export function TaskColumn({
|
|
32
|
+
export function TaskColumn({
|
|
33
|
+
status,
|
|
34
|
+
tasks,
|
|
35
|
+
agents,
|
|
36
|
+
projects,
|
|
37
|
+
tasksById,
|
|
38
|
+
onDrop,
|
|
39
|
+
selectionMode,
|
|
40
|
+
selectedIds,
|
|
41
|
+
onToggleSelect,
|
|
42
|
+
onSelectAll,
|
|
43
|
+
}: Props) {
|
|
31
44
|
const config = COLUMN_CONFIG[status]
|
|
32
45
|
const [dragOver, setDragOver] = useState(false)
|
|
33
46
|
const [quickAddValue, setQuickAddValue] = useState('')
|
|
34
47
|
const [adding, setAdding] = useState(false)
|
|
35
|
-
const
|
|
48
|
+
const createTaskMutation = useCreateTaskMutation()
|
|
36
49
|
|
|
37
50
|
const handleDragOver = useCallback((e: React.DragEvent) => {
|
|
38
51
|
e.preventDefault()
|
|
@@ -58,8 +71,7 @@ export function TaskColumn({ status, tasks, onDrop, selectionMode, selectedIds,
|
|
|
58
71
|
if (!title || adding) return
|
|
59
72
|
setAdding(true)
|
|
60
73
|
try {
|
|
61
|
-
await
|
|
62
|
-
await loadTasks()
|
|
74
|
+
await createTaskMutation.mutateAsync({ title, description: '', agentId: '', status })
|
|
63
75
|
setQuickAddValue('')
|
|
64
76
|
} finally {
|
|
65
77
|
setAdding(false)
|
|
@@ -116,6 +128,9 @@ export function TaskColumn({ status, tasks, onDrop, selectionMode, selectedIds,
|
|
|
116
128
|
<TaskCard
|
|
117
129
|
key={task.id}
|
|
118
130
|
task={task}
|
|
131
|
+
agents={agents}
|
|
132
|
+
projects={projects}
|
|
133
|
+
tasksById={tasksById}
|
|
119
134
|
index={idx}
|
|
120
135
|
selectionMode={selectionMode}
|
|
121
136
|
selected={selectedIds?.has(task.id)}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { useMemo, useState } from 'react'
|
|
4
4
|
import { useAppStore } from '@/stores/use-app-store'
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { useAgentsQuery } from '@/features/agents/queries'
|
|
6
|
+
import { useClearDoneTasksMutation, useTasksQuery } from '@/features/tasks/queries'
|
|
7
7
|
import type { BoardTaskStatus } from '@/types'
|
|
8
8
|
import { EmptyState } from '@/components/shared/empty-state'
|
|
9
9
|
import { SearchInput } from '@/components/ui/search-input'
|
|
@@ -20,20 +20,18 @@ const STATUS_DOT: Record<BoardTaskStatus, string> = {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export function TaskList({ inSidebar }: { inSidebar?: boolean }) {
|
|
23
|
-
const tasks = useAppStore((s) => s.tasks)
|
|
24
|
-
const loadTasks = useAppStore((s) => s.loadTasks)
|
|
25
|
-
const agents = useAppStore((s) => s.agents)
|
|
26
23
|
const setEditingTaskId = useAppStore((s) => s.setEditingTaskId)
|
|
27
24
|
const setTaskSheetOpen = useAppStore((s) => s.setTaskSheetOpen)
|
|
28
25
|
const activeProjectFilter = useAppStore((s) => s.activeProjectFilter)
|
|
26
|
+
const { data: tasks = {} } = useTasksQuery({ includeArchived: true })
|
|
27
|
+
const { data: agents = {} } = useAgentsQuery()
|
|
28
|
+
const clearDoneMutation = useClearDoneTasksMutation()
|
|
29
29
|
const [search, setSearch] = useState('')
|
|
30
30
|
const [clearing, setClearing] = useState(false)
|
|
31
31
|
|
|
32
|
-
useEffect(() => { loadTasks() }, [loadTasks])
|
|
33
|
-
useWs('tasks', loadTasks, 5000)
|
|
34
|
-
|
|
35
32
|
const sorted = useMemo(() =>
|
|
36
33
|
Object.values(tasks)
|
|
34
|
+
.filter((t) => t.status !== 'archived')
|
|
37
35
|
.filter((t) => !activeProjectFilter || t.projectId === activeProjectFilter)
|
|
38
36
|
.sort((a, b) => b.updatedAt - a.updatedAt),
|
|
39
37
|
[tasks, activeProjectFilter],
|
|
@@ -58,8 +56,7 @@ export function TaskList({ inSidebar }: { inSidebar?: boolean }) {
|
|
|
58
56
|
const handleClearDone = async () => {
|
|
59
57
|
setClearing(true)
|
|
60
58
|
try {
|
|
61
|
-
await
|
|
62
|
-
await loadTasks()
|
|
59
|
+
await clearDoneMutation.mutateAsync()
|
|
63
60
|
} catch { /* silent */ }
|
|
64
61
|
setClearing(false)
|
|
65
62
|
}
|