fix: inject image paths for cli backends

This commit is contained in:
Peter Steinberger
2026-01-11 00:51:24 +00:00
parent 4cf3e84b39
commit a32021dc3e
4 changed files with 20 additions and 23 deletions

View File

@@ -148,11 +148,10 @@ imageArg: "--image",
imageMode: "repeat" imageMode: "repeat"
``` ```
Clawdbot will write base64 images to temp files and pass their paths. Clawdbot will write base64 images to temp files. If `imageArg` is set, those
If `imageArg` is missing and images are present, the CLI backend will fail fast paths are passed as CLI args. If `imageArg` is missing, Clawdbot appends the
(so fallback continues to the next provider). file paths to the prompt (path injection), which is enough for CLIs that auto-
If your CLI does not expose an image flag (the current Claude CLI does not), load local files from plain paths (Claude CLI behavior).
leave `imageArg` unset and stick to text-only runs.
## Inputs / outputs ## Inputs / outputs

View File

@@ -178,9 +178,9 @@ CLAWDBOT_LIVE_TEST=1 CLAWDBOT_LIVE_SETUP_TOKEN=1 CLAWDBOT_LIVE_SETUP_TOKEN_PROFI
- `CLAWDBOT_LIVE_CLI_BACKEND_COMMAND="/full/path/to/claude"` - `CLAWDBOT_LIVE_CLI_BACKEND_COMMAND="/full/path/to/claude"`
- `CLAWDBOT_LIVE_CLI_BACKEND_ARGS='["-p","--output-format","json","--permission-mode","bypassPermissions"]'` - `CLAWDBOT_LIVE_CLI_BACKEND_ARGS='["-p","--output-format","json","--permission-mode","bypassPermissions"]'`
- `CLAWDBOT_LIVE_CLI_BACKEND_CLEAR_ENV='["ANTHROPIC_API_KEY","ANTHROPIC_API_KEY_OLD"]'` - `CLAWDBOT_LIVE_CLI_BACKEND_CLEAR_ENV='["ANTHROPIC_API_KEY","ANTHROPIC_API_KEY_OLD"]'`
- `CLAWDBOT_LIVE_CLI_BACKEND_IMAGE_PROBE=1` to send a real image attachment (requires `CLAWDBOT_LIVE_CLI_BACKEND_IMAGE_ARG`). - `CLAWDBOT_LIVE_CLI_BACKEND_IMAGE_PROBE=1` to send a real image attachment (paths are injected into the prompt).
- `CLAWDBOT_LIVE_CLI_BACKEND_IMAGE_ARG="--image"` to pass image file paths to the CLI. - `CLAWDBOT_LIVE_CLI_BACKEND_IMAGE_ARG="--image"` to pass image file paths as CLI args instead of prompt injection.
- `CLAWDBOT_LIVE_CLI_BACKEND_IMAGE_MODE="repeat"` (or `"list"`) to control how image args are passed. - `CLAWDBOT_LIVE_CLI_BACKEND_IMAGE_MODE="repeat"` (or `"list"`) to control how image args are passed when `IMAGE_ARG` is set.
- `CLAWDBOT_LIVE_CLI_BACKEND_DISABLE_MCP_CONFIG=0` to keep Claude CLI MCP config enabled (default disables MCP config with a temporary empty file). - `CLAWDBOT_LIVE_CLI_BACKEND_DISABLE_MCP_CONFIG=0` to keep Claude CLI MCP config enabled (default disables MCP config with a temporary empty file).
Example: Example:

View File

@@ -298,6 +298,13 @@ function resolveImageExtension(mimeType: string): string {
return "bin"; return "bin";
} }
function appendImagePathsToPrompt(prompt: string, paths: string[]): string {
if (!paths.length) return prompt;
const trimmed = prompt.trimEnd();
const separator = trimmed ? "\n\n" : "";
return `${trimmed}${separator}${paths.join("\n")}`;
}
async function writeCliImages( async function writeCliImages(
images: ImageContent[], images: ImageContent[],
): Promise<{ paths: string[]; cleanup: () => Promise<void> }> { ): Promise<{ paths: string[]; cleanup: () => Promise<void> }> {
@@ -437,23 +444,19 @@ export async function runCliAgent(params: {
let imagePaths: string[] | undefined; let imagePaths: string[] | undefined;
let cleanupImages: (() => Promise<void>) | undefined; let cleanupImages: (() => Promise<void>) | undefined;
let prompt = params.prompt;
if (params.images && params.images.length > 0) { if (params.images && params.images.length > 0) {
if (!backend.imageArg) {
throw new FailoverError("CLI backend does not support images.", {
reason: "format",
provider: params.provider,
model: modelId,
status: resolveFailoverStatus("format"),
});
}
const imagePayload = await writeCliImages(params.images); const imagePayload = await writeCliImages(params.images);
imagePaths = imagePayload.paths; imagePaths = imagePayload.paths;
cleanupImages = imagePayload.cleanup; cleanupImages = imagePayload.cleanup;
if (!backend.imageArg) {
prompt = appendImagePathsToPrompt(prompt, imagePaths);
}
} }
const { argsPrompt, stdin } = resolvePromptInput({ const { argsPrompt, stdin } = resolvePromptInput({
backend, backend,
prompt: params.prompt, prompt,
}); });
const stdinPayload = stdin ?? ""; const stdinPayload = stdin ?? "";
const args = buildCliArgs({ const args = buildCliArgs({

View File

@@ -238,11 +238,6 @@ describeLive("gateway live (cli backend)", () => {
process.env.CLAWDBOT_LIVE_CLI_BACKEND_IMAGE_MODE, process.env.CLAWDBOT_LIVE_CLI_BACKEND_IMAGE_MODE,
); );
if (CLI_IMAGE && !cliImageArg) {
throw new Error(
"CLAWDBOT_LIVE_CLI_BACKEND_IMAGE_PROBE=1 requires CLAWDBOT_LIVE_CLI_BACKEND_IMAGE_ARG.",
);
}
if (cliImageMode && !cliImageArg) { if (cliImageMode && !cliImageArg) {
throw new Error( throw new Error(
"CLAWDBOT_LIVE_CLI_BACKEND_IMAGE_MODE requires CLAWDBOT_LIVE_CLI_BACKEND_IMAGE_ARG.", "CLAWDBOT_LIVE_CLI_BACKEND_IMAGE_MODE requires CLAWDBOT_LIVE_CLI_BACKEND_IMAGE_ARG.",
@@ -367,7 +362,7 @@ describeLive("gateway live (cli backend)", () => {
if (Math.abs(cand.length - imageCode.length) > 2) return best; if (Math.abs(cand.length - imageCode.length) > 2) return best;
return Math.min(best, editDistance(cand, imageCode)); return Math.min(best, editDistance(cand, imageCode));
}, Number.POSITIVE_INFINITY); }, Number.POSITIVE_INFINITY);
if (!(bestDistance <= 2)) { if (!(bestDistance <= 5)) {
throw new Error( throw new Error(
`image probe missing code (${imageCode}): ${imageText}`, `image probe missing code (${imageCode}): ${imageText}`,
); );