From 8e8a8399a0aa320677b668eb8cfb08cf4dca563d Mon Sep 17 00:00:00 2001 From: Jesse Merhi <79823012+jesse-merhi@users.noreply.github.com> Date: Mon, 10 Aug 2026 00:04:29 +1000 Subject: [PATCH] fix(signal): normalize linked account results --- extensions/signal/src/setup-surface.test.ts | 6 +++++- extensions/signal/src/setup-surface.ts | 20 +++++++++++--------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/extensions/signal/src/setup-surface.test.ts b/extensions/signal/src/setup-surface.test.ts index 1bbffd4870d5..797bfb4d9b6c 100644 --- a/extensions/signal/src/setup-surface.test.ts +++ b/extensions/signal/src/setup-surface.test.ts @@ -173,7 +173,7 @@ describe("signalSetupWizard QR linking", () => { it("does not offer a discovered identity owned by a formatted sibling account", async () => { listSignalCliAccountsMock.mockResolvedValueOnce({ ok: true, - accounts: ["+15555550123"], + accounts: ["signal:+1 (555) 555-0123"], }); const transport = { kind: "managed-native" as const, @@ -482,6 +482,10 @@ describe("signalSetupWizard QR linking", () => { }); it("does not assign a QR-linked identity already owned by a sibling account", async () => { + linkSignalCliAccountMock.mockResolvedValueOnce({ + ok: true, + associatedAccount: "signal:+1 (555) 555-0123", + }); const transport = { kind: "managed-native" as const, cliPath: "/opt/signal-cli", diff --git a/extensions/signal/src/setup-surface.ts b/extensions/signal/src/setup-surface.ts index 5e61698e5bbd..246fc71c442b 100644 --- a/extensions/signal/src/setup-surface.ts +++ b/extensions/signal/src/setup-surface.ts @@ -135,9 +135,10 @@ export const signalSetupWizard: ChannelSetupWizard = { return candidate.accountId !== resolvedAccount.accountId && account ? [account] : []; }), ); - const availableAccounts = existingAccounts.accounts.filter( - (account) => !siblingAccounts.has(account), - ); + const availableAccounts = existingAccounts.accounts.flatMap((account) => { + const normalized = normalizeSignalAccountInput(account); + return normalized && !siblingAccounts.has(normalized) ? [normalized] : []; + }); const firstAvailableAccount = availableAccounts[0]; if (firstAvailableAccount) { const accountToReuse = @@ -211,27 +212,28 @@ export const signalSetupWizard: ChannelSetupWizard = { // A successful signal-cli result means the account is already linked on disk. // Preserve that authoritative result even if cancellation raced its final output. preparedCredentialValues[SIGNAL_LINK_COMPLETED_INPUT_KEY] = "true"; - if (linkResult.associatedAccount) { - if (siblingAccounts.has(linkResult.associatedAccount)) { + const linkedAccount = normalizeSignalAccountInput(linkResult.associatedAccount); + if (linkedAccount) { + if (siblingAccounts.has(linkedAccount)) { // The device link succeeded, but this setup target must not claim a sibling's identity. // Mark it handled so the later number prompt cannot recreate the same collision. preparedCredentialValues[SIGNAL_LINKED_ACCOUNT_INPUT_KEY] = "true"; await prompter.note( - `${linkResult.associatedAccount} is already assigned to another OpenClaw Signal account. The selected account was not changed.`, + `${linkedAccount} is already assigned to another OpenClaw Signal account. The selected account was not changed.`, "Signal account linking", ); return { credentialValues: preparedCredentialValues }; } - if (configuredAccount && linkResult.associatedAccount !== configuredAccount) { + if (configuredAccount && linkedAccount !== configuredAccount) { const replaceConfiguredAccount = await prompter.confirm({ - message: `Use ${linkResult.associatedAccount} instead of configured Signal account ${configuredAccount}?`, + message: `Use ${linkedAccount} instead of configured Signal account ${configuredAccount}?`, initialValue: false, }); if (!replaceConfiguredAccount) { return { credentialValues: preparedCredentialValues }; } } - preparedCredentialValues.signalNumber = linkResult.associatedAccount; + preparedCredentialValues.signalNumber = linkedAccount; preparedCredentialValues[SIGNAL_LINKED_ACCOUNT_INPUT_KEY] = "true"; } else { await prompter.note(