@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
|
@@ -28,6 +28,7 @@ import { resolveStoredOllamaMode } from '@/lib/ollama-mode'
|
|
|
28
28
|
import { errorMessage } from '@/lib/shared-utils'
|
|
29
29
|
import { getDefaultAgentToolIds } from '@/lib/agent-default-tools'
|
|
30
30
|
import { getEnabledExtensionIds, getEnabledToolIds } from '@/lib/capability-selection'
|
|
31
|
+
import { buildAgentSelectableProviders, resolveAgentSelectableProviderCredentials } from '@/lib/agent-provider-options'
|
|
31
32
|
|
|
32
33
|
const HB_PRESETS = [1800, 3600, 7200, 21600, 43200] as const
|
|
33
34
|
const FALLBACK_ELEVENLABS_VOICE_ID = 'JBFqnCBsd6RMkjVDRZzb'
|
|
@@ -46,6 +47,7 @@ const AUTO_SYNC_MODEL_PROVIDER_IDS = new Set<ProviderType>([
|
|
|
46
47
|
'ollama',
|
|
47
48
|
])
|
|
48
49
|
const CONNECTION_TEST_TIMEOUT_MS = 40_000
|
|
50
|
+
type AgentProviderId = string
|
|
49
51
|
|
|
50
52
|
type SafeAgentWallet = Omit<AgentWallet, 'encryptedPrivateKey'> & {
|
|
51
53
|
balanceAtomic?: string
|
|
@@ -171,6 +173,8 @@ export function AgentSheet() {
|
|
|
171
173
|
const loadProjects = useAppStore((s) => s.loadProjects)
|
|
172
174
|
const providers = useAppStore((s) => s.providers)
|
|
173
175
|
const loadProviders = useAppStore((s) => s.loadProviders)
|
|
176
|
+
const providerConfigs = useAppStore((s) => s.providerConfigs)
|
|
177
|
+
const loadProviderConfigs = useAppStore((s) => s.loadProviderConfigs)
|
|
174
178
|
const gatewayProfiles = useAppStore((s) => s.gatewayProfiles)
|
|
175
179
|
const loadGatewayProfiles = useAppStore((s) => s.loadGatewayProfiles)
|
|
176
180
|
const credentials = useAppStore((s) => s.credentials)
|
|
@@ -197,7 +201,7 @@ export function AgentSheet() {
|
|
|
197
201
|
const [soulInitial, setSoulInitial] = useState('')
|
|
198
202
|
const [soulSaveState, setSoulSaveState] = useState<'idle' | 'saved'>('idle')
|
|
199
203
|
const [systemPrompt, setSystemPrompt] = useState('')
|
|
200
|
-
const [provider, setProvider] = useState<
|
|
204
|
+
const [provider, setProvider] = useState<AgentProviderId>('claude-cli')
|
|
201
205
|
const [model, setModel] = useState('')
|
|
202
206
|
const [credentialId, setCredentialId] = useState<string | null>(null)
|
|
203
207
|
const [apiEndpoint, setApiEndpoint] = useState<string | null>(null)
|
|
@@ -308,8 +312,15 @@ export function AgentSheet() {
|
|
|
308
312
|
}
|
|
309
313
|
}, [])
|
|
310
314
|
|
|
311
|
-
const
|
|
312
|
-
|
|
315
|
+
const agentSelectableProviders = useMemo(
|
|
316
|
+
() => buildAgentSelectableProviders(providers, providerConfigs),
|
|
317
|
+
[providers, providerConfigs],
|
|
318
|
+
)
|
|
319
|
+
const currentProvider = agentSelectableProviders.find((p) => p.id === provider)
|
|
320
|
+
const providerCredentials = useMemo(
|
|
321
|
+
() => resolveAgentSelectableProviderCredentials(provider, credentials, providerConfigs),
|
|
322
|
+
[credentials, provider, providerConfigs],
|
|
323
|
+
)
|
|
313
324
|
const openclawCredentials = Object.values(credentials).filter((c) => c.provider === 'openclaw')
|
|
314
325
|
const openclawGatewayProfiles = gatewayProfiles.filter((item) => item.provider === 'openclaw')
|
|
315
326
|
const setAgentPrefill = useAppStore((s) => s.setAgentPrefill)
|
|
@@ -327,15 +338,15 @@ export function AgentSheet() {
|
|
|
327
338
|
? 'Global default'
|
|
328
339
|
: 'Built-in fallback'
|
|
329
340
|
const syncLiveProviderModels = useCallback(async (
|
|
330
|
-
providerId:
|
|
341
|
+
providerId: string,
|
|
331
342
|
nextCredentialId: string | null,
|
|
332
343
|
nextEndpoint: string | null,
|
|
333
344
|
nextOllamaMode: 'local' | 'cloud',
|
|
334
345
|
force = false,
|
|
335
346
|
): Promise<{ synced: boolean; models: string[] } | null> => {
|
|
336
347
|
if (openclawEnabled) return null
|
|
337
|
-
if (!AUTO_SYNC_MODEL_PROVIDER_IDS.has(providerId)) return null
|
|
338
|
-
const providerInfo =
|
|
348
|
+
if (!AUTO_SYNC_MODEL_PROVIDER_IDS.has(providerId as ProviderType)) return null
|
|
349
|
+
const providerInfo = agentSelectableProviders.find((item) => item.id === providerId)
|
|
339
350
|
if (!providerInfo?.supportsModelDiscovery) return null
|
|
340
351
|
|
|
341
352
|
const result = await fetchProviderModelDiscovery({
|
|
@@ -358,7 +369,7 @@ export function AgentSheet() {
|
|
|
358
369
|
|
|
359
370
|
setModel((currentModel) => currentModel.trim() || result.models[0] || '')
|
|
360
371
|
return { synced: !sameModels, models: result.models }
|
|
361
|
-
}, [loadProviders, openclawEnabled
|
|
372
|
+
}, [agentSelectableProviders, loadProviders, openclawEnabled])
|
|
362
373
|
|
|
363
374
|
const providerNeedsKey = !editing && (
|
|
364
375
|
(currentProvider?.requiresApiKey && providerCredentials.length === 0 && !addingKey) ||
|
|
@@ -371,7 +382,7 @@ export function AgentSheet() {
|
|
|
371
382
|
return
|
|
372
383
|
}
|
|
373
384
|
if (openclawEnabled) return
|
|
374
|
-
if (!AUTO_SYNC_MODEL_PROVIDER_IDS.has(provider)) return
|
|
385
|
+
if (!AUTO_SYNC_MODEL_PROVIDER_IDS.has(provider as ProviderType)) return
|
|
375
386
|
if (!currentProvider?.supportsModelDiscovery) return
|
|
376
387
|
|
|
377
388
|
const requiresCredential = currentProvider.requiresApiKey || (provider === 'ollama' && ollamaMode === 'cloud')
|
|
@@ -388,6 +399,7 @@ export function AgentSheet() {
|
|
|
388
399
|
if (open) {
|
|
389
400
|
loadSettings()
|
|
390
401
|
loadProviders()
|
|
402
|
+
loadProviderConfigs()
|
|
391
403
|
loadGatewayProfiles()
|
|
392
404
|
loadCredentials()
|
|
393
405
|
loadSkills()
|
|
@@ -435,7 +447,7 @@ export function AgentSheet() {
|
|
|
435
447
|
}))
|
|
436
448
|
setOpenclawEnabled(editing.provider === 'openclaw')
|
|
437
449
|
setProjectId(editing.projectId)
|
|
438
|
-
setAvatarSeed(editing.avatarSeed ||
|
|
450
|
+
setAvatarSeed(editing.avatarSeed || Math.random().toString(36).slice(2, 10))
|
|
439
451
|
setAvatarUrl(editing.avatarUrl || null)
|
|
440
452
|
setThinkingLevel(editing.thinkingLevel || '')
|
|
441
453
|
setMemoryScopeMode(editing.memoryScopeMode || 'auto')
|
|
@@ -515,7 +527,7 @@ export function AgentSheet() {
|
|
|
515
527
|
}))
|
|
516
528
|
setOpenclawEnabled(src.provider === 'openclaw')
|
|
517
529
|
setProjectId(src.projectId)
|
|
518
|
-
setAvatarSeed(
|
|
530
|
+
setAvatarSeed(Math.random().toString(36).slice(2, 10))
|
|
519
531
|
setAvatarUrl(null)
|
|
520
532
|
setThinkingLevel(src.thinkingLevel || '')
|
|
521
533
|
setMemoryScopeMode(src.memoryScopeMode || 'auto')
|
|
@@ -637,7 +649,7 @@ export function AgentSheet() {
|
|
|
637
649
|
setModel(currentProvider.models[0])
|
|
638
650
|
}
|
|
639
651
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
640
|
-
}, [provider,
|
|
652
|
+
}, [provider, agentSelectableProviders])
|
|
641
653
|
|
|
642
654
|
// Reset test status when connection params change
|
|
643
655
|
useEffect(() => {
|
|
@@ -713,7 +725,7 @@ export function AgentSheet() {
|
|
|
713
725
|
|
|
714
726
|
const addRoutingTargetFromCurrent = () => {
|
|
715
727
|
const nextTarget: AgentRoutingTarget = {
|
|
716
|
-
id:
|
|
728
|
+
id: Math.random().toString(16).slice(2, 10),
|
|
717
729
|
label: routingTargets.length === 0 ? 'Primary route' : `Route ${routingTargets.length + 1}`,
|
|
718
730
|
role: routingTargets.length === 0 ? 'primary' : 'backup',
|
|
719
731
|
provider,
|
|
@@ -873,13 +885,18 @@ export function AgentSheet() {
|
|
|
873
885
|
|
|
874
886
|
const handleExport = () => {
|
|
875
887
|
if (!editing) return
|
|
888
|
+
const recommendedProviders = agentSelectableProviders.some((providerOption) => (
|
|
889
|
+
providerOption.id === editing.provider && providerOption.type === 'builtin'
|
|
890
|
+
))
|
|
891
|
+
? [editing.provider as ProviderType]
|
|
892
|
+
: undefined
|
|
876
893
|
const pack: AgentPackManifest = {
|
|
877
894
|
schemaVersion: 1,
|
|
878
895
|
kind: 'swarmclaw-agent-pack',
|
|
879
896
|
name: `${editing.name} Pack`,
|
|
880
897
|
description: editing.description || undefined,
|
|
881
898
|
exportedAt: Date.now(),
|
|
882
|
-
recommendedProviders
|
|
899
|
+
recommendedProviders,
|
|
883
900
|
agents: [{
|
|
884
901
|
id: editing.name.replace(/\s+/g, '-').toLowerCase(),
|
|
885
902
|
name: editing.name,
|
|
@@ -1148,7 +1165,7 @@ export function AgentSheet() {
|
|
|
1148
1165
|
type="button"
|
|
1149
1166
|
onClick={() => {
|
|
1150
1167
|
setAvatarUrl(null)
|
|
1151
|
-
if (!avatarSeed) setAvatarSeed(
|
|
1168
|
+
if (!avatarSeed) setAvatarSeed(Math.random().toString(36).slice(2, 10))
|
|
1152
1169
|
}}
|
|
1153
1170
|
className="text-[11px] text-text-3 hover:text-red-400 transition-colors self-start cursor-pointer"
|
|
1154
1171
|
>
|
|
@@ -1169,7 +1186,7 @@ export function AgentSheet() {
|
|
|
1169
1186
|
/>
|
|
1170
1187
|
<button
|
|
1171
1188
|
type="button"
|
|
1172
|
-
onClick={() => { setAvatarSeed(
|
|
1189
|
+
onClick={() => { setAvatarSeed(Math.random().toString(36).slice(2, 10)); setAvatarUrl(null) }}
|
|
1173
1190
|
className="inline-flex items-center gap-1.5 px-3 py-2 rounded-[10px] border border-white/[0.08] bg-transparent text-text-3 text-[12px] font-600 cursor-pointer transition-all hover:bg-white/[0.04] hover:text-text-2 active:scale-95 shrink-0"
|
|
1174
1191
|
style={{ fontFamily: 'inherit' }}
|
|
1175
1192
|
title="Shuffle avatar"
|
|
@@ -1213,7 +1230,7 @@ export function AgentSheet() {
|
|
|
1213
1230
|
if (!apiEndpoint) setApiEndpoint('http://localhost:18789')
|
|
1214
1231
|
} else {
|
|
1215
1232
|
setOpenclawEnabled(false)
|
|
1216
|
-
const first =
|
|
1233
|
+
const first = agentSelectableProviders[0]?.id || 'claude-cli'
|
|
1217
1234
|
setProvider(first)
|
|
1218
1235
|
setModel('')
|
|
1219
1236
|
setApiEndpoint(null)
|
|
@@ -1445,13 +1462,17 @@ export function AgentSheet() {
|
|
|
1445
1462
|
{!openclawEnabled && <div className="mb-8">
|
|
1446
1463
|
<SectionLabel>Provider</SectionLabel>
|
|
1447
1464
|
<div className="grid grid-cols-3 gap-3">
|
|
1448
|
-
{
|
|
1449
|
-
const
|
|
1465
|
+
{agentSelectableProviders.map((p) => {
|
|
1466
|
+
const nextCredentials = resolveAgentSelectableProviderCredentials(p.id, credentials, providerConfigs)
|
|
1467
|
+
const isConnected = !p.requiresApiKey || nextCredentials.length > 0
|
|
1450
1468
|
return (
|
|
1451
1469
|
<button
|
|
1452
1470
|
key={p.id}
|
|
1453
1471
|
onClick={() => {
|
|
1454
1472
|
setProvider(p.id)
|
|
1473
|
+
if (!nextCredentials.some((item) => item.id === credentialId)) {
|
|
1474
|
+
setCredentialId(nextCredentials[0]?.id || null)
|
|
1475
|
+
}
|
|
1455
1476
|
setGatewayProfileId(null)
|
|
1456
1477
|
}}
|
|
1457
1478
|
className={`relative py-3.5 px-4 rounded-[14px] text-center cursor-pointer transition-all duration-200
|
|
@@ -2161,7 +2182,7 @@ export function AgentSheet() {
|
|
|
2161
2182
|
</div>
|
|
2162
2183
|
<div className="space-y-3">
|
|
2163
2184
|
{routingTargets.map((target, index) => {
|
|
2164
|
-
const targetCredentials =
|
|
2185
|
+
const targetCredentials = resolveAgentSelectableProviderCredentials(target.provider, credentials, providerConfigs)
|
|
2165
2186
|
return (
|
|
2166
2187
|
<div key={target.id} className="p-4 rounded-[12px] border border-white/[0.08] bg-white/[0.02] space-y-3">
|
|
2167
2188
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
|
|
@@ -2182,19 +2203,24 @@ export function AgentSheet() {
|
|
|
2182
2203
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
|
|
2183
2204
|
<select
|
|
2184
2205
|
value={target.provider}
|
|
2185
|
-
onChange={(e) =>
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2206
|
+
onChange={(e) => {
|
|
2207
|
+
const nextProviderId = e.target.value
|
|
2208
|
+
const nextCredentials = resolveAgentSelectableProviderCredentials(nextProviderId, credentials, providerConfigs)
|
|
2209
|
+
updateRoutingTarget(target.id, {
|
|
2210
|
+
provider: nextProviderId,
|
|
2211
|
+
credentialId: nextCredentials[0]?.id || null,
|
|
2212
|
+
gatewayProfileId: nextProviderId === 'openclaw' ? target.gatewayProfileId : null,
|
|
2213
|
+
ollamaMode: nextProviderId === 'ollama'
|
|
2189
2214
|
? resolveStoredOllamaMode({
|
|
2190
2215
|
ollamaMode: target.ollamaMode ?? null,
|
|
2191
2216
|
apiEndpoint: target.apiEndpoint ?? null,
|
|
2192
2217
|
})
|
|
2193
2218
|
: null,
|
|
2194
|
-
|
|
2219
|
+
})
|
|
2220
|
+
}}
|
|
2195
2221
|
className={inputClass}
|
|
2196
2222
|
>
|
|
2197
|
-
{
|
|
2223
|
+
{agentSelectableProviders.map((item) => (
|
|
2198
2224
|
<option key={item.id} value={item.id}>{item.name}</option>
|
|
2199
2225
|
))}
|
|
2200
2226
|
</select>
|
|
@@ -26,6 +26,7 @@ import { ModelCombobox } from '@/components/shared/model-combobox'
|
|
|
26
26
|
import { buildOpenClawMainSessionKey } from '@/lib/openclaw/openclaw-agent-id'
|
|
27
27
|
import { StructuredSessionLauncher } from '@/components/protocols/structured-session-launcher'
|
|
28
28
|
import { useWs } from '@/hooks/use-ws'
|
|
29
|
+
import { buildAgentSelectableProviders } from '@/lib/agent-provider-options'
|
|
29
30
|
|
|
30
31
|
interface Props {
|
|
31
32
|
agent: Agent
|
|
@@ -61,17 +62,27 @@ const PROVIDER_LABELS: Record<string, string> = {
|
|
|
61
62
|
function ModelSwitcherInline({ session, agent }: { session: Session; agent: Agent }) {
|
|
62
63
|
const providers = useAppStore((s) => s.providers)
|
|
63
64
|
const loadProviders = useAppStore((s) => s.loadProviders)
|
|
65
|
+
const providerConfigs = useAppStore((s) => s.providerConfigs)
|
|
66
|
+
const loadProviderConfigs = useAppStore((s) => s.loadProviderConfigs)
|
|
64
67
|
const refreshSession = useAppStore((s) => s.refreshSession)
|
|
65
68
|
const streaming = useChatStore((s) => s.streaming)
|
|
66
69
|
const [expanded, setExpanded] = useState(false)
|
|
67
70
|
const [selectedProvider, setSelectedProvider] = useState(agent.provider)
|
|
68
71
|
const [saving, setSaving] = useState(false)
|
|
69
72
|
|
|
70
|
-
useEffect(() => {
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
void loadProviders()
|
|
75
|
+
void loadProviderConfigs()
|
|
76
|
+
}, [loadProviderConfigs, loadProviders])
|
|
71
77
|
useEffect(() => { setSelectedProvider(agent.provider) }, [agent.provider])
|
|
72
78
|
|
|
73
|
-
const
|
|
74
|
-
|
|
79
|
+
const agentSelectableProviders = useMemo(
|
|
80
|
+
() => buildAgentSelectableProviders(providers, providerConfigs),
|
|
81
|
+
[providerConfigs, providers],
|
|
82
|
+
)
|
|
83
|
+
const currentProviderInfo = agentSelectableProviders.find((p) => p.id === selectedProvider)
|
|
84
|
+
const activeAgentProvider = agentSelectableProviders.find((p) => p.id === agent.provider)
|
|
85
|
+
const providerLabel = PROVIDER_LABELS[agent.provider] || activeAgentProvider?.name || agent.provider.replace(/-/g, ' ')
|
|
75
86
|
|
|
76
87
|
const handleModelChange = async (model: string) => {
|
|
77
88
|
if (saving) return
|
|
@@ -122,7 +133,7 @@ function ModelSwitcherInline({ session, agent }: { session: Session; agent: Agen
|
|
|
122
133
|
</button>
|
|
123
134
|
</div>
|
|
124
135
|
<div className="flex flex-wrap gap-1 mb-2">
|
|
125
|
-
{
|
|
136
|
+
{agentSelectableProviders.filter((p) => p.models.length > 0).map((p) => (
|
|
126
137
|
<button
|
|
127
138
|
key={p.id}
|
|
128
139
|
type="button"
|
|
@@ -4,7 +4,7 @@ import { useMemo, useState } from 'react'
|
|
|
4
4
|
import { api } from '@/lib/app/api-client'
|
|
5
5
|
import { useAppStore } from '@/stores/use-app-store'
|
|
6
6
|
import { dedup, errorMessage } from '@/lib/shared-utils'
|
|
7
|
-
import type {
|
|
7
|
+
import type { ProviderId, GatewayProfile } from '@/types'
|
|
8
8
|
import {
|
|
9
9
|
SETUP_PROVIDERS,
|
|
10
10
|
SWARMCLAW_ASSISTANT_PROMPT,
|
|
@@ -21,7 +21,7 @@ import type {
|
|
|
21
21
|
ProviderCheckResponse,
|
|
22
22
|
} from './types'
|
|
23
23
|
import { STEP_ORDER } from './types'
|
|
24
|
-
import { stepIndex } from './utils'
|
|
24
|
+
import { requiresSetupProviderVerification, stepIndex } from './utils'
|
|
25
25
|
import { SparkleIcon } from './shared'
|
|
26
26
|
import { StepProgress } from './step-progress'
|
|
27
27
|
import { StepProviders } from './step-providers'
|
|
@@ -53,7 +53,7 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
53
53
|
[editingProviderId, configuredProviders],
|
|
54
54
|
)
|
|
55
55
|
const totalSteps = STEP_ORDER.length
|
|
56
|
-
const configuredProviderIds = new Set(configuredProviders.map((cp) => cp.
|
|
56
|
+
const configuredProviderIds = new Set(configuredProviders.map((cp) => cp.setupProvider))
|
|
57
57
|
const canContinueFromProviders = configuredProviders.length > 0
|
|
58
58
|
|
|
59
59
|
const skip = async () => {
|
|
@@ -76,7 +76,7 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
76
76
|
|
|
77
77
|
const selectProvider = (nextProvider: SetupProvider) => {
|
|
78
78
|
const meta = SETUP_PROVIDERS.find((candidate) => candidate.id === nextProvider)
|
|
79
|
-
const existing = configuredProviders.find((cp) => cp.
|
|
79
|
+
const existing = configuredProviders.find((cp) => cp.setupProvider === nextProvider)
|
|
80
80
|
setActiveProvider(nextProvider)
|
|
81
81
|
setEditingProviderId(existing?.id || null)
|
|
82
82
|
setActiveProviderLabel(existing?.name || meta?.name || '')
|
|
@@ -94,6 +94,7 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
94
94
|
return {
|
|
95
95
|
...draft,
|
|
96
96
|
providerConfigId: fallback?.id || null,
|
|
97
|
+
setupProvider: fallback?.setupProvider || null,
|
|
97
98
|
provider: fallback?.provider || null,
|
|
98
99
|
credentialId: fallback?.credentialId || null,
|
|
99
100
|
apiEndpoint: fallback?.endpoint || null,
|
|
@@ -118,13 +119,14 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
118
119
|
if (!editingProviderId && draftAgents.length === 0) {
|
|
119
120
|
const cp = configured
|
|
120
121
|
setDraftAgents([{
|
|
121
|
-
id: `auto:${
|
|
122
|
+
id: `auto:${Math.random().toString(36).slice(2, 10)}`,
|
|
122
123
|
templateId: 'auto',
|
|
123
124
|
name: 'Assistant',
|
|
124
125
|
description: 'A helpful assistant.',
|
|
125
126
|
systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
|
|
126
127
|
soul: '',
|
|
127
128
|
providerConfigId: cp.id,
|
|
129
|
+
setupProvider: cp.setupProvider,
|
|
128
130
|
provider: cp.provider,
|
|
129
131
|
model: cp.defaultModel,
|
|
130
132
|
credentialId: cp.credentialId,
|
|
@@ -138,7 +140,7 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
138
140
|
autoDraftSkillSuggestions: true,
|
|
139
141
|
orchestratorEnabled: false,
|
|
140
142
|
orchestratorMission: '',
|
|
141
|
-
avatarSeed:
|
|
143
|
+
avatarSeed: Math.random().toString(36).slice(2, 10),
|
|
142
144
|
avatarUrl: null,
|
|
143
145
|
enabled: true,
|
|
144
146
|
}])
|
|
@@ -149,6 +151,7 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
149
151
|
if (draft.providerConfigId !== editingProviderId) return draft
|
|
150
152
|
return {
|
|
151
153
|
...draft,
|
|
154
|
+
setupProvider: configured.setupProvider,
|
|
152
155
|
provider: configured.provider,
|
|
153
156
|
credentialId: configured.credentialId,
|
|
154
157
|
apiEndpoint: configured.endpoint,
|
|
@@ -179,13 +182,14 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
179
182
|
const addBlankAgent = () => {
|
|
180
183
|
const defaultProvider = configuredProviders[0] || null
|
|
181
184
|
const newAgent: StarterDraftAgent = {
|
|
182
|
-
id: `custom:${
|
|
185
|
+
id: `custom:${Math.random().toString(36).slice(2, 10)}`,
|
|
183
186
|
templateId: 'custom',
|
|
184
187
|
name: `Agent ${draftAgents.length + 1}`,
|
|
185
188
|
description: '',
|
|
186
189
|
systemPrompt: '',
|
|
187
190
|
soul: '',
|
|
188
191
|
providerConfigId: defaultProvider?.id || null,
|
|
192
|
+
setupProvider: defaultProvider?.setupProvider || null,
|
|
189
193
|
provider: defaultProvider?.provider || null,
|
|
190
194
|
model: defaultProvider?.defaultModel || '',
|
|
191
195
|
credentialId: defaultProvider?.credentialId || null,
|
|
@@ -199,7 +203,7 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
199
203
|
autoDraftSkillSuggestions: true,
|
|
200
204
|
orchestratorEnabled: false,
|
|
201
205
|
orchestratorMission: '',
|
|
202
|
-
avatarSeed:
|
|
206
|
+
avatarSeed: Math.random().toString(36).slice(2, 10),
|
|
203
207
|
avatarUrl: null,
|
|
204
208
|
enabled: true,
|
|
205
209
|
}
|
|
@@ -224,13 +228,14 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
224
228
|
|
|
225
229
|
setDraftAgents((current) => current.map((draft) => {
|
|
226
230
|
if (draft.id !== id) return draft
|
|
227
|
-
const previousDefault = draft.
|
|
231
|
+
const previousDefault = draft.setupProvider ? getDefaultModelForProvider(draft.setupProvider) : ''
|
|
228
232
|
const nextModel = !draft.model || draft.model === previousDefault
|
|
229
233
|
? configuredProvider.defaultModel
|
|
230
234
|
: draft.model
|
|
231
235
|
return {
|
|
232
236
|
...draft,
|
|
233
237
|
providerConfigId: configuredProvider.id,
|
|
238
|
+
setupProvider: configuredProvider.setupProvider,
|
|
234
239
|
provider: configuredProvider.provider,
|
|
235
240
|
credentialId: configuredProvider.credentialId,
|
|
236
241
|
apiEndpoint: configuredProvider.endpoint,
|
|
@@ -246,6 +251,10 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
246
251
|
setError('Every enabled agent needs a provider assignment before you continue.')
|
|
247
252
|
return
|
|
248
253
|
}
|
|
254
|
+
if (enabledDrafts.some((draft) => draft.setupProvider === 'custom' && !draft.model.trim())) {
|
|
255
|
+
setError('Every custom-provider agent needs a model before you continue.')
|
|
256
|
+
return
|
|
257
|
+
}
|
|
249
258
|
|
|
250
259
|
setSaving(true)
|
|
251
260
|
setError('')
|
|
@@ -254,12 +263,12 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
254
263
|
const checkedCombos = new Map<string, ProviderCheckResponse>()
|
|
255
264
|
for (const draft of enabledDrafts) {
|
|
256
265
|
const cp = configuredProviders.find((c) => c.id === draft.providerConfigId)
|
|
257
|
-
if (!cp || cp.
|
|
258
|
-
const comboKey = `${cp.
|
|
266
|
+
if (!cp || !requiresSetupProviderVerification(cp.setupProvider)) continue
|
|
267
|
+
const comboKey = `${cp.setupProvider}|${draft.apiEndpoint || cp.endpoint || ''}|${draft.model}`
|
|
259
268
|
if (checkedCombos.has(comboKey)) continue
|
|
260
269
|
try {
|
|
261
270
|
const result = await api<ProviderCheckResponse>('POST', '/setup/check-provider', {
|
|
262
|
-
provider: cp.
|
|
271
|
+
provider: cp.setupProvider,
|
|
263
272
|
credentialId: cp.credentialId || undefined,
|
|
264
273
|
endpoint: draft.apiEndpoint || cp.endpoint || undefined,
|
|
265
274
|
model: draft.model || undefined,
|
|
@@ -276,7 +285,7 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
276
285
|
}
|
|
277
286
|
|
|
278
287
|
const gatewayProfileIdsByProviderConfig = new Map<string, string>()
|
|
279
|
-
const openClawProviders = configuredProviders.filter((candidate) => candidate.
|
|
288
|
+
const openClawProviders = configuredProviders.filter((candidate) => candidate.setupProvider === 'openclaw')
|
|
280
289
|
if (openClawProviders.length > 0) {
|
|
281
290
|
const existingGateways = await api<GatewayProfile[]>('GET', '/gateways')
|
|
282
291
|
let shouldCreateDefault = existingGateways.length === 0
|
|
@@ -322,8 +331,8 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
322
331
|
description: draft.description.trim(),
|
|
323
332
|
systemPrompt: draft.systemPrompt.trim(),
|
|
324
333
|
soul: draft.soul.trim() || undefined,
|
|
325
|
-
provider: draft.provider
|
|
326
|
-
model: draft.model.trim() || getDefaultModelForProvider(draft.
|
|
334
|
+
provider: draft.provider,
|
|
335
|
+
model: draft.model.trim() || (draft.setupProvider ? getDefaultModelForProvider(draft.setupProvider) : ''),
|
|
327
336
|
credentialId: draft.credentialId || null,
|
|
328
337
|
tools: draft.tools,
|
|
329
338
|
capabilities: draft.capabilities,
|
|
@@ -355,7 +364,7 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
355
364
|
}
|
|
356
365
|
|
|
357
366
|
// Push soul and identity files to the OpenClaw gateway (non-fatal)
|
|
358
|
-
if (draft.
|
|
367
|
+
if (draft.setupProvider === 'openclaw') {
|
|
359
368
|
try {
|
|
360
369
|
if (draft.soul.trim()) {
|
|
361
370
|
await api('PUT', '/openclaw/agent-files', { agentId, filename: 'SOUL.md', content: draft.soul.trim() })
|
|
@@ -373,8 +382,8 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
373
382
|
created.push({
|
|
374
383
|
id: agentId,
|
|
375
384
|
name: draft.name.trim(),
|
|
376
|
-
provider: draft.provider as
|
|
377
|
-
providerName: configuredProviders.find((candidate) => candidate.id === draft.providerConfigId)?.name || draft.provider
|
|
385
|
+
provider: draft.provider as ProviderId,
|
|
386
|
+
providerName: configuredProviders.find((candidate) => candidate.id === draft.providerConfigId)?.name || String(draft.provider || ''),
|
|
378
387
|
})
|
|
379
388
|
}
|
|
380
389
|
|
|
@@ -69,10 +69,10 @@ export function ConfiguredProviderChips({
|
|
|
69
69
|
{formatEndpointHost(cp.endpoint)
|
|
70
70
|
? `· ${formatEndpointHost(cp.endpoint)}`
|
|
71
71
|
: ''}
|
|
72
|
-
{cp.
|
|
72
|
+
{cp.setupProvider === 'openclaw' && cp.deployment?.useCase
|
|
73
73
|
? ` · ${OPENCLAW_USE_CASE_LABELS[cp.deployment.useCase]}`
|
|
74
74
|
: ''}
|
|
75
|
-
{cp.
|
|
75
|
+
{cp.setupProvider === 'openclaw' && cp.deployment?.exposure
|
|
76
76
|
? ` · ${OPENCLAW_EXPOSURE_LABELS[cp.deployment.exposure]}`
|
|
77
77
|
: ''}
|
|
78
78
|
{cp.defaultModel ? ` · ${cp.defaultModel}` : ''}
|
|
@@ -36,9 +36,10 @@ function ModelCombobox({
|
|
|
36
36
|
const fetched = useRef<string | null>(null)
|
|
37
37
|
|
|
38
38
|
const effectiveEndpoint = endpointOverride || provider?.endpoint || null
|
|
39
|
+
const supportsModelDiscovery = Boolean(provider && provider.setupProvider !== 'custom')
|
|
39
40
|
|
|
40
41
|
const fetchModels = useCallback(async (force?: boolean) => {
|
|
41
|
-
if (!provider) return
|
|
42
|
+
if (!provider || !supportsModelDiscovery) return
|
|
42
43
|
const cacheKey = `${provider.provider}|${effectiveEndpoint || ''}|${provider.credentialId || ''}`
|
|
43
44
|
if (!force && fetched.current === cacheKey) return
|
|
44
45
|
fetched.current = cacheKey
|
|
@@ -63,11 +64,21 @@ function ModelCombobox({
|
|
|
63
64
|
} finally {
|
|
64
65
|
setLoading(false)
|
|
65
66
|
}
|
|
66
|
-
}, [provider, effectiveEndpoint])
|
|
67
|
+
}, [provider, effectiveEndpoint, supportsModelDiscovery])
|
|
67
68
|
|
|
68
69
|
useEffect(() => {
|
|
70
|
+
if (!provider) {
|
|
71
|
+
setModels([])
|
|
72
|
+
setFetchError('')
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
if (!supportsModelDiscovery) {
|
|
76
|
+
setModels(provider.defaultModel ? [provider.defaultModel] : [])
|
|
77
|
+
setFetchError('')
|
|
78
|
+
return
|
|
79
|
+
}
|
|
69
80
|
fetchModels()
|
|
70
|
-
}, [fetchModels])
|
|
81
|
+
}, [fetchModels, provider, supportsModelDiscovery])
|
|
71
82
|
|
|
72
83
|
// Close dropdown on outside click
|
|
73
84
|
useEffect(() => {
|
|
@@ -116,38 +127,40 @@ function ModelCombobox({
|
|
|
116
127
|
</svg>
|
|
117
128
|
</a>
|
|
118
129
|
)}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
<
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
<
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
<
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
130
|
+
{supportsModelDiscovery && (
|
|
131
|
+
<button
|
|
132
|
+
type="button"
|
|
133
|
+
onClick={() => {
|
|
134
|
+
if (models.length > 0 && !loading) {
|
|
135
|
+
setOpen(!open)
|
|
136
|
+
if (!open) setSearch(value)
|
|
137
|
+
} else {
|
|
138
|
+
fetchModels(true)
|
|
139
|
+
}
|
|
140
|
+
}}
|
|
141
|
+
disabled={loading}
|
|
142
|
+
className="text-text-3 hover:text-accent-bright transition-colors bg-transparent border-none cursor-pointer disabled:opacity-40"
|
|
143
|
+
title={models.length > 0 ? 'Show models' : 'Fetch available models'}
|
|
144
|
+
>
|
|
145
|
+
{loading ? (
|
|
146
|
+
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" className="animate-spin">
|
|
147
|
+
<circle cx="7" cy="7" r="5.5" stroke="currentColor" strokeWidth="1.5" opacity="0.25" />
|
|
148
|
+
<path d="M12.5 7A5.5 5.5 0 0 0 7 1.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />
|
|
149
|
+
</svg>
|
|
150
|
+
) : models.length > 0 ? (
|
|
151
|
+
<svg width="12" height="12" viewBox="0 0 12 12" fill="none">
|
|
152
|
+
<path d="M3 4.5L6 7.5L9 4.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
153
|
+
</svg>
|
|
154
|
+
) : (
|
|
155
|
+
<svg width="14" height="14" viewBox="0 0 14 14" fill="none">
|
|
156
|
+
<path d="M1.5 7A5.5 5.5 0 1 1 7 12.5" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" />
|
|
157
|
+
<path d="M1.5 12.5V9.5H4.5" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round" />
|
|
158
|
+
</svg>
|
|
159
|
+
)}
|
|
160
|
+
</button>
|
|
161
|
+
)}
|
|
149
162
|
</div>
|
|
150
|
-
{fetchError && models.length === 0 && (
|
|
163
|
+
{fetchError && models.length === 0 && supportsModelDiscovery && (
|
|
151
164
|
<div className="mt-1 text-[11px] text-amber-300/80">{fetchError}</div>
|
|
152
165
|
)}
|
|
153
166
|
{open && filtered.length > 0 && (
|
|
@@ -348,7 +361,7 @@ export function StepAgents({
|
|
|
348
361
|
/>
|
|
349
362
|
<button
|
|
350
363
|
type="button"
|
|
351
|
-
onClick={() => onUpdateDraft(draft.id, { avatarSeed:
|
|
364
|
+
onClick={() => onUpdateDraft(draft.id, { avatarSeed: Math.random().toString(36).slice(2, 10), avatarUrl: null })}
|
|
352
365
|
className="inline-flex items-center gap-1.5 px-3 py-2 rounded-[10px] border border-white/[0.08] bg-transparent text-text-3 text-[12px] font-600 cursor-pointer transition-all hover:bg-white/[0.04] hover:text-text-2 active:scale-95 shrink-0"
|
|
353
366
|
title="Shuffle avatar"
|
|
354
367
|
>
|
|
@@ -423,7 +436,7 @@ export function StepAgents({
|
|
|
423
436
|
focus:border-accent-bright/30 focus:shadow-[0_0_30px_rgba(99,102,241,0.1)]"
|
|
424
437
|
/>
|
|
425
438
|
</div>
|
|
426
|
-
{matchedProvider?.
|
|
439
|
+
{matchedProvider?.setupProvider === 'openclaw' ? (
|
|
427
440
|
<div className="md:col-span-2">
|
|
428
441
|
<label className="block text-[12px] text-text-3 font-500 mb-1.5 ml-1">Model</label>
|
|
429
442
|
<div className="flex items-center gap-3 px-4 py-3 rounded-[12px] border border-white/[0.08] bg-bg">
|
|
@@ -448,7 +461,7 @@ export function StepAgents({
|
|
|
448
461
|
provider={matchedProvider}
|
|
449
462
|
endpointOverride={draft.apiEndpoint}
|
|
450
463
|
onChange={(model) => onUpdateDraft(draft.id, { model })}
|
|
451
|
-
modelLibraryUrl={matchedProvider ? SETUP_PROVIDERS.find((sp) => sp.id === matchedProvider.
|
|
464
|
+
modelLibraryUrl={matchedProvider ? SETUP_PROVIDERS.find((sp) => sp.id === matchedProvider.setupProvider)?.modelLibraryUrl : null}
|
|
452
465
|
/>
|
|
453
466
|
</div>
|
|
454
467
|
)}
|
|
@@ -457,7 +470,7 @@ export function StepAgents({
|
|
|
457
470
|
value={draft.soul}
|
|
458
471
|
onChange={(soul) => onUpdateDraft(draft.id, { soul })}
|
|
459
472
|
/>
|
|
460
|
-
{matchedProvider?.
|
|
473
|
+
{matchedProvider?.setupProvider === 'openclaw' && (
|
|
461
474
|
<p className="mt-1.5 ml-1 text-[11px] text-text-3/70">
|
|
462
475
|
Synced to the gateway as SOUL.md on save.
|
|
463
476
|
</p>
|