This commit is contained in:
oogway 2026-01-30 15:54:25 +00:00 committed by GitHub
commit 7cdf45a8c2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 85 additions and 4 deletions

View File

@ -13,7 +13,31 @@ export const GATEWAY_CLIENT_IDS = {
PROBE: "openclaw-probe",
} as const;
export type GatewayClientId = (typeof GATEWAY_CLIENT_IDS)[keyof typeof GATEWAY_CLIENT_IDS];
// Legacy client IDs for backward compatibility
// These are deprecated but still accepted to prevent breakage during upgrades
export const LEGACY_GATEWAY_CLIENT_IDS = {
// Clawdbot era (pre-2026.1.29)
CLAWDBOT_CONTROL_UI: "clawdbot-control-ui",
CLAWDBOT_MACOS_APP: "clawdbot-macos",
CLAWDBOT_IOS_APP: "clawdbot-ios",
CLAWDBOT_ANDROID_APP: "clawdbot-android",
CLAWDBOT_PROBE: "clawdbot-probe",
// Moltbot era (intermediate rebrand)
MOLTBOT_CONTROL_UI: "moltbot-control-ui",
MOLTBOT_MACOS_APP: "moltbot-macos",
MOLTBOT_IOS_APP: "moltbot-ios",
MOLTBOT_ANDROID_APP: "moltbot-android",
MOLTBOT_PROBE: "moltbot-probe",
} as const;
export const ALL_GATEWAY_CLIENT_IDS = {
...GATEWAY_CLIENT_IDS,
...LEGACY_GATEWAY_CLIENT_IDS,
} as const;
export type GatewayClientId =
| (typeof GATEWAY_CLIENT_IDS)[keyof typeof GATEWAY_CLIENT_IDS]
| (typeof LEGACY_GATEWAY_CLIENT_IDS)[keyof typeof LEGACY_GATEWAY_CLIENT_IDS];
// Back-compat naming (internal): these values are IDs, not display names.
export const GATEWAY_CLIENT_NAMES = GATEWAY_CLIENT_IDS;
@ -42,7 +66,7 @@ export type GatewayClientInfo = {
instanceId?: string;
};
const GATEWAY_CLIENT_ID_SET = new Set<GatewayClientId>(Object.values(GATEWAY_CLIENT_IDS));
const GATEWAY_CLIENT_ID_SET = new Set<GatewayClientId>(Object.values(ALL_GATEWAY_CLIENT_IDS));
const GATEWAY_CLIENT_MODE_SET = new Set<GatewayClientMode>(Object.values(GATEWAY_CLIENT_MODES));
export function normalizeGatewayClientId(raw?: string | null): GatewayClientId | undefined {

View File

@ -1,6 +1,6 @@
import { Type } from "@sinclair/typebox";
import { SESSION_LABEL_MAX_LENGTH } from "../../../sessions/session-label.js";
import { GATEWAY_CLIENT_IDS, GATEWAY_CLIENT_MODES } from "../client-info.js";
import { ALL_GATEWAY_CLIENT_IDS, GATEWAY_CLIENT_MODES } from "../client-info.js";
export const NonEmptyString = Type.String({ minLength: 1 });
export const SessionLabelString = Type.String({
@ -9,7 +9,7 @@ export const SessionLabelString = Type.String({
});
export const GatewayClientIdSchema = Type.Union(
Object.values(GATEWAY_CLIENT_IDS).map((value) => Type.Literal(value)),
Object.values(ALL_GATEWAY_CLIENT_IDS).map((value) => Type.Literal(value)),
);
export const GatewayClientModeSchema = Type.Union(

View File

@ -91,3 +91,60 @@ test("accepts openclaw-android as a valid gateway client id", async () => {
ws.close();
});
test("accepts legacy clawdbot-ios as a valid gateway client id (backward compat)", async () => {
const ws = new WebSocket(`ws://127.0.0.1:${port}`);
await new Promise<void>((resolve) => ws.once("open", resolve));
const res = await connectReq(ws, { clientId: "clawdbot-ios", platform: "ios" });
// We don't care if auth fails here; we only care that schema validation accepts the client id.
// A schema rejection would close the socket before sending a response.
if (!res.ok) {
// allow unauthorized error when gateway requires auth
// but reject schema validation errors
const message = String(res.error?.message ?? "");
if (message.includes("invalid connect params")) {
throw new Error(message);
}
}
ws.close();
});
test("accepts legacy clawdbot-android as a valid gateway client id (backward compat)", async () => {
const ws = new WebSocket(`ws://127.0.0.1:${port}`);
await new Promise<void>((resolve) => ws.once("open", resolve));
const res = await connectReq(ws, { clientId: "clawdbot-android", platform: "android" });
// We don't care if auth fails here; we only care that schema validation accepts the client id.
// A schema rejection would close the socket before sending a response.
if (!res.ok) {
// allow unauthorized error when gateway requires auth
// but reject schema validation errors
const message = String(res.error?.message ?? "");
if (message.includes("invalid connect params")) {
throw new Error(message);
}
}
ws.close();
});
test("accepts legacy moltbot-macos as a valid gateway client id (backward compat)", async () => {
const ws = new WebSocket(`ws://127.0.0.1:${port}`);
await new Promise<void>((resolve) => ws.once("open", resolve));
const res = await connectReq(ws, { clientId: "moltbot-macos", platform: "macos" });
// We don't care if auth fails here; we only care that schema validation accepts the client id.
// A schema rejection would close the socket before sending a response.
if (!res.ok) {
// allow unauthorized error when gateway requires auth
// but reject schema validation errors
const message = String(res.error?.message ?? "");
if (message.includes("invalid connect params")) {
throw new Error(message);
}
}
ws.close();
});