@swarmclawai/swarmclaw 0.7.7 → 0.8.0
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 +12 -14
- package/next.config.ts +13 -2
- package/package.json +4 -2
- package/src/app/api/agents/[id]/thread/route.ts +9 -0
- package/src/app/api/agents/route.ts +4 -0
- package/src/app/api/agents/thread-route.test.ts +133 -0
- package/src/app/api/approvals/route.test.ts +148 -0
- package/src/app/api/canvas/[sessionId]/route.ts +3 -1
- package/src/app/api/chatrooms/[id]/chat/route.ts +4 -2
- package/src/app/api/chats/[id]/devserver/route.ts +48 -7
- package/src/app/api/chats/[id]/messages/route.ts +42 -18
- package/src/app/api/chats/[id]/route.ts +1 -1
- package/src/app/api/chats/[id]/stop/route.ts +5 -4
- package/src/app/api/chats/route.ts +23 -2
- package/src/app/api/clawhub/install/route.ts +28 -8
- package/src/app/api/connectors/[id]/route.ts +46 -3
- package/src/app/api/connectors/route.ts +12 -8
- package/src/app/api/external-agents/route.test.ts +165 -0
- package/src/app/api/gateways/[id]/health/route.ts +27 -12
- package/src/app/api/gateways/[id]/route.ts +2 -0
- package/src/app/api/gateways/health-route.test.ts +135 -0
- package/src/app/api/gateways/route.ts +2 -0
- package/src/app/api/mcp-servers/route.test.ts +130 -0
- package/src/app/api/openclaw/deploy/route.ts +38 -5
- package/src/app/api/plugins/install/route.ts +46 -6
- package/src/app/api/plugins/marketplace/route.ts +48 -15
- package/src/app/api/preview-server/route.ts +26 -11
- package/src/app/api/projects/[id]/route.ts +6 -2
- package/src/app/api/projects/route.ts +4 -3
- package/src/app/api/schedules/[id]/run/route.ts +4 -0
- package/src/app/api/schedules/route.test.ts +86 -0
- package/src/app/api/schedules/route.ts +6 -1
- package/src/app/api/secrets/[id]/route.ts +1 -0
- package/src/app/api/secrets/route.ts +2 -1
- package/src/app/api/settings/route.ts +2 -0
- package/src/app/api/setup/check-provider/route.test.ts +19 -0
- package/src/app/api/setup/check-provider/route.ts +40 -10
- package/src/app/api/skills/[id]/route.ts +12 -0
- package/src/app/api/skills/import/route.ts +14 -12
- package/src/app/api/skills/route.ts +13 -1
- package/src/app/api/tasks/[id]/route.ts +10 -1
- package/src/app/api/tasks/import/github/route.test.ts +65 -0
- package/src/app/api/tasks/import/github/route.ts +337 -0
- package/src/app/api/wallets/[id]/approve/route.ts +17 -3
- package/src/app/api/wallets/[id]/route.ts +79 -33
- package/src/app/api/wallets/[id]/send/route.ts +19 -33
- package/src/app/api/wallets/route.ts +78 -61
- package/src/app/api/webhooks/[id]/route.ts +33 -6
- package/src/app/api/webhooks/route.test.ts +272 -0
- package/src/cli/index.js +1 -0
- package/src/cli/spec.js +1 -0
- package/src/components/agents/agent-card.tsx +9 -2
- package/src/components/agents/agent-chat-list.tsx +18 -2
- package/src/components/agents/agent-list.tsx +1 -0
- package/src/components/agents/agent-sheet.tsx +257 -38
- package/src/components/agents/inspector-panel.tsx +41 -0
- package/src/components/canvas/canvas-panel.tsx +236 -65
- package/src/components/chat/chat-area.tsx +36 -19
- package/src/components/chat/chat-card.tsx +36 -13
- package/src/components/chat/chat-header.tsx +48 -16
- package/src/components/chat/chat-list.tsx +28 -4
- package/src/components/chat/checkpoint-timeline.tsx +50 -34
- package/src/components/chat/delegation-banner.test.ts +14 -1
- package/src/components/chat/delegation-banner.tsx +1 -1
- package/src/components/chat/message-bubble.tsx +208 -145
- package/src/components/chat/message-list.tsx +48 -19
- package/src/components/chatrooms/chatroom-message.tsx +2 -2
- package/src/components/chatrooms/chatroom-sheet.tsx +16 -2
- package/src/components/connectors/connector-health.tsx +1 -1
- package/src/components/connectors/connector-list.tsx +7 -2
- package/src/components/connectors/connector-sheet.tsx +337 -148
- package/src/components/gateways/gateway-sheet.tsx +2 -2
- package/src/components/layout/app-layout.tsx +40 -23
- package/src/components/mcp-servers/mcp-server-list.tsx +26 -5
- package/src/components/mcp-servers/mcp-server-sheet.tsx +19 -2
- package/src/components/openclaw/openclaw-deploy-panel.tsx +269 -21
- package/src/components/plugins/plugin-list.tsx +45 -9
- package/src/components/plugins/plugin-sheet.tsx +55 -7
- package/src/components/projects/project-detail.tsx +217 -0
- package/src/components/projects/project-sheet.tsx +176 -4
- package/src/components/providers/provider-list.tsx +2 -1
- package/src/components/providers/provider-sheet.tsx +21 -2
- package/src/components/schedules/schedule-card.tsx +25 -1
- package/src/components/schedules/schedule-sheet.tsx +44 -2
- package/src/components/secrets/secret-sheet.tsx +21 -2
- package/src/components/shared/agent-switch-dialog.tsx +12 -1
- package/src/components/shared/bottom-sheet.tsx +13 -3
- package/src/components/shared/command-palette.tsx +8 -1
- package/src/components/shared/confirm-dialog.tsx +19 -4
- package/src/components/shared/connector-platform-icon.test.ts +28 -0
- package/src/components/shared/connector-platform-icon.tsx +39 -6
- package/src/components/shared/settings/plugin-manager.tsx +29 -6
- package/src/components/shared/settings/section-capability-policy.tsx +45 -3
- package/src/components/shared/settings/section-voice.tsx +11 -3
- package/src/components/skills/skill-list.tsx +25 -0
- package/src/components/skills/skill-sheet.tsx +84 -12
- package/src/components/tasks/approvals-panel.tsx +289 -34
- package/src/components/tasks/task-board.tsx +410 -25
- package/src/components/tasks/task-card.tsx +66 -8
- package/src/components/tasks/task-sheet.tsx +16 -4
- package/src/components/ui/dialog.tsx +2 -2
- package/src/components/wallets/wallet-approval-dialog.tsx +4 -2
- package/src/components/wallets/wallet-panel.tsx +435 -90
- package/src/components/wallets/wallet-section.tsx +198 -48
- package/src/components/webhooks/webhook-sheet.tsx +22 -2
- package/src/lib/approval-display.ts +20 -0
- package/src/lib/canvas-content.ts +198 -0
- package/src/lib/chat-artifact-summary.ts +165 -0
- package/src/lib/chat-display.test.ts +91 -0
- package/src/lib/chat-display.ts +58 -0
- package/src/lib/chat-streaming-state.test.ts +47 -1
- package/src/lib/chat-streaming-state.ts +42 -0
- package/src/lib/ollama-model.ts +10 -0
- package/src/lib/openclaw-endpoint.test.ts +8 -0
- package/src/lib/openclaw-endpoint.ts +6 -1
- package/src/lib/plugin-install-cors.ts +46 -0
- package/src/lib/plugin-sources.test.ts +43 -0
- package/src/lib/plugin-sources.ts +77 -0
- package/src/lib/providers/ollama.ts +16 -6
- package/src/lib/providers/openclaw.test.ts +54 -0
- package/src/lib/providers/openclaw.ts +127 -11
- package/src/lib/schedule-dedupe-advanced.test.ts +1335 -0
- package/src/lib/schedule-dedupe.test.ts +66 -1
- package/src/lib/schedule-dedupe.ts +169 -12
- package/src/lib/schedule-origin.test.ts +20 -0
- package/src/lib/schedule-origin.ts +15 -0
- package/src/lib/server/__fixtures__/fake-mcp-stdio-server.mjs +27 -0
- package/src/lib/server/agent-availability.ts +16 -0
- package/src/lib/server/agent-runtime-config.ts +12 -4
- package/src/lib/server/agent-thread-session.test.ts +51 -0
- package/src/lib/server/agent-thread-session.ts +7 -0
- package/src/lib/server/approval-match.ts +205 -0
- package/src/lib/server/approvals-auto-approve.test.ts +538 -1
- package/src/lib/server/approvals.ts +214 -1
- package/src/lib/server/assistant-control.test.ts +29 -0
- package/src/lib/server/assistant-control.ts +23 -0
- package/src/lib/server/build-llm.test.ts +79 -0
- package/src/lib/server/build-llm.ts +14 -4
- package/src/lib/server/canvas-content.test.ts +32 -0
- package/src/lib/server/canvas-content.ts +6 -0
- package/src/lib/server/capability-router.test.ts +33 -0
- package/src/lib/server/capability-router.ts +80 -19
- package/src/lib/server/chat-execution-advanced.test.ts +651 -0
- package/src/lib/server/chat-execution-disabled.test.ts +94 -0
- package/src/lib/server/chat-execution-tool-events.test.ts +157 -0
- package/src/lib/server/chat-execution.ts +378 -73
- package/src/lib/server/clawhub-client.test.ts +14 -8
- package/src/lib/server/connectors/manager-reconnect.test.ts +47 -0
- package/src/lib/server/connectors/manager.test.ts +1147 -0
- package/src/lib/server/connectors/manager.ts +461 -137
- package/src/lib/server/connectors/pairing.ts +26 -5
- package/src/lib/server/connectors/types.ts +2 -0
- package/src/lib/server/connectors/whatsapp.test.ts +134 -0
- package/src/lib/server/connectors/whatsapp.ts +271 -47
- package/src/lib/server/context-manager.ts +6 -1
- package/src/lib/server/daemon-state.ts +84 -47
- package/src/lib/server/data-dir.test.ts +37 -0
- package/src/lib/server/data-dir.ts +20 -1
- package/src/lib/server/delegation-jobs-advanced.test.ts +513 -0
- package/src/lib/server/devserver-launch.test.ts +60 -0
- package/src/lib/server/devserver-launch.ts +85 -0
- package/src/lib/server/elevenlabs.test.ts +247 -1
- package/src/lib/server/elevenlabs.ts +147 -43
- package/src/lib/server/ethereum.ts +590 -0
- package/src/lib/server/eval/agent-regression-advanced.test.ts +302 -0
- package/src/lib/server/eval/agent-regression.test.ts +18 -1
- package/src/lib/server/eval/agent-regression.ts +383 -11
- package/src/lib/server/evm-swap.ts +475 -0
- package/src/lib/server/execution-log.ts +1 -0
- package/src/lib/server/heartbeat-service-timer.test.ts +173 -0
- package/src/lib/server/heartbeat-service.ts +20 -11
- package/src/lib/server/heartbeat-wake.test.ts +112 -0
- package/src/lib/server/heartbeat-wake.ts +338 -57
- package/src/lib/server/main-agent-loop-advanced.test.ts +538 -0
- package/src/lib/server/main-agent-loop.test.ts +260 -0
- package/src/lib/server/main-agent-loop.ts +559 -14
- package/src/lib/server/mcp-client.test.ts +16 -0
- package/src/lib/server/mcp-client.ts +25 -0
- package/src/lib/server/memory-integration.test.ts +719 -0
- package/src/lib/server/memory-policy.test.ts +43 -0
- package/src/lib/server/memory-policy.ts +132 -0
- package/src/lib/server/memory-tiers.test.ts +60 -0
- package/src/lib/server/memory-tiers.ts +16 -0
- package/src/lib/server/ollama-runtime.ts +58 -0
- package/src/lib/server/openclaw-deploy.test.ts +109 -1
- package/src/lib/server/openclaw-deploy.ts +557 -81
- package/src/lib/server/openclaw-gateway.test.ts +131 -0
- package/src/lib/server/openclaw-gateway.ts +10 -4
- package/src/lib/server/openclaw-health.test.ts +35 -0
- package/src/lib/server/openclaw-health.ts +215 -47
- package/src/lib/server/orchestrator-lg.ts +3 -2
- package/src/lib/server/orchestrator.ts +2 -0
- package/src/lib/server/plugins-advanced.test.ts +351 -0
- package/src/lib/server/plugins.ts +211 -6
- package/src/lib/server/project-context.ts +162 -0
- package/src/lib/server/project-utils.ts +150 -0
- package/src/lib/server/queue-advanced.test.ts +528 -0
- package/src/lib/server/queue-followups.test.ts +409 -2
- package/src/lib/server/queue-reconcile.test.ts +128 -0
- package/src/lib/server/queue.ts +527 -68
- package/src/lib/server/scheduler.ts +29 -1
- package/src/lib/server/session-note.test.ts +36 -0
- package/src/lib/server/session-note.ts +42 -0
- package/src/lib/server/session-run-manager.ts +83 -4
- package/src/lib/server/session-tools/canvas.ts +14 -12
- package/src/lib/server/session-tools/connector-inputs.test.ts +37 -0
- package/src/lib/server/session-tools/connector.test.ts +138 -0
- package/src/lib/server/session-tools/connector.ts +366 -54
- package/src/lib/server/session-tools/context.ts +17 -3
- package/src/lib/server/session-tools/crud.ts +484 -84
- package/src/lib/server/session-tools/delegate-fallback.test.ts +103 -0
- package/src/lib/server/session-tools/delegate-resume.test.ts +50 -0
- package/src/lib/server/session-tools/delegate.ts +102 -10
- package/src/lib/server/session-tools/discovery-approvals.test.ts +142 -0
- package/src/lib/server/session-tools/discovery.ts +80 -12
- package/src/lib/server/session-tools/file-normalize.test.ts +36 -0
- package/src/lib/server/session-tools/file.ts +43 -4
- package/src/lib/server/session-tools/human-loop.ts +35 -5
- package/src/lib/server/session-tools/index.ts +44 -9
- package/src/lib/server/session-tools/manage-connectors.test.ts +139 -0
- package/src/lib/server/session-tools/manage-schedules-advanced.test.ts +564 -0
- package/src/lib/server/session-tools/manage-schedules.test.ts +283 -0
- package/src/lib/server/session-tools/manage-tasks-advanced.test.ts +852 -0
- package/src/lib/server/session-tools/manage-tasks.test.ts +114 -0
- package/src/lib/server/session-tools/memory.test.ts +93 -0
- package/src/lib/server/session-tools/memory.ts +554 -75
- package/src/lib/server/session-tools/normalize-tool-args.ts +1 -1
- package/src/lib/server/session-tools/platform-access.test.ts +58 -0
- package/src/lib/server/session-tools/platform.ts +60 -19
- package/src/lib/server/session-tools/plugin-creator.ts +57 -1
- package/src/lib/server/session-tools/primitive-tools.test.ts +6 -0
- package/src/lib/server/session-tools/schedule.ts +6 -1
- package/src/lib/server/session-tools/shell-normalize.test.ts +25 -1
- package/src/lib/server/session-tools/shell.ts +22 -3
- package/src/lib/server/session-tools/wallet-tool.test.ts +254 -0
- package/src/lib/server/session-tools/wallet.ts +1374 -139
- package/src/lib/server/session-tools/web-inputs.test.ts +178 -0
- package/src/lib/server/session-tools/web.ts +621 -70
- package/src/lib/server/skill-discovery.ts +128 -0
- package/src/lib/server/skill-eligibility.test.ts +84 -0
- package/src/lib/server/skill-eligibility.ts +95 -0
- package/src/lib/server/skill-prompt-budget.test.ts +102 -0
- package/src/lib/server/skill-prompt-budget.ts +125 -0
- package/src/lib/server/skills-normalize.test.ts +54 -0
- package/src/lib/server/skills-normalize.ts +372 -26
- package/src/lib/server/solana.ts +214 -29
- package/src/lib/server/storage.ts +65 -36
- package/src/lib/server/stream-agent-chat.test.ts +437 -2
- package/src/lib/server/stream-agent-chat.ts +957 -79
- package/src/lib/server/system-events.ts +1 -1
- package/src/lib/server/tool-aliases.ts +2 -0
- package/src/lib/server/tool-capability-policy-advanced.test.ts +502 -0
- package/src/lib/server/tool-capability-policy.test.ts +24 -0
- package/src/lib/server/tool-capability-policy.ts +29 -1
- package/src/lib/server/tool-loop-detection.test.ts +105 -0
- package/src/lib/server/tool-loop-detection.ts +260 -0
- package/src/lib/server/tool-planning.test.ts +44 -0
- package/src/lib/server/tool-planning.ts +271 -0
- package/src/lib/server/wallet-execution.test.ts +198 -0
- package/src/lib/server/wallet-portfolio.test.ts +98 -0
- package/src/lib/server/wallet-portfolio.ts +724 -0
- package/src/lib/server/wallet-service.test.ts +57 -0
- package/src/lib/server/wallet-service.ts +213 -0
- package/src/lib/server/watch-jobs-advanced.test.ts +594 -0
- package/src/lib/server/watch-jobs.ts +17 -2
- package/src/lib/server/workspace-context.ts +111 -0
- package/src/lib/skill-save-payload.test.ts +39 -0
- package/src/lib/skill-save-payload.ts +37 -0
- package/src/lib/tasks.ts +28 -0
- package/src/lib/tool-definitions.ts +2 -1
- package/src/lib/tool-event-summary.test.ts +30 -0
- package/src/lib/tool-event-summary.ts +37 -0
- package/src/lib/validation/schemas.ts +1 -0
- package/src/lib/wallet-transactions.test.ts +75 -0
- package/src/lib/wallet-transactions.ts +43 -0
- package/src/lib/wallet.test.ts +17 -0
- package/src/lib/wallet.ts +183 -0
- package/src/proxy.test.ts +31 -0
- package/src/proxy.ts +34 -2
- package/src/stores/use-chat-store.ts +15 -1
- package/src/types/index.ts +249 -14
|
@@ -2,7 +2,7 @@ import fs from 'fs'
|
|
|
2
2
|
import http from 'http'
|
|
3
3
|
import https from 'https'
|
|
4
4
|
import type { StreamChatOptions } from './index'
|
|
5
|
-
import {
|
|
5
|
+
import { resolveOllamaRuntimeConfig } from '@/lib/server/ollama-runtime'
|
|
6
6
|
|
|
7
7
|
const IMAGE_EXTS = /\.(png|jpg|jpeg|gif|webp|bmp)$/i
|
|
8
8
|
const TEXT_EXTS = /\.(txt|md|csv|json|xml|html|js|ts|tsx|jsx|py|go|rs|java|c|cpp|h|yml|yaml|toml|env|log|sh|sql|css|scss)$/i
|
|
@@ -10,9 +10,19 @@ const TEXT_EXTS = /\.(txt|md|csv|json|xml|html|js|ts|tsx|jsx|py|go|rs|java|c|cpp
|
|
|
10
10
|
export function streamOllamaChat({ session, message, imagePath, apiKey, write, active, loadHistory, onUsage, signal }: StreamChatOptions): Promise<string> {
|
|
11
11
|
return new Promise((resolve) => {
|
|
12
12
|
const messages = buildMessages(session, message, imagePath, loadHistory)
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
const runtime = resolveOllamaRuntimeConfig({
|
|
14
|
+
model: session.model,
|
|
15
|
+
apiKey,
|
|
16
|
+
apiEndpoint: session.apiEndpoint,
|
|
17
|
+
})
|
|
18
|
+
const model = runtime.model || 'llama3'
|
|
19
|
+
const endpoint = runtime.endpoint
|
|
20
|
+
if (runtime.useCloud && !runtime.apiKey) {
|
|
21
|
+
write(`data: ${JSON.stringify({ t: 'err', text: 'Ollama Cloud model requires an API key. Set OLLAMA_API_KEY or attach an Ollama credential.' })}\n\n`)
|
|
22
|
+
active.delete(session.id)
|
|
23
|
+
resolve('')
|
|
24
|
+
return
|
|
25
|
+
}
|
|
16
26
|
|
|
17
27
|
const parsed = new URL(endpoint)
|
|
18
28
|
const isHttps = parsed.protocol === 'https:'
|
|
@@ -43,8 +53,8 @@ export function streamOllamaChat({ session, message, imagePath, apiKey, write, a
|
|
|
43
53
|
const headers: Record<string, string> = {
|
|
44
54
|
'Content-Type': 'application/json',
|
|
45
55
|
}
|
|
46
|
-
if (apiKey) {
|
|
47
|
-
headers['Authorization'] = `Bearer ${apiKey}`
|
|
56
|
+
if (runtime.apiKey) {
|
|
57
|
+
headers['Authorization'] = `Bearer ${runtime.apiKey}`
|
|
48
58
|
}
|
|
49
59
|
|
|
50
60
|
const apiReq = transport.request({
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import assert from 'node:assert/strict'
|
|
2
|
+
import { afterEach, test } from 'node:test'
|
|
3
|
+
|
|
4
|
+
import { resolveGatewayAgentId } from './openclaw'
|
|
5
|
+
import { loadAgents, saveAgents } from '../server/storage'
|
|
6
|
+
import type { Agent } from '@/types'
|
|
7
|
+
|
|
8
|
+
const originalAgents = loadAgents({ includeTrashed: true })
|
|
9
|
+
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
saveAgents(originalAgents)
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test('resolveGatewayAgentId prefers the matching OpenClaw agent name from storage', () => {
|
|
15
|
+
const agents = loadAgents({ includeTrashed: true })
|
|
16
|
+
agents['openclaw-agent-test'] = {
|
|
17
|
+
id: 'openclaw-agent-test',
|
|
18
|
+
name: 'Research Operator',
|
|
19
|
+
systemPrompt: '',
|
|
20
|
+
provider: 'openclaw',
|
|
21
|
+
model: 'default',
|
|
22
|
+
createdAt: Date.now(),
|
|
23
|
+
updatedAt: Date.now(),
|
|
24
|
+
} as Agent
|
|
25
|
+
saveAgents(agents)
|
|
26
|
+
|
|
27
|
+
const resolved = resolveGatewayAgentId({
|
|
28
|
+
id: 'session-1',
|
|
29
|
+
agentId: 'openclaw-agent-test',
|
|
30
|
+
shortcutForAgentId: 'openclaw-agent-test',
|
|
31
|
+
name: 'Some Other Name',
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
assert.equal(resolved, 'research-operator')
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
test('resolveGatewayAgentId honors explicit OpenClaw agent ids when provided', () => {
|
|
38
|
+
const resolved = resolveGatewayAgentId({
|
|
39
|
+
id: 'session-2',
|
|
40
|
+
openclawAgentId: 'Custom Gateway Agent',
|
|
41
|
+
name: 'Ignored',
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
assert.equal(resolved, 'custom-gateway-agent')
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
test('resolveGatewayAgentId falls back to the session name when no OpenClaw agent is available', () => {
|
|
48
|
+
const resolved = resolveGatewayAgentId({
|
|
49
|
+
id: 'session-3',
|
|
50
|
+
name: 'Fallback Agent Name',
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
assert.equal(resolved, 'fallback-agent-name')
|
|
54
|
+
})
|
|
@@ -3,6 +3,14 @@ import crypto, { randomUUID } from 'crypto'
|
|
|
3
3
|
import fs from 'fs'
|
|
4
4
|
import path from 'path'
|
|
5
5
|
import type { StreamChatOptions } from './index'
|
|
6
|
+
import type { Agent } from '@/types'
|
|
7
|
+
import { deriveOpenClawWsUrl } from '@/lib/openclaw-endpoint'
|
|
8
|
+
import { normalizeOpenClawAgentId } from '@/lib/openclaw-agent-id'
|
|
9
|
+
import { loadAgents } from '../server/storage'
|
|
10
|
+
import {
|
|
11
|
+
resolveOpenClawGatewayAgentIdFromList,
|
|
12
|
+
type OpenClawGatewayAgentSummary,
|
|
13
|
+
} from '../server/openclaw-agent-resolver'
|
|
6
14
|
|
|
7
15
|
// --- Device Identity (Ed25519 keypair for gateway auth) ---
|
|
8
16
|
|
|
@@ -105,13 +113,6 @@ export function getDeviceId(): string {
|
|
|
105
113
|
|
|
106
114
|
// --- Protocol helpers ---
|
|
107
115
|
|
|
108
|
-
function normalizeWsUrl(raw: string): string {
|
|
109
|
-
let url = raw.replace(/\/+$/, '')
|
|
110
|
-
if (!/^(https?|wss?):\/\//i.test(url)) url = `http://${url}`
|
|
111
|
-
url = url.replace(/^ws:/i, 'http:').replace(/^wss:/i, 'https:')
|
|
112
|
-
return url.replace(/^http:/i, 'ws:').replace(/^https:/i, 'wss:')
|
|
113
|
-
}
|
|
114
|
-
|
|
115
116
|
/**
|
|
116
117
|
* Build connect params for the OpenClaw gateway protocol.
|
|
117
118
|
*
|
|
@@ -277,6 +278,121 @@ async function connectToGateway(
|
|
|
277
278
|
return wsConnect(wsUrl, token, true, timeoutMs)
|
|
278
279
|
}
|
|
279
280
|
|
|
281
|
+
export function resolveGatewayAgentId(session: Record<string, unknown> & { id: string }): string {
|
|
282
|
+
const explicit = typeof session.openclawAgentId === 'string' && session.openclawAgentId.trim()
|
|
283
|
+
? session.openclawAgentId.trim()
|
|
284
|
+
: ''
|
|
285
|
+
if (explicit) return normalizeOpenClawAgentId(explicit)
|
|
286
|
+
|
|
287
|
+
const agentId = typeof session.shortcutForAgentId === 'string' && session.shortcutForAgentId.trim()
|
|
288
|
+
? session.shortcutForAgentId.trim()
|
|
289
|
+
: typeof session.agentId === 'string' && session.agentId.trim()
|
|
290
|
+
? session.agentId.trim()
|
|
291
|
+
: ''
|
|
292
|
+
if (agentId) {
|
|
293
|
+
const agents = loadAgents({ includeTrashed: true })
|
|
294
|
+
const agent = agents[agentId] as { name?: string; provider?: string } | undefined
|
|
295
|
+
if (agent?.provider === 'openclaw' && typeof agent.name === 'string' && agent.name.trim()) {
|
|
296
|
+
return normalizeOpenClawAgentId(agent.name)
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const sessionName = typeof session.name === 'string' && session.name.trim() ? session.name.trim() : ''
|
|
301
|
+
if (sessionName) return normalizeOpenClawAgentId(sessionName)
|
|
302
|
+
return 'main'
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
async function rpcOnConnectedGateway(
|
|
306
|
+
ws: InstanceType<typeof WebSocket>,
|
|
307
|
+
method: string,
|
|
308
|
+
params: unknown,
|
|
309
|
+
timeoutMs = 5_000,
|
|
310
|
+
): Promise<unknown> {
|
|
311
|
+
return new Promise((resolve, reject) => {
|
|
312
|
+
const requestId = randomUUID()
|
|
313
|
+
let settled = false
|
|
314
|
+
|
|
315
|
+
const cleanup = () => {
|
|
316
|
+
clearTimeout(timer)
|
|
317
|
+
ws.off('message', onMessage)
|
|
318
|
+
ws.off('close', onClose)
|
|
319
|
+
ws.off('error', onError)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const finish = (fn: () => void) => {
|
|
323
|
+
if (settled) return
|
|
324
|
+
settled = true
|
|
325
|
+
cleanup()
|
|
326
|
+
fn()
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const onMessage = (data: unknown) => {
|
|
330
|
+
try {
|
|
331
|
+
const msg = JSON.parse(String(data))
|
|
332
|
+
if (msg.type !== 'res' || msg.id !== requestId) return
|
|
333
|
+
if (msg.ok) {
|
|
334
|
+
finish(() => resolve(msg.payload))
|
|
335
|
+
} else {
|
|
336
|
+
const message = typeof msg.error?.message === 'string'
|
|
337
|
+
? msg.error.message
|
|
338
|
+
: `${method} failed`
|
|
339
|
+
finish(() => reject(new Error(message)))
|
|
340
|
+
}
|
|
341
|
+
} catch {
|
|
342
|
+
// Ignore unrelated or malformed frames while waiting for our response.
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const onClose = () => finish(() => reject(new Error('Gateway closed before RPC completed')))
|
|
347
|
+
const onError = (err: Error) => finish(() => reject(err))
|
|
348
|
+
const timer = setTimeout(() => {
|
|
349
|
+
finish(() => reject(new Error(`${method} timed out`)))
|
|
350
|
+
}, timeoutMs)
|
|
351
|
+
|
|
352
|
+
ws.on('message', onMessage)
|
|
353
|
+
ws.on('close', onClose)
|
|
354
|
+
ws.on('error', onError)
|
|
355
|
+
ws.send(JSON.stringify({ type: 'req', id: requestId, method, params }))
|
|
356
|
+
})
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
async function resolveConnectedGatewayAgentId(
|
|
360
|
+
ws: InstanceType<typeof WebSocket>,
|
|
361
|
+
session: Record<string, unknown> & { id: string },
|
|
362
|
+
): Promise<string> {
|
|
363
|
+
const fallback = resolveGatewayAgentId(session)
|
|
364
|
+
const explicitAgentId = typeof session.openclawAgentId === 'string' && session.openclawAgentId.trim()
|
|
365
|
+
? session.openclawAgentId.trim()
|
|
366
|
+
: ''
|
|
367
|
+
const localAgentId = typeof session.shortcutForAgentId === 'string' && session.shortcutForAgentId.trim()
|
|
368
|
+
? session.shortcutForAgentId.trim()
|
|
369
|
+
: typeof session.agentId === 'string' && session.agentId.trim()
|
|
370
|
+
? session.agentId.trim()
|
|
371
|
+
: ''
|
|
372
|
+
const agentRef = explicitAgentId || localAgentId || fallback
|
|
373
|
+
|
|
374
|
+
try {
|
|
375
|
+
const payload = await rpcOnConnectedGateway(ws, 'agents.list', {})
|
|
376
|
+
const gatewayAgents = Array.isArray((payload as { agents?: unknown[] } | undefined)?.agents)
|
|
377
|
+
? (payload as { agents: OpenClawGatewayAgentSummary[] }).agents
|
|
378
|
+
: []
|
|
379
|
+
if (gatewayAgents.length === 0) return fallback
|
|
380
|
+
|
|
381
|
+
const localAgents = localAgentId ? loadAgents({ includeTrashed: true }) : {}
|
|
382
|
+
const localAgent = localAgentId
|
|
383
|
+
? (localAgents[localAgentId] as Agent | undefined) || null
|
|
384
|
+
: null
|
|
385
|
+
|
|
386
|
+
return resolveOpenClawGatewayAgentIdFromList({
|
|
387
|
+
agentRef,
|
|
388
|
+
gatewayAgents,
|
|
389
|
+
localAgent: localAgent?.provider === 'openclaw' ? localAgent : null,
|
|
390
|
+
}) || fallback
|
|
391
|
+
} catch {
|
|
392
|
+
return fallback
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
280
396
|
// --- Provider ---
|
|
281
397
|
|
|
282
398
|
export function streamOpenClawChat({ session, message, imagePath, apiKey, write, active, signal }: StreamChatOptions): Promise<string> {
|
|
@@ -285,9 +401,8 @@ export function streamOpenClawChat({ session, message, imagePath, apiKey, write,
|
|
|
285
401
|
prompt = `[The user has shared an image at: ${imagePath}]\n\n${message}`
|
|
286
402
|
}
|
|
287
403
|
|
|
288
|
-
const wsUrl = session.apiEndpoint ?
|
|
404
|
+
const wsUrl = session.apiEndpoint ? deriveOpenClawWsUrl(session.apiEndpoint) : 'ws://127.0.0.1:18789'
|
|
289
405
|
const token = apiKey || session.apiKey || undefined
|
|
290
|
-
|
|
291
406
|
return new Promise((resolve) => {
|
|
292
407
|
let fullResponse = ''
|
|
293
408
|
let settled = false
|
|
@@ -302,13 +417,14 @@ export function streamOpenClawChat({ session, message, imagePath, apiKey, write,
|
|
|
302
417
|
resolve(fullResponse)
|
|
303
418
|
}
|
|
304
419
|
|
|
305
|
-
connectToGateway(wsUrl, token).then((result) => {
|
|
420
|
+
connectToGateway(wsUrl, token).then(async (result) => {
|
|
306
421
|
if (!result.ok || !result.ws) {
|
|
307
422
|
finish(result.message)
|
|
308
423
|
return
|
|
309
424
|
}
|
|
310
425
|
|
|
311
426
|
const ws = result.ws
|
|
427
|
+
const gatewayAgentId = await resolveConnectedGatewayAgentId(ws, session)
|
|
312
428
|
const timeout = setTimeout(() => {
|
|
313
429
|
ws.close()
|
|
314
430
|
finish('OpenClaw gateway timed out after 120s.')
|
|
@@ -328,7 +444,7 @@ export function streamOpenClawChat({ session, message, imagePath, apiKey, write,
|
|
|
328
444
|
method: 'agent',
|
|
329
445
|
params: {
|
|
330
446
|
message: prompt,
|
|
331
|
-
agentId:
|
|
447
|
+
agentId: gatewayAgentId,
|
|
332
448
|
timeout: 120,
|
|
333
449
|
idempotencyKey: randomUUID(),
|
|
334
450
|
},
|