@swarmclawai/swarmclaw 1.2.3 → 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 +20 -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]/models/route.test.ts +60 -0
- package/src/app/api/providers/[id]/models/route.ts +33 -1
- package/src/app/api/providers/[id]/route.test.ts +49 -0
- package/src/app/api/providers/[id]/route.ts +30 -1
- 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 +51 -25
- package/src/components/agents/inspector-panel.tsx +15 -4
- package/src/components/auth/setup-wizard/index.tsx +27 -18
- package/src/components/auth/setup-wizard/shared.tsx +2 -2
- package/src/components/auth/setup-wizard/step-agents.tsx +51 -38
- package/src/components/auth/setup-wizard/step-connect.tsx +48 -17
- package/src/components/auth/setup-wizard/types.ts +6 -4
- package/src/components/auth/setup-wizard/utils.test.ts +38 -8
- package/src/components/auth/setup-wizard/utils.ts +14 -8
- 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 +150 -77
- package/src/components/providers/provider-sheet.tsx +102 -77
- package/src/components/shared/model-combobox.tsx +5 -4
- 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/agent-provider-options.test.ts +152 -0
- package/src/lib/agent-provider-options.ts +84 -0
- package/src/lib/app/api-client.ts +2 -2
- package/src/lib/providers/index.test.ts +78 -0
- package/src/lib/providers/index.ts +13 -10
- package/src/lib/query/client.ts +17 -0
- package/src/lib/server/agents/agent-runtime-config.ts +6 -6
- 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 +42 -215
- package/src/lib/server/storage-normalization.ts +98 -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 +288 -22
- package/src/views/settings/section-providers.tsx +2 -2
|
@@ -1,26 +1,42 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import { useEffect, useState } from 'react'
|
|
3
|
+
import { useEffect, useMemo, useState } from 'react'
|
|
4
4
|
import { useAppStore } from '@/stores/use-app-store'
|
|
5
|
-
import { createProviderConfig, updateProviderConfig, deleteProviderConfig } from '@/lib/provider-config'
|
|
6
|
-
import { api } from '@/lib/app/api-client'
|
|
7
|
-
import { fetchProviderModelDiscovery } from '@/lib/provider-model-discovery-client'
|
|
8
5
|
import { BottomSheet } from '@/components/shared/bottom-sheet'
|
|
9
6
|
import { ConfirmDialog } from '@/components/shared/confirm-dialog'
|
|
10
7
|
import { toast } from 'sonner'
|
|
11
8
|
import { errorMessage } from '@/lib/shared-utils'
|
|
9
|
+
import {
|
|
10
|
+
useCheckProviderConnectionMutation,
|
|
11
|
+
useDeleteProviderMutation,
|
|
12
|
+
useProviderConfigsQuery,
|
|
13
|
+
useProviderModelDiscoveryMutation,
|
|
14
|
+
useProvidersQuery,
|
|
15
|
+
useResetProviderModelsMutation,
|
|
16
|
+
useSaveBuiltinProviderMutation,
|
|
17
|
+
useSaveCustomProviderMutation,
|
|
18
|
+
} from '@/features/providers/queries'
|
|
19
|
+
import { useCreateCredentialMutation, useCredentialsQuery } from '@/features/credentials/queries'
|
|
12
20
|
|
|
13
21
|
export function ProviderSheet() {
|
|
14
22
|
const open = useAppStore((s) => s.providerSheetOpen)
|
|
15
23
|
const setOpen = useAppStore((s) => s.setProviderSheetOpen)
|
|
16
24
|
const editingId = useAppStore((s) => s.editingProviderId)
|
|
17
25
|
const setEditingId = useAppStore((s) => s.setEditingProviderId)
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
26
|
+
const providerConfigsQuery = useProviderConfigsQuery({ enabled: open })
|
|
27
|
+
const providersQuery = useProvidersQuery({ enabled: open })
|
|
28
|
+
const credentialsQuery = useCredentialsQuery({ enabled: open })
|
|
29
|
+
const saveBuiltinProviderMutation = useSaveBuiltinProviderMutation()
|
|
30
|
+
const saveCustomProviderMutation = useSaveCustomProviderMutation()
|
|
31
|
+
const deleteProviderMutation = useDeleteProviderMutation()
|
|
32
|
+
const resetProviderModelsMutation = useResetProviderModelsMutation()
|
|
33
|
+
const checkProviderConnectionMutation = useCheckProviderConnectionMutation()
|
|
34
|
+
const providerModelDiscoveryMutation = useProviderModelDiscoveryMutation()
|
|
35
|
+
const createCredentialMutation = useCreateCredentialMutation()
|
|
36
|
+
|
|
37
|
+
const providerConfigs = providerConfigsQuery.data ?? []
|
|
38
|
+
const providers = providersQuery.data ?? []
|
|
39
|
+
const credentials = useMemo(() => credentialsQuery.data ?? {}, [credentialsQuery.data])
|
|
24
40
|
|
|
25
41
|
const [name, setName] = useState('')
|
|
26
42
|
const [baseUrl, setBaseUrl] = useState('')
|
|
@@ -46,14 +62,14 @@ export function ProviderSheet() {
|
|
|
46
62
|
const [deleting, setDeleting] = useState(false)
|
|
47
63
|
|
|
48
64
|
// Find editing provider in custom configs OR built-in list
|
|
49
|
-
const editingCustom = editingId ? providerConfigs.find((c) => c.id === editingId) : null
|
|
65
|
+
const editingCustom = editingId ? providerConfigs.find((c) => c.id === editingId && c.type === 'custom') : null
|
|
66
|
+
const editingBuiltinOverride = editingId ? providerConfigs.find((c) => c.id === editingId && c.type === 'builtin') : null
|
|
50
67
|
const editingBuiltin = editingId ? providers.find((p) => p.id === editingId) : null
|
|
51
68
|
const isBuiltin = !!editingBuiltin && !editingCustom
|
|
52
69
|
const editing = editingCustom || editingBuiltin
|
|
53
70
|
|
|
54
71
|
useEffect(() => {
|
|
55
72
|
if (open) {
|
|
56
|
-
loadCredentials()
|
|
57
73
|
setNewModel('')
|
|
58
74
|
setLiveModels([])
|
|
59
75
|
setLiveMessage('')
|
|
@@ -75,7 +91,7 @@ export function ProviderSheet() {
|
|
|
75
91
|
// Default to existing credential for this provider
|
|
76
92
|
const existingCred = Object.values(credentials).find((c) => c.provider === editingBuiltin.id)
|
|
77
93
|
setCredentialId(existingCred?.id || null)
|
|
78
|
-
setIsEnabled(
|
|
94
|
+
setIsEnabled(editingBuiltinOverride?.isEnabled !== false)
|
|
79
95
|
} else {
|
|
80
96
|
setName('')
|
|
81
97
|
setBaseUrl('')
|
|
@@ -85,7 +101,7 @@ export function ProviderSheet() {
|
|
|
85
101
|
setIsEnabled(true)
|
|
86
102
|
}
|
|
87
103
|
}
|
|
88
|
-
}, [open, editingId, credentials, editingBuiltin,
|
|
104
|
+
}, [open, editingId, credentials, editingBuiltin, editingBuiltinOverride, editingCustom])
|
|
89
105
|
|
|
90
106
|
// Reset test status when connection params change
|
|
91
107
|
useEffect(() => {
|
|
@@ -100,10 +116,11 @@ export function ProviderSheet() {
|
|
|
100
116
|
}, [editingId, credentialId, baseUrl, requiresApiKey])
|
|
101
117
|
|
|
102
118
|
const handleTestConnection = async () => {
|
|
119
|
+
if (!isBuiltin) return
|
|
103
120
|
setTestStatus('testing')
|
|
104
121
|
setTestMessage('')
|
|
105
122
|
try {
|
|
106
|
-
const result = await
|
|
123
|
+
const result = await checkProviderConnectionMutation.mutateAsync({
|
|
107
124
|
provider: editingId || 'custom',
|
|
108
125
|
credentialId,
|
|
109
126
|
endpoint: baseUrl,
|
|
@@ -135,11 +152,13 @@ export function ProviderSheet() {
|
|
|
135
152
|
const handleSave = async () => {
|
|
136
153
|
try {
|
|
137
154
|
if (isBuiltin) {
|
|
138
|
-
// Save model overrides for built-in providers
|
|
139
155
|
const modelList = models.split(',').map((m) => m.trim()).filter(Boolean)
|
|
140
|
-
await
|
|
141
|
-
|
|
142
|
-
|
|
156
|
+
await saveBuiltinProviderMutation.mutateAsync({
|
|
157
|
+
id: editingId || '',
|
|
158
|
+
models: modelList,
|
|
159
|
+
isEnabled,
|
|
160
|
+
})
|
|
161
|
+
toast.success('Built-in provider updated')
|
|
143
162
|
onClose()
|
|
144
163
|
return
|
|
145
164
|
}
|
|
@@ -152,14 +171,11 @@ export function ProviderSheet() {
|
|
|
152
171
|
credentialId,
|
|
153
172
|
isEnabled,
|
|
154
173
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
toast.success('Provider created')
|
|
161
|
-
}
|
|
162
|
-
await loadProviderConfigs()
|
|
174
|
+
await saveCustomProviderMutation.mutateAsync({
|
|
175
|
+
id: editingCustom?.id,
|
|
176
|
+
data,
|
|
177
|
+
})
|
|
178
|
+
toast.success(editingCustom ? 'Provider updated' : 'Provider created')
|
|
163
179
|
onClose()
|
|
164
180
|
} catch (err: unknown) {
|
|
165
181
|
toast.error(err instanceof Error ? err.message : 'Failed to save provider')
|
|
@@ -170,9 +186,8 @@ export function ProviderSheet() {
|
|
|
170
186
|
if (editingCustom) {
|
|
171
187
|
setDeleting(true)
|
|
172
188
|
try {
|
|
173
|
-
await
|
|
189
|
+
await deleteProviderMutation.mutateAsync(editingCustom.id)
|
|
174
190
|
toast.success('Provider deleted')
|
|
175
|
-
await loadProviderConfigs()
|
|
176
191
|
setConfirmDelete(false)
|
|
177
192
|
onClose()
|
|
178
193
|
} catch (err: unknown) {
|
|
@@ -184,35 +199,33 @@ export function ProviderSheet() {
|
|
|
184
199
|
}
|
|
185
200
|
|
|
186
201
|
const handleResetModels = async () => {
|
|
187
|
-
if (isBuiltin
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
if (updated) setModels(updated.models.join(', '))
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
const handleAddModel = () => {
|
|
197
|
-
if (!newModel.trim()) return
|
|
198
|
-
const current = models ? models + ', ' + newModel.trim() : newModel.trim()
|
|
199
|
-
setModels(current)
|
|
200
|
-
setNewModel('')
|
|
202
|
+
if (!isBuiltin || !editingId) return
|
|
203
|
+
await resetProviderModelsMutation.mutateAsync(editingId)
|
|
204
|
+
const refreshedProviders = (await providersQuery.refetch()).data ?? []
|
|
205
|
+
const updated = refreshedProviders.find((provider) => provider.id === editingId)
|
|
206
|
+
if (updated) setModels(updated.models.join(', '))
|
|
201
207
|
}
|
|
202
208
|
|
|
203
|
-
const
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
209
|
+
const handleCreateCredential = async () => {
|
|
210
|
+
const cred = await createCredentialMutation.mutateAsync({
|
|
211
|
+
provider: editingId || name || 'custom',
|
|
212
|
+
name: newKeyName.trim() || `${name || editingId || 'Custom'} key`,
|
|
213
|
+
apiKey: newKeyValue.trim(),
|
|
214
|
+
})
|
|
215
|
+
await credentialsQuery.refetch()
|
|
216
|
+
setCredentialId(cred.id)
|
|
217
|
+
setAddingKey(false)
|
|
218
|
+
setNewKeyName('')
|
|
219
|
+
setNewKeyValue('')
|
|
207
220
|
}
|
|
208
221
|
|
|
209
222
|
const handleLoadLiveModels = async (force = false) => {
|
|
210
|
-
if (!open) return
|
|
223
|
+
if (!open || !isBuiltin) return
|
|
211
224
|
const providerId = editingId || 'custom'
|
|
212
225
|
setLiveLoading(true)
|
|
213
226
|
setLiveMessage('')
|
|
214
227
|
try {
|
|
215
|
-
const result = await
|
|
228
|
+
const result = await providerModelDiscoveryMutation.mutateAsync({
|
|
216
229
|
providerId,
|
|
217
230
|
credentialId,
|
|
218
231
|
endpoint: baseUrl,
|
|
@@ -237,12 +250,24 @@ export function ProviderSheet() {
|
|
|
237
250
|
}
|
|
238
251
|
}
|
|
239
252
|
|
|
253
|
+
const handleAddModel = () => {
|
|
254
|
+
if (!newModel.trim()) return
|
|
255
|
+
const current = models ? models + ', ' + newModel.trim() : newModel.trim()
|
|
256
|
+
setModels(current)
|
|
257
|
+
setNewModel('')
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const handleRemoveModel = (index: number) => {
|
|
261
|
+
const list = models.split(',').map((m) => m.trim()).filter(Boolean)
|
|
262
|
+
list.splice(index, 1)
|
|
263
|
+
setModels(list.join(', '))
|
|
264
|
+
}
|
|
265
|
+
|
|
240
266
|
const credList = Object.values(credentials)
|
|
241
267
|
const modelList = models.split(',').map((m) => m.trim()).filter(Boolean)
|
|
242
268
|
const showApiKey = isBuiltin ? editingBuiltin?.requiresApiKey || editingBuiltin?.optionalApiKey : requiresApiKey
|
|
243
|
-
const canDiscoverModels = isBuiltin
|
|
244
|
-
|
|
245
|
-
: !!baseUrl.trim()
|
|
269
|
+
const canDiscoverModels = Boolean(isBuiltin && editingBuiltin?.supportsModelDiscovery)
|
|
270
|
+
const showTestButton = Boolean(isBuiltin && showApiKey && credentialId)
|
|
246
271
|
|
|
247
272
|
const inputClass = "w-full px-4 py-3.5 rounded-[14px] border border-white/[0.08] bg-surface text-text text-[15px] outline-none transition-all duration-200 placeholder:text-text-3/50 focus-glow"
|
|
248
273
|
|
|
@@ -295,7 +320,7 @@ export function ProviderSheet() {
|
|
|
295
320
|
</button>
|
|
296
321
|
)}
|
|
297
322
|
{isBuiltin && (
|
|
298
|
-
<button onClick={handleResetModels}
|
|
323
|
+
<button onClick={() => { void handleResetModels() }}
|
|
299
324
|
className="text-[11px] text-text-3 hover:text-text-2 transition-colors cursor-pointer bg-transparent border-none"
|
|
300
325
|
style={{ fontFamily: 'inherit' }}>
|
|
301
326
|
Reset to defaults
|
|
@@ -367,7 +392,7 @@ export function ProviderSheet() {
|
|
|
367
392
|
className={`${inputClass} resize-y min-h-[80px] font-mono text-[14px]`}
|
|
368
393
|
style={{ fontFamily: 'inherit' }}
|
|
369
394
|
/>
|
|
370
|
-
<p className="text-[11px] text-text-3/70 mt-2">Comma-separated model IDs
|
|
395
|
+
<p className="text-[11px] text-text-3/70 mt-2">Comma-separated model IDs. Custom providers are saved as-is, so add the models you want manually.</p>
|
|
371
396
|
</>
|
|
372
397
|
)}
|
|
373
398
|
</div>
|
|
@@ -451,14 +476,12 @@ export function ProviderSheet() {
|
|
|
451
476
|
onClick={async () => {
|
|
452
477
|
setSavingKey(true)
|
|
453
478
|
try {
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
} catch (err: unknown) { toast.error(`Failed to save: ${errorMessage(err)}`) }
|
|
461
|
-
finally { setSavingKey(false) }
|
|
479
|
+
await handleCreateCredential()
|
|
480
|
+
} catch (err: unknown) {
|
|
481
|
+
toast.error(`Failed to save: ${errorMessage(err)}`)
|
|
482
|
+
} finally {
|
|
483
|
+
setSavingKey(false)
|
|
484
|
+
}
|
|
462
485
|
}}
|
|
463
486
|
className="px-4 py-1.5 rounded-[8px] bg-accent-bright text-white text-[12px] font-600 cursor-pointer border-none hover:brightness-110 transition-all disabled:opacity-40"
|
|
464
487
|
style={{ fontFamily: 'inherit' }}
|
|
@@ -471,8 +494,8 @@ export function ProviderSheet() {
|
|
|
471
494
|
</div>
|
|
472
495
|
)}
|
|
473
496
|
|
|
474
|
-
{/* Enabled toggle
|
|
475
|
-
{
|
|
497
|
+
{/* Enabled toggle */}
|
|
498
|
+
{(isBuiltin || editingCustom) && (
|
|
476
499
|
<div className="mb-8">
|
|
477
500
|
<label className="flex items-center gap-3 cursor-pointer">
|
|
478
501
|
<div
|
|
@@ -484,17 +507,20 @@ export function ProviderSheet() {
|
|
|
484
507
|
${isEnabled ? 'left-[22px]' : 'left-0.5'}`} />
|
|
485
508
|
</div>
|
|
486
509
|
<span className="font-display text-[14px] font-600 text-text-2">Enabled</span>
|
|
510
|
+
{isBuiltin && (
|
|
511
|
+
<span className="text-[12px] text-text-3">Hidden from the agent sheet when off.</span>
|
|
512
|
+
)}
|
|
487
513
|
</label>
|
|
488
514
|
</div>
|
|
489
515
|
)}
|
|
490
516
|
|
|
491
517
|
{/* Test connection result */}
|
|
492
|
-
{testStatus === 'fail' && (
|
|
518
|
+
{isBuiltin && testStatus === 'fail' && (
|
|
493
519
|
<div className="mb-4 p-3 rounded-[12px] bg-red-500/[0.08] border border-red-500/20">
|
|
494
520
|
<p className="text-[13px] text-red-400">{testMessage || 'Connection test failed'}</p>
|
|
495
521
|
</div>
|
|
496
522
|
)}
|
|
497
|
-
{testStatus === 'pass' && (
|
|
523
|
+
{isBuiltin && testStatus === 'pass' && (
|
|
498
524
|
<div className="mb-4 p-3 rounded-[12px] bg-emerald-500/[0.08] border border-emerald-500/20">
|
|
499
525
|
<p className="text-[13px] text-emerald-400">{testMessage || 'Connected successfully'}</p>
|
|
500
526
|
</div>
|
|
@@ -509,25 +535,24 @@ export function ProviderSheet() {
|
|
|
509
535
|
<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' }}>
|
|
510
536
|
Cancel
|
|
511
537
|
</button>
|
|
512
|
-
{
|
|
538
|
+
{showTestButton && (
|
|
513
539
|
<button
|
|
514
540
|
onClick={handleTestConnection}
|
|
515
541
|
disabled={testStatus === 'testing'}
|
|
516
|
-
className="
|
|
542
|
+
className="py-3.5 px-6 rounded-[14px] border-none bg-emerald-600 text-white text-[15px] font-600 cursor-pointer active:scale-[0.97] disabled:opacity-30 transition-all shadow-[0_4px_20px_rgba(16,185,129,0.2)] hover:brightness-110"
|
|
517
543
|
style={{ fontFamily: 'inherit' }}
|
|
518
544
|
>
|
|
519
545
|
{testStatus === 'testing' ? 'Testing...' : testStatus === 'fail' ? 'Retry Connection' : 'Test Connection'}
|
|
520
546
|
</button>
|
|
521
|
-
) : (
|
|
522
|
-
<button
|
|
523
|
-
onClick={handleSave}
|
|
524
|
-
disabled={isBuiltin ? false : (!name.trim() || !baseUrl.trim())}
|
|
525
|
-
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"
|
|
526
|
-
style={{ fontFamily: 'inherit' }}
|
|
527
|
-
>
|
|
528
|
-
{editing ? 'Save' : 'Create'}
|
|
529
|
-
</button>
|
|
530
547
|
)}
|
|
548
|
+
<button
|
|
549
|
+
onClick={handleSave}
|
|
550
|
+
disabled={isBuiltin ? false : (!name.trim() || !baseUrl.trim())}
|
|
551
|
+
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"
|
|
552
|
+
style={{ fontFamily: 'inherit' }}
|
|
553
|
+
>
|
|
554
|
+
{editing ? 'Save' : 'Create'}
|
|
555
|
+
</button>
|
|
531
556
|
</div>
|
|
532
557
|
<ConfirmDialog
|
|
533
558
|
open={confirmDelete}
|
|
@@ -40,6 +40,7 @@ export function ModelCombobox({
|
|
|
40
40
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
41
41
|
const lastDiscoveryKeyRef = useRef<string | null>(null)
|
|
42
42
|
const loadProviders = useAppStore((s) => s.loadProviders)
|
|
43
|
+
const loadProviderConfigs = useAppStore((s) => s.loadProviderConfigs)
|
|
43
44
|
|
|
44
45
|
const availableModels = [...models, ...discoveredModels].filter((model, index, source) => source.indexOf(model) === index)
|
|
45
46
|
const trimmedQuery = query.trim()
|
|
@@ -53,8 +54,8 @@ export function ModelCombobox({
|
|
|
53
54
|
|
|
54
55
|
const persistModels = useCallback(async (next: string[]) => {
|
|
55
56
|
await api('PUT', `/providers/${providerId}/models`, { models: next })
|
|
56
|
-
await loadProviders()
|
|
57
|
-
}, [
|
|
57
|
+
await Promise.all([loadProviders(), loadProviderConfigs()])
|
|
58
|
+
}, [loadProviderConfigs, loadProviders, providerId])
|
|
58
59
|
|
|
59
60
|
const addModel = useCallback(async (name: string) => {
|
|
60
61
|
const next = [...models, name]
|
|
@@ -73,8 +74,8 @@ export function ModelCombobox({
|
|
|
73
74
|
} else {
|
|
74
75
|
await persistModels(next)
|
|
75
76
|
}
|
|
76
|
-
await loadProviders()
|
|
77
|
-
}, [models, defaultModels, value, onChange, providerId, persistModels, loadProviders])
|
|
77
|
+
await Promise.all([loadProviders(), loadProviderConfigs()])
|
|
78
|
+
}, [models, defaultModels, value, onChange, providerId, persistModels, loadProviderConfigs, loadProviders])
|
|
78
79
|
|
|
79
80
|
const selectModel = useCallback((m: string) => {
|
|
80
81
|
onChange(m)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import { useCallback,
|
|
3
|
+
import { useCallback, useMemo, useState } from 'react'
|
|
4
4
|
import { useRouter, useSearchParams } from 'next/navigation'
|
|
5
5
|
import { useAppStore } from '@/stores/use-app-store'
|
|
6
|
-
import { useWs } from '@/hooks/use-ws'
|
|
7
6
|
import type { Skill } from '@/types'
|
|
8
7
|
import { SkillsWorkspace } from './skills-workspace'
|
|
8
|
+
import { useSkillsQuery } from '@/features/skills/queries'
|
|
9
9
|
|
|
10
10
|
export function SkillList({ inSidebar }: { inSidebar?: boolean }) {
|
|
11
11
|
if (!inSidebar) return <SkillsWorkspace />
|
|
@@ -15,30 +15,17 @@ export function SkillList({ inSidebar }: { inSidebar?: boolean }) {
|
|
|
15
15
|
function SidebarSkillList() {
|
|
16
16
|
const router = useRouter()
|
|
17
17
|
const searchParams = useSearchParams()
|
|
18
|
-
const skills = useAppStore((s) => s.skills)
|
|
19
|
-
const loadSkills = useAppStore((s) => s.loadSkills)
|
|
20
18
|
const activeProjectFilter = useAppStore((s) => s.activeProjectFilter)
|
|
21
19
|
const setEditingSkillId = useAppStore((s) => s.setEditingSkillId)
|
|
22
20
|
const setSkillSheetOpen = useAppStore((s) => s.setSkillSheetOpen)
|
|
21
|
+
const skillsQuery = useSkillsQuery()
|
|
22
|
+
const skills = useMemo(() => skillsQuery.data ?? {}, [skillsQuery.data])
|
|
23
23
|
|
|
24
24
|
const [query, setQuery] = useState('')
|
|
25
|
-
const [ready, setReady] = useState(false)
|
|
26
25
|
|
|
27
26
|
const activeTab = searchParams.get('tab') === 'clawhub' ? 'clawhub' : 'skills'
|
|
28
27
|
const selectedSkillId = activeTab === 'skills' ? searchParams.get('skill') : null
|
|
29
28
|
|
|
30
|
-
useEffect(() => {
|
|
31
|
-
let active = true
|
|
32
|
-
void loadSkills().finally(() => {
|
|
33
|
-
if (active) setReady(true)
|
|
34
|
-
})
|
|
35
|
-
return () => {
|
|
36
|
-
active = false
|
|
37
|
-
}
|
|
38
|
-
}, [loadSkills])
|
|
39
|
-
|
|
40
|
-
useWs('skills', () => { void loadSkills() })
|
|
41
|
-
|
|
42
29
|
const setPageState = useCallback((patch: Record<string, string | null | undefined>) => {
|
|
43
30
|
const next = new URLSearchParams(searchParams.toString())
|
|
44
31
|
for (const [key, value] of Object.entries(patch)) {
|
|
@@ -92,7 +79,7 @@ function SidebarSkillList() {
|
|
|
92
79
|
</div>
|
|
93
80
|
|
|
94
81
|
<div className="mt-3 flex-1 overflow-y-auto">
|
|
95
|
-
{
|
|
82
|
+
{skillsQuery.isPending ? (
|
|
96
83
|
<div className="flex items-center justify-center py-10 text-[12px] text-text-3/65">
|
|
97
84
|
<span className="mr-3 h-4 w-4 animate-spin rounded-full border-2 border-white/[0.12] border-t-accent-bright" />
|
|
98
85
|
Loading skills...
|
|
@@ -5,20 +5,27 @@ import { useAppStore } from '@/stores/use-app-store'
|
|
|
5
5
|
import { BottomSheet } from '@/components/shared/bottom-sheet'
|
|
6
6
|
import { ConfirmDialog } from '@/components/shared/confirm-dialog'
|
|
7
7
|
import { AgentAvatar } from '@/components/agents/agent-avatar'
|
|
8
|
-
import { api } from '@/lib/app/api-client'
|
|
9
8
|
import { buildSkillSavePayload } from '@/lib/skill-save-payload'
|
|
10
9
|
import { toast } from 'sonner'
|
|
11
10
|
import type { Skill, SkillSecuritySummary } from '@/types'
|
|
11
|
+
import {
|
|
12
|
+
useDeleteSkillMutation,
|
|
13
|
+
useImportSkillFromUrlMutation,
|
|
14
|
+
useSaveSkillMutation,
|
|
15
|
+
useSkillsQuery,
|
|
16
|
+
} from '@/features/skills/queries'
|
|
17
|
+
import { useAgentsQuery } from '@/features/agents/queries'
|
|
12
18
|
|
|
13
19
|
export function SkillSheet() {
|
|
14
20
|
const open = useAppStore((s) => s.skillSheetOpen)
|
|
15
21
|
const setOpen = useAppStore((s) => s.setSkillSheetOpen)
|
|
16
22
|
const editingId = useAppStore((s) => s.editingSkillId)
|
|
17
23
|
const setEditingId = useAppStore((s) => s.setEditingSkillId)
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
24
|
+
const skillsQuery = useSkillsQuery({ enabled: open })
|
|
25
|
+
const agentsQuery = useAgentsQuery({ enabled: open })
|
|
26
|
+
const importSkillFromUrlMutation = useImportSkillFromUrlMutation()
|
|
27
|
+
const saveSkillMutation = useSaveSkillMutation()
|
|
28
|
+
const deleteSkillMutation = useDeleteSkillMutation()
|
|
22
29
|
const fileRef = useRef<HTMLInputElement>(null)
|
|
23
30
|
|
|
24
31
|
const [name, setName] = useState('')
|
|
@@ -35,6 +42,8 @@ export function SkillSheet() {
|
|
|
35
42
|
const [confirmDelete, setConfirmDelete] = useState(false)
|
|
36
43
|
const [deleting, setDeleting] = useState(false)
|
|
37
44
|
|
|
45
|
+
const skills = skillsQuery.data ?? {}
|
|
46
|
+
const agents = agentsQuery.data ?? {}
|
|
38
47
|
const editing = editingId ? skills[editingId] : null
|
|
39
48
|
const agentList = Object.values(agents)
|
|
40
49
|
|
|
@@ -44,7 +53,7 @@ export function SkillSheet() {
|
|
|
44
53
|
setImportError('')
|
|
45
54
|
setImportNotice('')
|
|
46
55
|
try {
|
|
47
|
-
const result = await
|
|
56
|
+
const result = await importSkillFromUrlMutation.mutateAsync(importUrl.trim())
|
|
48
57
|
setName(result.name || '')
|
|
49
58
|
setFilename(result.filename || '')
|
|
50
59
|
setDescription(result.description || '')
|
|
@@ -62,10 +71,6 @@ export function SkillSheet() {
|
|
|
62
71
|
}
|
|
63
72
|
}
|
|
64
73
|
|
|
65
|
-
useEffect(() => {
|
|
66
|
-
if (open) loadAgents()
|
|
67
|
-
}, [open, loadAgents])
|
|
68
|
-
|
|
69
74
|
useEffect(() => {
|
|
70
75
|
if (open) {
|
|
71
76
|
setImportUrl('')
|
|
@@ -133,14 +138,11 @@ export function SkillSheet() {
|
|
|
133
138
|
agentIds,
|
|
134
139
|
}, metadataPreview)
|
|
135
140
|
try {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
toast.success('Skill created successfully')
|
|
142
|
-
}
|
|
143
|
-
await loadSkills()
|
|
141
|
+
await saveSkillMutation.mutateAsync({
|
|
142
|
+
id: editing?.id,
|
|
143
|
+
data: data as Record<string, unknown>,
|
|
144
|
+
})
|
|
145
|
+
toast.success(editing ? 'Skill updated successfully' : 'Skill created successfully')
|
|
144
146
|
onClose()
|
|
145
147
|
} catch (err: unknown) {
|
|
146
148
|
toast.error(err instanceof Error ? err.message : 'Failed to save skill')
|
|
@@ -151,9 +153,8 @@ export function SkillSheet() {
|
|
|
151
153
|
if (!editing) return
|
|
152
154
|
setDeleting(true)
|
|
153
155
|
try {
|
|
154
|
-
await
|
|
156
|
+
await deleteSkillMutation.mutateAsync(editing.id)
|
|
155
157
|
toast.success('Skill deleted')
|
|
156
|
-
await loadSkills()
|
|
157
158
|
setConfirmDelete(false)
|
|
158
159
|
onClose()
|
|
159
160
|
} catch (err: unknown) {
|