fix(pairing): accept positional provider args

This commit is contained in:
Peter Steinberger
2026-01-10 16:36:43 +01:00
parent 41c8bdfada
commit 81f9093c3c
23 changed files with 112 additions and 52 deletions

View File

@@ -2,10 +2,11 @@ import { Command } from "commander";
import { describe, expect, it, vi } from "vitest";
const listProviderPairingRequests = vi.fn();
const approveProviderPairingCode = vi.fn();
vi.mock("../pairing/pairing-store.js", () => ({
listProviderPairingRequests,
approveProviderPairingCode: vi.fn(),
approveProviderPairingCode,
}));
vi.mock("../telegram/send.js", () => ({
@@ -61,6 +62,18 @@ describe("pairing cli", () => {
);
});
it("accepts provider as positional for list", async () => {
const { registerPairingCli } = await import("./pairing-cli.js");
listProviderPairingRequests.mockResolvedValueOnce([]);
const program = new Command();
program.name("test");
registerPairingCli(program);
await program.parseAsync(["pairing", "list", "telegram"], { from: "user" });
expect(listProviderPairingRequests).toHaveBeenCalledWith("telegram");
});
it("labels Discord ids as discordUserId", async () => {
const { registerPairingCli } = await import("./pairing-cli.js");
listProviderPairingRequests.mockResolvedValueOnce([
@@ -84,4 +97,31 @@ describe("pairing cli", () => {
expect.stringContaining("discordUserId=999"),
);
});
it("accepts provider as positional for approve (npm-run compatible)", async () => {
const { registerPairingCli } = await import("./pairing-cli.js");
approveProviderPairingCode.mockResolvedValueOnce({
id: "123",
entry: {
id: "123",
code: "ABCDEFGH",
createdAt: "2026-01-08T00:00:00Z",
lastSeenAt: "2026-01-08T00:00:00Z",
},
});
const log = vi.spyOn(console, "log").mockImplementation(() => {});
const program = new Command();
program.name("test");
registerPairingCli(program);
await program.parseAsync(["pairing", "approve", "telegram", "ABCDEFGH"], {
from: "user",
});
expect(approveProviderPairingCode).toHaveBeenCalledWith({
provider: "telegram",
code: "ABCDEFGH",
});
expect(log).toHaveBeenCalledWith(expect.stringContaining("Approved"));
});
});

View File

@@ -83,13 +83,17 @@ export function registerPairingCli(program: Command) {
pairing
.command("list")
.description("List pending pairing requests")
.requiredOption(
"--provider <provider>",
`Provider (${PROVIDERS.join(", ")})`,
)
.option("--provider <provider>", `Provider (${PROVIDERS.join(", ")})`)
.argument("[provider]", `Provider (${PROVIDERS.join(", ")})`)
.option("--json", "Print JSON", false)
.action(async (opts) => {
const provider = parseProvider(opts.provider);
.action(async (providerArg, opts) => {
const providerRaw = opts.provider ?? providerArg;
if (!providerRaw) {
throw new Error(
`Provider required. Use --provider <provider> or pass it as the first argument (expected one of: ${PROVIDERS.join(", ")})`,
);
}
const provider = parseProvider(providerRaw);
const requests = await listProviderPairingRequests(provider);
if (opts.json) {
console.log(JSON.stringify({ provider, requests }, null, 2));
@@ -111,20 +115,35 @@ export function registerPairingCli(program: Command) {
pairing
.command("approve")
.description("Approve a pairing code and allow that sender")
.requiredOption(
"--provider <provider>",
`Provider (${PROVIDERS.join(", ")})`,
.option("--provider <provider>", `Provider (${PROVIDERS.join(", ")})`)
.argument(
"<codeOrProvider>",
"Pairing code (or provider when using 2 args)",
)
.argument("<code>", "Pairing code (shown to the requester)")
.argument("[code]", "Pairing code (when provider is passed as the 1st arg)")
.option("--notify", "Notify the requester on the same provider", false)
.action(async (code, opts) => {
const provider = parseProvider(opts.provider);
.action(async (codeOrProvider, code, opts) => {
const providerRaw = opts.provider ?? codeOrProvider;
const resolvedCode = opts.provider ? codeOrProvider : code;
if (!opts.provider && !code) {
throw new Error(
`Usage: clawdbot pairing approve <provider> <code> (or: clawdbot pairing approve --provider <provider> <code>)`,
);
}
if (opts.provider && code != null) {
throw new Error(
`Too many arguments. Use: clawdbot pairing approve --provider <provider> <code>`,
);
}
const provider = parseProvider(providerRaw);
const approved = await approveProviderPairingCode({
provider,
code: String(code),
code: String(resolvedCode),
});
if (!approved) {
throw new Error(`No pending pairing request found for code: ${code}`);
throw new Error(
`No pending pairing request found for code: ${String(resolvedCode)}`,
);
}
console.log(`Approved ${provider} sender ${approved.id}.`);