Automation: tell a tool name or an unknown id from a command without a tool in command_run (fixes #1759) (#1765)

This commit is contained in:
Marco Arnulfo
2026-10-15 02:23:58 -04:00
committed by GitHub
parent 432d3172d4
commit 58e125ccf1
2 changed files with 35 additions and 1 deletions
+17 -1
View File
@@ -2,15 +2,31 @@
use serde_json::{Value, json};
use crate::{Args, Automation, Content, Result, ToolError, encode_png, failed, info, tools};
use pdfcraft_engine::commands;
use pdfcraft_render::{RenderRequest, RequestKind};
/// The most steps one `command_batch` runs.
pub(crate) const MAX_BATCH_STEPS: usize = 1000;
/// Why `id` has no tool to run: a tool name passed as a command id, an id the registry doesn't
/// know, or a real command that nothing automates yet. They need different fixes from the caller.
fn no_tool_for(id: &str) -> ToolError {
if commands::command(id).is_some() {
return failed(format!("command {id:?} has no headless tool; see command_list"));
}
match tools::find(id) {
Some(def) => match def.command {
Some(command) => failed(format!("{id:?} is a tool, not a command id; use the command id {command:?}, or call the tool directly")),
None => failed(format!("{id:?} is a tool, not a command id; call it directly (command ids are in command_list)")),
},
None => failed(format!("unknown command id {id:?}; see command_list")),
}
}
impl Automation {
pub(crate) fn command_run(&mut self, args: &Args) -> Result<Vec<Content>> {
let id = args.str("id")?;
let tool = tools::tool_for_command(id).ok_or_else(|| failed(format!("command {id:?} has no headless tool; see command_list")))?;
let tool = tools::tool_for_command(id).ok_or_else(|| no_tool_for(id))?;
let def = tools::find(tool).ok_or_else(|| failed("command tool is unavailable"))?;
let mut params = match args.get("params") {
None | Some(Value::Null) => serde_json::Map::new(),
+18
View File
@@ -5179,6 +5179,24 @@ fn command_batch_refuses_more_than_a_thousand_steps() {
assert!(err.to_string().contains("at most 1000 steps"), "{err}");
}
#[test]
fn command_batch_tells_a_tool_name_from_an_unknown_or_toolless_command() {
let dir = workdir("batch-ids");
let mut a = auto(&dir);
let steps = json!([{"id":"page_rotate"}, {"id":"doc_inspect"}, {"id":"no.such.command"}, {"id":"help.about"}]);
let r = ok(&mut a, "command_batch", json!({"steps": steps, "stop_on_error": false}));
let errors: Vec<&str> = r["results"].as_array().unwrap().iter().map(|s| s["error"].as_str().unwrap()).collect();
assert_eq!(
errors,
[
r#""page_rotate" is a tool, not a command id; use the command id "page.rotate", or call the tool directly"#,
r#""doc_inspect" is a tool, not a command id; call it directly (command ids are in command_list)"#,
r#"unknown command id "no.such.command"; see command_list"#,
r#"command "help.about" has no headless tool; see command_list"#,
]
);
}
#[test]
fn thai_text_through_tools_saves_reopens_extracts_and_renders() {
let dir = workdir("thai-content");