fix: 🔥 Additional fixes based on commnets

This commit is contained in:
Shawn Smith
2025-11-11 19:29:30 -08:00
parent a93d3b6fdc
commit 7a3cf36bb8
5 changed files with 174 additions and 11 deletions

View File

@@ -8,4 +8,4 @@ invokable: true
Take the prompt provided by the user and using the terminal tool run the following command in the background: Take the prompt provided by the user and using the terminal tool run the following command in the background:
cn -p {{prompt}} cn -p "{{prompt}}"

View File

@@ -8,4 +8,4 @@ invokable: true
Take the prompt provided by the user and using the terminal tool run the following command in the foreground: Take the prompt provided by the user and using the terminal tool run the following command in the foreground:
cn -p {{prompt}} cn -p "{{prompt}}"

View File

@@ -97,9 +97,8 @@ if (!prompt) {
Configures output handling for TTY-less environments: Configures output handling for TTY-less environments:
- Sets UTF-8 encoding - Sets UTF-8 encoding for stdout/stderr
- Ensures line-buffered output - Redirects error messages to stderr in headless mode
- Disables progress indicators
## Usage Examples ## Usage Examples

View File

@@ -0,0 +1,130 @@
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { hasSuppliedPrompt, isHeadlessMode, isServe } from "./cli.js";
describe("CLI utility functions", () => {
let originalArgv: string[];
beforeEach(() => {
originalArgv = process.argv;
});
afterEach(() => {
process.argv = originalArgv;
});
describe("isHeadlessMode", () => {
it("should return true when -p flag is present", () => {
process.argv = ["node", "script.js", "-p", "test prompt"];
expect(isHeadlessMode()).toBe(true);
});
it("should return true when --print flag is present", () => {
process.argv = ["node", "script.js", "--print", "test prompt"];
expect(isHeadlessMode()).toBe(true);
});
it("should return false when no print flag is present", () => {
process.argv = ["node", "script.js", "other", "args"];
expect(isHeadlessMode()).toBe(false);
});
});
describe("isServe", () => {
it("should return true when serve command is present", () => {
process.argv = ["node", "script.js", "serve"];
expect(isServe()).toBe(true);
});
it("should return false when serve command is not present", () => {
process.argv = ["node", "script.js", "-p", "test"];
expect(isServe()).toBe(false);
});
});
describe("hasSuppliedPrompt", () => {
it("should return true when prompt immediately follows -p", () => {
process.argv = ["node", "script.js", "-p", "test prompt"];
expect(hasSuppliedPrompt()).toBe(true);
});
it("should return true when prompt immediately follows --print", () => {
process.argv = ["node", "script.js", "--print", "test prompt"];
expect(hasSuppliedPrompt()).toBe(true);
});
it("should return true when prompt follows other flags after -p", () => {
// This is the bug fix - handles cases like: cn -p --config my.yaml "Prompt"
process.argv = [
"node",
"script.js",
"-p",
"--config",
"my.yaml",
"test prompt",
];
expect(hasSuppliedPrompt()).toBe(true);
});
it("should return true when prompt follows multiple flags after --print", () => {
process.argv = [
"node",
"script.js",
"--print",
"--config",
"my.yaml",
"--model",
"gpt-4",
"test prompt",
];
expect(hasSuppliedPrompt()).toBe(true);
});
it("should return false when only flags and their values follow -p", () => {
process.argv = ["node", "script.js", "-p", "--config", "my.yaml"];
expect(hasSuppliedPrompt()).toBe(false);
});
it("should return false when only unknown flags follow -p", () => {
process.argv = ["node", "script.js", "-p", "--some-flag"];
expect(hasSuppliedPrompt()).toBe(false);
});
it("should return false when no -p or --print flag is present", () => {
process.argv = ["node", "script.js", "test prompt"];
expect(hasSuppliedPrompt()).toBe(false);
});
it("should return true when --prompt flag is present", () => {
process.argv = ["node", "script.js", "-p", "--prompt"];
expect(hasSuppliedPrompt()).toBe(true);
});
it("should return true when --agent flag is present", () => {
process.argv = ["node", "script.js", "-p", "--agent"];
expect(hasSuppliedPrompt()).toBe(true);
});
it("should return false when -p is last argument with no prompt", () => {
process.argv = ["node", "script.js", "-p"];
expect(hasSuppliedPrompt()).toBe(false);
});
it("should handle quoted prompts with flags in between", () => {
process.argv = [
"node",
"script.js",
"-p",
"--config",
"my.yaml",
"Explain this code",
];
expect(hasSuppliedPrompt()).toBe(true);
});
it("should return false when prompt appears before -p flag", () => {
process.argv = ["node", "script.js", "test prompt", "-p"];
expect(hasSuppliedPrompt()).toBe(false);
});
});
});

View File

@@ -46,12 +46,46 @@ export function hasSuppliedPrompt(): boolean {
return false; return false;
} }
// Check if there's a non-flag argument after -p/--print // Check if --prompt flag is present (indicates a prompt is coming)
// or if there are --prompt or --agent flags // Note: --agent doesn't supply a prompt, it just specifies which agent to use
const hasPromptArg = // Piped stdin should still be read when --agent is present
args.length > printIndex + 1 && !args[printIndex + 1].startsWith("-");
const hasPromptFlag = args.includes("--prompt"); const hasPromptFlag = args.includes("--prompt");
const hasAgentFlag = args.includes("--agent"); if (hasPromptFlag) {
return true;
}
return hasPromptArg || hasPromptFlag || hasAgentFlag; // Check if there's a non-flag argument after -p/--print
// We need to skip flags that take values (like --config, --model, etc.)
// Known flags that take values
const flagsWithValues = new Set([
"--config",
"--model",
"--output",
"--mode",
"--workflow",
"-m",
"-c",
"-o",
]);
const argsAfterPrint = args.slice(printIndex + 1);
for (let i = 0; i < argsAfterPrint.length; i++) {
const arg = argsAfterPrint[i];
// If this is a flag that takes a value, skip both the flag and its value
if (flagsWithValues.has(arg)) {
i++; // Skip the next argument (the value)
continue;
}
// If this is any other flag (starts with -), skip it
if (arg.startsWith("-")) {
continue;
}
// Found a non-flag argument - this is the prompt
return true;
}
return false;
} }