Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion crates/xgen-cli/src/composition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,14 @@ pub struct LocalRunRequest {
pub final_response_schema: Option<serde_json::Value>,
/// Optional exact process checks required before completion. Requires a response schema.
pub completion_checks: Option<Vec<xgen_provider_openai::CompletionCheck>>,
/// Admit `response_candidate` for a goal that plans no steps.
///
/// Off, a goal needing only an answer closes as
/// `proposal_rejected.completion_without_receipt_completed_plan`: the model
/// has nothing to show a receipt for, and `completion_candidate` requires
/// one. The REPL has always turned this on; `run` could not, so the same
/// question answered interactively failed as a single invocation.
pub conversation_responses: bool,
}

impl LocalRunRequest {
Expand Down Expand Up @@ -174,6 +182,7 @@ impl LocalRunRequest {
max_model_turns: None,
final_response_schema: None,
completion_checks: None,
conversation_responses: false,
}
}
}
Expand Down Expand Up @@ -888,7 +897,8 @@ where
F: FnOnce(&str),
O: FnMut(DriverProgress) -> DriverProgressControl,
{
run_local_composed(request, None, false, None, on_started, on_progress)
let conversational = request.conversation_responses;
run_local_composed(request, None, conversational, None, on_started, on_progress)
}

/// Start an isolated evaluation Run using the ordinary local tools and driver.
Expand Down Expand Up @@ -3897,6 +3907,7 @@ mod tests {
max_model_turns: None,
final_response_schema: None,
completion_checks: None,
conversation_responses: false,
};
assert_eq!(
run_local(request).unwrap(),
Expand Down Expand Up @@ -3955,6 +3966,7 @@ mod tests {
max_model_turns: None,
final_response_schema: None,
completion_checks: None,
conversation_responses: false,
};
assert!(matches!(
run_local_with_process_session_progress(
Expand Down
11 changes: 11 additions & 0 deletions crates/xgen-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,13 @@ struct RunArgs {
/// Bound work performed by this process invocation.
#[arg(long, default_value_t = 32)]
max_ticks: u32,
/// Answer a goal that plans no steps, instead of requiring receipt-completed steps.
///
/// The REPL admits this contract already. Without it a question needing no
/// tool closes as `proposal_rejected.completion_without_receipt_completed_plan`,
/// so a host that drives `run` per message cannot hold a conversation.
#[arg(long)]
conversation_responses: bool,
/// Agent loop budget recorded in the Run manifest for workspace discovery runs.
#[arg(
long,
Expand Down Expand Up @@ -516,6 +523,9 @@ impl repl::ReplHost for InteractiveHost {
max_model_turns: None,
final_response_schema: None,
completion_checks: None,
// The interactive driver admits this contract regardless; said
// here so the request describes the Run it actually starts.
conversation_responses: true,
},
&process_session,
|run_id| {
Expand Down Expand Up @@ -852,6 +862,7 @@ fn run_command(args: RunArgs) -> ExitCode {
max_model_turns: args.max_model_turns,
final_response_schema,
completion_checks,
conversation_responses: args.conversation_responses,
},
|run_id| eprintln!("XGEN_STARTED run_id={run_id}"),
))
Expand Down