CLI: default pairing channel for pairing commands

This commit is contained in:
Vignesh Natarajan
2026-02-20 19:59:54 -08:00
parent be756b9a89
commit c0d5fc8d1e
3 changed files with 41 additions and 4 deletions

View File

@@ -163,6 +163,15 @@ describe("pairing cli", () => {
expect(listChannelPairingRequests).toHaveBeenCalledWith("zalo");
});
it("defaults list to the sole available channel", async () => {
listPairingChannels.mockReturnValueOnce(["slack"]);
listChannelPairingRequests.mockResolvedValueOnce([]);
await runPairing(["pairing", "list"]);
expect(listChannelPairingRequests).toHaveBeenCalledWith("slack");
});
it("accepts channel as positional for approve (npm-run compatible)", async () => {
mockApprovedPairing();
@@ -199,4 +208,20 @@ describe("pairing cli", () => {
accountId: "yy",
});
});
it("defaults approve to the sole available channel when only code is provided", async () => {
listPairingChannels.mockReturnValueOnce(["slack"]);
mockApprovedPairing();
await runPairing(["pairing", "approve", "ABCDEFGH"]);
expect(approveChannelPairingCode).toHaveBeenCalledWith({
channel: "slack",
code: "ABCDEFGH",
});
});
it("keeps approve usage error when multiple channels exist and channel is omitted", async () => {
await expect(runPairing(["pairing", "approve", "ABCDEFGH"])).rejects.toThrow("Usage:");
});
});

View File

@@ -68,7 +68,7 @@ export function registerPairingCli(program: Command) {
.argument("[channel]", `Channel (${channels.join(", ")})`)
.option("--json", "Print JSON", false)
.action(async (channelArg, opts) => {
const channelRaw = opts.channel ?? channelArg;
const channelRaw = opts.channel ?? channelArg ?? (channels.length === 1 ? channels[0] : "");
if (!channelRaw) {
throw new Error(
`Channel required. Use --channel <channel> or pass it as the first argument (expected one of: ${channels.join(", ")})`,
@@ -120,9 +120,20 @@ export function registerPairingCli(program: Command) {
.argument("[code]", "Pairing code (when channel is passed as the 1st arg)")
.option("--notify", "Notify the requester on the same channel", false)
.action(async (codeOrChannel, code, opts) => {
const channelRaw = opts.channel ?? codeOrChannel;
const resolvedCode = opts.channel ? codeOrChannel : code;
if (!opts.channel && !code) {
const defaultChannel = channels.length === 1 ? channels[0] : "";
const usingExplicitChannel = Boolean(opts.channel);
const hasPositionalCode = code != null;
const channelRaw = usingExplicitChannel
? opts.channel
: hasPositionalCode
? codeOrChannel
: defaultChannel;
const resolvedCode = usingExplicitChannel
? codeOrChannel
: hasPositionalCode
? code
: codeOrChannel;
if (!channelRaw || !resolvedCode) {
throw new Error(
`Usage: ${formatCliCommand("openclaw pairing approve <channel> <code>")} (or: ${formatCliCommand("openclaw pairing approve --channel <channel> <code>")})`,
);