mirror of
https://github.com/instructkr/claw-code.git
synced 2026-04-28 02:34:59 +08:00
fix: #136 support --output-format json with --compact flag
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -3870,6 +3870,7 @@ impl LiveCli {
|
|||||||
compact: bool,
|
compact: bool,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
match output_format {
|
match output_format {
|
||||||
|
CliOutputFormat::Json if compact => self.run_prompt_compact_json(input),
|
||||||
CliOutputFormat::Text if compact => self.run_prompt_compact(input),
|
CliOutputFormat::Text if compact => self.run_prompt_compact(input),
|
||||||
CliOutputFormat::Text => self.run_turn(input),
|
CliOutputFormat::Text => self.run_turn(input),
|
||||||
CliOutputFormat::Json => self.run_prompt_json(input),
|
CliOutputFormat::Json => self.run_prompt_json(input),
|
||||||
@@ -3889,6 +3890,32 @@ impl LiveCli {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn run_prompt_compact_json(&mut self, input: &str) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let (mut runtime, hook_abort_monitor) = self.prepare_turn_runtime(false)?;
|
||||||
|
let mut permission_prompter = CliPermissionPrompter::new(self.permission_mode);
|
||||||
|
let result = runtime.run_turn(input, Some(&mut permission_prompter));
|
||||||
|
hook_abort_monitor.stop();
|
||||||
|
let summary = result?;
|
||||||
|
self.replace_runtime(runtime)?;
|
||||||
|
self.persist_session()?;
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
json!({
|
||||||
|
"message": final_assistant_text(&summary),
|
||||||
|
"compact": true,
|
||||||
|
"model": self.model,
|
||||||
|
"usage": {
|
||||||
|
"input_tokens": summary.usage.input_tokens,
|
||||||
|
"output_tokens": summary.usage.output_tokens,
|
||||||
|
"cache_creation_input_tokens": summary.usage.cache_creation_input_tokens,
|
||||||
|
"cache_read_input_tokens": summary.usage.cache_read_input_tokens,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn run_prompt_json(&mut self, input: &str) -> Result<(), Box<dyn std::error::Error>> {
|
fn run_prompt_json(&mut self, input: &str) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let (mut runtime, hook_abort_monitor) = self.prepare_turn_runtime(false)?;
|
let (mut runtime, hook_abort_monitor) = self.prepare_turn_runtime(false)?;
|
||||||
let mut permission_prompter = CliPermissionPrompter::new(self.permission_mode);
|
let mut permission_prompter = CliPermissionPrompter::new(self.permission_mode);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use std::sync::atomic::{AtomicU64, Ordering};
|
|||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
use mock_anthropic_service::{MockAnthropicService, SCENARIO_PREFIX};
|
use mock_anthropic_service::{MockAnthropicService, SCENARIO_PREFIX};
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
static TEMP_COUNTER: AtomicU64 = AtomicU64::new(0);
|
static TEMP_COUNTER: AtomicU64 = AtomicU64::new(0);
|
||||||
|
|
||||||
@@ -125,6 +126,60 @@ fn compact_flag_streaming_text_only_emits_final_message_text() {
|
|||||||
fs::remove_dir_all(&workspace).expect("workspace cleanup should succeed");
|
fs::remove_dir_all(&workspace).expect("workspace cleanup should succeed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn compact_flag_with_json_output_emits_structured_json() {
|
||||||
|
let runtime = tokio::runtime::Runtime::new().expect("tokio runtime should build");
|
||||||
|
let server = runtime
|
||||||
|
.block_on(MockAnthropicService::spawn())
|
||||||
|
.expect("mock service should start");
|
||||||
|
let base_url = server.base_url();
|
||||||
|
|
||||||
|
let workspace = unique_temp_dir("compact-json");
|
||||||
|
let config_home = workspace.join("config-home");
|
||||||
|
let home = workspace.join("home");
|
||||||
|
fs::create_dir_all(&workspace).expect("workspace should exist");
|
||||||
|
fs::create_dir_all(&config_home).expect("config home should exist");
|
||||||
|
fs::create_dir_all(&home).expect("home should exist");
|
||||||
|
|
||||||
|
let prompt = format!("{SCENARIO_PREFIX}streaming_text");
|
||||||
|
let output = run_claw(
|
||||||
|
&workspace,
|
||||||
|
&config_home,
|
||||||
|
&home,
|
||||||
|
&base_url,
|
||||||
|
&[
|
||||||
|
"--model",
|
||||||
|
"sonnet",
|
||||||
|
"--permission-mode",
|
||||||
|
"read-only",
|
||||||
|
"--output-format",
|
||||||
|
"json",
|
||||||
|
"--compact",
|
||||||
|
&prompt,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
output.status.success(),
|
||||||
|
"compact json run should succeed
|
||||||
|
stdout:
|
||||||
|
{}
|
||||||
|
|
||||||
|
stderr:
|
||||||
|
{}",
|
||||||
|
String::from_utf8_lossy(&output.stdout),
|
||||||
|
String::from_utf8_lossy(&output.stderr),
|
||||||
|
);
|
||||||
|
let stdout = String::from_utf8(output.stdout).expect("stdout should be utf8");
|
||||||
|
let parsed: Value = serde_json::from_str(&stdout).expect("compact json stdout should parse");
|
||||||
|
assert_eq!(parsed["message"], "Mock streaming says hello from the parity harness.");
|
||||||
|
assert_eq!(parsed["compact"], true);
|
||||||
|
assert_eq!(parsed["model"], "claude-sonnet-4-6");
|
||||||
|
assert!(parsed["usage"].is_object());
|
||||||
|
|
||||||
|
fs::remove_dir_all(&workspace).expect("workspace cleanup should succeed");
|
||||||
|
}
|
||||||
|
|
||||||
fn run_claw(
|
fn run_claw(
|
||||||
cwd: &std::path::Path,
|
cwd: &std::path::Path,
|
||||||
config_home: &std::path::Path,
|
config_home: &std::path::Path,
|
||||||
|
|||||||
Reference in New Issue
Block a user