CLI: guard empty channel removal labels

This commit is contained in:
Gustavo Madeira Santana
2026-04-17 02:58:04 -04:00
parent 16e187ba0f
commit d63966b0d8
2 changed files with 38 additions and 1 deletions

View File

@@ -112,4 +112,37 @@ describe("removeChannelConfigWizard", () => {
"Channel removed",
);
});
it("uses a placeholder when an unknown channel key sanitizes to empty", async () => {
const unsafeChannel = "\u001B[31m\u0007";
select.mockResolvedValueOnce(unsafeChannel).mockResolvedValueOnce("done");
const next = await removeChannelConfigWizard(
{
channels: {
[unsafeChannel]: { token: "secret" },
telegram: { token: "secret" },
},
} as never,
{} as never,
);
expect(select).toHaveBeenCalledWith(
expect.objectContaining({
options: expect.arrayContaining([
expect.objectContaining({ value: unsafeChannel, label: "<invalid channel key>" }),
]),
}),
);
expect(confirm).toHaveBeenCalledWith(
expect.objectContaining({
message: "Delete <invalid channel key> configuration from ~/.openclaw/openclaw.json?",
}),
);
expect(next.channels).toEqual({ telegram: { token: "secret" } });
expect(note).toHaveBeenCalledWith(
"<invalid channel key> removed from config.\nNote: credentials/sessions on disk are unchanged.",
"Channel removed",
);
});
});

View File

@@ -25,11 +25,15 @@ function listConfiguredChannelRemovalChoices(
return Object.keys(channels)
.map((id) => ({
id,
label: labelsById.get(id) ?? sanitizeTerminalText(id),
label: labelsById.get(id) ?? formatUnknownChannelRemovalLabel(id),
}))
.toSorted(compareChannelRemovalChoices);
}
function formatUnknownChannelRemovalLabel(id: string): string {
return sanitizeTerminalText(id) || "<invalid channel key>";
}
function compareChannelRemovalChoices(
left: ConfiguredChannelRemovalChoice,
right: ConfiguredChannelRemovalChoice,