fix(coding-agent): support all-argument prompt defaults closes #6695

This commit is contained in:
David Brailovsky
2026-07-17 13:52:32 +02:00
parent ce48d9b4ef
commit 64f83c85d9
4 changed files with 17 additions and 5 deletions
+1
View File
@@ -8,6 +8,7 @@
### Fixed ### Fixed
- Fixed prompt-template defaults for all arguments (`${@:-default}` and `${ARGUMENTS:-default}`) ([#6695](https://github.com/earendil-works/pi/issues/6695)).
- Fixed obsolete custom UI, custom tool, and custom editor examples in the extension documentation ([#6735](https://github.com/earendil-works/pi/issues/6735)). - Fixed obsolete custom UI, custom tool, and custom editor examples in the extension documentation ([#6735](https://github.com/earendil-works/pi/issues/6735)).
- Fixed Kimi Coding sessions to show API-equivalent implied costs with the subscription indicator. - Fixed Kimi Coding sessions to show API-equivalent implied costs with the subscription indicator.
- Fixed OpenAI Responses early stream endings to trigger automatic retry instead of ending the agent run ([#6727](https://github.com/earendil-works/pi/issues/6727)). - Fixed OpenAI Responses early stream endings to trigger automatic retry instead of ending the agent run ([#6727](https://github.com/earendil-works/pi/issues/6727)).
@@ -69,6 +69,7 @@ Templates support positional arguments, defaults, and simple slicing:
- `$1`, `$2`, ... positional args - `$1`, `$2`, ... positional args
- `$@` or `$ARGUMENTS` for all args joined - `$@` or `$ARGUMENTS` for all args joined
- `${1:-default}` uses arg 1 when present/non-empty, otherwise `default` - `${1:-default}` uses arg 1 when present/non-empty, otherwise `default`
- `${@:-default}` or `${ARGUMENTS:-default}` uses all arguments when present/non-empty, otherwise `default`
- `${@:N}` for args from the Nth position (1-indexed) - `${@:N}` for args from the Nth position (1-indexed)
- `${@:N:L}` for `L` args starting at N - `${@:N:L}` for `L` args starting at N
@@ -60,6 +60,7 @@ export function parseCommandArgs(argsString: string): string[] {
* - $1, $2, ... for positional args * - $1, $2, ... for positional args
* - $@ and $ARGUMENTS for all args * - $@ and $ARGUMENTS for all args
* - ${N:-default} for positional arg N with default when missing/empty * - ${N:-default} for positional arg N with default when missing/empty
* - ${@:-default} and ${ARGUMENTS:-default} for all args with a default when empty
* - ${@:N} for args from Nth onwards (bash-style slicing) * - ${@:N} for args from Nth onwards (bash-style slicing)
* - ${@:N:L} for L args starting from Nth * - ${@:N:L} for L args starting from Nth
* *
@@ -70,11 +71,11 @@ export function substituteArgs(content: string, args: string[]): string {
const allArgs = args.join(" "); const allArgs = args.join(" ");
return content.replace( return content.replace(
/\$\{(\d+):-([^}]*)\}|\$\{@:(\d+)(?::(\d+))?\}|\$(ARGUMENTS|@|\d+)/g, /\$\{(\d+|ARGUMENTS|@):-([^}]*)\}|\$\{@:(\d+)(?::(\d+))?\}|\$(ARGUMENTS|@|\d+)/g,
(_match, defaultNum, defaultValue, sliceStart, sliceLength, simple) => { (_match, defaultTarget, defaultValue, sliceStart, sliceLength, simple) => {
if (defaultNum) { if (defaultTarget) {
const index = parseInt(defaultNum, 10) - 1; const value =
const value = args[index]; defaultTarget === "@" || defaultTarget === "ARGUMENTS" ? allArgs : args[parseInt(defaultTarget, 10) - 1];
return value ? value : defaultValue; return value ? value : defaultValue;
} }
@@ -199,6 +199,15 @@ describe("substituteArgs - positional defaults", () => {
expect(substituteArgs(`List exactly \${1:-7} next steps`, [])).toBe("List exactly 7 next steps"); expect(substituteArgs(`List exactly \${1:-7} next steps`, [])).toBe("List exactly 7 next steps");
}); });
test("should support defaults for all arguments", () => {
const template = `\${@:-default}\n\${ARGUMENTS:-default}`;
expect(substituteArgs(template, [])).toBe("default\ndefault");
expect(substituteArgs(template, ["This", "would", "be", "the", "arguments"])).toBe(
"This would be the arguments\nThis would be the arguments",
);
});
test("should use positional arg when present", () => { test("should use positional arg when present", () => {
expect(substituteArgs(`List exactly \${1:-7} next steps`, ["3"])).toBe("List exactly 3 next steps"); expect(substituteArgs(`List exactly \${1:-7} next steps`, ["3"])).toBe("List exactly 3 next steps");
}); });