From 486bacc98b574088791ce03f0d8c3a15b6cce361 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 23 Jan 2026 08:44:54 +0000 Subject: [PATCH] fix: improve parameterized spell variable handling Changes: 1. Pubkey creator now asks for $pubkey (not $me), with $me as default value 2. Event creator requires explicit $event mention in command 3. Relay creator doesn't require explicit mention (implicitly filtered) 4. Fix variable substitution to work with all single-letter tag filters Variable substitution improvements: - $pubkey, $event, $relay now substitute in ALL single-letter tag filters (#d, #e, #p, #r, etc.) - Previously only handled specific hardcoded tags - Handles any tag filter starting with # and single letter All tests passing (1017/1017) and build successful. --- .../CreateParameterizedSpellDialog.tsx | 33 ++++++++--- src/lib/spell-conversion.ts | 59 +++++++++++-------- 2 files changed, 59 insertions(+), 33 deletions(-) diff --git a/src/components/CreateParameterizedSpellDialog.tsx b/src/components/CreateParameterizedSpellDialog.tsx index b1ea330..c87ced6 100644 --- a/src/components/CreateParameterizedSpellDialog.tsx +++ b/src/components/CreateParameterizedSpellDialog.tsx @@ -31,14 +31,27 @@ type PublishingState = | "saving" | "error"; -const PARAMETER_INFO = { +const PARAMETER_INFO: Record< + "$pubkey" | "$event" | "$relay", + { + title: string; + description: string; + placeholder: string; + variable: string; + variableDescription: string; + defaultValue?: string; + requireVariable: boolean; + } +> = { $pubkey: { title: "Create Profile Spell", description: "Create a spell that works with any profile", - placeholder: "req -k 1 -a $me -l 50", - variable: "$me", + placeholder: "req -k 1 -a $pubkey -l 50", + variable: "$pubkey", variableDescription: - "Use $me in your command to reference the target profile", + "Use $pubkey in your command to reference the target profile", + defaultValue: "$me", + requireVariable: true, }, $event: { title: "Create Event Spell", @@ -46,7 +59,8 @@ const PARAMETER_INFO = { placeholder: "req -k 1 -e $event -l 50", variable: "$event", variableDescription: - "Use $event in your command to reference the target event", + "Use $event in your command (e.g., -e $event for replies, --id $event for direct reference)", + requireVariable: true, }, $relay: { title: "Create Relay Spell", @@ -54,7 +68,8 @@ const PARAMETER_INFO = { placeholder: "req -k 1 -l 50", variable: "$relay", variableDescription: - "Use $relay in your command to reference the target relay", + "$relay is implicitly used for filtering - you can optionally use it in tags like -d $relay", + requireVariable: false, }, }; @@ -93,7 +108,7 @@ export function CreateParameterizedSpellDialog({ const commandValid = command.trim().length > 0; const nameValid = name.trim().length > 0; const hasRequiredVariable = - parameterType === "$relay" || command.includes(info.variable); + !info.requireVariable || command.includes(info.variable); const isFormValid = commandValid && nameValid && hasRequiredVariable; @@ -130,7 +145,7 @@ export function CreateParameterizedSpellDialog({ description: description.trim() || undefined, isPublished: false, parameterType, - parameterDefault: [info.variable], + parameterDefault: [info.defaultValue || info.variable], }); // Success! @@ -185,7 +200,7 @@ export function CreateParameterizedSpellDialog({ description: description.trim() || undefined, isPublished: false, parameterType, - parameterDefault: [info.variable], + parameterDefault: [info.defaultValue || info.variable], }); // 2. Use PublishSpellAction to handle signing and publishing diff --git a/src/lib/spell-conversion.ts b/src/lib/spell-conversion.ts index b930678..b6454c4 100644 --- a/src/lib/spell-conversion.ts +++ b/src/lib/spell-conversion.ts @@ -545,21 +545,23 @@ export function applySpellParameters( throw new Error("Parameterized $pubkey spell requires target pubkey"); } - // Substitute $pubkey placeholders + // Substitute $pubkey in authors if (filter.authors) { filter.authors = filter.authors.flatMap((author) => author === "$pubkey" ? values : [author], ); } - if (filter["#p"]) { - filter["#p"] = filter["#p"].flatMap((p) => - p === "$pubkey" ? values : [p], - ); - } - if (filter["#P"]) { - filter["#P"] = filter["#P"].flatMap((p) => - p === "$pubkey" ? values : [p], - ); + + // Substitute $pubkey in all single-letter tag filters (#p, #P, etc.) + for (const key in filter) { + if (key.startsWith("#") && key.length === 2) { + const tagArray = filter[key as keyof NostrFilter] as string[]; + if (Array.isArray(tagArray)) { + (filter as any)[key] = tagArray.flatMap((val) => + val === "$pubkey" ? values : [val], + ); + } + } } break; } @@ -574,21 +576,24 @@ export function applySpellParameters( ); } - if (filter["#e"]) { - filter["#e"] = filter["#e"].flatMap((e) => - e === "$event" ? values : [e], - ); - } - if (filter["#a"]) { - filter["#a"] = filter["#a"].flatMap((a) => - a === "$event" ? values : [a], - ); - } + // Substitute $event in ids if (filter.ids) { filter.ids = filter.ids.flatMap((id) => id === "$event" ? values : [id], ); } + + // Substitute $event in all single-letter tag filters (#e, #a, etc.) + for (const key in filter) { + if (key.startsWith("#") && key.length === 2) { + const tagArray = filter[key as keyof NostrFilter] as string[]; + if (Array.isArray(tagArray)) { + (filter as any)[key] = tagArray.flatMap((val) => + val === "$event" ? values : [val], + ); + } + } + } break; } @@ -600,10 +605,16 @@ export function applySpellParameters( throw new Error("Parameterized $relay spell requires target relay"); } - if (filter["#r"]) { - filter["#r"] = filter["#r"].flatMap((r) => - r === "$relay" ? values : [r], - ); + // Replace $relay in all single-letter tag filters (#d, #r, etc.) + for (const key in filter) { + if (key.startsWith("#") && key.length === 2) { + const tagArray = filter[key as keyof NostrFilter] as string[]; + if (Array.isArray(tagArray)) { + (filter as any)[key] = tagArray.flatMap((val) => + val === "$relay" ? values : [val], + ); + } + } } break; }