From cb30efb88505b0aa19beee0af0424c23340b9a39 Mon Sep 17 00:00:00 2001 From: Pekka Heikura Date: Sat, 13 Jun 2026 17:47:37 +0300 Subject: [PATCH 1/2] feat(cli): -f/--file prompt-file support (llama.cpp-compatible) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Read the prompt from a file via -f/--file (llama.cpp's arg name), resolved once at the top of Execute into settings.Prompt so all downstream prompt paths work unchanged. Overrides -p when both are given; reads the file as-is (no trailing-newline stripping). A missing file errors loudly (exit 1) instead of running with an empty prompt. Motivation: prompts longer than the OS command-line length limit (~32K chars on Windows) can't be passed via -p — a long-context prompt blew the limit during #213 profiling. Verified: short file (30 tok), ~16K-token file (10460 tok prefilled, no "filename too long"), and missing-file clean error. Co-Authored-By: Claude Opus 4.8 --- src/SharpInference.Cli/RunCommand.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/SharpInference.Cli/RunCommand.cs b/src/SharpInference.Cli/RunCommand.cs index afae1c8..3cdee4c 100644 --- a/src/SharpInference.Cli/RunCommand.cs +++ b/src/SharpInference.Cli/RunCommand.cs @@ -24,7 +24,11 @@ public sealed class Settings : CommandSettings [CommandOption("-p|--prompt")] [Description("Input prompt (default: interactive chat)")] - public string? Prompt { get; init; } + public string? Prompt { get; set; } + + [CommandOption("-f|--file")] + [Description("Read the prompt from a file (llama.cpp -f/--file). Overrides -p when both are given; useful for prompts longer than the shell's command-line limit.")] + public string? PromptFile { get; init; } [CommandOption("-n|--n-predict")] [Description("Number of tokens to predict (default: 512)")] @@ -188,6 +192,18 @@ public sealed class Settings : CommandSettings protected override int Execute(CommandContext context, Settings settings, CancellationToken cancellation) { + // --file/-f (llama.cpp): load the prompt from a file. Overrides -p; lets prompts exceed + // the shell command-line length limit. Read as-is (no trailing-newline stripping). + if (settings.PromptFile is { Length: > 0 } promptFile) + { + if (!File.Exists(promptFile)) + { + AnsiConsole.MarkupLine($"[red]Prompt file not found:[/] {promptFile}"); + return 1; + } + settings.Prompt = File.ReadAllText(promptFile); + } + if (settings.MinBatchBlas > 0) SimdKernels.MinBatchForBlas = settings.MinBatchBlas; From 8af623495497ecd98b2da99196726fb1d6ac5897 Mon Sep 17 00:00:00 2001 From: Pekka Heikura Date: Sat, 13 Jun 2026 18:10:37 +0300 Subject: [PATCH 2/2] review(#233): escape path in error + handle prompt-file read failures (gemini) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gemini MEDIUM: (1) AnsiConsole.MarkupLine would choke on a path containing Spectre markup chars ([ ]) — Markup.Escape the path in the not-found message and the read-error message. (2) File.ReadAllText I/O failures (locked/permissions/bad path) were unhandled (stack trace) — wrap in try/catch over IOException/UnauthorizedAccessException/SecurityException/ NotSupportedException, fail loud with a clean message + exit 1. Verified a bracketed missing path now renders correctly. Co-Authored-By: Claude Opus 4.8 --- src/SharpInference.Cli/RunCommand.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/SharpInference.Cli/RunCommand.cs b/src/SharpInference.Cli/RunCommand.cs index 3cdee4c..a2cfc0e 100644 --- a/src/SharpInference.Cli/RunCommand.cs +++ b/src/SharpInference.Cli/RunCommand.cs @@ -198,10 +198,21 @@ protected override int Execute(CommandContext context, Settings settings, Cancel { if (!File.Exists(promptFile)) { - AnsiConsole.MarkupLine($"[red]Prompt file not found:[/] {promptFile}"); + AnsiConsole.MarkupLine($"[red]Prompt file not found:[/] {Markup.Escape(promptFile)}"); + return 1; + } + // Read failures (locked file, permissions, bad path) should fail loud + clean, not + // throw a stack trace; Escape the message since paths can carry Spectre markup chars. + try + { + settings.Prompt = File.ReadAllText(promptFile); + } + catch (Exception ex) when (ex is IOException or UnauthorizedAccessException + or System.Security.SecurityException or NotSupportedException) + { + AnsiConsole.MarkupLine($"[red]Error reading prompt file:[/] {Markup.Escape(ex.Message)}"); return 1; } - settings.Prompt = File.ReadAllText(promptFile); } if (settings.MinBatchBlas > 0)