diff --git a/src/app/api/integrations/probe/route.ts b/src/app/api/integrations/probe/route.ts index 9598dac..e70d057 100644 --- a/src/app/api/integrations/probe/route.ts +++ b/src/app/api/integrations/probe/route.ts @@ -13,6 +13,7 @@ export const dynamic = 'force-dynamic' type ProbeBody = { target?: 'openclaw' | 'vault' | 'apisix' gatewayUrl?: string + gatewayOrigin?: string gatewayToken?: string vaultUrl?: string vaultNamespace?: string @@ -64,7 +65,21 @@ function formatGatewayError(error: OpenClawGatewayError | null, client: OpenClaw return error.message } -async function probeOpenClaw(body: ProbeBody): Promise { +function resolveGatewayOrigin(override: string | undefined, request: NextRequest): string { + const explicit = override?.trim() + if (explicit) { + return explicit + } + + const headerOrigin = request.headers.get('origin')?.trim() + if (headerOrigin) { + return headerOrigin + } + + return request.nextUrl.origin +} + +async function probeOpenClaw(body: ProbeBody, request: NextRequest): Promise { const config = await resolveOpenClawGatewayConfig({ gatewayUrl: body.gatewayUrl, gatewayToken: body.gatewayToken, @@ -84,6 +99,7 @@ async function probeOpenClaw(body: ProbeBody): Promise { try { await client.connect({ gatewayUrl: config.gatewayUrl, + gatewayOrigin: resolveGatewayOrigin(body.gatewayOrigin, request), gatewayToken: config.gatewayToken, clientLabel: 'console.svc.plus Probe', }) @@ -223,7 +239,7 @@ export async function POST(request: NextRequest): Promise { switch (body.target) { case 'openclaw': - return probeOpenClaw(body) + return probeOpenClaw(body, request) case 'vault': return probeVault(body) case 'apisix': diff --git a/src/app/api/openclaw/assistant/route.ts b/src/app/api/openclaw/assistant/route.ts index 399b72e..5cef89a 100644 --- a/src/app/api/openclaw/assistant/route.ts +++ b/src/app/api/openclaw/assistant/route.ts @@ -18,6 +18,7 @@ export const dynamic = 'force-dynamic' type BootstrapBody = { action: 'bootstrap' gatewayUrl?: string + gatewayOrigin?: string gatewayToken?: string vaultUrl?: string vaultNamespace?: string @@ -31,6 +32,7 @@ type BootstrapBody = { type SendBody = { action: 'send' gatewayUrl?: string + gatewayOrigin?: string gatewayToken?: string vaultUrl?: string vaultNamespace?: string @@ -112,7 +114,21 @@ function resolveSessionKey(params: { return makeAgentSessionKey(params.agentId?.trim() ?? '', params.mainSessionKey) } -async function handleBootstrap(body: BootstrapBody): Promise { +function resolveGatewayOrigin(override: string | undefined, request: NextRequest): string { + const explicit = override?.trim() + if (explicit) { + return explicit + } + + const headerOrigin = request.headers.get('origin')?.trim() + if (headerOrigin) { + return headerOrigin + } + + return request.nextUrl.origin +} + +async function handleBootstrap(body: BootstrapBody, request: NextRequest): Promise { const gateway = await resolveOpenClawGatewayConfig({ gatewayUrl: body.gatewayUrl, gatewayToken: body.gatewayToken, @@ -132,6 +148,7 @@ async function handleBootstrap(body: BootstrapBody): Promise { try { const connected = await client.connect({ gatewayUrl: gateway.gatewayUrl, + gatewayOrigin: resolveGatewayOrigin(body.gatewayOrigin, request), gatewayToken: gateway.gatewayToken, }) @@ -178,7 +195,7 @@ async function handleBootstrap(body: BootstrapBody): Promise { } } -async function handleSend(body: SendBody): Promise { +async function handleSend(body: SendBody, request: NextRequest): Promise { const gateway = await resolveOpenClawGatewayConfig({ gatewayUrl: body.gatewayUrl, gatewayToken: body.gatewayToken, @@ -258,6 +275,7 @@ async function handleSend(body: SendBody): Promise { client = new OpenClawGatewayClient() const connected = await client.connect({ gatewayUrl: gateway.gatewayUrl, + gatewayOrigin: resolveGatewayOrigin(body.gatewayOrigin, request), gatewayToken: gateway.gatewayToken, }) @@ -396,11 +414,11 @@ export async function POST(request: NextRequest): Promise { } if (body.action === 'bootstrap') { - return handleBootstrap(body) + return handleBootstrap(body, request) } if (body.action === 'send') { - return handleSend(body) + return handleSend(body, request) } return jsonError('Unsupported assistant action.', 400, 'UNSUPPORTED_ACTION') diff --git a/src/components/AskAIDialog.tsx b/src/components/AskAIDialog.tsx index c55cfdd..3647a9c 100644 --- a/src/components/AskAIDialog.tsx +++ b/src/components/AskAIDialog.tsx @@ -30,6 +30,7 @@ export function AskAIDialog({ const router = useRouter(); const resolvedDefaults: IntegrationDefaults = defaults ?? { openclawUrl: "", + openclawOrigin: "", openclawTokenConfigured: false, vaultUrl: "", vaultNamespace: "", diff --git a/src/components/openclaw/OpenClawAssistantPane.tsx b/src/components/openclaw/OpenClawAssistantPane.tsx index f5d78af..01bc6d5 100644 --- a/src/components/openclaw/OpenClawAssistantPane.tsx +++ b/src/components/openclaw/OpenClawAssistantPane.tsx @@ -230,6 +230,7 @@ export function OpenClawAssistantPane({ ); const applyDefaults = useOpenClawConsoleStore((state) => state.applyDefaults); const openclawUrl = useOpenClawConsoleStore((state) => state.openclawUrl); + const openclawOrigin = useOpenClawConsoleStore((state) => state.openclawOrigin); const openclawToken = useOpenClawConsoleStore((state) => state.openclawToken); const vaultUrl = useOpenClawConsoleStore((state) => state.vaultUrl); const vaultNamespace = useOpenClawConsoleStore( @@ -436,6 +437,7 @@ export function OpenClawAssistantPane({ body: JSON.stringify({ action: "bootstrap", gatewayUrl: openclawUrl, + gatewayOrigin: openclawOrigin, gatewayToken: openclawToken, vaultUrl, vaultNamespace, @@ -479,6 +481,7 @@ export function OpenClawAssistantPane({ copy.connectFailed, copy.serverMissing, openclawToken, + openclawOrigin, openclawUrl, vaultNamespace, vaultSecretKey, @@ -585,6 +588,7 @@ export function OpenClawAssistantPane({ body: JSON.stringify({ action: "send", gatewayUrl: openclawUrl, + gatewayOrigin: openclawOrigin, gatewayToken: openclawToken, vaultUrl, vaultNamespace, @@ -668,6 +672,7 @@ export function OpenClawAssistantPane({ isChinese, mainSessionKey, openclawToken, + openclawOrigin, openclawUrl, vaultNamespace, vaultSecretKey, diff --git a/src/lib/openclaw/types.ts b/src/lib/openclaw/types.ts index 9089e5a..d9232dd 100644 --- a/src/lib/openclaw/types.ts +++ b/src/lib/openclaw/types.ts @@ -79,6 +79,7 @@ export type OpenClawStreamEvent = export type IntegrationDefaults = { openclawUrl: string + openclawOrigin: string openclawTokenConfigured: boolean vaultUrl: string vaultNamespace: string diff --git a/src/modules/extensions/builtin/user-center/components/IntegrationsConsole.tsx b/src/modules/extensions/builtin/user-center/components/IntegrationsConsole.tsx index 669fabe..35e677f 100644 --- a/src/modules/extensions/builtin/user-center/components/IntegrationsConsole.tsx +++ b/src/modules/extensions/builtin/user-center/components/IntegrationsConsole.tsx @@ -89,6 +89,7 @@ function stringValue(value: unknown): string | undefined { const EMPTY_DEFAULTS: IntegrationDefaults = { openclawUrl: "", + openclawOrigin: "", openclawTokenConfigured: false, vaultUrl: "", vaultNamespace: "", @@ -118,6 +119,7 @@ export function IntegrationsConsole({ const applyDefaults = useOpenClawConsoleStore((state) => state.applyDefaults); const openclawUrl = useOpenClawConsoleStore((state) => state.openclawUrl); + const openclawOrigin = useOpenClawConsoleStore((state) => state.openclawOrigin); const openclawToken = useOpenClawConsoleStore((state) => state.openclawToken); const vaultUrl = useOpenClawConsoleStore((state) => state.vaultUrl); const vaultNamespace = useOpenClawConsoleStore( @@ -135,6 +137,9 @@ export function IntegrationsConsole({ const setOpenclawUrl = useOpenClawConsoleStore( (state) => state.setOpenclawUrl, ); + const setOpenclawOrigin = useOpenClawConsoleStore( + (state) => state.setOpenclawOrigin, + ); const setOpenclawToken = useOpenClawConsoleStore( (state) => state.setOpenclawToken, ); @@ -240,6 +245,7 @@ export function IntegrationsConsole({ body: JSON.stringify({ target, gatewayUrl: openclawUrl, + gatewayOrigin: openclawOrigin, gatewayToken: openclawToken, vaultUrl, vaultNamespace, @@ -382,6 +388,19 @@ export function IntegrationsConsole({ + + setOpenclawOrigin(event.target.value)} + className={inputClassName()} + placeholder="https://preview.svc.plus" + /> + +