@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
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
|
2
|
+
import { api } from '@/lib/app/api-client'
|
|
3
|
+
import type {
|
|
4
|
+
ClawHubSkill,
|
|
5
|
+
Skill,
|
|
6
|
+
SkillInvocationConfig,
|
|
7
|
+
SkillCommandDispatch,
|
|
8
|
+
SkillSuggestion,
|
|
9
|
+
} from '@/types'
|
|
10
|
+
|
|
11
|
+
type QueryOptions = {
|
|
12
|
+
enabled?: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ClawHubSearchResponse {
|
|
16
|
+
skills: ClawHubSkill[]
|
|
17
|
+
total: number
|
|
18
|
+
page: number
|
|
19
|
+
nextCursor?: string | null
|
|
20
|
+
error?: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type ClawHubPreview = Partial<Skill> & {
|
|
24
|
+
name: string
|
|
25
|
+
content: string
|
|
26
|
+
description?: string
|
|
27
|
+
invocation?: SkillInvocationConfig | null
|
|
28
|
+
commandDispatch?: SkillCommandDispatch | null
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function invalidateSkillQueries(queryClient: ReturnType<typeof useQueryClient>) {
|
|
32
|
+
await queryClient.invalidateQueries({ queryKey: skillQueryKeys.all })
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const skillQueryKeys = {
|
|
36
|
+
all: ['skills'] as const,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const skillSuggestionQueryKeys = {
|
|
40
|
+
all: ['skill-suggestions'] as const,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function useSkillsQuery(options: QueryOptions = {}) {
|
|
44
|
+
return useQuery<Record<string, Skill>>({
|
|
45
|
+
queryKey: skillQueryKeys.all,
|
|
46
|
+
queryFn: () => api<Record<string, Skill>>('GET', '/skills'),
|
|
47
|
+
enabled: options.enabled,
|
|
48
|
+
staleTime: 20_000,
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function useSkillSuggestionsQuery(options: QueryOptions = {}) {
|
|
53
|
+
return useQuery<SkillSuggestion[]>({
|
|
54
|
+
queryKey: skillSuggestionQueryKeys.all,
|
|
55
|
+
queryFn: () => api<SkillSuggestion[]>('GET', '/skill-suggestions'),
|
|
56
|
+
enabled: options.enabled,
|
|
57
|
+
staleTime: 20_000,
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function useImportSkillFromUrlMutation() {
|
|
62
|
+
return useMutation({
|
|
63
|
+
mutationFn: (url: string) =>
|
|
64
|
+
api<Partial<Skill> & { name: string; filename: string; description?: string; content: string; sourceFormat?: 'openclaw' | 'plain' }>(
|
|
65
|
+
'POST',
|
|
66
|
+
'/skills/import',
|
|
67
|
+
{ url },
|
|
68
|
+
),
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function useSaveSkillMutation() {
|
|
73
|
+
const queryClient = useQueryClient()
|
|
74
|
+
return useMutation({
|
|
75
|
+
mutationFn: ({
|
|
76
|
+
id,
|
|
77
|
+
data,
|
|
78
|
+
}: {
|
|
79
|
+
id?: string | null
|
|
80
|
+
data: Record<string, unknown>
|
|
81
|
+
}) => (id ? api('PUT', `/skills/${id}`, data) : api('POST', '/skills', data)),
|
|
82
|
+
onSuccess: async () => {
|
|
83
|
+
await invalidateSkillQueries(queryClient)
|
|
84
|
+
},
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function useDeleteSkillMutation() {
|
|
89
|
+
const queryClient = useQueryClient()
|
|
90
|
+
return useMutation({
|
|
91
|
+
mutationFn: (id: string) => api('DELETE', `/skills/${id}`),
|
|
92
|
+
onSuccess: async () => {
|
|
93
|
+
await invalidateSkillQueries(queryClient)
|
|
94
|
+
},
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function useGenerateSkillSuggestionMutation() {
|
|
99
|
+
const queryClient = useQueryClient()
|
|
100
|
+
return useMutation({
|
|
101
|
+
mutationFn: (sessionId: string) => api<SkillSuggestion>('POST', '/skill-suggestions', { sessionId }),
|
|
102
|
+
onSuccess: async () => {
|
|
103
|
+
await queryClient.invalidateQueries({ queryKey: skillSuggestionQueryKeys.all })
|
|
104
|
+
},
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function useApproveSkillSuggestionMutation() {
|
|
109
|
+
const queryClient = useQueryClient()
|
|
110
|
+
return useMutation({
|
|
111
|
+
mutationFn: (id: string) => api('POST', `/skill-suggestions/${id}/approve`),
|
|
112
|
+
onSuccess: async () => {
|
|
113
|
+
await Promise.all([
|
|
114
|
+
queryClient.invalidateQueries({ queryKey: skillSuggestionQueryKeys.all }),
|
|
115
|
+
invalidateSkillQueries(queryClient),
|
|
116
|
+
])
|
|
117
|
+
},
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function useRejectSkillSuggestionMutation() {
|
|
122
|
+
const queryClient = useQueryClient()
|
|
123
|
+
return useMutation({
|
|
124
|
+
mutationFn: (id: string) => api('POST', `/skill-suggestions/${id}/reject`),
|
|
125
|
+
onSuccess: async () => {
|
|
126
|
+
await queryClient.invalidateQueries({ queryKey: skillSuggestionQueryKeys.all })
|
|
127
|
+
},
|
|
128
|
+
})
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function useClawHubSearchMutation() {
|
|
132
|
+
return useMutation({
|
|
133
|
+
mutationFn: ({
|
|
134
|
+
query,
|
|
135
|
+
page,
|
|
136
|
+
limit,
|
|
137
|
+
cursor,
|
|
138
|
+
}: {
|
|
139
|
+
query: string
|
|
140
|
+
page: number
|
|
141
|
+
limit: number
|
|
142
|
+
cursor?: string | null
|
|
143
|
+
}) => {
|
|
144
|
+
const params = new URLSearchParams({
|
|
145
|
+
q: query,
|
|
146
|
+
page: String(page),
|
|
147
|
+
limit: String(limit),
|
|
148
|
+
})
|
|
149
|
+
if (cursor) params.set('cursor', cursor)
|
|
150
|
+
return api<ClawHubSearchResponse>('GET', `/clawhub/search?${params.toString()}`)
|
|
151
|
+
},
|
|
152
|
+
})
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function useClawHubPreviewMutation() {
|
|
156
|
+
return useMutation({
|
|
157
|
+
mutationFn: (payload: {
|
|
158
|
+
name: string
|
|
159
|
+
description?: string
|
|
160
|
+
author?: string
|
|
161
|
+
tags?: string[]
|
|
162
|
+
url: string
|
|
163
|
+
}) => api<ClawHubPreview>('POST', '/clawhub/preview', payload),
|
|
164
|
+
})
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function useInstallClawHubSkillMutation() {
|
|
168
|
+
const queryClient = useQueryClient()
|
|
169
|
+
return useMutation({
|
|
170
|
+
mutationFn: (payload: {
|
|
171
|
+
name: string
|
|
172
|
+
description?: string
|
|
173
|
+
url: string
|
|
174
|
+
author?: string
|
|
175
|
+
tags?: string[]
|
|
176
|
+
content?: string
|
|
177
|
+
}) => api('POST', '/clawhub/install', payload),
|
|
178
|
+
onSuccess: async () => {
|
|
179
|
+
await invalidateSkillQueries(queryClient)
|
|
180
|
+
},
|
|
181
|
+
})
|
|
182
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
|
2
|
+
import { api } from '@/lib/app/api-client'
|
|
3
|
+
import {
|
|
4
|
+
bulkUpdateTasks,
|
|
5
|
+
createTask,
|
|
6
|
+
fetchTasks,
|
|
7
|
+
importGitHubIssues,
|
|
8
|
+
updateTask,
|
|
9
|
+
type GitHubIssueImportRequest,
|
|
10
|
+
type GitHubIssueImportResult,
|
|
11
|
+
} from '@/lib/tasks'
|
|
12
|
+
import type { BoardTask, BoardTaskStatus, TaskComment } from '@/types'
|
|
13
|
+
|
|
14
|
+
export type {
|
|
15
|
+
GitHubIssueImportRequest,
|
|
16
|
+
GitHubIssueImportResult,
|
|
17
|
+
} from '@/lib/tasks'
|
|
18
|
+
|
|
19
|
+
type TasksRecord = Record<string, BoardTask>
|
|
20
|
+
type QueryOptions = {
|
|
21
|
+
enabled?: boolean
|
|
22
|
+
includeArchived?: boolean
|
|
23
|
+
}
|
|
24
|
+
type TasksSnapshot = Array<[readonly unknown[], TasksRecord | undefined]>
|
|
25
|
+
|
|
26
|
+
export const taskQueryKeys = {
|
|
27
|
+
all: ['tasks'] as const,
|
|
28
|
+
lists: () => ['tasks', 'list'] as const,
|
|
29
|
+
list: (params: { includeArchived: boolean }) => ['tasks', 'list', params] as const,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function includeArchivedFromKey(key: readonly unknown[]): boolean {
|
|
33
|
+
const params = key[2]
|
|
34
|
+
return typeof params === 'object' && params !== null && (params as { includeArchived?: boolean }).includeArchived === true
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function captureTaskSnapshots(queryClient: ReturnType<typeof useQueryClient>): TasksSnapshot {
|
|
38
|
+
return queryClient.getQueriesData<TasksRecord>({ queryKey: taskQueryKeys.lists() }) as TasksSnapshot
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function restoreTaskSnapshots(
|
|
42
|
+
queryClient: ReturnType<typeof useQueryClient>,
|
|
43
|
+
snapshots: TasksSnapshot | undefined,
|
|
44
|
+
): void {
|
|
45
|
+
if (!snapshots) return
|
|
46
|
+
for (const [key, data] of snapshots) {
|
|
47
|
+
queryClient.setQueryData(key, data)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function applyTaskListPatch(
|
|
52
|
+
current: TasksRecord | undefined,
|
|
53
|
+
taskId: string,
|
|
54
|
+
nextTask: BoardTask | null,
|
|
55
|
+
includeArchived: boolean,
|
|
56
|
+
): TasksRecord | undefined {
|
|
57
|
+
if (!current) return current
|
|
58
|
+
const next = { ...current }
|
|
59
|
+
if (!nextTask || (!includeArchived && nextTask.status === 'archived')) {
|
|
60
|
+
delete next[taskId]
|
|
61
|
+
return next
|
|
62
|
+
}
|
|
63
|
+
next[taskId] = nextTask
|
|
64
|
+
return next
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function patchTaskCaches(
|
|
68
|
+
queryClient: ReturnType<typeof useQueryClient>,
|
|
69
|
+
updater: (current: TasksRecord | undefined, includeArchived: boolean) => TasksRecord | undefined,
|
|
70
|
+
): TasksSnapshot {
|
|
71
|
+
const snapshots = captureTaskSnapshots(queryClient)
|
|
72
|
+
for (const [key] of snapshots) {
|
|
73
|
+
queryClient.setQueryData<TasksRecord>(key, (current) => updater(current, includeArchivedFromKey(key)))
|
|
74
|
+
}
|
|
75
|
+
return snapshots
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function useTasksQuery(options: QueryOptions = {}) {
|
|
79
|
+
const includeArchived = options.includeArchived ?? false
|
|
80
|
+
return useQuery<TasksRecord>({
|
|
81
|
+
queryKey: taskQueryKeys.list({ includeArchived }),
|
|
82
|
+
queryFn: () => fetchTasks(includeArchived),
|
|
83
|
+
enabled: options.enabled,
|
|
84
|
+
staleTime: 10_000,
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function useCreateTaskMutation() {
|
|
89
|
+
const queryClient = useQueryClient()
|
|
90
|
+
return useMutation({
|
|
91
|
+
mutationFn: createTask,
|
|
92
|
+
onSuccess: async () => {
|
|
93
|
+
await queryClient.invalidateQueries({ queryKey: taskQueryKeys.all })
|
|
94
|
+
},
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function useUpdateTaskMutation() {
|
|
99
|
+
const queryClient = useQueryClient()
|
|
100
|
+
return useMutation({
|
|
101
|
+
mutationFn: ({ id, patch }: { id: string; patch: Partial<BoardTask> }) => updateTask(id, patch),
|
|
102
|
+
onMutate: async ({ id, patch }) => {
|
|
103
|
+
await queryClient.cancelQueries({ queryKey: taskQueryKeys.lists() })
|
|
104
|
+
const snapshots = patchTaskCaches(queryClient, (current, includeArchived) => {
|
|
105
|
+
const existing = current?.[id]
|
|
106
|
+
if (!existing) return current
|
|
107
|
+
const nextTask = { ...existing, ...patch, updatedAt: Date.now() }
|
|
108
|
+
return applyTaskListPatch(current, id, nextTask, includeArchived)
|
|
109
|
+
})
|
|
110
|
+
return { snapshots }
|
|
111
|
+
},
|
|
112
|
+
onError: (_error, _variables, context) => {
|
|
113
|
+
restoreTaskSnapshots(queryClient, context?.snapshots)
|
|
114
|
+
},
|
|
115
|
+
onSettled: async () => {
|
|
116
|
+
await queryClient.invalidateQueries({ queryKey: taskQueryKeys.all })
|
|
117
|
+
},
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function useBulkUpdateTasksMutation() {
|
|
122
|
+
const queryClient = useQueryClient()
|
|
123
|
+
return useMutation({
|
|
124
|
+
mutationFn: ({ ids, patch }: { ids: string[]; patch: { status?: BoardTaskStatus; agentId?: string; projectId?: string | null } }) =>
|
|
125
|
+
bulkUpdateTasks(ids, patch),
|
|
126
|
+
onMutate: async ({ ids, patch }) => {
|
|
127
|
+
await queryClient.cancelQueries({ queryKey: taskQueryKeys.lists() })
|
|
128
|
+
const snapshots = patchTaskCaches(queryClient, (current, includeArchived) => {
|
|
129
|
+
if (!current) return current
|
|
130
|
+
const next = { ...current }
|
|
131
|
+
for (const id of ids) {
|
|
132
|
+
const existing = next[id]
|
|
133
|
+
if (!existing) continue
|
|
134
|
+
const updated: BoardTask = {
|
|
135
|
+
...existing,
|
|
136
|
+
...patch,
|
|
137
|
+
agentId: patch.agentId ?? existing.agentId,
|
|
138
|
+
projectId: patch.projectId === undefined ? existing.projectId : patch.projectId ?? undefined,
|
|
139
|
+
updatedAt: Date.now(),
|
|
140
|
+
}
|
|
141
|
+
if (!includeArchived && updated.status === 'archived') {
|
|
142
|
+
delete next[id]
|
|
143
|
+
continue
|
|
144
|
+
}
|
|
145
|
+
next[id] = updated
|
|
146
|
+
}
|
|
147
|
+
return next
|
|
148
|
+
})
|
|
149
|
+
return { snapshots }
|
|
150
|
+
},
|
|
151
|
+
onError: (_error, _variables, context) => {
|
|
152
|
+
restoreTaskSnapshots(queryClient, context?.snapshots)
|
|
153
|
+
},
|
|
154
|
+
onSettled: async () => {
|
|
155
|
+
await queryClient.invalidateQueries({ queryKey: taskQueryKeys.all })
|
|
156
|
+
},
|
|
157
|
+
})
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function useClearDoneTasksMutation() {
|
|
161
|
+
const queryClient = useQueryClient()
|
|
162
|
+
return useMutation({
|
|
163
|
+
mutationFn: () => api('DELETE', '/tasks?filter=done'),
|
|
164
|
+
onSuccess: async () => {
|
|
165
|
+
await queryClient.invalidateQueries({ queryKey: taskQueryKeys.all })
|
|
166
|
+
},
|
|
167
|
+
})
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export function useImportGitHubIssuesMutation() {
|
|
171
|
+
const queryClient = useQueryClient()
|
|
172
|
+
return useMutation<GitHubIssueImportResult, Error, GitHubIssueImportRequest>({
|
|
173
|
+
mutationFn: importGitHubIssues,
|
|
174
|
+
onSuccess: async () => {
|
|
175
|
+
await queryClient.invalidateQueries({ queryKey: taskQueryKeys.all })
|
|
176
|
+
},
|
|
177
|
+
})
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function useAppendTaskCommentMutation() {
|
|
181
|
+
const queryClient = useQueryClient()
|
|
182
|
+
return useMutation({
|
|
183
|
+
mutationFn: ({ id, comment }: { id: string; comment: TaskComment }) =>
|
|
184
|
+
updateTask(id, { appendComment: comment } as Partial<BoardTask> & { appendComment: TaskComment }),
|
|
185
|
+
onSettled: async () => {
|
|
186
|
+
await queryClient.invalidateQueries({ queryKey: taskQueryKeys.all })
|
|
187
|
+
},
|
|
188
|
+
})
|
|
189
|
+
}
|
package/src/hooks/use-ws.ts
CHANGED
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
import { useEffect, useRef } from 'react'
|
|
4
4
|
import { subscribeWs, unsubscribeWs, isWsConnected, onWsStateChange, offWsStateChange } from '@/lib/ws-client'
|
|
5
|
+
import { hmrSingleton } from '@/lib/shared-utils'
|
|
5
6
|
import { usePageActive } from './use-page-active'
|
|
6
7
|
|
|
7
8
|
/** Shared fallback intervals keyed by topic — multiple useWs instances share one interval. */
|
|
8
|
-
const sharedFallbacks = new Map<string, {
|
|
9
|
+
const sharedFallbacks = hmrSingleton('useWs_sharedFallbacks', () => new Map<string, {
|
|
9
10
|
interval: ReturnType<typeof setInterval> | null
|
|
10
11
|
handlers: Set<() => void>
|
|
11
12
|
ms: number
|
|
12
|
-
}>()
|
|
13
|
+
}>())
|
|
13
14
|
|
|
14
15
|
function runAllHandlers(topic: string): void {
|
|
15
16
|
const entry = sharedFallbacks.get(topic)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { fetchWithTimeout, isAbortError, isTimeoutError } from '@/lib/fetch-timeout'
|
|
2
2
|
import { safeStorageGet, safeStorageSet, safeStorageRemove } from './safe-storage'
|
|
3
|
-
import { sleep } from '@/lib/shared-utils'
|
|
3
|
+
import { sleep, hmrSingleton } from '@/lib/shared-utils'
|
|
4
4
|
|
|
5
5
|
const ACCESS_KEY_STORAGE = 'sc_access_key'
|
|
6
6
|
const DEFAULT_API_TIMEOUT_MS = 12_000
|
|
7
7
|
const DEFAULT_GET_RETRIES = 2
|
|
8
8
|
const RETRY_DELAY_BASE_MS = 300
|
|
9
|
-
const inflightGetRequests = new Map<string, Promise<unknown>>()
|
|
9
|
+
const inflightGetRequests = hmrSingleton('apiClient_inflightGetRequests', () => new Map<string, Promise<unknown>>())
|
|
10
10
|
|
|
11
11
|
export function getStoredAccessKey(): string {
|
|
12
12
|
return safeStorageGet(ACCESS_KEY_STORAGE) || ''
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { QueryClient } from '@tanstack/react-query'
|
|
2
|
+
|
|
3
|
+
export function createAppQueryClient(): QueryClient {
|
|
4
|
+
return new QueryClient({
|
|
5
|
+
defaultOptions: {
|
|
6
|
+
queries: {
|
|
7
|
+
staleTime: 15_000,
|
|
8
|
+
gcTime: 5 * 60_000,
|
|
9
|
+
retry: 0,
|
|
10
|
+
refetchOnWindowFocus: false,
|
|
11
|
+
},
|
|
12
|
+
mutations: {
|
|
13
|
+
retry: 0,
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
})
|
|
17
|
+
}
|
|
@@ -7,7 +7,7 @@ import type {
|
|
|
7
7
|
} from '@/types'
|
|
8
8
|
import { deriveOpenClawWsUrl, normalizeProviderEndpoint } from '@/lib/openclaw/openclaw-endpoint'
|
|
9
9
|
import { resolveProviderApiEndpoint, resolveProviderCredentialId } from '@/lib/server/provider-endpoint'
|
|
10
|
-
import { loadGatewayProfiles } from '@/lib/server/
|
|
10
|
+
import { loadGatewayProfiles } from '@/lib/server/gateways/gateway-profile-repository'
|
|
11
11
|
import { isProviderCoolingDown } from '@/lib/server/provider-health'
|
|
12
12
|
|
|
13
13
|
const DEFAULT_OPENCLAW_ENDPOINT = 'http://localhost:18789/v1'
|