@swarmclawai/swarmclaw 1.2.4 → 1.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/bin/daemon-cmd.js +169 -0
- package/bin/server-cmd.js +3 -0
- package/bin/swarmclaw.js +11 -0
- package/package.json +17 -16
- package/src/app/api/agents/[id]/clone/route.ts +3 -32
- package/src/app/api/agents/[id]/route.ts +6 -158
- package/src/app/api/agents/[id]/status/route.ts +2 -3
- package/src/app/api/agents/[id]/thread/route.ts +4 -17
- package/src/app/api/agents/bulk/route.ts +5 -47
- package/src/app/api/agents/route.ts +5 -119
- package/src/app/api/agents/trash/route.ts +13 -24
- package/src/app/api/auth/route.ts +3 -9
- package/src/app/api/autonomy/estop/route.ts +5 -5
- package/src/app/api/chatrooms/[id]/chat/route.ts +11 -5
- package/src/app/api/chatrooms/[id]/route.ts +23 -2
- package/src/app/api/chatrooms/route.ts +13 -2
- package/src/app/api/chats/[id]/clear/route.ts +2 -13
- package/src/app/api/chats/[id]/deploy/route.ts +2 -3
- package/src/app/api/chats/[id]/edit-resend/route.ts +7 -13
- package/src/app/api/chats/[id]/mailbox/route.ts +6 -8
- package/src/app/api/chats/[id]/queue/route.ts +17 -64
- package/src/app/api/chats/[id]/retry/route.ts +4 -22
- package/src/app/api/chats/[id]/route.ts +10 -138
- package/src/app/api/chats/heartbeat/route.ts +2 -1
- package/src/app/api/chats/migrate-messages/route.ts +7 -0
- package/src/app/api/chats/route.ts +13 -134
- package/src/app/api/connectors/[id]/access/route.ts +12 -229
- package/src/app/api/connectors/[id]/doctor/route.ts +1 -1
- package/src/app/api/connectors/[id]/health/route.ts +12 -39
- package/src/app/api/connectors/[id]/route.ts +14 -122
- package/src/app/api/connectors/[id]/webhook/route.ts +1 -1
- package/src/app/api/connectors/doctor/route.ts +1 -1
- package/src/app/api/connectors/route.ts +12 -70
- package/src/app/api/credentials/[id]/route.ts +2 -4
- package/src/app/api/credentials/route.ts +10 -19
- package/src/app/api/daemon/health-check/route.ts +3 -4
- package/src/app/api/daemon/route.ts +10 -8
- package/src/app/api/documents/route.ts +11 -10
- package/src/app/api/external-agents/route.ts +3 -3
- package/src/app/api/gateways/[id]/health/route.ts +2 -3
- package/src/app/api/gateways/[id]/route.ts +7 -122
- package/src/app/api/gateways/route.ts +3 -103
- package/src/app/api/mcp-servers/[id]/tools/route.ts +5 -5
- package/src/app/api/openclaw/dashboard-url/route.ts +8 -16
- package/src/app/api/openclaw/directory/route.ts +2 -2
- package/src/app/api/openclaw/history/route.ts +3 -5
- package/src/app/api/providers/[id]/route.test.ts +49 -0
- package/src/app/api/providers/ollama/route.ts +6 -5
- package/src/app/api/schedules/[id]/route.ts +14 -108
- package/src/app/api/schedules/[id]/run/route.ts +6 -67
- package/src/app/api/schedules/route.ts +9 -51
- package/src/app/api/settings/route.ts +4 -3
- package/src/app/api/setup/check-provider/route.ts +23 -1
- package/src/app/api/setup/openclaw-device/route.ts +2 -2
- package/src/app/api/system/status/route.ts +2 -2
- package/src/app/api/tasks/[id]/route.ts +16 -202
- package/src/app/api/tasks/bulk/route.ts +5 -86
- package/src/app/api/tasks/metrics/route.ts +2 -1
- package/src/app/api/tasks/route.ts +11 -171
- package/src/app/api/upload/route.ts +1 -1
- package/src/app/api/uploads/[filename]/route.ts +1 -1
- package/src/app/api/uploads/route.ts +1 -1
- package/src/app/api/webhooks/[id]/history/route.ts +2 -2
- package/src/app/layout.tsx +9 -6
- package/src/app/protocols/page.tsx +71 -89
- package/src/app/tasks/page.tsx +32 -32
- package/src/cli/index.js +1 -0
- package/src/cli/spec.js +1 -0
- package/src/components/agents/agent-sheet.tsx +5 -5
- package/src/components/auth/setup-wizard/index.tsx +4 -4
- package/src/components/auth/setup-wizard/step-agents.tsx +1 -1
- package/src/components/auth/setup-wizard/step-connect.tsx +1 -1
- package/src/components/auth/setup-wizard/utils.ts +1 -1
- package/src/components/chatrooms/chatroom-sheet.tsx +16 -276
- package/src/components/connectors/connector-list.tsx +26 -40
- package/src/components/connectors/connector-sheet.tsx +95 -149
- package/src/components/gateways/gateway-sheet.tsx +61 -110
- package/src/components/layout/live-query-sync.tsx +121 -0
- package/src/components/protocols/structured-session-launcher.tsx +24 -45
- package/src/components/providers/app-query-provider.tsx +17 -0
- package/src/components/providers/provider-list.tsx +60 -61
- package/src/components/providers/provider-sheet.tsx +74 -56
- package/src/components/skills/skill-list.tsx +5 -18
- package/src/components/skills/skill-sheet.tsx +21 -20
- package/src/components/skills/skills-workspace.tsx +48 -87
- package/src/components/tasks/task-card.tsx +20 -13
- package/src/components/tasks/task-column.tsx +22 -7
- package/src/components/tasks/task-list.tsx +8 -11
- package/src/components/tasks/task-sheet.tsx +111 -103
- package/src/features/agents/queries.ts +20 -0
- package/src/features/chatrooms/queries.ts +20 -0
- package/src/features/chats/queries.ts +27 -0
- package/src/features/connectors/queries.ts +145 -0
- package/src/features/credentials/queries.ts +37 -0
- package/src/features/extensions/queries.ts +26 -0
- package/src/features/external-agents/queries.ts +36 -0
- package/src/features/gateways/queries.ts +274 -0
- package/src/features/missions/queries.ts +23 -0
- package/src/features/projects/queries.ts +20 -0
- package/src/features/protocols/queries.ts +149 -0
- package/src/features/providers/queries.ts +142 -0
- package/src/features/settings/queries.ts +20 -0
- package/src/features/skills/queries.ts +182 -0
- package/src/features/tasks/queries.ts +189 -0
- package/src/hooks/use-ws.ts +3 -2
- package/src/lib/app/api-client.ts +2 -2
- package/src/lib/providers/index.test.ts +108 -0
- package/src/lib/providers/index.ts +38 -15
- package/src/lib/query/client.ts +17 -0
- package/src/lib/server/agents/agent-runtime-config.ts +1 -1
- package/src/lib/server/agents/agent-service.ts +429 -0
- package/src/lib/server/agents/agent-thread-session.ts +6 -5
- package/src/lib/server/agents/autonomy-contract.ts +1 -4
- package/src/lib/server/agents/delegation-advisory.test.ts +206 -0
- package/src/lib/server/agents/delegation-advisory.ts +251 -0
- package/src/lib/server/agents/main-agent-loop.ts +98 -40
- package/src/lib/server/agents/subagent-runtime.ts +12 -0
- package/src/lib/server/autonomy/supervisor-reflection.test.ts +20 -1
- package/src/lib/server/autonomy/supervisor-reflection.ts +39 -19
- package/src/lib/server/build-llm.ts +7 -15
- package/src/lib/server/capability-router.test.ts +70 -1
- package/src/lib/server/capability-router.ts +24 -99
- package/src/lib/server/chat-execution/chat-execution-utils.ts +0 -15
- package/src/lib/server/chat-execution/chat-streaming-utils.ts +2 -4
- package/src/lib/server/chat-execution/chat-turn-finalization.ts +77 -12
- package/src/lib/server/chat-execution/chat-turn-partial-persistence.ts +4 -4
- package/src/lib/server/chat-execution/chat-turn-preflight.ts +2 -2
- package/src/lib/server/chat-execution/chat-turn-preparation.ts +41 -17
- package/src/lib/server/chat-execution/chat-turn-stream-execution.ts +4 -2
- package/src/lib/server/chat-execution/chat-turn-tool-routing.test.ts +45 -0
- package/src/lib/server/chat-execution/chat-turn-tool-routing.ts +48 -17
- package/src/lib/server/chat-execution/continuation-evaluator.ts +4 -1
- package/src/lib/server/chat-execution/direct-memory-intent.test.ts +9 -0
- package/src/lib/server/chat-execution/direct-memory-intent.ts +12 -2
- package/src/lib/server/chat-execution/message-classifier.test.ts +35 -23
- package/src/lib/server/chat-execution/message-classifier.ts +74 -32
- package/src/lib/server/chat-execution/prompt-builder.test.ts +29 -0
- package/src/lib/server/chat-execution/prompt-builder.ts +37 -2
- package/src/lib/server/chat-execution/prompt-sections.test.ts +56 -0
- package/src/lib/server/chat-execution/prompt-sections.ts +193 -0
- package/src/lib/server/chat-execution/stream-agent-chat.ts +63 -7
- package/src/lib/server/chat-execution/stream-continuation.test.ts +36 -0
- package/src/lib/server/chat-execution/stream-continuation.ts +28 -13
- package/src/lib/server/chatrooms/chatroom-agent-signals.ts +26 -18
- package/src/lib/server/chatrooms/chatroom-helpers.ts +19 -18
- package/src/lib/server/chatrooms/chatroom-repository.ts +16 -0
- package/src/lib/server/chatrooms/chatroom-routing.test.ts +96 -0
- package/src/lib/server/chatrooms/chatroom-routing.ts +207 -53
- package/src/lib/server/chatrooms/mailbox-utils.ts +4 -2
- package/src/lib/server/chatrooms/session-mailbox.ts +50 -40
- package/src/lib/server/chats/chat-session-service.ts +410 -0
- package/src/lib/server/connectors/access.ts +1 -1
- package/src/lib/server/connectors/commands.ts +7 -6
- package/src/lib/server/connectors/connector-inbound.ts +14 -7
- package/src/lib/server/connectors/connector-outbound.ts +16 -11
- package/src/lib/server/connectors/connector-service.ts +453 -0
- package/src/lib/server/connectors/delivery.ts +17 -12
- package/src/lib/server/connectors/inbound-audio-transcription.ts +5 -14
- package/src/lib/server/connectors/media.ts +1 -1
- package/src/lib/server/connectors/response-media.ts +1 -1
- package/src/lib/server/connectors/session-consolidation.ts +11 -7
- package/src/lib/server/connectors/session.ts +9 -7
- package/src/lib/server/connectors/voice-note.ts +2 -1
- package/src/lib/server/context-manager.ts +20 -1
- package/src/lib/server/cost.ts +2 -3
- package/src/lib/server/credentials/credential-repository.ts +43 -4
- package/src/lib/server/credentials/credential-service.ts +112 -0
- package/src/lib/server/daemon/admin-metadata.ts +64 -0
- package/src/lib/server/daemon/controller.ts +577 -0
- package/src/lib/server/daemon/daemon-runtime.ts +352 -0
- package/src/lib/server/daemon/daemon-status-repository.ts +63 -0
- package/src/lib/server/daemon/types.ts +101 -0
- package/src/lib/server/embeddings.ts +3 -9
- package/src/lib/server/eval/agent-regression.ts +3 -2
- package/src/lib/server/eval/runner.ts +2 -2
- package/src/lib/server/execution-brief.test.ts +167 -0
- package/src/lib/server/execution-brief.ts +295 -0
- package/src/lib/server/execution-engine/chat-turn.ts +9 -0
- package/src/lib/server/execution-engine/import-boundary.test.ts +44 -0
- package/src/lib/server/execution-engine/index.ts +35 -0
- package/src/lib/server/execution-engine/task-attempt.ts +303 -0
- package/src/lib/server/execution-engine/types.ts +33 -0
- package/src/lib/server/gateways/gateway-profile-repository.ts +47 -3
- package/src/lib/server/gateways/gateway-profile-service.ts +200 -0
- package/src/lib/server/memory/session-archive-memory.ts +12 -10
- package/src/lib/server/messages/message-repository.ts +330 -0
- package/src/lib/server/missions/mission-service/core.ts +8 -6
- package/src/lib/server/openclaw/agent-resolver.ts +2 -3
- package/src/lib/server/openclaw/doctor.ts +1 -1
- package/src/lib/server/openclaw/gateway.test.ts +10 -1
- package/src/lib/server/openclaw/gateway.ts +5 -14
- package/src/lib/server/openclaw/health.ts +3 -11
- package/src/lib/server/openclaw/sync.ts +8 -6
- package/src/lib/server/persistence/storage-context.ts +3 -0
- package/src/lib/server/protocols/protocol-agent-turn.ts +25 -17
- package/src/lib/server/protocols/protocol-normalization.ts +1 -1
- package/src/lib/server/protocols/protocol-queries.ts +13 -7
- package/src/lib/server/protocols/protocol-run-lifecycle.ts +16 -20
- package/src/lib/server/protocols/protocol-run-repository.ts +81 -0
- package/src/lib/server/protocols/protocol-step-processors.ts +23 -31
- package/src/lib/server/protocols/protocol-swarm.ts +8 -8
- package/src/lib/server/protocols/protocol-template-repository.ts +42 -0
- package/src/lib/server/protocols/protocol-templates.ts +4 -2
- package/src/lib/server/protocols/protocol-types.ts +10 -7
- package/src/lib/server/provider-endpoint.ts +7 -12
- package/src/lib/server/provider-model-discovery.ts +2 -11
- package/src/lib/server/query-expansion.ts +5 -6
- package/src/lib/server/run-context.test.ts +365 -0
- package/src/lib/server/run-context.ts +367 -0
- package/src/lib/server/runtime/heartbeat-service.ts +7 -5
- package/src/lib/server/runtime/queue/core.ts +61 -190
- package/src/lib/server/runtime/run-ledger.ts +8 -0
- package/src/lib/server/runtime/session-run-manager/drain.ts +2 -2
- package/src/lib/server/runtime/session-run-manager/enqueue.ts +6 -0
- package/src/lib/server/runtime/session-run-manager/state.ts +4 -0
- package/src/lib/server/schedules/schedule-route-service.ts +230 -0
- package/src/lib/server/service-result.ts +16 -0
- package/src/lib/server/session-note.ts +2 -3
- package/src/lib/server/session-reset-policy.ts +4 -3
- package/src/lib/server/session-tools/connector.ts +9 -6
- package/src/lib/server/session-tools/context-mgmt.ts +58 -9
- package/src/lib/server/session-tools/crud.ts +162 -10
- package/src/lib/server/session-tools/delegate.ts +1 -1
- package/src/lib/server/session-tools/manage-tasks.test.ts +152 -0
- package/src/lib/server/session-tools/memory.ts +6 -4
- package/src/lib/server/session-tools/session-info.test.ts +56 -0
- package/src/lib/server/session-tools/session-info.ts +119 -12
- package/src/lib/server/session-tools/skill-runtime.ts +3 -1
- package/src/lib/server/session-tools/skills.ts +15 -15
- package/src/lib/server/session-tools/subagent.test.ts +115 -1
- package/src/lib/server/session-tools/subagent.ts +125 -7
- package/src/lib/server/session-tools/team-context.ts +4 -3
- package/src/lib/server/session-tools/wallet.ts +0 -58
- package/src/lib/server/sessions/session-lineage.ts +55 -0
- package/src/lib/server/sessions/session-repository.ts +2 -2
- package/src/lib/server/skills/learned-skills.ts +24 -23
- package/src/lib/server/skills/runtime-skill-resolver.ts +2 -1
- package/src/lib/server/skills/skill-repository.ts +136 -13
- package/src/lib/server/skills/skill-suggestions.ts +25 -28
- package/src/lib/server/storage-normalization.test.ts +44 -267
- package/src/lib/server/storage-normalization.ts +75 -0
- package/src/lib/server/storage.ts +19 -0
- package/src/lib/server/structured-extract.ts +3 -14
- package/src/lib/server/tasks/task-followups.ts +16 -11
- package/src/lib/server/tasks/task-result.test.ts +25 -29
- package/src/lib/server/tasks/task-result.ts +5 -9
- package/src/lib/server/tasks/task-route-service.ts +449 -0
- package/src/lib/server/text-normalization.ts +41 -0
- package/src/lib/server/tool-planning.ts +6 -42
- package/src/lib/server/upload-path.ts +5 -0
- package/src/lib/server/working-state/extraction.ts +614 -0
- package/src/lib/server/working-state/normalization.ts +866 -0
- package/src/lib/server/working-state/prompt.ts +60 -0
- package/src/lib/server/working-state/repository.ts +38 -0
- package/src/lib/server/working-state/service.test.ts +253 -0
- package/src/lib/server/working-state/service.ts +293 -0
- package/src/lib/validation/schemas.ts +1 -0
- package/src/lib/ws-client.ts +3 -3
- package/src/stores/slices/task-slice.ts +1 -4
- package/src/stores/use-chatroom-store.ts +2 -2
- package/src/types/index.ts +277 -12
|
@@ -2,10 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import { useCallback, useEffect, useMemo, useState } from 'react'
|
|
4
4
|
import { useAppStore } from '@/stores/use-app-store'
|
|
5
|
-
import { useChatroomStore } from '@/stores/use-chatroom-store'
|
|
6
|
-
import { useWs } from '@/hooks/use-ws'
|
|
7
|
-
import { useMountedRef } from '@/hooks/use-mounted-ref'
|
|
8
|
-
import { api } from '@/lib/app/api-client'
|
|
9
5
|
import type { Connector } from '@/types'
|
|
10
6
|
import {
|
|
11
7
|
ConnectorPlatformIcon,
|
|
@@ -16,6 +12,9 @@ import {
|
|
|
16
12
|
import { AgentAvatar } from '@/components/agents/agent-avatar'
|
|
17
13
|
import { PageLoader } from '@/components/ui/page-loader'
|
|
18
14
|
import { StatusDot } from '@/components/ui/status-dot'
|
|
15
|
+
import { useConnectorsQuery, useConnectorActionMutation } from '@/features/connectors/queries'
|
|
16
|
+
import { useAgentsQuery } from '@/features/agents/queries'
|
|
17
|
+
import { useChatroomsQuery } from '@/features/chatrooms/queries'
|
|
19
18
|
|
|
20
19
|
function relativeTime(ts: number): string {
|
|
21
20
|
const diff = Date.now() - ts
|
|
@@ -45,33 +44,24 @@ function getConnectorGroup(connector: Connector): ConnectorGroup {
|
|
|
45
44
|
}
|
|
46
45
|
|
|
47
46
|
export function ConnectorList({ inSidebar }: { inSidebar?: boolean }) {
|
|
48
|
-
const connectors = useAppStore((s) => s.connectors)
|
|
49
|
-
const loadConnectors = useAppStore((s) => s.loadConnectors)
|
|
50
47
|
const setConnectorSheetOpen = useAppStore((s) => s.setConnectorSheetOpen)
|
|
51
48
|
const setEditingConnectorId = useAppStore((s) => s.setEditingConnectorId)
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
const
|
|
49
|
+
const connectorsQuery = useConnectorsQuery()
|
|
50
|
+
const agentsQuery = useAgentsQuery()
|
|
51
|
+
const chatroomsQuery = useChatroomsQuery()
|
|
52
|
+
const connectorActionMutation = useConnectorActionMutation()
|
|
53
|
+
const connectors = useMemo(() => connectorsQuery.data ?? {}, [connectorsQuery.data])
|
|
54
|
+
const agents = agentsQuery.data ?? {}
|
|
55
|
+
const chatrooms = chatroomsQuery.data ?? {}
|
|
56
56
|
const [toggling, setToggling] = useState<string | null>(null)
|
|
57
57
|
const [reconnecting, setReconnecting] = useState<string | null>(null)
|
|
58
|
-
const [loaded, setLoaded] = useState(false)
|
|
59
58
|
const [error, setError] = useState<string | null>(null)
|
|
60
59
|
const [groupFilter, setGroupFilter] = useState<'all' | ConnectorGroup>('all')
|
|
61
|
-
const mountedRef = useMountedRef()
|
|
62
60
|
const openConnector = useCallback((id: string | null) => {
|
|
63
61
|
setEditingConnectorId(id)
|
|
64
62
|
setConnectorSheetOpen(true)
|
|
65
63
|
}, [setEditingConnectorId, setConnectorSheetOpen])
|
|
66
64
|
|
|
67
|
-
const refresh = useCallback(async () => {
|
|
68
|
-
await Promise.all([loadConnectors(), loadAgents(), loadChatrooms()])
|
|
69
|
-
if (mountedRef.current) setLoaded(true)
|
|
70
|
-
}, [loadConnectors, loadAgents, loadChatrooms, mountedRef])
|
|
71
|
-
|
|
72
|
-
useEffect(() => { void refresh() }, [refresh])
|
|
73
|
-
useWs('connectors', loadConnectors, 15_000)
|
|
74
|
-
|
|
75
65
|
// Auto-clear error after 5s
|
|
76
66
|
useEffect(() => {
|
|
77
67
|
if (error) { const t = setTimeout(() => setError(null), 5000); return () => clearTimeout(t) }
|
|
@@ -80,38 +70,34 @@ export function ConnectorList({ inSidebar }: { inSidebar?: boolean }) {
|
|
|
80
70
|
const handleToggle = async (e: React.MouseEvent, c: Connector) => {
|
|
81
71
|
e.stopPropagation()
|
|
82
72
|
const action = c.status === 'running' ? 'stop' : 'start'
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
setError(null)
|
|
86
|
-
}
|
|
73
|
+
setToggling(c.id)
|
|
74
|
+
setError(null)
|
|
87
75
|
try {
|
|
88
|
-
await
|
|
89
|
-
await refresh()
|
|
76
|
+
await connectorActionMutation.mutateAsync({ id: c.id, action })
|
|
90
77
|
} catch (err: unknown) {
|
|
91
78
|
const msg = err instanceof Error && err.message ? err.message : `Failed to ${action}`
|
|
92
|
-
|
|
93
|
-
await refresh()
|
|
79
|
+
setError(msg)
|
|
94
80
|
} finally {
|
|
95
|
-
|
|
81
|
+
setToggling(null)
|
|
96
82
|
}
|
|
97
83
|
}
|
|
98
84
|
|
|
99
85
|
const handleReconnect = async (e: React.MouseEvent, c: Connector) => {
|
|
100
86
|
e.stopPropagation()
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
setError(null)
|
|
104
|
-
}
|
|
87
|
+
setReconnecting(c.id)
|
|
88
|
+
setError(null)
|
|
105
89
|
try {
|
|
106
|
-
try {
|
|
107
|
-
|
|
108
|
-
|
|
90
|
+
try {
|
|
91
|
+
await connectorActionMutation.mutateAsync({ id: c.id, action: 'stop' })
|
|
92
|
+
} catch {
|
|
93
|
+
// Connector may already be stopped.
|
|
94
|
+
}
|
|
95
|
+
await connectorActionMutation.mutateAsync({ id: c.id, action: 'start' })
|
|
109
96
|
} catch (err: unknown) {
|
|
110
97
|
const msg = err instanceof Error && err.message ? err.message : 'Failed to reconnect'
|
|
111
|
-
|
|
112
|
-
await refresh()
|
|
98
|
+
setError(msg)
|
|
113
99
|
} finally {
|
|
114
|
-
|
|
100
|
+
setReconnecting(null)
|
|
115
101
|
}
|
|
116
102
|
}
|
|
117
103
|
|
|
@@ -158,7 +144,7 @@ export function ConnectorList({ inSidebar }: { inSidebar?: boolean }) {
|
|
|
158
144
|
},
|
|
159
145
|
}
|
|
160
146
|
|
|
161
|
-
if (
|
|
147
|
+
if (connectorsQuery.isPending || agentsQuery.isPending || chatroomsQuery.isPending) {
|
|
162
148
|
return <PageLoader label="Loading connectors..." />
|
|
163
149
|
}
|
|
164
150
|
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import { useState, useEffect, useCallback, useMemo } from 'react'
|
|
3
|
+
import { useState, useEffect, useCallback, useMemo, useRef } from 'react'
|
|
4
4
|
import { useAppStore } from '@/stores/use-app-store'
|
|
5
5
|
import { BottomSheet } from '@/components/shared/bottom-sheet'
|
|
6
|
-
import { api } from '@/lib/app/api-client'
|
|
7
|
-
import { useWs } from '@/hooks/use-ws'
|
|
8
6
|
import { toast } from 'sonner'
|
|
9
7
|
import type {
|
|
10
8
|
Connector,
|
|
11
9
|
ConnectorAccessMutationAction,
|
|
12
|
-
ConnectorAccessMutationResponse,
|
|
13
10
|
ConnectorAccessSnapshot,
|
|
14
11
|
ConnectorPlatform,
|
|
15
12
|
} from '@/types'
|
|
@@ -20,11 +17,25 @@ import { SheetFooter } from '@/components/shared/sheet-footer'
|
|
|
20
17
|
import { SectionLabel } from '@/components/shared/section-label'
|
|
21
18
|
import { HintTip } from '@/components/shared/hint-tip'
|
|
22
19
|
import { ConfirmDialog } from '@/components/shared/confirm-dialog'
|
|
23
|
-
import { useChatroomStore } from '@/stores/use-chatroom-store'
|
|
24
20
|
import { ConnectorHealth } from '@/components/connectors/connector-health'
|
|
25
21
|
import { ConnectorAccessPanel } from '@/components/connectors/connector-access-panel'
|
|
26
22
|
import { AdvancedSettingsSection } from '@/components/shared/advanced-settings-section'
|
|
27
23
|
import { errorMessage } from '@/lib/shared-utils'
|
|
24
|
+
import {
|
|
25
|
+
useConnectorsQuery,
|
|
26
|
+
useConnectorAccessMutation,
|
|
27
|
+
useConnectorAccessQuery,
|
|
28
|
+
useConnectorActionMutation,
|
|
29
|
+
useConnectorDoctorMutation,
|
|
30
|
+
useConnectorQuery,
|
|
31
|
+
useDeleteConnectorMutation,
|
|
32
|
+
useSaveConnectorMutation,
|
|
33
|
+
} from '@/features/connectors/queries'
|
|
34
|
+
import { useAgentsQuery } from '@/features/agents/queries'
|
|
35
|
+
import { useCredentialsQuery, useCreateCredentialMutation } from '@/features/credentials/queries'
|
|
36
|
+
import { useChatroomsQuery } from '@/features/chatrooms/queries'
|
|
37
|
+
import { useAppSettingsQuery } from '@/features/settings/queries'
|
|
38
|
+
import { useConnectorExtensionOptionsQuery } from '@/features/extensions/queries'
|
|
28
39
|
|
|
29
40
|
/** Auto-detect URLs in text and make them clickable links that open in a new tab */
|
|
30
41
|
function linkify(text: string) {
|
|
@@ -58,11 +69,6 @@ interface ConnectorDoctorPolicyPreview {
|
|
|
58
69
|
typingIndicators?: boolean
|
|
59
70
|
}
|
|
60
71
|
|
|
61
|
-
interface ConnectorDoctorResponse {
|
|
62
|
-
warnings?: string[]
|
|
63
|
-
policy?: ConnectorDoctorPolicyPreview | null
|
|
64
|
-
}
|
|
65
|
-
|
|
66
72
|
interface ConnectorConfigOption {
|
|
67
73
|
value: string
|
|
68
74
|
label: string
|
|
@@ -538,16 +544,33 @@ const ACCESS_CONTROL_FIELDS: ConnectorConfigField[] = [
|
|
|
538
544
|
export function ConnectorSheet() {
|
|
539
545
|
const open = useAppStore((s) => s.connectorSheetOpen)
|
|
540
546
|
const setOpen = useAppStore((s) => s.setConnectorSheetOpen)
|
|
541
|
-
|
|
542
|
-
const
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
547
|
+
const editingId = useAppStore((s) => s.editingConnectorId)
|
|
548
|
+
const setEditingId = useAppStore((s) => s.setEditingConnectorId)
|
|
549
|
+
const connectorsQuery = useConnectorsQuery({ enabled: open })
|
|
550
|
+
const connectorDetailQuery = useConnectorQuery(editingId, {
|
|
551
|
+
enabled: open && !!editingId,
|
|
552
|
+
refetchInterval: open && editingId ? 2_000 : false,
|
|
553
|
+
})
|
|
554
|
+
const agentsQuery = useAgentsQuery({ enabled: open })
|
|
555
|
+
const credentialsQuery = useCredentialsQuery({ enabled: open })
|
|
556
|
+
const chatroomsQuery = useChatroomsQuery({ enabled: open })
|
|
557
|
+
const appSettingsQuery = useAppSettingsQuery({ enabled: open })
|
|
558
|
+
const connectorExtensionOptionsQuery = useConnectorExtensionOptionsQuery({ enabled: open })
|
|
559
|
+
const connectorDoctorMutation = useConnectorDoctorMutation()
|
|
560
|
+
const connectorAccessMutation = useConnectorAccessMutation(editingId)
|
|
561
|
+
const connectorAccessQuery = useConnectorAccessQuery(editingId, { enabled: open && !!editingId })
|
|
562
|
+
const saveConnectorMutation = useSaveConnectorMutation()
|
|
563
|
+
const connectorActionMutation = useConnectorActionMutation()
|
|
564
|
+
const deleteConnectorMutation = useDeleteConnectorMutation()
|
|
565
|
+
const createCredentialMutation = useCreateCredentialMutation()
|
|
566
|
+
const initializedKeyRef = useRef<string | null>(null)
|
|
567
|
+
|
|
568
|
+
const dynamicPlatforms = useMemo(() => connectorExtensionOptionsQuery.data ?? [], [connectorExtensionOptionsQuery.data])
|
|
569
|
+
const connectors = connectorsQuery.data ?? {}
|
|
570
|
+
const agents = agentsQuery.data ?? {}
|
|
571
|
+
const appSettings = appSettingsQuery.data ?? {}
|
|
572
|
+
const credentials = credentialsQuery.data ?? {}
|
|
573
|
+
const chatrooms = chatroomsQuery.data ?? {}
|
|
551
574
|
|
|
552
575
|
const ALL_PLATFORMS = useMemo(() => {
|
|
553
576
|
const extensionPlatforms = dynamicPlatforms.map(p => ({
|
|
@@ -561,18 +584,6 @@ export function ConnectorSheet() {
|
|
|
561
584
|
}))
|
|
562
585
|
return [...PLATFORMS, ...extensionPlatforms]
|
|
563
586
|
}, [dynamicPlatforms])
|
|
564
|
-
const editingId = useAppStore((s) => s.editingConnectorId)
|
|
565
|
-
const setEditingId = useAppStore((s) => s.setEditingConnectorId)
|
|
566
|
-
const connectors = useAppStore((s) => s.connectors)
|
|
567
|
-
const loadConnectors = useAppStore((s) => s.loadConnectors)
|
|
568
|
-
const agents = useAppStore((s) => s.agents)
|
|
569
|
-
const appSettings = useAppStore((s) => s.appSettings)
|
|
570
|
-
const credentials = useAppStore((s) => s.credentials)
|
|
571
|
-
const loadAgents = useAppStore((s) => s.loadAgents)
|
|
572
|
-
const loadCredentials = useAppStore((s) => s.loadCredentials)
|
|
573
|
-
|
|
574
|
-
const chatrooms = useChatroomStore((s) => s.chatrooms)
|
|
575
|
-
const loadChatrooms = useChatroomStore((s) => s.loadChatrooms)
|
|
576
587
|
|
|
577
588
|
const [name, setName] = useState('')
|
|
578
589
|
const [platform, setPlatform] = useState<ConnectorPlatform>('discord')
|
|
@@ -584,9 +595,6 @@ export function ConnectorSheet() {
|
|
|
584
595
|
const [saving, setSaving] = useState(false)
|
|
585
596
|
const [actionLoading, setActionLoading] = useState(false)
|
|
586
597
|
const [showSetup, setShowSetup] = useState(false)
|
|
587
|
-
const [qrDataUrl, setQrDataUrl] = useState<string | null>(null)
|
|
588
|
-
const [waAuthenticated, setWaAuthenticated] = useState(false)
|
|
589
|
-
const [waHasCreds, setWaHasCreds] = useState(false)
|
|
590
598
|
const [waConnecting, setWaConnecting] = useState(false)
|
|
591
599
|
const [showNewCred, setShowNewCred] = useState(false)
|
|
592
600
|
const [newCredName, setNewCredName] = useState('')
|
|
@@ -595,8 +603,6 @@ export function ConnectorSheet() {
|
|
|
595
603
|
const [doctorWarnings, setDoctorWarnings] = useState<string[]>([])
|
|
596
604
|
const [doctorPolicy, setDoctorPolicy] = useState<ConnectorDoctorPolicyPreview | null>(null)
|
|
597
605
|
const [doctorLoading, setDoctorLoading] = useState(false)
|
|
598
|
-
const [accessSnapshot, setAccessSnapshot] = useState<ConnectorAccessSnapshot | null>(null)
|
|
599
|
-
const [accessLoading, setAccessLoading] = useState(false)
|
|
600
606
|
const [accessError, setAccessError] = useState<string | null>(null)
|
|
601
607
|
const [accessPending, setAccessPending] = useState(false)
|
|
602
608
|
const [confirmDelete, setConfirmDelete] = useState(false)
|
|
@@ -611,21 +617,22 @@ export function ConnectorSheet() {
|
|
|
611
617
|
const supportsAccessControls = platform === 'whatsapp' || platform === 'bluebubbles'
|
|
612
618
|
|
|
613
619
|
const editing = editingId ? connectors[editingId] as Connector | undefined : null
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
loadAgents()
|
|
618
|
-
loadCredentials()
|
|
619
|
-
loadChatrooms()
|
|
620
|
-
setShowSetup(false)
|
|
621
|
-
setShowAdvancedSettings(false)
|
|
622
|
-
}
|
|
623
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
624
|
-
}, [open])
|
|
620
|
+
const runtimeConnector = connectorDetailQuery.data ?? editing ?? null
|
|
621
|
+
const accessSnapshot = connectorAccessQuery.data ?? null
|
|
622
|
+
const accessLoading = connectorAccessQuery.isPending
|
|
625
623
|
|
|
626
624
|
// Sync form fields when editing connector changes (by ID, not reference)
|
|
627
625
|
const editingIdRef = editing?.id ?? null
|
|
628
626
|
useEffect(() => {
|
|
627
|
+
if (!open) {
|
|
628
|
+
initializedKeyRef.current = null
|
|
629
|
+
return
|
|
630
|
+
}
|
|
631
|
+
if (editingId && !editing) return
|
|
632
|
+
const initKey = editing?.id || '__new__'
|
|
633
|
+
if (initializedKeyRef.current === initKey) return
|
|
634
|
+
setShowSetup(false)
|
|
635
|
+
setShowAdvancedSettings(false)
|
|
629
636
|
if (editing) {
|
|
630
637
|
setName(editing.name)
|
|
631
638
|
setPlatform(editing.platform)
|
|
@@ -642,43 +649,22 @@ export function ConnectorSheet() {
|
|
|
642
649
|
setChatroomId('')
|
|
643
650
|
setCredentialId('')
|
|
644
651
|
setConfig({})
|
|
652
|
+
setShowNewCred(false)
|
|
653
|
+
setNewCredName('')
|
|
654
|
+
setNewCredValue('')
|
|
645
655
|
}
|
|
646
|
-
setQrDataUrl(null)
|
|
647
|
-
setWaAuthenticated(false)
|
|
648
|
-
setWaHasCreds(false)
|
|
649
656
|
setWaConnecting(false)
|
|
650
|
-
|
|
657
|
+
initializedKeyRef.current = initKey
|
|
658
|
+
}, [editing, editingId, editingIdRef, open])
|
|
651
659
|
|
|
652
660
|
// Poll for QR code when WhatsApp connector is running or connecting
|
|
653
|
-
const
|
|
654
|
-
const
|
|
655
|
-
|
|
656
|
-
try {
|
|
657
|
-
const data = await api<Record<string, unknown>>('GET', `/connectors/${editing.id}`)
|
|
658
|
-
setQrDataUrl((data.qrDataUrl as string | null) || null)
|
|
659
|
-
setWaAuthenticated((data.authenticated as boolean) ?? false)
|
|
660
|
-
setWaHasCreds((data.hasCredentials as boolean) ?? false)
|
|
661
|
-
if (data.status === 'running' && editing.status !== 'running') {
|
|
662
|
-
const store = useAppStore.getState()
|
|
663
|
-
const updated = { ...store.connectors }
|
|
664
|
-
if (updated[editing.id]) {
|
|
665
|
-
updated[editing.id] = { ...updated[editing.id], status: 'running' as const }
|
|
666
|
-
useAppStore.setState({ connectors: updated })
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
} catch { /* ignore */ }
|
|
670
|
-
}, [editing])
|
|
671
|
-
|
|
672
|
-
useEffect(() => {
|
|
673
|
-
if (editing && isWaRunning) pollWaStatus()
|
|
674
|
-
}, [editing, editing?.id, isWaRunning, pollWaStatus])
|
|
675
|
-
|
|
676
|
-
useWs('connectors', pollWaStatus, isWaRunning ? 2000 : undefined)
|
|
677
|
-
|
|
661
|
+
const qrDataUrl = runtimeConnector?.qrDataUrl ?? null
|
|
662
|
+
const waAuthenticated = runtimeConnector?.authenticated === true
|
|
663
|
+
const waHasCreds = runtimeConnector?.hasCredentials === true
|
|
678
664
|
const loadDoctorPreview = useCallback(async () => {
|
|
679
665
|
setDoctorLoading(true)
|
|
680
666
|
try {
|
|
681
|
-
const data = await
|
|
667
|
+
const data = await connectorDoctorMutation.mutateAsync({
|
|
682
668
|
id: editing?.id || null,
|
|
683
669
|
name,
|
|
684
670
|
platform,
|
|
@@ -695,6 +681,7 @@ export function ConnectorSheet() {
|
|
|
695
681
|
} finally {
|
|
696
682
|
setDoctorLoading(false)
|
|
697
683
|
}
|
|
684
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- connectorDoctorMutation omitted: mutateAsync is stable at runtime but the wrapper isn't reference-stable, causing an infinite render loop
|
|
698
685
|
}, [editing?.id, name, platform, routeMode, agentId, chatroomId, credentialId, config])
|
|
699
686
|
|
|
700
687
|
useEffect(() => {
|
|
@@ -702,8 +689,6 @@ export function ConnectorSheet() {
|
|
|
702
689
|
setDoctorWarnings([])
|
|
703
690
|
setDoctorPolicy(null)
|
|
704
691
|
setDoctorLoading(false)
|
|
705
|
-
setAccessSnapshot(null)
|
|
706
|
-
setAccessLoading(false)
|
|
707
692
|
setAccessError(null)
|
|
708
693
|
setAccessPending(false)
|
|
709
694
|
setConfirmDelete(false)
|
|
@@ -732,35 +717,6 @@ export function ConnectorSheet() {
|
|
|
732
717
|
})
|
|
733
718
|
}, [])
|
|
734
719
|
|
|
735
|
-
const loadAccessSnapshot = useCallback(async () => {
|
|
736
|
-
if (!editing?.id) {
|
|
737
|
-
setAccessSnapshot(null)
|
|
738
|
-
setAccessError(null)
|
|
739
|
-
return
|
|
740
|
-
}
|
|
741
|
-
setAccessLoading(true)
|
|
742
|
-
setAccessError(null)
|
|
743
|
-
try {
|
|
744
|
-
const snapshot = await api<ConnectorAccessSnapshot>('GET', `/connectors/${editing.id}/access`)
|
|
745
|
-
setAccessSnapshot(snapshot)
|
|
746
|
-
} catch (err: unknown) {
|
|
747
|
-
setAccessSnapshot(null)
|
|
748
|
-
setAccessError(errorMessage(err))
|
|
749
|
-
} finally {
|
|
750
|
-
setAccessLoading(false)
|
|
751
|
-
}
|
|
752
|
-
}, [editing?.id])
|
|
753
|
-
|
|
754
|
-
useEffect(() => {
|
|
755
|
-
if (!open || !editing?.id) {
|
|
756
|
-
setAccessSnapshot(null)
|
|
757
|
-
setAccessLoading(false)
|
|
758
|
-
setAccessError(null)
|
|
759
|
-
return
|
|
760
|
-
}
|
|
761
|
-
void loadAccessSnapshot()
|
|
762
|
-
}, [editing?.id, loadAccessSnapshot, open])
|
|
763
|
-
|
|
764
720
|
const handleAccessAction = useCallback(async (
|
|
765
721
|
action: ConnectorAccessMutationAction,
|
|
766
722
|
payload?: {
|
|
@@ -774,16 +730,14 @@ export function ConnectorSheet() {
|
|
|
774
730
|
setAccessPending(true)
|
|
775
731
|
setAccessError(null)
|
|
776
732
|
try {
|
|
777
|
-
const result = await
|
|
733
|
+
const result = await connectorAccessMutation.mutateAsync({
|
|
778
734
|
action,
|
|
779
735
|
senderId: payload?.senderId || null,
|
|
780
736
|
senderIdAlt: payload?.senderIdAlt || null,
|
|
781
737
|
code: payload?.code || null,
|
|
782
738
|
dmAddressingMode: payload?.dmAddressingMode || null,
|
|
783
739
|
})
|
|
784
|
-
setAccessSnapshot(result.snapshot)
|
|
785
740
|
applySnapshotToConfig(result.snapshot)
|
|
786
|
-
await loadConnectors()
|
|
787
741
|
} catch (err: unknown) {
|
|
788
742
|
const message = errorMessage(err)
|
|
789
743
|
setAccessError(message)
|
|
@@ -791,7 +745,7 @@ export function ConnectorSheet() {
|
|
|
791
745
|
} finally {
|
|
792
746
|
setAccessPending(false)
|
|
793
747
|
}
|
|
794
|
-
}, [applySnapshotToConfig, editing?.id
|
|
748
|
+
}, [applySnapshotToConfig, connectorAccessMutation, editing?.id])
|
|
795
749
|
|
|
796
750
|
const handleSave = async () => {
|
|
797
751
|
const hasTarget = routeMode === 'agent' ? !!agentId : !!chatroomId
|
|
@@ -801,12 +755,16 @@ export function ConnectorSheet() {
|
|
|
801
755
|
? { agentId, chatroomId: null }
|
|
802
756
|
: { agentId: null, chatroomId }
|
|
803
757
|
try {
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
758
|
+
await saveConnectorMutation.mutateAsync({
|
|
759
|
+
id: editing?.id,
|
|
760
|
+
payload: {
|
|
761
|
+
name: name || `${platformConfig?.label} Bot`,
|
|
762
|
+
platform,
|
|
763
|
+
...routePayload,
|
|
764
|
+
credentialId: credentialId || null,
|
|
765
|
+
config,
|
|
766
|
+
},
|
|
767
|
+
})
|
|
810
768
|
setOpen(false)
|
|
811
769
|
setEditingId(null)
|
|
812
770
|
} catch (err: unknown) {
|
|
@@ -820,19 +778,12 @@ export function ConnectorSheet() {
|
|
|
820
778
|
if (!editing) return
|
|
821
779
|
setActionLoading(true)
|
|
822
780
|
try {
|
|
823
|
-
await
|
|
781
|
+
await connectorActionMutation.mutateAsync({ id: editing.id, action })
|
|
824
782
|
if (action === 'start' && editing.platform === 'whatsapp') {
|
|
825
783
|
setWaConnecting(true)
|
|
826
|
-
setWaAuthenticated(false)
|
|
827
|
-
setQrDataUrl(null)
|
|
828
|
-
// Don't reset waHasCreds — it will be updated by poll
|
|
829
784
|
} else if (action === 'stop') {
|
|
830
785
|
setWaConnecting(false)
|
|
831
|
-
setWaAuthenticated(false)
|
|
832
|
-
setWaHasCreds(false)
|
|
833
|
-
setQrDataUrl(null)
|
|
834
786
|
}
|
|
835
|
-
await loadConnectors()
|
|
836
787
|
} catch (err: unknown) {
|
|
837
788
|
setWaConnecting(false)
|
|
838
789
|
toast.error(`Failed to ${action}: ${errorMessage(err)}`)
|
|
@@ -845,8 +796,7 @@ export function ConnectorSheet() {
|
|
|
845
796
|
if (!editing) return
|
|
846
797
|
setDeleting(true)
|
|
847
798
|
try {
|
|
848
|
-
await
|
|
849
|
-
await loadConnectors()
|
|
799
|
+
await deleteConnectorMutation.mutateAsync(editing.id)
|
|
850
800
|
setConfirmDelete(false)
|
|
851
801
|
setOpen(false)
|
|
852
802
|
setEditingId(null)
|
|
@@ -861,13 +811,9 @@ export function ConnectorSheet() {
|
|
|
861
811
|
if (!editing) return
|
|
862
812
|
setActionLoading(true)
|
|
863
813
|
try {
|
|
864
|
-
await
|
|
865
|
-
setWaAuthenticated(false)
|
|
866
|
-
setWaHasCreds(false)
|
|
867
|
-
setQrDataUrl(null)
|
|
814
|
+
await connectorActionMutation.mutateAsync({ id: editing.id, action: 'repair' })
|
|
868
815
|
setWaConnecting(true)
|
|
869
816
|
setConfirmWhatsAppAction(null)
|
|
870
|
-
await loadConnectors()
|
|
871
817
|
} catch (err: unknown) {
|
|
872
818
|
toast.error(`Failed to ${mode === 'unlink' ? 'unlink' : 're-pair'}: ${errorMessage(err)}`)
|
|
873
819
|
} finally {
|
|
@@ -888,9 +834,9 @@ export function ConnectorSheet() {
|
|
|
888
834
|
if (advancedPlatformFields.some((field) => hasConfiguredValue(field.key))) badges.push('Platform overrides')
|
|
889
835
|
if (advancedAccessFields.some((field) => hasConfiguredValue(field.key)) || accessSnapshot?.pendingPairingRequests.length || accessSnapshot?.storedAllowedSenderIds.length) badges.push('Access lists')
|
|
890
836
|
if (COMMON_CONFIG_FIELDS.some((field) => hasConfiguredValue(field.key))) badges.push('Runtime policy')
|
|
891
|
-
if (doctorWarnings.length > 0 ||
|
|
837
|
+
if (doctorWarnings.length > 0 || runtimeConnector?.lastError) badges.push('Diagnostics')
|
|
892
838
|
return Array.from(new Set(badges))
|
|
893
|
-
}, [accessSnapshot?.pendingPairingRequests.length, accessSnapshot?.storedAllowedSenderIds.length, advancedAccessFields, advancedPlatformFields, doctorWarnings.length,
|
|
839
|
+
}, [accessSnapshot?.pendingPairingRequests.length, accessSnapshot?.storedAllowedSenderIds.length, advancedAccessFields, advancedPlatformFields, doctorWarnings.length, hasConfiguredValue, runtimeConnector?.lastError])
|
|
894
840
|
const configuredAdvancedCount = useMemo(() => {
|
|
895
841
|
const advancedKeys = new Set([
|
|
896
842
|
...advancedPlatformFields.map((field) => field.key),
|
|
@@ -1063,10 +1009,10 @@ export function ConnectorSheet() {
|
|
|
1063
1009
|
<div className="text-[14px] font-600 text-text">{platformConfig.label}</div>
|
|
1064
1010
|
<div className="flex items-center gap-2 mt-0.5">
|
|
1065
1011
|
<span className={`w-2 h-2 rounded-full ${
|
|
1066
|
-
|
|
1067
|
-
|
|
1012
|
+
runtimeConnector?.status === 'running' ? 'bg-green-400 shadow-[0_0_6px_rgba(74,222,128,0.5)]' :
|
|
1013
|
+
runtimeConnector?.status === 'error' ? 'bg-red-400' : 'bg-white/20'
|
|
1068
1014
|
}`} />
|
|
1069
|
-
<span className="text-[12px] text-text-3 capitalize">{editing.status}</span>
|
|
1015
|
+
<span className="text-[12px] text-text-3 capitalize">{runtimeConnector?.status || editing.status}</span>
|
|
1070
1016
|
</div>
|
|
1071
1017
|
</div>
|
|
1072
1018
|
</div>
|
|
@@ -1233,12 +1179,12 @@ export function ConnectorSheet() {
|
|
|
1233
1179
|
onClick={async () => {
|
|
1234
1180
|
setSavingCred(true)
|
|
1235
1181
|
try {
|
|
1236
|
-
const cred = await
|
|
1182
|
+
const cred = await createCredentialMutation.mutateAsync({
|
|
1237
1183
|
provider: platform,
|
|
1238
1184
|
name: newCredName.trim() || `${platformConfig.label} Bot Token`,
|
|
1239
1185
|
apiKey: newCredValue.trim(),
|
|
1240
1186
|
})
|
|
1241
|
-
await
|
|
1187
|
+
await credentialsQuery.refetch()
|
|
1242
1188
|
setCredentialId(cred.id)
|
|
1243
1189
|
setShowNewCred(false)
|
|
1244
1190
|
setNewCredName('')
|
|
@@ -1288,7 +1234,7 @@ export function ConnectorSheet() {
|
|
|
1288
1234
|
|
|
1289
1235
|
{/* Start/Stop controls for editing */}
|
|
1290
1236
|
{editing && (() => {
|
|
1291
|
-
const effectiveRunning =
|
|
1237
|
+
const effectiveRunning = runtimeConnector?.status === 'running' || waConnecting
|
|
1292
1238
|
return (
|
|
1293
1239
|
<div className="mb-6 p-4 rounded-[14px] border border-white/[0.06] bg-white/[0.01]">
|
|
1294
1240
|
<div className="flex items-center justify-between">
|
|
@@ -1297,10 +1243,10 @@ export function ConnectorSheet() {
|
|
|
1297
1243
|
<div className="text-[12px] text-text-3 mt-0.5 flex items-center gap-1.5">
|
|
1298
1244
|
<span className={`w-2 h-2 rounded-full inline-block ${
|
|
1299
1245
|
effectiveRunning ? 'bg-green-400 shadow-[0_0_6px_rgba(74,222,128,0.5)]' :
|
|
1300
|
-
|
|
1246
|
+
runtimeConnector?.status === 'error' ? 'bg-red-400' : 'bg-white/20'
|
|
1301
1247
|
}`} />
|
|
1302
1248
|
{effectiveRunning ? (waAuthenticated ? 'Connected and listening' : 'Connecting...') :
|
|
1303
|
-
|
|
1249
|
+
runtimeConnector?.status === 'error' ? 'Error — see below' : 'Not connected'}
|
|
1304
1250
|
</div>
|
|
1305
1251
|
</div>
|
|
1306
1252
|
{effectiveRunning ? (
|
|
@@ -1328,7 +1274,7 @@ export function ConnectorSheet() {
|
|
|
1328
1274
|
})()}
|
|
1329
1275
|
|
|
1330
1276
|
{/* WhatsApp QR code */}
|
|
1331
|
-
{editing &&
|
|
1277
|
+
{editing && platform === 'whatsapp' && (runtimeConnector?.status === 'running' || waConnecting) && qrDataUrl && (
|
|
1332
1278
|
<div className="mb-6 p-5 rounded-[14px] border border-white/[0.06] bg-white/[0.01] text-center"
|
|
1333
1279
|
style={{ animation: 'fade-in 0.3s ease-out' }}>
|
|
1334
1280
|
<div className="text-[13px] font-600 text-text-2 mb-1">Scan with WhatsApp</div>
|
|
@@ -1344,7 +1290,7 @@ export function ConnectorSheet() {
|
|
|
1344
1290
|
)}
|
|
1345
1291
|
|
|
1346
1292
|
{/* WhatsApp connected (authenticated, no QR) */}
|
|
1347
|
-
{editing &&
|
|
1293
|
+
{editing && platform === 'whatsapp' && (runtimeConnector?.status === 'running' || waConnecting) && !qrDataUrl && waAuthenticated && (
|
|
1348
1294
|
<div className="mb-6 p-5 rounded-[14px] border border-white/[0.06] bg-white/[0.01] text-center">
|
|
1349
1295
|
<div className="text-[13px] font-600 text-green-400 mb-1">Connected</div>
|
|
1350
1296
|
<p className="text-[11px] text-text-3 mb-3">WhatsApp is paired and listening for messages</p>
|
|
@@ -1360,7 +1306,7 @@ export function ConnectorSheet() {
|
|
|
1360
1306
|
)}
|
|
1361
1307
|
|
|
1362
1308
|
{/* WhatsApp waiting for QR / reconnecting (not yet authenticated, no QR yet) */}
|
|
1363
|
-
{editing &&
|
|
1309
|
+
{editing && platform === 'whatsapp' && (runtimeConnector?.status === 'running' || waConnecting) && !qrDataUrl && !waAuthenticated && (
|
|
1364
1310
|
<div className="mb-6 p-5 rounded-[14px] border border-white/[0.06] bg-white/[0.01] text-center">
|
|
1365
1311
|
<div className="flex items-center justify-center gap-2 mb-1">
|
|
1366
1312
|
<span className="w-3 h-3 rounded-full border-2 border-blue-500 border-t-transparent animate-spin" />
|
|
@@ -1387,10 +1333,10 @@ export function ConnectorSheet() {
|
|
|
1387
1333
|
)}
|
|
1388
1334
|
|
|
1389
1335
|
{/* Error display */}
|
|
1390
|
-
{
|
|
1336
|
+
{runtimeConnector?.lastError && (
|
|
1391
1337
|
<div className="mb-6 p-4 rounded-[14px] bg-red-500/[0.06] border border-red-500/15">
|
|
1392
1338
|
<div className="text-[12px] font-600 text-red-400 mb-1">Error</div>
|
|
1393
|
-
<div className="text-[12px] text-red-400/70 leading-[1.5] font-mono">{
|
|
1339
|
+
<div className="text-[12px] text-red-400/70 leading-[1.5] font-mono">{runtimeConnector.lastError}</div>
|
|
1394
1340
|
</div>
|
|
1395
1341
|
)}
|
|
1396
1342
|
|