fix: honor nostr setup account label

This commit is contained in:
Tak Hoffman 2026-04-03 12:25:48 -05:00
parent 17060ca124
commit 35256d6f1d
No known key found for this signature in database
2 changed files with 54 additions and 15 deletions

View File

@ -203,6 +203,34 @@ describe("nostr setup wizard", () => {
expect(result.cfg.channels?.nostr?.privateKey).toBe(TEST_HEX_PRIVATE_KEY);
expect(result.cfg.channels?.nostr?.relays).toEqual(TEST_SETUP_RELAY_URLS);
});
it("preserves the selected named account label during setup", async () => {
const prompter = createTestWizardPrompter({
text: vi.fn(async ({ message }: { message: string }) => {
if (message === "Nostr private key (nsec... or hex)") {
return TEST_HEX_PRIVATE_KEY;
}
if (message === "Relay URLs (comma-separated, optional)") {
return "";
}
throw new Error(`Unexpected prompt: ${message}`);
}) as WizardPrompter["text"],
});
const result = await runSetupWizardConfigure({
configure: nostrConfigure,
cfg: {} as OpenClawConfig,
prompter,
options: {},
accountOverrides: {
nostr: "work",
},
});
expect(result.accountId).toBe("work");
expect(result.cfg.channels?.nostr?.defaultAccount).toBe("work");
expect(result.cfg.channels?.nostr?.privateKey).toBe(TEST_HEX_PRIVATE_KEY);
});
});
describe("nostr account helpers", () => {

View File

@ -40,6 +40,13 @@ const NOSTR_ALLOW_FROM_HELP_LINES = [
`Docs: ${formatDocsLink("/channels/nostr", "channels/nostr")}`,
];
function buildNostrSetupPatch(accountId: string, patch: Record<string, unknown>) {
return {
...(accountId !== DEFAULT_ACCOUNT_ID ? { defaultAccount: accountId } : {}),
...patch,
};
}
function parseRelayUrls(raw: string): { relays: string[]; error?: string } {
const entries = splitSetupEntries(raw);
const relays: string[] = [];
@ -89,12 +96,12 @@ const nostrDmPolicy: ChannelSetupDmPolicy = createTopLevelChannelDmPolicy({
});
export const nostrSetupAdapter: ChannelSetupAdapter = {
resolveAccountId: () => DEFAULT_ACCOUNT_ID,
applyAccountName: ({ cfg, name }) =>
resolveAccountId: ({ accountId }) => accountId?.trim() || DEFAULT_ACCOUNT_ID,
applyAccountName: ({ cfg, accountId, name }) =>
patchTopLevelChannelConfigSection({
cfg,
channel,
patch: name?.trim() ? { name: name.trim() } : {},
patch: buildNostrSetupPatch(accountId, name?.trim() ? { name: name.trim() } : {}),
}),
validateInput: ({ input }) => {
const typedInput = input as {
@ -118,7 +125,7 @@ export const nostrSetupAdapter: ChannelSetupAdapter = {
}
return null;
},
applyAccountConfig: ({ cfg, input }) => {
applyAccountConfig: ({ cfg, accountId, input }) => {
const typedInput = input as {
useEnv?: boolean;
privateKey?: string;
@ -132,17 +139,18 @@ export const nostrSetupAdapter: ChannelSetupAdapter = {
channel,
enabled: true,
clearFields: typedInput.useEnv ? ["privateKey"] : undefined,
patch: {
patch: buildNostrSetupPatch(accountId, {
...(typedInput.useEnv ? {} : { privateKey: typedInput.privateKey?.trim() }),
...(relayResult.relays.length > 0 ? { relays: relayResult.relays } : {}),
},
}),
});
},
};
export const nostrSetupWizard: ChannelSetupWizard = {
channel,
resolveAccountIdForConfigure: () => DEFAULT_ACCOUNT_ID,
resolveAccountIdForConfigure: ({ accountOverride, defaultAccountId }) =>
accountOverride?.trim() || defaultAccountId,
resolveShouldPromptAccountIds: () => false,
status: createStandardChannelSetupStatus({
channelLabel: "Nostr",
@ -170,13 +178,13 @@ export const nostrSetupWizard: ChannelSetupWizard = {
accountId === DEFAULT_ACCOUNT_ID &&
Boolean(process.env.NOSTR_PRIVATE_KEY?.trim()) &&
!hasConfiguredSecretInput(resolveNostrAccount({ cfg, accountId }).config.privateKey),
apply: async ({ cfg }) =>
apply: async ({ cfg, accountId }) =>
patchTopLevelChannelConfigSection({
cfg,
channel,
enabled: true,
clearFields: ["privateKey"],
patch: {},
patch: buildNostrSetupPatch(accountId, {}),
}),
},
credentials: [
@ -200,20 +208,20 @@ export const nostrSetupWizard: ChannelSetupWizard = {
envValue: process.env.NOSTR_PRIVATE_KEY?.trim(),
};
},
applyUseEnv: async ({ cfg }) =>
applyUseEnv: async ({ cfg, accountId }) =>
patchTopLevelChannelConfigSection({
cfg,
channel,
enabled: true,
clearFields: ["privateKey"],
patch: {},
patch: buildNostrSetupPatch(accountId, {}),
}),
applySet: async ({ cfg, resolvedValue }) =>
applySet: async ({ cfg, accountId, resolvedValue }) =>
patchTopLevelChannelConfigSection({
cfg,
channel,
enabled: true,
patch: { privateKey: resolvedValue },
patch: buildNostrSetupPatch(accountId, { privateKey: resolvedValue }),
}),
},
],
@ -234,14 +242,17 @@ export const nostrSetupWizard: ChannelSetupWizard = {
},
keepPrompt: (value) => `Relay URLs set (${value}). Keep them?`,
validate: ({ value }) => parseRelayUrls(value).error,
applySet: async ({ cfg, value }) => {
applySet: async ({ cfg, accountId, value }) => {
const relayResult = parseRelayUrls(value);
return patchTopLevelChannelConfigSection({
cfg,
channel,
enabled: true,
clearFields: relayResult.relays.length > 0 ? undefined : ["relays"],
patch: relayResult.relays.length > 0 ? { relays: relayResult.relays } : {},
patch: buildNostrSetupPatch(
accountId,
relayResult.relays.length > 0 ? { relays: relayResult.relays } : {},
),
});
},
},