fix(cli): take global flags after the command, and call --json again

Only --json was taken after the command, so `wait --paused --timeout
60s`, the order the guide's own synopsis and agents use, failed with
"unknown argument '--timeout'", and `-i` after the command did too.
And since that --json was taken as the output flag, `call X --json
'{...}'`, the documented way to pass arguments as JSON, never reached
call: its object then failed as "not key=value".

--timeout, -i and --json now go anywhere on the line; no command has
options of those names. After `call`, a --json followed by an object
is the arguments, and any other --json the output flag. A trailing
--timeout or -i without its value is a usage error that says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jorijn van der Graaf 2026-11-01 03:21:41 +01:00
commit 7574ad5c4e
Signed by: jorijnvdgraaf
GPG key ID: 2937E59CDCC1BCFB
2 changed files with 23 additions and 4 deletions

View file

@ -161,6 +161,10 @@ int main() {
Check(r.code == 0 && Has(r.out, "'score >= 1' held at frame"), "wait for a condition");
r = Run({ "--timeout", "100ms", "wait", "score < 0" }, instances);
Check(r.code == 5 && Has(r.err, "was not true within"), "a wait that times out exits 5 and says what the paths were");
r = Run({ "wait", "score < 0", "--timeout", "100ms" }, instances);
Check(r.code == 5 && Has(r.err, "was not true within"), std::format("global flags also go after the command's own ({})", r.err));
r = Run({ "wait", "--frames", "1", "--timeout" }, instances);
Check(r.code == 2 && Has(r.err, "--timeout needs a value"), "a global flag without its value is a usage error");
r = Run({ "log", "--last", "5" }, instances);
Check(r.code == 0 && Has(r.out, "AGENT"), "log shows the agent's actions");
@ -178,6 +182,12 @@ int main() {
} catch (const ParseError&) {
}
Check(r.code == 0 && json, "--json prints JSON");
r = Run({ "status", "--json" }, instances);
Check(r.code == 0 && r.out.starts_with("{"), "--json after the command too");
r = Run({ "call", "Player_SetAim", "--json", R"({"slot": 4, "yaw": 5})" }, instances);
Check(r.code == 0 && Has(r.out, R"({"slot":4,"yaw":5.0})"), std::format("call takes its arguments as JSON ({})", r.out + r.err));
r = Run({ "call", "Player_SetAim", "--json", R"({"slot": 4})", "yaw=7", "--json" }, instances);
Check(r.code == 0 && Has(r.out, R"({"slot":4,"yaw":7.0})"), std::format("JSON arguments with key=value on top, and --json after them ({})", r.out + r.err));
r = Run({ "stauts" }, instances);
Check(r.code == 2 && Has(r.err, "did you mean 'status'"), "a mistyped command name gets a suggestion");