fix(coding-agent): parse multiline prompt template args

closes #4553
This commit is contained in:
Mario Zechner
2026-05-16 23:36:25 +02:00
parent 22a9c484e7
commit d0fe8570e9
3 changed files with 63 additions and 6 deletions

View File

@@ -13,7 +13,12 @@ import { tmpdir } from "os";
import { join } from "path";
import { afterAll, describe, expect, test } from "vitest";
import { getAgentDir } from "../src/config.js";
import { loadPromptTemplates, parseCommandArgs, substituteArgs } from "../src/core/prompt-templates.js";
import {
expandPromptTemplate,
loadPromptTemplates,
parseCommandArgs,
substituteArgs,
} from "../src/core/prompt-templates.js";
// ============================================================================
// substituteArgs
@@ -335,10 +340,25 @@ describe("parseCommandArgs", () => {
expect(parseCommandArgs("日本語 🎉 café")).toEqual(["日本語", "🎉", "café"]);
});
test("should handle newlines in arguments", () => {
test("should handle newlines in quoted arguments", () => {
expect(parseCommandArgs('"line1\nline2" second')).toEqual(["line1\nline2", "second"]);
});
test("should treat unquoted newlines as separators", () => {
expect(parseCommandArgs("label-2\n\nHere is some description #2.")).toEqual([
"label-2",
"Here",
"is",
"some",
"description",
"#2.",
]);
});
test("should collapse mixed unquoted whitespace", () => {
expect(parseCommandArgs("a\n\n\tb c")).toEqual(["a", "b", "c"]);
});
test("should handle escaped quotes inside quoted strings", () => {
// Note: This implementation doesn't handle escaped quotes - backslash is literal
expect(parseCommandArgs('"quoted \\"text\\""')).toEqual(["quoted \\text\\"]);
@@ -357,6 +377,40 @@ describe("parseCommandArgs", () => {
// Integration
// ============================================================================
describe("expandPromptTemplate", () => {
test("should split template arguments on unquoted newlines", () => {
const result = expandPromptTemplate("/arg-test label-2\n\nHere is some description #2.", [
{
name: "arg-test",
description: "test",
content: `- arg1: $1\n- rest: \${@:2}`,
sourceInfo: { path: "/tmp/arg-test.md", source: "local", scope: "temporary", origin: "top-level" },
filePath: "/tmp/arg-test.md",
},
]);
expect(result).toBe("- arg1: label-2\n- rest: Here is some description #2.");
});
test("should support template command separated from args by newline", () => {
const result = expandPromptTemplate("/arg-test\nlabel-2", [
{
name: "arg-test",
description: "test",
content: "arg1: $1",
sourceInfo: { path: "/tmp/arg-test.md", source: "local", scope: "temporary", origin: "top-level" },
filePath: "/tmp/arg-test.md",
},
]);
expect(result).toBe("arg1: label-2");
});
});
// ============================================================================
// Integration
// ============================================================================
describe("parseCommandArgs + substituteArgs integration", () => {
test("should parse and substitute together correctly", () => {
const input = 'Button "onClick handler" "disabled support"';