Repository navigation
Offer Change keys in the desktop app #569
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,10 @@ use std::time::{Duration, Instant}; | |
| /// rather than closed. The CLI tests run the real server against this text. | ||
| const BOUND_LINE: &str = "codetrial: open http://"; | ||
|
|
||
| /// What the server prints once Change keys has rewritten its config. The | ||
| /// server's copy is `KEYS_SAVED_LINE` in src/web/setup_edit.rs. | ||
| const KEYS_SAVED_LINE: &str = "codetrial: keys saved; restart to use them"; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: This string is duplicated across the crate boundary and nothing pins the two copies together. If the server's text changes, the app never restarts after a save and the new keys stay unused, with no error. Add a CLI test that runs the real server and asserts it prints this exact line, as the CLI tests do for Prompt for AI agents |
||
|
|
||
| /// How much of the server's stderr explains an exit. The reason is its last | ||
| /// line; the ones before it are the warnings it printed on the way. | ||
| const REASON_LINES: usize = 12; | ||
|
|
@@ -39,6 +43,19 @@ pub struct Launch { | |
| /// A CLI config whose keys Setup offers to use on a first launch. The | ||
| /// server decides what is offered and what using it writes. | ||
| pub import_config: Option<PathBuf>, | ||
| /// What Change keys asks for, new on every launch. The server has no | ||
| /// terminal to print one to, so the app makes it, hands it over in the | ||
| /// environment, and fills it into the Setup page in its own window. | ||
| pub change_keys_code: String, | ||
| } | ||
|
|
||
| /// A code for `Launch::change_keys_code`: 32 hex digits from the operating | ||
| /// system's generator. | ||
| pub fn change_keys_code() -> Result<String, String> { | ||
| let mut bytes = [0u8; 16]; | ||
| getrandom::fill(&mut bytes) | ||
| .map_err(|error| format!("cannot make a Change keys code: {error}"))?; | ||
| Ok(bytes.iter().map(|byte| format!("{byte:02x}")).collect()) | ||
| } | ||
|
|
||
| /// The CLI config in `start`: the CLI's own two places there and nowhere else. | ||
|
|
@@ -57,6 +74,8 @@ pub fn cli_config_in(start: &Path) -> Option<PathBuf> { | |
| pub enum Status { | ||
| /// Listening on `Launch::addr`. | ||
| Ready, | ||
| /// Change keys saved new keys, which only a new launch uses. | ||
| KeysSaved, | ||
| /// Gone, and why, in words for the person looking at the window. | ||
| Exited(String), | ||
| } | ||
|
|
@@ -116,6 +135,7 @@ fn command(launch: &Launch) -> Command { | |
| // data folder is the one place it can sensibly mean. | ||
| .current_dir(&launch.data_dir) | ||
| .env("CODETRIAL_EXIT_WITH_STDIN", "1") | ||
| .env("CODETRIAL_CHANGE_KEYS_CODE", &launch.change_keys_code) | ||
| .stdin(Stdio::piped()) | ||
| .stdout(Stdio::piped()) | ||
| .stderr(Stdio::piped()); | ||
|
|
@@ -177,6 +197,13 @@ pub fn start( | |
| copiers.push(std::thread::spawn(move || { | ||
| let mut bound = false; | ||
| copy_lines(stdout, &log, |line| { | ||
| if bound && line == KEYS_SAVED_LINE { | ||
| let finished = finished.lock().expect("report order lock"); | ||
| if !*finished { | ||
| report(Status::KeysSaved); | ||
| } | ||
| return; | ||
| } | ||
| if bound || !line.starts_with(BOUND_LINE) { | ||
| return; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -68,13 +68,24 @@ server's rules: | |
| quitting or by crashing, the server goes too and does not keep the port. | ||
| This one stays in the environment even for `--data-dir`, because it is not | ||
| configuration but a description of the pipe the launcher handed over. | ||
| - `CODETRIAL_CHANGE_KEYS_CODE`: the code the lobby's Change keys asks for. | ||
| A server started from a terminal makes its own and prints it there; this | ||
| one has no terminal, so the app makes a new code at every launch, hands it | ||
| over here, and fills it into the Setup page when that page loads in its | ||
| window. It never travels in a URL or reaches the server log. Once a save | ||
| rewrites the config, the server prints `codetrial: keys saved; restart to | ||
| use them`, and the app stops the server and starts it again onto the new | ||
| keys, back on the lobby. The save itself refuses while an interview is | ||
| running or writing its report. With the interview in the default browser | ||
| the app cannot fill the code there, so Change keys works only in the | ||
| window. | ||
| - `--no-update-check`: the lobby never offers a newer release, whatever the | ||
| config file says about `CODETRIAL_UPDATE_CHECK`. That check compares the | ||
| server with the `latest` release, and the app is published as | ||
| `desktop-latest`, so it would offer every desktop install an update to the | ||
| CLI binary. | ||
|
|
||
| All five are ordinary server options, and a CLI install can use them the same | ||
| All six are ordinary server options, and a CLI install can use them the same | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: The intro still says the server starts with "five things" a launcher needs, but this PR adds a sixth, so the count now disagrees with the list and with "All six" below. Change "five" to "six" on the intro line. Prompt for AI agents |
||
| way. `codetrial --help` lists the four flags, and the README's configuration | ||
| table lists `CODETRIAL_ALLOWED_HOSTS`. | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -660,6 +660,16 @@ pub fn exit_with_stdin(value: Option<&str>) -> bool { | |
| parse_bool(value, false) | ||
| } | ||
|
|
||
| /// `CODETRIAL_CHANGE_KEYS_CODE`: the code the desktop app hands its child. | ||
| /// One too short to stand in for the code `run_web` makes is no code, so a | ||
| /// launcher that set it carelessly gets no Change keys rather than a weak one. | ||
| pub fn change_keys_code(value: Option<&str>) -> Option<String> { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Prompt for AI agents |
||
| value | ||
| .map(str::trim) | ||
| .filter(|code| code.len() >= 24 && code.bytes().all(|byte| byte.is_ascii_alphanumeric())) | ||
| .map(str::to_string) | ||
| } | ||
|
|
||
| pub fn gemini_candidate_video_enabled(value: Option<&str>) -> bool { | ||
| parse_bool(value, DEFAULT_GEMINI_CANDIDATE_VIDEO_ENABLED) | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
server.stop(STOP_GRACE)ends the child at once, because stdin closing exits it, so the grace period does not apply. An interview admitted after the save'sis_idlecheck and before this line is cut off with its report lost (the PR text acknowledges this). As a follow-up, once the save has written the config the server could refuse new interviews (restartPendingis already tracked), so the window closes at the save rather than at the restart.