Synced from monorepo
Changes: - Persist submitter identity for /feedback - Let custom models use rotating tokens from named auth providers - Template stale tool/param name literals in server-native descriptions - Minimal mode commits thinking in full, lookups as one-liners - Tighten durable append internals - Nudge model to end turn on no-op bash commands - Per-fetch signing nonce in the managed-config envelope, with a server-side replay probe - Include working tree in startup status
This commit is contained in:
parent
ba76b0a683
commit
a881e6703f
140 changed files with 6746 additions and 2377 deletions
|
|
@ -6,20 +6,11 @@ use crate::common::*;
|
|||
/// so screen assertions can tell the two apart.
|
||||
const REASONING_SENTINEL: &str = "REASONINGSENTINEL";
|
||||
|
||||
/// Dogfood bug: "I don't see thoughts in the transcript". With thinking
|
||||
/// enabled (`[ui] show_thinking_blocks` — the default, set
|
||||
/// explicitly here so the test doesn't depend on the rollout default),
|
||||
/// minimal commits reasoning as a **collapsed** `Thought for Xs` header
|
||||
/// (print-once display policy) — the body is intentionally not in the live
|
||||
/// scrollback. The advertised full-fidelity `/transcript` view must therefore
|
||||
/// render the thinking body **expanded**, or the reasoning is unreachable.
|
||||
///
|
||||
/// Flow: stream a reasoning+text turn → the answer commits, the reasoning
|
||||
/// collapses to its header (body nowhere on screen) → `/transcript` with
|
||||
/// `PAGER=cat` dumps the full view → the reasoning body appears.
|
||||
/// `[ui] show_thinking_blocks` is set explicitly (not left to the default)
|
||||
/// so the test doesn't depend on the rollout default.
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
#[ignore]
|
||||
async fn minimal_transcript_expands_collapsed_thinking() {
|
||||
async fn minimal_commits_thinking_body_to_scrollback() {
|
||||
// The model must run on the Responses backend — reasoning summary deltas
|
||||
// are a Responses-API stream shape (the scripted events below).
|
||||
let content = ContentController::start_with_models(vec![
|
||||
|
|
@ -54,10 +45,7 @@ async fn minimal_transcript_expands_collapsed_thinking() {
|
|||
)
|
||||
.expect("write config");
|
||||
|
||||
// Minimal env + PAGER=cat (non-interactive dump, same as
|
||||
// `minimal_transcript_opens_in_pager`).
|
||||
let mut env = content.env_for_pager();
|
||||
env.push(("PAGER".to_string(), "cat".to_string()));
|
||||
let env = content.env_for_pager();
|
||||
let env_refs: Vec<(&str, &str)> = env.iter().map(|(k, v)| (k.as_str(), v.as_str())).collect();
|
||||
let binary = pager_binary().expect("resolve pager binary");
|
||||
let mut harness = PtyHarness::new(&binary, DEFAULT_ROWS, DEFAULT_COLS, MINIMAL_ARGS, &env_refs)
|
||||
|
|
@ -73,34 +61,17 @@ async fn minimal_transcript_expands_collapsed_thinking() {
|
|||
.wait_for_full_text(MOCK_RESPONSE_SENTINEL, Duration::from_secs(30))
|
||||
.expect("turn committed");
|
||||
|
||||
// The reasoning committed as its collapsed header: the body is NOT in the
|
||||
// live view (that's the print-once display policy, not a bug)…
|
||||
harness
|
||||
.wait_for_full_text("Thought for", Duration::from_secs(10))
|
||||
.expect("collapsed thinking header committed");
|
||||
assert!(
|
||||
!harness.full_text().contains(REASONING_SENTINEL),
|
||||
"reasoning body must be collapsed in the live view\nfull:\n{}",
|
||||
harness.full_text()
|
||||
);
|
||||
|
||||
// …so the transcript is the only way to read it. cat dumps the full view.
|
||||
inject_keys_paced(&mut harness, b"/transcript");
|
||||
harness.inject_keys(b"\r").expect("submit /transcript");
|
||||
|
||||
.expect("thinking header committed");
|
||||
harness
|
||||
.wait_for_full_text(REASONING_SENTINEL, Duration::from_secs(15))
|
||||
.wait_for_full_text(REASONING_SENTINEL, Duration::from_secs(10))
|
||||
.unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"transcript must expand the collapsed thinking body: {e}\nfull:\n{}",
|
||||
"reasoning body must be committed to scrollback: {e}\nfull:\n{}",
|
||||
harness.full_text()
|
||||
)
|
||||
});
|
||||
|
||||
// And the inline TUI survives the suspend/restore round trip.
|
||||
harness
|
||||
.wait_for_text(MINIMAL_IDLE_SENTINEL, Duration::from_secs(10))
|
||||
.expect("inline TUI restored after the pager exited");
|
||||
assert!(
|
||||
!harness.contains_text("panicked"),
|
||||
"pager panicked\nscreen:\n{}",
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
// Per-test-case module for the `pty_e2e` integration test crate.
|
||||
#[allow(unused_imports)]
|
||||
use crate::common::*;
|
||||
|
||||
const BODY_SENTINEL: &str = "READBODYONLYSENTINEL";
|
||||
const DONE_SENTINEL: &str = "LOOKUP_TURN_DONE";
|
||||
|
||||
/// Uses `read_file` rather than `grep`: the grep tool shells out to `rg`,
|
||||
/// which is absent from the Bazel remote-exec sandbox (only xai-grok-tools'
|
||||
/// own test targets ship `@ripgrep_hermetic//:rg`), and a failed spawn
|
||||
/// degrades to a zero-match result that vacuously passes the absence assert.
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
#[ignore]
|
||||
async fn minimal_lookup_commits_one_line_summary() {
|
||||
let content = ContentController::start().await.expect("start content");
|
||||
|
||||
let fixture = content.home().join("haystack.txt");
|
||||
std::fs::write(&fixture, format!("{BODY_SENTINEL} body line\n")).expect("write fixture");
|
||||
|
||||
enqueue_tool_turn(
|
||||
&content,
|
||||
"call_read",
|
||||
"read_file",
|
||||
json!({ "target_file": fixture.to_string_lossy() }).to_string(),
|
||||
);
|
||||
content.set_response(DONE_SENTINEL);
|
||||
|
||||
let mut harness = spawn_minimal_in_dir(
|
||||
&content,
|
||||
DEFAULT_ROWS,
|
||||
DEFAULT_COLS,
|
||||
&["--yolo", "--trust"],
|
||||
content.home(),
|
||||
);
|
||||
wait_minimal_ready(&mut harness);
|
||||
|
||||
harness
|
||||
.inject_keys(format!("{PROMPT}\r").as_bytes())
|
||||
.expect("submit prompt");
|
||||
harness
|
||||
.wait_for_full_text(DONE_SENTINEL, Duration::from_secs(60))
|
||||
.expect("tool turn settles");
|
||||
harness
|
||||
.wait_for_text(MINIMAL_IDLE_SENTINEL, Duration::from_secs(20))
|
||||
.expect("return to idle");
|
||||
|
||||
harness
|
||||
.wait_for_full_text("haystack.txt", Duration::from_secs(10))
|
||||
.expect("read header committed");
|
||||
assert!(
|
||||
!harness.full_text().contains(BODY_SENTINEL),
|
||||
"successful read must commit as a one-line header, without file \
|
||||
content\nfull:\n{}",
|
||||
harness.full_text()
|
||||
);
|
||||
|
||||
harness.inject_keys(b"\x05").expect("ctrl+e expand");
|
||||
harness
|
||||
.wait_for_full_text(BODY_SENTINEL, Duration::from_secs(10))
|
||||
.unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"Ctrl+E must re-print the read with its file content: {e}\nfull:\n{}",
|
||||
harness.full_text()
|
||||
)
|
||||
});
|
||||
|
||||
assert!(
|
||||
!harness.contains_text("panicked"),
|
||||
"pager panicked\nscreen:\n{}",
|
||||
harness.screen_contents()
|
||||
);
|
||||
|
||||
quit_minimal(&mut harness);
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
mod minimal_cli_screen_mode_does_not_persist;
|
||||
mod minimal_commits_response_to_scrollback;
|
||||
mod minimal_commits_thinking_body_to_scrollback;
|
||||
mod minimal_committed_content_survives_overlay_grow;
|
||||
mod minimal_continue_reprints_transcript;
|
||||
mod minimal_ctrl_c_arms_and_quits;
|
||||
|
|
@ -16,6 +17,7 @@ mod minimal_double_esc_committed_queued_prompt_single_render;
|
|||
mod minimal_esc_mid_turn_is_swallowed;
|
||||
mod minimal_flush_left_no_hpad;
|
||||
mod minimal_help_opens_command_palette;
|
||||
mod minimal_lookup_commits_one_line_summary;
|
||||
mod minimal_new_session_keeps_history_and_resets;
|
||||
mod minimal_queue_indicator_shows_while_running;
|
||||
mod minimal_resize_preserves_committed_scrollback;
|
||||
|
|
@ -25,6 +27,5 @@ mod minimal_short_response_stays_on_screen;
|
|||
mod minimal_slash_dropdown_dismisses_with_esc;
|
||||
mod minimal_slash_switches_from_fullscreen;
|
||||
mod minimal_slash_switches_to_fullscreen;
|
||||
mod minimal_transcript_expands_collapsed_thinking;
|
||||
mod minimal_transcript_opens_in_pager;
|
||||
mod minimal_transcript_pager_restore_no_artifacts;
|
||||
|
|
|
|||
Loading…
Reference in a new issue