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.
This commit is contained in:
Claude
2026-01-23 08:44:54 +00:00
parent 217131fa61
commit 486bacc98b
2 changed files with 59 additions and 33 deletions

View File

@@ -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

View File

@@ -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;
}