fix: resolve gateway URL at runtime via /api/studio fallback (#66)
Fixes #57 — NEXT_PUBLIC_GATEWAY_URL is a build-time variable that gets baked into the client bundle. Changing it in .env and restarting has no effect without a rebuild. - normalizeLocalGatewayDefaults now accepts the sanitized public form ({url, tokenConfigured}) from /api/studio - When no saved gateway URL exists, prefer runtime localGatewayDefaults (from openclaw.json or CLAW3D_GATEWAY_URL env var) over the potentially stale build-time NEXT_PUBLIC_GATEWAY_URL - loadLocalGatewayDefaults falls back to CLAW3D_GATEWAY_URL/TOKEN env vars when openclaw.json is absent - Added runtime env vars documentation to .env.example and README Co-authored-by: robotica4us-collab <neo@openclaw.ai> Made-with: Cursor
This commit is contained in:
committed by
iamlukethedev
parent
456cfae771
commit
e71b62444c
@@ -103,10 +103,14 @@ const DEFAULT_UPSTREAM_GATEWAY_URL =
|
||||
|
||||
const normalizeLocalGatewayDefaults = (value: unknown): StudioGatewaySettings | null => {
|
||||
if (!value || typeof value !== "object") return null;
|
||||
const raw = value as { url?: unknown; token?: unknown };
|
||||
const raw = value as { url?: unknown; token?: unknown; tokenConfigured?: unknown };
|
||||
const url = typeof raw.url === "string" ? raw.url.trim() : "";
|
||||
if (!url) return null;
|
||||
// Accept both full settings ({ url, token }) and the sanitized public
|
||||
// form ({ url, tokenConfigured }) returned by /api/studio. When only
|
||||
// tokenConfigured is present the actual token isn't available on the
|
||||
// client — leave it empty so the connection dialog can prompt if needed.
|
||||
const token = typeof raw.token === "string" ? raw.token.trim() : "";
|
||||
if (!url || !token) return null;
|
||||
return { url, token };
|
||||
};
|
||||
|
||||
@@ -548,12 +552,22 @@ export const useGatewayConnection = (
|
||||
const settings = envelope.settings ?? null;
|
||||
const gateway = settings?.gateway ?? null;
|
||||
if (cancelled) return;
|
||||
setLocalGatewayDefaults(normalizeLocalGatewayDefaults(envelope.localGatewayDefaults));
|
||||
const nextGatewayUrl = gateway?.url?.trim() ? gateway.url : DEFAULT_UPSTREAM_GATEWAY_URL;
|
||||
const nextToken =
|
||||
gateway && "token" in gateway && typeof gateway.token === "string"
|
||||
? gateway.token
|
||||
: "";
|
||||
const normalizedDefaults = normalizeLocalGatewayDefaults(envelope.localGatewayDefaults);
|
||||
setLocalGatewayDefaults(normalizedDefaults);
|
||||
// When the user has no saved gateway URL, prefer the runtime
|
||||
// localGatewayDefaults (from openclaw.json / CLAW3D_GATEWAY_URL)
|
||||
// over the build-time NEXT_PUBLIC_GATEWAY_URL which may be stale
|
||||
// or empty if the operator forgot to rebuild after .env changes.
|
||||
const hasSavedUrl = Boolean(gateway?.url?.trim());
|
||||
const resolvedUrl = hasSavedUrl
|
||||
? gateway!.url
|
||||
: normalizedDefaults?.url || DEFAULT_UPSTREAM_GATEWAY_URL;
|
||||
const nextGatewayUrl = resolvedUrl;
|
||||
const nextToken = hasSavedUrl
|
||||
? (gateway && "token" in gateway && typeof gateway.token === "string"
|
||||
? gateway.token
|
||||
: "")
|
||||
: normalizedDefaults?.token ?? "";
|
||||
loadedGatewaySettings.current = {
|
||||
gatewayUrl: nextGatewayUrl.trim(),
|
||||
token: nextToken,
|
||||
|
||||
@@ -44,8 +44,15 @@ const readOpenclawGatewayDefaults = (): { url: string; token: string } | null =>
|
||||
}
|
||||
};
|
||||
|
||||
export const loadLocalGatewayDefaults = () => {
|
||||
return readOpenclawGatewayDefaults();
|
||||
export const loadLocalGatewayDefaults = (): { url: string; token: string } | null => {
|
||||
const fromFile = readOpenclawGatewayDefaults();
|
||||
if (fromFile) return fromFile;
|
||||
// Fall back to env vars so operators can configure the gateway URL at
|
||||
// runtime without openclaw.json and without a rebuild.
|
||||
const envUrl = process.env.CLAW3D_GATEWAY_URL?.trim();
|
||||
const envToken = process.env.CLAW3D_GATEWAY_TOKEN?.trim();
|
||||
if (envUrl) return { url: envUrl, token: envToken ?? "" };
|
||||
return null;
|
||||
};
|
||||
|
||||
export const loadStudioSettings = (): StudioSettings => {
|
||||
|
||||
Reference in New Issue
Block a user