// Onboarding adapter for ADP OpenClaw channel plugin
import type {
ChannelOnboardingAdapter,
OpenClawConfig,
WizardPrompter,
} from "openclaw/plugin-sdk";
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk";
const channel = "adp-openclaw" as const;
type AdpOpenclawChannelConfig = {
enabled?: boolean;
wsUrl?: string;
clientToken?: string;
signKey?: string;
};
function getChannelConfig(cfg: OpenClawConfig): AdpOpenclawChannelConfig | undefined {
return cfg.channels?.["adp-openclaw"] as AdpOpenclawChannelConfig | undefined;
}
function isConfigured(channelCfg?: AdpOpenclawChannelConfig): boolean {
// clientToken is required for configured status
const clientToken = channelCfg?.clientToken?.trim() || process.env.ADP_OPENCLAW_CLIENT_TOKEN;
return Boolean(clientToken);
}
function updateAdpOpenclawConfig(
cfg: OpenClawConfig,
updates: { wsUrl?: string; clientToken?: string; signKey?: string; enabled?: boolean },
): OpenClawConfig {
return {
...cfg,
channels: {
...cfg.channels,
"adp-openclaw": {
...cfg.channels?.["adp-openclaw"],
...updates,
enabled: updates.enabled ?? true,
},
},
};
}
async function noteAdpOpenclawSetup(prompter: WizardPrompter): Promise<void> {
await prompter.note(
[
"ADP OpenClaw connects to a WebSocket server for real-time messaging.",
"You need a clientToken to authenticate with the server.",
"The signKey is used for HMAC signature generation (default: ADPOpenClaw).",
].join("\n"),
"ADP OpenClaw setup",
);
}
export const adpOpenclawOnboardingAdapter: ChannelOnboardingAdapter = {
channel,
getStatus: async ({ cfg }) => {
const channelCfg = getChannelConfig(cfg);
const configured = isConfigured(channelCfg);
return {
channel,
configured,
statusLines: [`ADP OpenClaw: ${configured ? "configured" : "needs clientToken"}`],
selectionHint: configured ? "configured" : "requires clientToken",
quickstartScore: configured ? 1 : 10,
};
},
configure: async ({ cfg, prompter }) => {
let next = cfg;
const accountId = DEFAULT_ACCOUNT_ID;
await noteAdpOpenclawSetup(prompter);
const channelCfg = getChannelConfig(next);
const existingClientToken = channelCfg?.clientToken?.trim();
const existingSignKey = channelCfg?.signKey?.trim();
// Check for env vars
const envClientToken = process.env.ADP_OPENCLAW_CLIENT_TOKEN?.trim();
const envSignKey = process.env.ADP_OPENCLAW_SIGN_KEY?.trim();
if (envClientToken) {
const useEnv = await prompter.confirm({
message: "ADP_OPENCLAW_CLIENT_TOKEN detected in env. Use environment variables?",
initialValue: true,
});
if (useEnv) {
next = updateAdpOpenclawConfig(next, { enabled: true });
return { cfg: next, accountId };
}
}
// Prompt for clientToken (required)
const clientTokenInput = await prompter.text({
message: "Client Token",
placeholder: "your-client-token",
initialValue: existingClientToken || undefined,
validate: (value) => (String(value ?? "").trim() ? undefined : "Required"),
});
const clientToken = String(clientTokenInput).trim();
// Prompt for signKey (optional, has default)
const signKeyInput = await prompter.text({
message: "Sign Key (press Enter for default: ADPOpenClaw)",
placeholder: "ADPOpenClaw",
initialValue: existingSignKey || envSignKey || undefined,
});
const signKey = String(signKeyInput ?? "").trim() || undefined;
next = updateAdpOpenclawConfig(next, {
clientToken,
...(signKey ? { signKey } : {}),
enabled: true,
});
return { cfg: next, accountId };
},
disable: (cfg) => {
return {
...cfg,
channels: {
...cfg.channels,
"adp-openclaw": {
...cfg.channels?.["adp-openclaw"],
enabled: false,
},
},
};
},
};