@swarmclawai/swarmclaw 0.6.4 → 0.6.7
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 +62 -30
- package/package.json +10 -1
- package/src/app/api/agents/[id]/clone/route.ts +40 -0
- package/src/app/api/agents/route.ts +39 -14
- package/src/app/api/chatrooms/[id]/chat/route.ts +58 -3
- package/src/app/api/chatrooms/[id]/moderate/route.ts +150 -0
- package/src/app/api/chatrooms/[id]/route.ts +34 -2
- package/src/app/api/chatrooms/route.ts +26 -3
- package/src/app/api/connectors/[id]/health/route.ts +64 -0
- package/src/app/api/connectors/route.ts +17 -2
- package/src/app/api/knowledge/route.ts +6 -1
- package/src/app/api/openclaw/doctor/route.ts +17 -0
- package/src/app/api/schedules/[id]/run/route.ts +3 -0
- package/src/app/api/sessions/[id]/chat/route.ts +5 -1
- package/src/app/api/sessions/route.ts +11 -2
- package/src/app/api/tasks/[id]/route.ts +18 -13
- package/src/app/api/tasks/route.ts +44 -1
- package/src/app/api/usage/route.ts +16 -7
- package/src/app/api/wallets/[id]/approve/route.ts +62 -0
- package/src/app/api/wallets/[id]/balance-history/route.ts +18 -0
- package/src/app/api/wallets/[id]/route.ts +118 -0
- package/src/app/api/wallets/[id]/send/route.ts +118 -0
- package/src/app/api/wallets/[id]/transactions/route.ts +18 -0
- package/src/app/api/wallets/route.ts +74 -0
- package/src/app/globals.css +8 -0
- package/src/cli/index.js +20 -0
- package/src/cli/index.ts +223 -39
- package/src/cli/spec.js +14 -0
- package/src/components/agents/agent-avatar.tsx +15 -1
- package/src/components/agents/agent-card.tsx +38 -6
- package/src/components/agents/agent-chat-list.tsx +79 -3
- package/src/components/agents/agent-sheet.tsx +191 -26
- package/src/components/auth/setup-wizard.tsx +268 -353
- package/src/components/chat/chat-area.tsx +24 -9
- package/src/components/chat/chat-header.tsx +48 -19
- package/src/components/chat/chat-tool-toggles.tsx +1 -1
- package/src/components/chat/delegation-banner.test.ts +27 -0
- package/src/components/chat/delegation-banner.tsx +109 -23
- package/src/components/chat/message-bubble.tsx +17 -16
- package/src/components/chat/message-list.tsx +6 -5
- package/src/components/chat/streaming-bubble.tsx +3 -2
- package/src/components/chat/thinking-indicator.tsx +3 -2
- package/src/components/chat/transfer-agent-picker.tsx +1 -1
- package/src/components/chatrooms/agent-hover-card.tsx +1 -1
- package/src/components/chatrooms/chatroom-input.tsx +1 -1
- package/src/components/chatrooms/chatroom-message.tsx +165 -23
- package/src/components/chatrooms/chatroom-sheet.tsx +289 -4
- package/src/components/chatrooms/chatroom-typing-bar.tsx +1 -1
- package/src/components/chatrooms/chatroom-view.tsx +62 -17
- package/src/components/connectors/connector-health.tsx +120 -0
- package/src/components/connectors/connector-list.tsx +1 -1
- package/src/components/connectors/connector-sheet.tsx +9 -0
- package/src/components/home/home-view.tsx +25 -3
- package/src/components/input/chat-input.tsx +8 -1
- package/src/components/knowledge/knowledge-list.tsx +1 -1
- package/src/components/knowledge/knowledge-sheet.tsx +1 -1
- package/src/components/layout/app-layout.tsx +35 -4
- package/src/components/memory/memory-agent-list.tsx +1 -1
- package/src/components/memory/memory-browser.tsx +1 -0
- package/src/components/memory/memory-card.tsx +3 -2
- package/src/components/memory/memory-detail.tsx +3 -3
- package/src/components/memory/memory-sheet.tsx +2 -2
- package/src/components/projects/project-detail.tsx +4 -4
- package/src/components/schedules/schedule-list.tsx +55 -9
- package/src/components/schedules/schedule-sheet.tsx +134 -23
- package/src/components/secrets/secret-sheet.tsx +1 -1
- package/src/components/secrets/secrets-list.tsx +1 -1
- package/src/components/sessions/session-card.tsx +1 -1
- package/src/components/shared/agent-picker-list.tsx +1 -1
- package/src/components/shared/agent-switch-dialog.tsx +1 -1
- package/src/components/shared/command-palette.tsx +237 -0
- package/src/components/shared/connector-platform-icon.tsx +1 -0
- package/src/components/shared/settings/section-user-preferences.tsx +4 -4
- package/src/components/skills/skill-list.tsx +1 -1
- package/src/components/skills/skill-sheet.tsx +1 -1
- package/src/components/tasks/task-board.tsx +3 -3
- package/src/components/tasks/task-card.tsx +22 -2
- package/src/components/tasks/task-sheet.tsx +112 -17
- package/src/components/usage/metrics-dashboard.tsx +13 -25
- package/src/components/wallets/wallet-approval-dialog.tsx +99 -0
- package/src/components/wallets/wallet-panel.tsx +616 -0
- package/src/components/wallets/wallet-section.tsx +100 -0
- package/src/hooks/use-swipe.ts +49 -0
- package/src/lib/providers/anthropic.ts +16 -2
- package/src/lib/providers/claude-cli.ts +7 -1
- package/src/lib/providers/index.ts +7 -0
- package/src/lib/providers/ollama.ts +16 -2
- package/src/lib/providers/openai.ts +7 -2
- package/src/lib/providers/openclaw.ts +6 -1
- package/src/lib/providers/provider-defaults.ts +7 -0
- package/src/lib/schedule-templates.ts +115 -0
- package/src/lib/server/agent-registry.ts +2 -2
- package/src/lib/server/alert-dispatch.ts +64 -0
- package/src/lib/server/chat-execution.ts +76 -4
- package/src/lib/server/chatroom-health.ts +60 -0
- package/src/lib/server/chatroom-helpers.test.ts +94 -0
- package/src/lib/server/chatroom-helpers.ts +86 -12
- package/src/lib/server/chatroom-routing.ts +65 -0
- package/src/lib/server/connectors/discord.ts +3 -0
- package/src/lib/server/connectors/email.ts +267 -0
- package/src/lib/server/connectors/inbound-audio-transcription.test.ts +191 -0
- package/src/lib/server/connectors/inbound-audio-transcription.ts +261 -0
- package/src/lib/server/connectors/manager.ts +239 -5
- package/src/lib/server/connectors/openclaw.ts +3 -0
- package/src/lib/server/connectors/slack.ts +6 -0
- package/src/lib/server/connectors/telegram.ts +18 -0
- package/src/lib/server/connectors/types.ts +2 -0
- package/src/lib/server/connectors/whatsapp-text.test.ts +29 -0
- package/src/lib/server/connectors/whatsapp-text.ts +26 -0
- package/src/lib/server/connectors/whatsapp.ts +17 -5
- package/src/lib/server/cost.ts +70 -0
- package/src/lib/server/create-notification.ts +2 -0
- package/src/lib/server/daemon-state.ts +124 -0
- package/src/lib/server/dag-validation.ts +115 -0
- package/src/lib/server/memory-db.ts +12 -7
- package/src/lib/server/openclaw-doctor.ts +48 -0
- package/src/lib/server/orchestrator-lg.ts +12 -2
- package/src/lib/server/orchestrator.ts +6 -1
- package/src/lib/server/queue-followups.test.ts +224 -0
- package/src/lib/server/queue.ts +238 -24
- package/src/lib/server/scheduler.ts +3 -0
- package/src/lib/server/session-run-manager.ts +22 -1
- package/src/lib/server/session-tools/chatroom.ts +11 -2
- package/src/lib/server/session-tools/context-mgmt.ts +2 -2
- package/src/lib/server/session-tools/index.ts +8 -2
- package/src/lib/server/session-tools/memory.ts +23 -4
- package/src/lib/server/session-tools/openclaw-workspace.ts +132 -0
- package/src/lib/server/session-tools/shell.ts +1 -1
- package/src/lib/server/session-tools/wallet.ts +124 -0
- package/src/lib/server/session-tools/web.ts +2 -2
- package/src/lib/server/solana.ts +122 -0
- package/src/lib/server/storage.ts +158 -6
- package/src/lib/server/stream-agent-chat.ts +126 -63
- package/src/lib/server/task-mention.test.ts +41 -0
- package/src/lib/server/task-mention.ts +3 -2
- package/src/lib/setup-defaults.ts +277 -0
- package/src/lib/tool-definitions.ts +1 -0
- package/src/lib/validation/schemas.ts +69 -0
- package/src/lib/view-routes.ts +1 -0
- package/src/stores/use-app-store.ts +15 -3
- package/src/stores/use-chatroom-store.ts +52 -2
- package/src/types/index.ts +98 -2
- package/tsconfig.json +2 -1
|
@@ -4,36 +4,14 @@ import { useMemo, useState } from 'react'
|
|
|
4
4
|
import { api } from '@/lib/api-client'
|
|
5
5
|
import { useAppStore } from '@/stores/use-app-store'
|
|
6
6
|
import type { ProviderType, Credential } from '@/types'
|
|
7
|
+
import {
|
|
8
|
+
SETUP_PROVIDERS,
|
|
9
|
+
DEFAULT_AGENTS,
|
|
10
|
+
type SetupProvider,
|
|
11
|
+
} from '@/lib/setup-defaults'
|
|
7
12
|
|
|
8
|
-
type WizardProvider =
|
|
9
|
-
| 'anthropic'
|
|
10
|
-
| 'openai'
|
|
11
|
-
| 'google'
|
|
12
|
-
| 'deepseek'
|
|
13
|
-
| 'groq'
|
|
14
|
-
| 'together'
|
|
15
|
-
| 'mistral'
|
|
16
|
-
| 'xai'
|
|
17
|
-
| 'fireworks'
|
|
18
|
-
| 'ollama'
|
|
19
|
-
| 'openclaw'
|
|
20
13
|
type CheckState = 'idle' | 'checking' | 'ok' | 'error'
|
|
21
14
|
|
|
22
|
-
interface WizardProviderOption {
|
|
23
|
-
id: WizardProvider
|
|
24
|
-
name: string
|
|
25
|
-
description: string
|
|
26
|
-
requiresKey: boolean
|
|
27
|
-
supportsEndpoint: boolean
|
|
28
|
-
defaultEndpoint?: string
|
|
29
|
-
keyUrl?: string
|
|
30
|
-
keyLabel?: string
|
|
31
|
-
keyPlaceholder?: string
|
|
32
|
-
optionalKey?: boolean
|
|
33
|
-
badge?: string
|
|
34
|
-
icon: string
|
|
35
|
-
}
|
|
36
|
-
|
|
37
15
|
interface ProviderCheckResponse {
|
|
38
16
|
ok: boolean
|
|
39
17
|
message: string
|
|
@@ -60,240 +38,11 @@ interface SetupWizardProps {
|
|
|
60
38
|
onComplete: () => void
|
|
61
39
|
}
|
|
62
40
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
'browser',
|
|
69
|
-
'manage_agents',
|
|
70
|
-
'manage_tasks',
|
|
71
|
-
'manage_schedules',
|
|
72
|
-
'manage_skills',
|
|
73
|
-
'manage_connectors',
|
|
74
|
-
'manage_sessions',
|
|
75
|
-
'manage_secrets',
|
|
76
|
-
'manage_documents',
|
|
77
|
-
'manage_webhooks',
|
|
78
|
-
'claude_code',
|
|
79
|
-
'codex_cli',
|
|
80
|
-
'opencode_cli',
|
|
81
|
-
]
|
|
82
|
-
|
|
83
|
-
const SWARMCLAW_ASSISTANT_PROMPT = `You are the default SwarmClaw assistant inside the SwarmClaw dashboard.
|
|
84
|
-
|
|
85
|
-
Primary objective:
|
|
86
|
-
- Help the user operate SwarmClaw itself before anything else.
|
|
87
|
-
|
|
88
|
-
When the user asks about SwarmClaw, prioritize concrete guidance with exact UI paths and commands:
|
|
89
|
-
- Sessions: create, configure provider/model, and run chats.
|
|
90
|
-
- Agents: create specialist agents/orchestrators, set provider/model, tools, and prompts.
|
|
91
|
-
- Providers: connect API keys/endpoints, troubleshoot auth/model issues.
|
|
92
|
-
- Tasks + Schedules: queue work and automate recurring runs.
|
|
93
|
-
- Skills + Connectors + Webhooks + Secrets + Memory: explain when to use each and how to configure safely.
|
|
94
|
-
|
|
95
|
-
Behavior:
|
|
96
|
-
- Be concise, direct, and action-oriented.
|
|
97
|
-
- If the request is ambiguous, ask one focused clarifying question.
|
|
98
|
-
- Prefer step-by-step instructions that can be executed immediately.
|
|
99
|
-
- When the user asks for direct execution (for example browsing, screenshots, research, or file edits), use available tools and return real results instead of only describing what to do.
|
|
100
|
-
- If a capability depends on provider/tool configuration, call that out explicitly.`
|
|
101
|
-
|
|
102
|
-
const PROVIDERS: WizardProviderOption[] = [
|
|
103
|
-
{
|
|
104
|
-
id: 'openai',
|
|
105
|
-
name: 'OpenAI',
|
|
106
|
-
description: 'Great default for most users. Fast, reliable GPT models.',
|
|
107
|
-
requiresKey: true,
|
|
108
|
-
supportsEndpoint: true,
|
|
109
|
-
defaultEndpoint: 'https://api.openai.com/v1',
|
|
110
|
-
keyUrl: 'https://platform.openai.com/api-keys',
|
|
111
|
-
keyLabel: 'platform.openai.com',
|
|
112
|
-
badge: 'Recommended',
|
|
113
|
-
icon: 'O',
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
id: 'anthropic',
|
|
117
|
-
name: 'Anthropic',
|
|
118
|
-
description: 'Claude models — strong for coding, analysis, and long-form reasoning.',
|
|
119
|
-
requiresKey: true,
|
|
120
|
-
supportsEndpoint: false,
|
|
121
|
-
keyUrl: 'https://console.anthropic.com/settings/keys',
|
|
122
|
-
keyLabel: 'console.anthropic.com',
|
|
123
|
-
icon: 'A',
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
id: 'google',
|
|
127
|
-
name: 'Google Gemini',
|
|
128
|
-
description: 'Gemini models with strong multimodal and coding support.',
|
|
129
|
-
requiresKey: true,
|
|
130
|
-
supportsEndpoint: false,
|
|
131
|
-
keyUrl: 'https://aistudio.google.com/app/apikey',
|
|
132
|
-
keyLabel: 'aistudio.google.com',
|
|
133
|
-
keyPlaceholder: 'AIza...',
|
|
134
|
-
icon: 'G',
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
id: 'deepseek',
|
|
138
|
-
name: 'DeepSeek',
|
|
139
|
-
description: 'High-value reasoning and coding models from DeepSeek.',
|
|
140
|
-
requiresKey: true,
|
|
141
|
-
supportsEndpoint: false,
|
|
142
|
-
keyUrl: 'https://platform.deepseek.com/api_keys',
|
|
143
|
-
keyLabel: 'platform.deepseek.com',
|
|
144
|
-
icon: 'D',
|
|
145
|
-
},
|
|
146
|
-
{
|
|
147
|
-
id: 'groq',
|
|
148
|
-
name: 'Groq',
|
|
149
|
-
description: 'Very fast inference with open and reasoning model options.',
|
|
150
|
-
requiresKey: true,
|
|
151
|
-
supportsEndpoint: false,
|
|
152
|
-
keyUrl: 'https://console.groq.com/keys',
|
|
153
|
-
keyLabel: 'console.groq.com',
|
|
154
|
-
icon: 'G',
|
|
155
|
-
},
|
|
156
|
-
{
|
|
157
|
-
id: 'together',
|
|
158
|
-
name: 'Together AI',
|
|
159
|
-
description: 'Broad catalog of open models with OpenAI-compatible APIs.',
|
|
160
|
-
requiresKey: true,
|
|
161
|
-
supportsEndpoint: false,
|
|
162
|
-
keyUrl: 'https://api.together.xyz/settings/api-keys',
|
|
163
|
-
keyLabel: 'api.together.xyz',
|
|
164
|
-
icon: 'T',
|
|
165
|
-
},
|
|
166
|
-
{
|
|
167
|
-
id: 'mistral',
|
|
168
|
-
name: 'Mistral AI',
|
|
169
|
-
description: 'Efficient frontier models with strong latency and quality.',
|
|
170
|
-
requiresKey: true,
|
|
171
|
-
supportsEndpoint: false,
|
|
172
|
-
keyUrl: 'https://console.mistral.ai/api-keys/',
|
|
173
|
-
keyLabel: 'console.mistral.ai',
|
|
174
|
-
icon: 'M',
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
id: 'xai',
|
|
178
|
-
name: 'xAI (Grok)',
|
|
179
|
-
description: 'Grok models for fast answers, coding, and analysis.',
|
|
180
|
-
requiresKey: true,
|
|
181
|
-
supportsEndpoint: false,
|
|
182
|
-
keyUrl: 'https://console.x.ai',
|
|
183
|
-
keyLabel: 'console.x.ai',
|
|
184
|
-
icon: 'X',
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
id: 'fireworks',
|
|
188
|
-
name: 'Fireworks AI',
|
|
189
|
-
description: 'Serverless and optimized open-model inference endpoints.',
|
|
190
|
-
requiresKey: true,
|
|
191
|
-
supportsEndpoint: false,
|
|
192
|
-
keyUrl: 'https://fireworks.ai/account/api-keys',
|
|
193
|
-
keyLabel: 'fireworks.ai',
|
|
194
|
-
icon: 'F',
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
id: 'openclaw',
|
|
198
|
-
name: 'OpenClaw',
|
|
199
|
-
description: 'Connect to your local or remote OpenClaw gateway (multi-OpenClaw ready).',
|
|
200
|
-
requiresKey: false,
|
|
201
|
-
supportsEndpoint: true,
|
|
202
|
-
defaultEndpoint: 'http://localhost:18789/v1',
|
|
203
|
-
optionalKey: true,
|
|
204
|
-
badge: 'OpenClaw',
|
|
205
|
-
icon: 'C',
|
|
206
|
-
},
|
|
207
|
-
{
|
|
208
|
-
id: 'ollama',
|
|
209
|
-
name: 'Ollama',
|
|
210
|
-
description: 'Run local open-source models. No API key required.',
|
|
211
|
-
requiresKey: false,
|
|
212
|
-
supportsEndpoint: true,
|
|
213
|
-
defaultEndpoint: 'http://localhost:11434',
|
|
214
|
-
badge: 'Local',
|
|
215
|
-
icon: 'L',
|
|
216
|
-
},
|
|
217
|
-
]
|
|
218
|
-
|
|
219
|
-
const DEFAULT_AGENTS: Record<WizardProvider, { name: string; description: string; systemPrompt: string; model: string; tools: string[] }> = {
|
|
220
|
-
anthropic: {
|
|
221
|
-
name: 'Assistant',
|
|
222
|
-
description: 'A helpful Claude-powered assistant.',
|
|
223
|
-
systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
|
|
224
|
-
model: 'claude-sonnet-4-6',
|
|
225
|
-
tools: STARTER_AGENT_TOOLS,
|
|
226
|
-
},
|
|
227
|
-
openai: {
|
|
228
|
-
name: 'Assistant',
|
|
229
|
-
description: 'A helpful GPT-powered assistant.',
|
|
230
|
-
systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
|
|
231
|
-
model: 'gpt-4o',
|
|
232
|
-
tools: STARTER_AGENT_TOOLS,
|
|
233
|
-
},
|
|
234
|
-
google: {
|
|
235
|
-
name: 'Assistant',
|
|
236
|
-
description: 'A helpful Gemini-powered assistant.',
|
|
237
|
-
systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
|
|
238
|
-
model: 'gemini-2.5-pro',
|
|
239
|
-
tools: STARTER_AGENT_TOOLS,
|
|
240
|
-
},
|
|
241
|
-
deepseek: {
|
|
242
|
-
name: 'Assistant',
|
|
243
|
-
description: 'A helpful DeepSeek-powered assistant.',
|
|
244
|
-
systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
|
|
245
|
-
model: 'deepseek-chat',
|
|
246
|
-
tools: STARTER_AGENT_TOOLS,
|
|
247
|
-
},
|
|
248
|
-
groq: {
|
|
249
|
-
name: 'Assistant',
|
|
250
|
-
description: 'A low-latency assistant powered by Groq.',
|
|
251
|
-
systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
|
|
252
|
-
model: 'llama-3.3-70b-versatile',
|
|
253
|
-
tools: STARTER_AGENT_TOOLS,
|
|
254
|
-
},
|
|
255
|
-
together: {
|
|
256
|
-
name: 'Assistant',
|
|
257
|
-
description: 'A helpful assistant powered by Together AI.',
|
|
258
|
-
systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
|
|
259
|
-
model: 'meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8',
|
|
260
|
-
tools: STARTER_AGENT_TOOLS,
|
|
261
|
-
},
|
|
262
|
-
mistral: {
|
|
263
|
-
name: 'Assistant',
|
|
264
|
-
description: 'A helpful assistant powered by Mistral.',
|
|
265
|
-
systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
|
|
266
|
-
model: 'mistral-large-latest',
|
|
267
|
-
tools: STARTER_AGENT_TOOLS,
|
|
268
|
-
},
|
|
269
|
-
xai: {
|
|
270
|
-
name: 'Assistant',
|
|
271
|
-
description: 'A helpful assistant powered by xAI Grok.',
|
|
272
|
-
systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
|
|
273
|
-
model: 'grok-3',
|
|
274
|
-
tools: STARTER_AGENT_TOOLS,
|
|
275
|
-
},
|
|
276
|
-
fireworks: {
|
|
277
|
-
name: 'Assistant',
|
|
278
|
-
description: 'A helpful assistant powered by Fireworks AI.',
|
|
279
|
-
systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
|
|
280
|
-
model: 'accounts/fireworks/models/deepseek-r1-0528',
|
|
281
|
-
tools: STARTER_AGENT_TOOLS,
|
|
282
|
-
},
|
|
283
|
-
ollama: {
|
|
284
|
-
name: 'Assistant',
|
|
285
|
-
description: 'A local assistant running through Ollama.',
|
|
286
|
-
systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
|
|
287
|
-
model: 'llama3',
|
|
288
|
-
tools: STARTER_AGENT_TOOLS,
|
|
289
|
-
},
|
|
290
|
-
openclaw: {
|
|
291
|
-
name: 'OpenClaw Operator',
|
|
292
|
-
description: 'A manager agent for talking to and coordinating OpenClaw instances.',
|
|
293
|
-
systemPrompt: 'You are an operator focused on reliable execution, clear status updates, and task completion.',
|
|
294
|
-
model: 'default',
|
|
295
|
-
tools: STARTER_AGENT_TOOLS,
|
|
296
|
-
},
|
|
41
|
+
interface ConfiguredProvider {
|
|
42
|
+
provider: SetupProvider
|
|
43
|
+
credentialId: string | null
|
|
44
|
+
agentId: string
|
|
45
|
+
agentName: string
|
|
297
46
|
}
|
|
298
47
|
|
|
299
48
|
function SparkleIcon() {
|
|
@@ -339,13 +88,13 @@ function StepDots({ current, total }: { current: number; total: number }) {
|
|
|
339
88
|
)
|
|
340
89
|
}
|
|
341
90
|
|
|
342
|
-
function SkipLink({ onClick }: { onClick: () => void }) {
|
|
91
|
+
function SkipLink({ onClick, label }: { onClick: () => void; label?: string }) {
|
|
343
92
|
return (
|
|
344
93
|
<button
|
|
345
94
|
onClick={onClick}
|
|
346
95
|
className="mt-8 text-[13px] text-text-3 hover:text-text-2 transition-colors cursor-pointer bg-transparent border-none"
|
|
347
96
|
>
|
|
348
|
-
Skip setup for now
|
|
97
|
+
{label || 'Skip setup for now'}
|
|
349
98
|
</button>
|
|
350
99
|
)
|
|
351
100
|
}
|
|
@@ -359,6 +108,30 @@ function ProviderBadge({ label }: { label?: string }) {
|
|
|
359
108
|
)
|
|
360
109
|
}
|
|
361
110
|
|
|
111
|
+
function ConfiguredChips({ providers }: { providers: ConfiguredProvider[] }) {
|
|
112
|
+
if (providers.length === 0) return null
|
|
113
|
+
return (
|
|
114
|
+
<div className="flex flex-wrap gap-2 justify-center mb-6">
|
|
115
|
+
{providers.map((cp) => (
|
|
116
|
+
<span
|
|
117
|
+
key={cp.provider}
|
|
118
|
+
className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full bg-emerald-500/10 border border-emerald-500/25 text-emerald-300 text-[12px] font-500"
|
|
119
|
+
>
|
|
120
|
+
<span className="w-1.5 h-1.5 rounded-full bg-emerald-400" />
|
|
121
|
+
{cp.agentName}
|
|
122
|
+
</span>
|
|
123
|
+
))}
|
|
124
|
+
</div>
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const CONNECTOR_ICONS = [
|
|
129
|
+
{ name: 'Discord', icon: 'D' },
|
|
130
|
+
{ name: 'Slack', icon: 'S' },
|
|
131
|
+
{ name: 'Telegram', icon: 'T' },
|
|
132
|
+
{ name: 'WhatsApp', icon: 'W' },
|
|
133
|
+
]
|
|
134
|
+
|
|
362
135
|
function getOpenClawErrorHint(message: string): string | null {
|
|
363
136
|
const lower = message.toLowerCase()
|
|
364
137
|
if (lower.includes('timeout') || lower.includes('timed out'))
|
|
@@ -374,7 +147,7 @@ function getOpenClawErrorHint(message: string): string | null {
|
|
|
374
147
|
|
|
375
148
|
export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
376
149
|
const [step, setStep] = useState(0)
|
|
377
|
-
const [provider, setProvider] = useState<
|
|
150
|
+
const [provider, setProvider] = useState<SetupProvider | null>(null)
|
|
378
151
|
const [endpoint, setEndpoint] = useState('')
|
|
379
152
|
const [apiKey, setApiKey] = useState('')
|
|
380
153
|
const [credentialId, setCredentialId] = useState<string | null>(null)
|
|
@@ -391,15 +164,18 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
391
164
|
const [agentPrompt, setAgentPrompt] = useState('')
|
|
392
165
|
const [agentModel, setAgentModel] = useState('')
|
|
393
166
|
|
|
167
|
+
const [configuredProviders, setConfiguredProviders] = useState<ConfiguredProvider[]>([])
|
|
168
|
+
|
|
394
169
|
const selectedProvider = useMemo(
|
|
395
|
-
() =>
|
|
170
|
+
() => SETUP_PROVIDERS.find((p) => p.id === provider) || null,
|
|
396
171
|
[provider],
|
|
397
172
|
)
|
|
398
|
-
const totalSteps =
|
|
173
|
+
const totalSteps = 4
|
|
399
174
|
const requiresKey = selectedProvider?.requiresKey || false
|
|
400
175
|
const supportsEndpoint = selectedProvider?.supportsEndpoint || false
|
|
401
176
|
const keyIsOptional = selectedProvider?.optionalKey || false
|
|
402
177
|
const requiresVerifiedConnection = provider === 'openclaw'
|
|
178
|
+
const configuredIds = new Set(configuredProviders.map((cp) => cp.provider))
|
|
403
179
|
|
|
404
180
|
const skip = async () => {
|
|
405
181
|
try {
|
|
@@ -410,9 +186,9 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
410
186
|
onComplete()
|
|
411
187
|
}
|
|
412
188
|
|
|
413
|
-
const selectProvider = (next:
|
|
189
|
+
const selectProvider = (next: SetupProvider) => {
|
|
414
190
|
const defaults = DEFAULT_AGENTS[next]
|
|
415
|
-
const meta =
|
|
191
|
+
const meta = SETUP_PROVIDERS.find((p) => p.id === next)
|
|
416
192
|
|
|
417
193
|
setProvider(next)
|
|
418
194
|
setEndpoint(meta?.defaultEndpoint || '')
|
|
@@ -462,9 +238,9 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
462
238
|
setCheckState(result.ok ? 'ok' : 'error')
|
|
463
239
|
setCheckMessage(result.message || (result.ok ? 'Connected successfully.' : 'Connection failed.'))
|
|
464
240
|
return !!result.ok
|
|
465
|
-
} catch (err:
|
|
241
|
+
} catch (err: unknown) {
|
|
466
242
|
setCheckState('error')
|
|
467
|
-
setCheckMessage(err
|
|
243
|
+
setCheckMessage(err instanceof Error ? err.message : String(err))
|
|
468
244
|
return false
|
|
469
245
|
}
|
|
470
246
|
}
|
|
@@ -476,10 +252,10 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
476
252
|
const report = await api<SetupDoctorResponse>('GET', '/setup/doctor')
|
|
477
253
|
setDoctorReport(report)
|
|
478
254
|
setDoctorState('done')
|
|
479
|
-
} catch (err:
|
|
255
|
+
} catch (err: unknown) {
|
|
480
256
|
setDoctorState('error')
|
|
481
257
|
setDoctorReport(null)
|
|
482
|
-
setDoctorError(err
|
|
258
|
+
setDoctorError(err instanceof Error ? err.message : String(err))
|
|
483
259
|
}
|
|
484
260
|
}
|
|
485
261
|
|
|
@@ -515,14 +291,14 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
515
291
|
|
|
516
292
|
setCredentialId(nextCredentialId || null)
|
|
517
293
|
setStep(2)
|
|
518
|
-
} catch (err:
|
|
519
|
-
setError(err
|
|
294
|
+
} catch (err: unknown) {
|
|
295
|
+
setError(err instanceof Error ? err.message : String(err))
|
|
520
296
|
} finally {
|
|
521
297
|
setSaving(false)
|
|
522
298
|
}
|
|
523
299
|
}
|
|
524
300
|
|
|
525
|
-
const
|
|
301
|
+
const createAgentAndFinish = async (addAnother: boolean) => {
|
|
526
302
|
if (!provider || !agentName.trim()) return
|
|
527
303
|
if (requiresVerifiedConnection && checkState !== 'ok') {
|
|
528
304
|
setError('OpenClaw connection is not verified. Go back and run the connection check.')
|
|
@@ -546,35 +322,51 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
546
322
|
payload.apiEndpoint = endpoint.trim()
|
|
547
323
|
}
|
|
548
324
|
|
|
549
|
-
const
|
|
550
|
-
|
|
551
|
-
!!agents.default
|
|
552
|
-
&& Object.keys(agents).length === 1
|
|
553
|
-
&& agentName.trim().toLowerCase() === 'assistant'
|
|
325
|
+
const isFirstProvider = configuredProviders.length === 0
|
|
326
|
+
let agentId: string
|
|
554
327
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
328
|
+
if (isFirstProvider) {
|
|
329
|
+
const agents = await api<Record<string, { id: string }>>('GET', '/agents')
|
|
330
|
+
const canReuseDefault =
|
|
331
|
+
!!agents.default
|
|
332
|
+
&& Object.keys(agents).length === 1
|
|
333
|
+
&& agentName.trim().toLowerCase() === DEFAULT_AGENTS[provider].name.toLowerCase()
|
|
558
334
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
335
|
+
agentId = canReuseDefault
|
|
336
|
+
? 'default'
|
|
337
|
+
: (await api<{ id: string }>('POST', '/agents', payload)).id
|
|
338
|
+
|
|
339
|
+
if (canReuseDefault) {
|
|
340
|
+
await api('PUT', '/agents/default', payload)
|
|
341
|
+
}
|
|
562
342
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
343
|
+
// Create/update __main__ chat for the first provider
|
|
344
|
+
const appState = useAppStore.getState()
|
|
345
|
+
const currentUser = appState.currentUser
|
|
346
|
+
if (currentUser && agentId) {
|
|
347
|
+
const sessionMap = await api<Record<string, { id: string; name: string; user: string }>>('GET', '/sessions')
|
|
348
|
+
const existingMain = Object.values(sessionMap).find((s) => s.name === '__main__' && s.user === currentUser)
|
|
349
|
+
const mainId = existingMain?.id || `main-${currentUser}`
|
|
350
|
+
const selectedModel = (payload.model as string) || DEFAULT_AGENTS[provider].model
|
|
351
|
+
const selectedEndpoint = supportsEndpoint ? (payload.apiEndpoint as string | undefined) || null : null
|
|
352
|
+
const selectedTools = Array.isArray(payload.tools) ? payload.tools as string[] : DEFAULT_AGENTS[provider].tools
|
|
353
|
+
|
|
354
|
+
if (!existingMain) {
|
|
355
|
+
await api('POST', '/sessions', {
|
|
356
|
+
id: mainId,
|
|
357
|
+
name: '__main__',
|
|
358
|
+
user: currentUser,
|
|
359
|
+
agentId,
|
|
360
|
+
provider,
|
|
361
|
+
model: selectedModel,
|
|
362
|
+
credentialId: credentialId || null,
|
|
363
|
+
apiEndpoint: selectedEndpoint,
|
|
364
|
+
tools: selectedTools,
|
|
365
|
+
heartbeatEnabled: true,
|
|
366
|
+
})
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
await api('PUT', `/sessions/${mainId}`, {
|
|
578
370
|
agentId,
|
|
579
371
|
provider,
|
|
580
372
|
model: selectedModel,
|
|
@@ -583,25 +375,45 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
583
375
|
tools: selectedTools,
|
|
584
376
|
heartbeatEnabled: true,
|
|
585
377
|
})
|
|
586
|
-
}
|
|
587
378
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
heartbeatEnabled: true,
|
|
596
|
-
})
|
|
379
|
+
await appState.loadSessions()
|
|
380
|
+
appState.setCurrentSession(mainId)
|
|
381
|
+
}
|
|
382
|
+
} else {
|
|
383
|
+
// Additional providers just create the agent
|
|
384
|
+
agentId = (await api<{ id: string }>('POST', '/agents', payload)).id
|
|
385
|
+
}
|
|
597
386
|
|
|
598
|
-
|
|
599
|
-
|
|
387
|
+
const newConfigured: ConfiguredProvider = {
|
|
388
|
+
provider,
|
|
389
|
+
credentialId: credentialId || null,
|
|
390
|
+
agentId,
|
|
391
|
+
agentName: agentName.trim(),
|
|
600
392
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
393
|
+
const nextConfigured = [...configuredProviders, newConfigured]
|
|
394
|
+
setConfiguredProviders(nextConfigured)
|
|
395
|
+
|
|
396
|
+
if (addAnother) {
|
|
397
|
+
// Reset for next provider selection
|
|
398
|
+
setProvider(null)
|
|
399
|
+
setEndpoint('')
|
|
400
|
+
setApiKey('')
|
|
401
|
+
setCredentialId(null)
|
|
402
|
+
setCheckState('idle')
|
|
403
|
+
setCheckMessage('')
|
|
404
|
+
setAgentName('')
|
|
405
|
+
setAgentDescription('')
|
|
406
|
+
setAgentPrompt('')
|
|
407
|
+
setAgentModel('')
|
|
408
|
+
setError('')
|
|
409
|
+
setStep(0)
|
|
410
|
+
} else {
|
|
411
|
+
// Finish setup
|
|
412
|
+
await api('PUT', '/settings', { setupCompleted: true })
|
|
413
|
+
setStep(3)
|
|
414
|
+
}
|
|
415
|
+
} catch (err: unknown) {
|
|
416
|
+
setError(err instanceof Error ? err.message : String(err))
|
|
605
417
|
} finally {
|
|
606
418
|
setSaving(false)
|
|
607
419
|
}
|
|
@@ -629,44 +441,58 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
629
441
|
{step === 0 && (
|
|
630
442
|
<>
|
|
631
443
|
<h1 className="font-display text-[36px] font-800 leading-[1.05] tracking-[-0.04em] mb-3">
|
|
632
|
-
2-Minute Setup
|
|
444
|
+
{configuredProviders.length > 0 ? 'Add Another Provider' : '2-Minute Setup'}
|
|
633
445
|
</h1>
|
|
634
446
|
<p className="text-[15px] text-text-2 mb-2">
|
|
635
|
-
|
|
447
|
+
{configuredProviders.length > 0
|
|
448
|
+
? 'Pick another provider to set up, or finish below.'
|
|
449
|
+
: 'No coding required. Pick a provider, paste a key if needed, and start chatting.'}
|
|
636
450
|
</p>
|
|
637
451
|
<p className="text-[13px] text-text-3 mb-8">
|
|
638
452
|
You can change providers, models, and agent settings anytime later.
|
|
639
453
|
</p>
|
|
640
454
|
|
|
455
|
+
<ConfiguredChips providers={configuredProviders} />
|
|
456
|
+
|
|
641
457
|
<div className="flex flex-col gap-3 max-h-[44vh] overflow-y-auto pr-1">
|
|
642
|
-
{
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
<div className="
|
|
657
|
-
|
|
658
|
-
|
|
458
|
+
{SETUP_PROVIDERS.map((p) => {
|
|
459
|
+
const isConfigured = configuredIds.has(p.id)
|
|
460
|
+
return (
|
|
461
|
+
<button
|
|
462
|
+
key={p.id}
|
|
463
|
+
onClick={() => !isConfigured && selectProvider(p.id)}
|
|
464
|
+
disabled={isConfigured}
|
|
465
|
+
className={`w-full px-5 py-4 rounded-[14px] border border-white/[0.08] bg-surface text-left
|
|
466
|
+
transition-all duration-200 flex items-start gap-4
|
|
467
|
+
${isConfigured
|
|
468
|
+
? 'opacity-40 cursor-not-allowed'
|
|
469
|
+
: 'cursor-pointer hover:border-accent-bright/30 hover:bg-surface-hover'
|
|
470
|
+
}`}
|
|
471
|
+
>
|
|
472
|
+
<div className="w-10 h-10 rounded-[10px] bg-white/[0.04] border border-white/[0.06] flex items-center justify-center shrink-0 mt-0.5">
|
|
473
|
+
<span className="text-[16px] font-display font-700 text-accent-bright">
|
|
474
|
+
{p.icon}
|
|
475
|
+
</span>
|
|
659
476
|
</div>
|
|
660
|
-
<div
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
477
|
+
<div>
|
|
478
|
+
<div className="text-[15px] font-display font-600 text-text mb-1">
|
|
479
|
+
{p.name}
|
|
480
|
+
{isConfigured
|
|
481
|
+
? <span className="ml-2 text-[10px] text-emerald-400 uppercase tracking-[0.08em]">Configured</span>
|
|
482
|
+
: <ProviderBadge label={p.badge} />
|
|
483
|
+
}
|
|
665
484
|
</div>
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
485
|
+
<div className="text-[13px] text-text-3 leading-relaxed">{p.description}</div>
|
|
486
|
+
{!p.requiresKey && !isConfigured && (
|
|
487
|
+
<div className="mt-1.5 inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md bg-emerald-500/10 text-emerald-400 text-[11px] font-500">
|
|
488
|
+
<span className="w-1.5 h-1.5 rounded-full bg-emerald-400" />
|
|
489
|
+
No API key required
|
|
490
|
+
</div>
|
|
491
|
+
)}
|
|
492
|
+
</div>
|
|
493
|
+
</button>
|
|
494
|
+
)
|
|
495
|
+
})}
|
|
670
496
|
</div>
|
|
671
497
|
|
|
672
498
|
<div className="mt-4 text-left">
|
|
@@ -702,7 +528,13 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
702
528
|
)}
|
|
703
529
|
</div>
|
|
704
530
|
|
|
705
|
-
<SkipLink
|
|
531
|
+
<SkipLink
|
|
532
|
+
onClick={configuredProviders.length > 0 ? async () => {
|
|
533
|
+
await api('PUT', '/settings', { setupCompleted: true })
|
|
534
|
+
setStep(3)
|
|
535
|
+
} : skip}
|
|
536
|
+
label={configuredProviders.length > 0 ? 'Finish Setup' : 'Skip setup for now'}
|
|
537
|
+
/>
|
|
706
538
|
</>
|
|
707
539
|
)}
|
|
708
540
|
|
|
@@ -831,17 +663,23 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
831
663
|
</button>
|
|
832
664
|
</div>
|
|
833
665
|
|
|
834
|
-
<SkipLink
|
|
666
|
+
<SkipLink
|
|
667
|
+
onClick={configuredProviders.length > 0 ? async () => {
|
|
668
|
+
await api('PUT', '/settings', { setupCompleted: true })
|
|
669
|
+
setStep(3)
|
|
670
|
+
} : skip}
|
|
671
|
+
label={configuredProviders.length > 0 ? 'Finish Setup' : 'Skip setup for now'}
|
|
672
|
+
/>
|
|
835
673
|
</>
|
|
836
674
|
)}
|
|
837
675
|
|
|
838
676
|
{step === 2 && provider && selectedProvider && (
|
|
839
677
|
<>
|
|
840
678
|
<h1 className="font-display text-[36px] font-800 leading-[1.05] tracking-[-0.04em] mb-3">
|
|
841
|
-
|
|
679
|
+
Create Your Agent
|
|
842
680
|
</h1>
|
|
843
681
|
<p className="text-[15px] text-text-2 mb-7">
|
|
844
|
-
We'll create a starter
|
|
682
|
+
We'll create a starter agent so you can begin immediately.
|
|
845
683
|
</p>
|
|
846
684
|
|
|
847
685
|
<div className="mb-5 p-4 rounded-[14px] border border-white/[0.08] bg-surface text-left">
|
|
@@ -921,17 +759,94 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
|
|
921
759
|
Back
|
|
922
760
|
</button>
|
|
923
761
|
<button
|
|
924
|
-
onClick={
|
|
762
|
+
onClick={() => createAgentAndFinish(true)}
|
|
925
763
|
disabled={!agentName.trim() || saving}
|
|
926
|
-
className="px-
|
|
764
|
+
className="px-6 py-3.5 rounded-[14px] border border-white/[0.08] bg-white/[0.03] text-text text-[14px]
|
|
765
|
+
font-display font-600 cursor-pointer hover:bg-white/[0.06] transition-all duration-200 disabled:opacity-40"
|
|
766
|
+
>
|
|
767
|
+
{saving ? 'Creating...' : 'Create & Add Another'}
|
|
768
|
+
</button>
|
|
769
|
+
<button
|
|
770
|
+
onClick={() => createAgentAndFinish(false)}
|
|
771
|
+
disabled={!agentName.trim() || saving}
|
|
772
|
+
className="px-8 py-3.5 rounded-[14px] border-none bg-accent-bright text-white text-[15px] font-display font-600
|
|
927
773
|
cursor-pointer hover:brightness-110 active:scale-[0.97] transition-all duration-200
|
|
928
774
|
shadow-[0_6px_28px_rgba(99,102,241,0.3)] disabled:opacity-30"
|
|
929
775
|
>
|
|
930
|
-
{saving ? 'Creating...' : 'Create
|
|
776
|
+
{saving ? 'Creating...' : 'Create & Finish'}
|
|
931
777
|
</button>
|
|
932
778
|
</div>
|
|
933
779
|
|
|
934
|
-
<SkipLink
|
|
780
|
+
<SkipLink
|
|
781
|
+
onClick={configuredProviders.length > 0 ? async () => {
|
|
782
|
+
await api('PUT', '/settings', { setupCompleted: true })
|
|
783
|
+
setStep(3)
|
|
784
|
+
} : skip}
|
|
785
|
+
label={configuredProviders.length > 0 ? 'Finish Setup' : 'Skip setup for now'}
|
|
786
|
+
/>
|
|
787
|
+
</>
|
|
788
|
+
)}
|
|
789
|
+
|
|
790
|
+
{step === 3 && (
|
|
791
|
+
<>
|
|
792
|
+
<h1 className="font-display text-[36px] font-800 leading-[1.05] tracking-[-0.04em] mb-3">
|
|
793
|
+
You're All Set
|
|
794
|
+
</h1>
|
|
795
|
+
<p className="text-[15px] text-text-2 mb-7">
|
|
796
|
+
{configuredProviders.length === 1
|
|
797
|
+
? 'Your agent is ready to chat.'
|
|
798
|
+
: `${configuredProviders.length} agents created and ready to chat.`}
|
|
799
|
+
</p>
|
|
800
|
+
|
|
801
|
+
{configuredProviders.length > 0 && (
|
|
802
|
+
<div className="mb-6 p-4 rounded-[14px] border border-white/[0.08] bg-surface text-left">
|
|
803
|
+
<div className="text-[12px] uppercase tracking-[0.08em] text-text-3 mb-3">Agents Created</div>
|
|
804
|
+
<div className="space-y-2">
|
|
805
|
+
{configuredProviders.map((cp) => {
|
|
806
|
+
const meta = SETUP_PROVIDERS.find((p) => p.id === cp.provider)
|
|
807
|
+
return (
|
|
808
|
+
<div key={cp.provider} className="flex items-center gap-3">
|
|
809
|
+
<div className="w-8 h-8 rounded-[8px] bg-white/[0.04] border border-white/[0.06] flex items-center justify-center shrink-0">
|
|
810
|
+
<span className="text-[13px] font-display font-700 text-accent-bright">
|
|
811
|
+
{meta?.icon || '?'}
|
|
812
|
+
</span>
|
|
813
|
+
</div>
|
|
814
|
+
<div>
|
|
815
|
+
<div className="text-[14px] text-text font-500">{cp.agentName}</div>
|
|
816
|
+
<div className="text-[12px] text-text-3">{meta?.name || cp.provider}</div>
|
|
817
|
+
</div>
|
|
818
|
+
</div>
|
|
819
|
+
)
|
|
820
|
+
})}
|
|
821
|
+
</div>
|
|
822
|
+
</div>
|
|
823
|
+
)}
|
|
824
|
+
|
|
825
|
+
<div className="mb-8 p-4 rounded-[14px] border border-white/[0.08] bg-surface text-left">
|
|
826
|
+
<div className="text-[12px] uppercase tracking-[0.08em] text-text-3 mb-3">Coming Soon — Connectors</div>
|
|
827
|
+
<p className="text-[13px] text-text-2 mb-3">
|
|
828
|
+
Bridge your agents to chat platforms. Set this up anytime from Connectors.
|
|
829
|
+
</p>
|
|
830
|
+
<div className="flex gap-3">
|
|
831
|
+
{CONNECTOR_ICONS.map((c) => (
|
|
832
|
+
<div key={c.name} className="flex flex-col items-center gap-1.5">
|
|
833
|
+
<div className="w-10 h-10 rounded-[10px] bg-white/[0.04] border border-white/[0.06] flex items-center justify-center">
|
|
834
|
+
<span className="text-[14px] font-display font-600 text-text-3">{c.icon}</span>
|
|
835
|
+
</div>
|
|
836
|
+
<span className="text-[10px] text-text-3">{c.name}</span>
|
|
837
|
+
</div>
|
|
838
|
+
))}
|
|
839
|
+
</div>
|
|
840
|
+
</div>
|
|
841
|
+
|
|
842
|
+
<button
|
|
843
|
+
onClick={onComplete}
|
|
844
|
+
className="px-10 py-3.5 rounded-[14px] border-none bg-accent-bright text-white text-[15px] font-display font-600
|
|
845
|
+
cursor-pointer hover:brightness-110 active:scale-[0.97] transition-all duration-200
|
|
846
|
+
shadow-[0_6px_28px_rgba(99,102,241,0.3)]"
|
|
847
|
+
>
|
|
848
|
+
Get Started
|
|
849
|
+
</button>
|
|
935
850
|
</>
|
|
936
851
|
)}
|
|
937
852
|
</div>
|