Skip to content

Commit 2385843

Browse files
committed
fix(cli): verify task completion to detect partial responses
Fixes bounty issue #1506 The CLI run command now tracks whether a TaskComplete event was received. If the event stream ends without completion or an explicit error, it is treated as a partial response/error condition. This prevents misleading success status when the server disconnects prematurely.
1 parent 8f839ec commit 2385843

1 file changed

Lines changed: 38 additions & 17 deletions

File tree

cortex-cli/src/run_cmd.rs

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -241,17 +241,15 @@ impl RunCli {
241241
pub async fn run(self) -> Result<()> {
242242
// Validate temperature if provided
243243
if let Some(temp) = self.temperature
244-
&& !(0.0..=2.0).contains(&temp)
245-
{
246-
bail!("Temperature must be between 0.0 and 2.0, got {temp}");
247-
}
244+
&& !(0.0..=2.0).contains(&temp) {
245+
bail!("Temperature must be between 0.0 and 2.0, got {temp}");
246+
}
248247

249248
// Validate top_p if provided
250249
if let Some(top_p) = self.top_p
251-
&& !(0.0..=1.0).contains(&top_p)
252-
{
253-
bail!("top-p must be between 0.0 and 1.0, got {top_p}");
254-
}
250+
&& !(0.0..=1.0).contains(&top_p) {
251+
bail!("top-p must be between 0.0 and 1.0, got {top_p}");
252+
}
255253

256254
// Build the message from arguments
257255
let mut message = self
@@ -437,10 +435,9 @@ impl RunCli {
437435
SessionMode::New { title } => {
438436
let id = uuid::Uuid::new_v4().to_string();
439437
if let Some(ref t) = title
440-
&& self.verbose
441-
{
442-
eprintln!("New session: {id} (title: {t})");
443-
}
438+
&& self.verbose {
439+
eprintln!("New session: {id} (title: {t})");
440+
}
444441
id
445442
}
446443
};
@@ -522,6 +519,7 @@ impl RunCli {
522519
let mut event_count = 0u64;
523520
let mut streaming_started = false;
524521
let mut error_occurred = false;
522+
let mut completed = false;
525523

526524
// Set up timeout if specified
527525
let timeout_duration = if self.timeout > 0 {
@@ -535,11 +533,11 @@ impl RunCli {
535533
while let Ok(event) = handle.event_rx.recv().await {
536534
// Check timeout
537535
if let Some(timeout) = timeout_duration
538-
&& start_time.elapsed() > timeout
539-
{
540-
eprintln!("Timeout reached after {} seconds", self.timeout);
541-
break;
542-
}
536+
&& start_time.elapsed() > timeout {
537+
eprintln!("Timeout reached after {} seconds", self.timeout);
538+
error_occurred = true;
539+
break;
540+
}
543541

544542
event_count += 1;
545543

@@ -626,6 +624,7 @@ impl RunCli {
626624
// Tool call completed
627625
}
628626
EventMsg::TaskComplete(_) => {
627+
completed = true;
629628
break;
630629
}
631630
EventMsg::Error(e) => {
@@ -667,6 +666,28 @@ impl RunCli {
667666
}
668667
}
669668

669+
// Check for partial response (disconnected without TaskComplete or Error)
670+
if !completed && !error_occurred {
671+
error_occurred = true;
672+
let err_msg = "Response incomplete (stream ended unexpectedly)";
673+
674+
if is_json {
675+
let err_json = serde_json::json!({
676+
"type": "error",
677+
"message": err_msg,
678+
"session_id": session_id,
679+
});
680+
eprintln!("{}", serde_json::to_string(&err_json)?);
681+
} else {
682+
eprintln!(
683+
"{}Error:{} {}",
684+
TermColor::Red.ansi_code(),
685+
TermColor::Default.ansi_code(),
686+
err_msg
687+
);
688+
}
689+
}
690+
670691
// Handle JSON result output
671692
if matches!(self.format, OutputFormat::Json) {
672693
let result = serde_json::json!({

0 commit comments

Comments
 (0)