feat(coding-agent): add prompt template argument defaults
This commit is contained in:
@@ -59,46 +59,45 @@ export function parseCommandArgs(argsString: string): string[] {
|
||||
* Supports:
|
||||
* - $1, $2, ... for positional args
|
||||
* - $@ and $ARGUMENTS for all args
|
||||
* - ${N:-default} for positional arg N with default when missing/empty
|
||||
* - ${@:N} for args from Nth onwards (bash-style slicing)
|
||||
* - ${@:N:L} for L args starting from Nth
|
||||
*
|
||||
* Note: Replacement happens on the template string only. Argument values
|
||||
* Note: Replacement happens on the template string only. Argument and default values
|
||||
* containing patterns like $1, $@, or $ARGUMENTS are NOT recursively substituted.
|
||||
*/
|
||||
export function substituteArgs(content: string, args: string[]): string {
|
||||
let result = content;
|
||||
|
||||
// Replace $1, $2, etc. with positional args FIRST (before wildcards)
|
||||
// This prevents wildcard replacement values containing $<digit> patterns from being re-substituted
|
||||
result = result.replace(/\$(\d+)/g, (_, num) => {
|
||||
const index = parseInt(num, 10) - 1;
|
||||
return args[index] ?? "";
|
||||
});
|
||||
|
||||
// Replace ${@:start} or ${@:start:length} with sliced args (bash-style)
|
||||
// Process BEFORE simple $@ to avoid conflicts
|
||||
result = result.replace(/\$\{@:(\d+)(?::(\d+))?\}/g, (_, startStr, lengthStr) => {
|
||||
let start = parseInt(startStr, 10) - 1; // Convert to 0-indexed (user provides 1-indexed)
|
||||
// Treat 0 as 1 (bash convention: args start at 1)
|
||||
if (start < 0) start = 0;
|
||||
|
||||
if (lengthStr) {
|
||||
const length = parseInt(lengthStr, 10);
|
||||
return args.slice(start, start + length).join(" ");
|
||||
}
|
||||
return args.slice(start).join(" ");
|
||||
});
|
||||
|
||||
// Pre-compute all args joined (optimization)
|
||||
const allArgs = args.join(" ");
|
||||
|
||||
// Replace $ARGUMENTS with all args joined (new syntax, aligns with Claude, Codex, OpenCode)
|
||||
result = result.replace(/\$ARGUMENTS/g, allArgs);
|
||||
return content.replace(
|
||||
/\$\{(\d+):-([^}]*)\}|\$\{@:(\d+)(?::(\d+))?\}|\$(ARGUMENTS|@|\d+)/g,
|
||||
(_match, defaultNum, defaultValue, sliceStart, sliceLength, simple) => {
|
||||
if (defaultNum) {
|
||||
const index = parseInt(defaultNum, 10) - 1;
|
||||
const value = args[index];
|
||||
return value ? value : defaultValue;
|
||||
}
|
||||
|
||||
// Replace $@ with all args joined (existing syntax)
|
||||
result = result.replace(/\$@/g, allArgs);
|
||||
if (sliceStart) {
|
||||
let start = parseInt(sliceStart, 10) - 1; // Convert to 0-indexed (user provides 1-indexed)
|
||||
// Treat 0 as 1 (bash convention: args start at 1)
|
||||
if (start < 0) start = 0;
|
||||
|
||||
return result;
|
||||
if (sliceLength) {
|
||||
const length = parseInt(sliceLength, 10);
|
||||
return args.slice(start, start + length).join(" ");
|
||||
}
|
||||
return args.slice(start).join(" ");
|
||||
}
|
||||
|
||||
if (simple === "ARGUMENTS" || simple === "@") {
|
||||
return allArgs;
|
||||
}
|
||||
|
||||
const index = parseInt(simple, 10) - 1;
|
||||
return args[index] ?? "";
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function loadTemplateFromFile(filePath: string, sourceInfo: SourceInfo): PromptTemplate | null {
|
||||
|
||||
Reference in New Issue
Block a user