Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/utils/slashCommands/compact.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,4 +214,23 @@ describe("multiline continue messages", () => {
continueMessage: undefined,
});
});

it("does not parse lines after newline as flags", () => {
// Bug: multiline content starting with -t or -c should not be parsed as flags
const result = parseCommand("/compact\n-t should be treated as message content");
expect(result).toEqual({
type: "compact",
maxOutputTokens: undefined,
continueMessage: "-t should be treated as message content",
});
});

it("does not parse lines after newline as flags with existing flag", () => {
const result = parseCommand("/compact -t 5000\n-c this is not a flag");
expect(result).toEqual({
type: "compact",
maxOutputTokens: 5000,
continueMessage: "-c this is not a flag",
});
});
});
16 changes: 11 additions & 5 deletions src/utils/slashCommands/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,16 +171,22 @@ const compactCommandDefinition: SlashCommandDefinition = {
key: "compact",
description:
"Compact conversation history using AI summarization. Use -t <tokens> to set max output tokens. Add continue message on lines after the command.",
handler: ({ cleanRemainingTokens, rawInput }): ParsedCommand => {
handler: ({ rawInput }): ParsedCommand => {
// Split rawInput into first line (for flags) and remaining lines (for multiline continue)
// rawInput format: "-t 5000\nContinue here" or "\nContinue here" (starts with newline if no flags)
const hasMultilineContent = rawInput.includes("\n");
const lines = rawInput.split("\n");
// Note: firstLine could be empty string if rawInput starts with \n (which is fine)
const firstLine = lines[0]; // First line contains flags
const remainingLines = lines.slice(1).join("\n").trim();

// Tokenize ONLY the first line to extract flags
// This prevents content after newlines from being parsed as flags
const firstLineTokens = (firstLine.match(/(?:[^\s"]+|"[^"]*")+/g) ?? []).map((token) =>
token.replace(/^"(.*)"$/, "$1")
);

// Parse flags from first line using minimist
const parsed = minimist(cleanRemainingTokens, {
const parsed = minimist(firstLineTokens, {
string: ["t", "c"],
unknown: (arg: string) => {
// Unknown flags starting with - are errors
Expand All @@ -191,8 +197,8 @@ const compactCommandDefinition: SlashCommandDefinition = {
},
});

// Check for unknown flags
const unknownFlags = cleanRemainingTokens.filter(
// Check for unknown flags (only from first line)
const unknownFlags = firstLineTokens.filter(
(token) => token.startsWith("-") && token !== "-t" && token !== "-c"
);
if (unknownFlags.length > 0) {
Expand Down