-
Notifications
You must be signed in to change notification settings - Fork 6.3k
feat: tui command on goose-cli #9385
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,4 +9,5 @@ pub mod review; | |
| pub mod schedule; | ||
| pub mod session; | ||
| pub mod term; | ||
| pub mod tui; | ||
| pub mod update; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| use anyhow::{anyhow, Context, Result}; | ||
| use std::path::{Path, PathBuf}; | ||
| use std::process::Command; | ||
|
|
||
| const TUI_NPM_SPEC_ENV: &str = "GOOSE_TUI_NPM_SPEC"; | ||
| const TUI_REL_PATH: &str = "ui/text/dist/tui.js"; | ||
| const DEFAULT_NPM_SPEC: &str = "@aaif/goose@latest"; | ||
| const NPM_BIN_NAME: &str = "goose-tui"; | ||
|
|
||
| enum TuiSource { | ||
| LocalScript(PathBuf), | ||
| Npx(String), | ||
| } | ||
|
|
||
| fn find_local_script() -> Option<PathBuf> { | ||
| let exe = std::env::current_exe().ok()?; | ||
| let exe_dir = exe.parent().unwrap_or_else(|| Path::new(".")); | ||
|
|
||
| let mut dir = Some(exe_dir.to_path_buf()); | ||
| for _ in 0..6 { | ||
| if let Some(d) = dir.clone() { | ||
| let candidate = d.join(TUI_REL_PATH); | ||
| if candidate.is_file() { | ||
| return Some(candidate); | ||
| } | ||
| dir = d.parent().map(Path::to_path_buf); | ||
| } | ||
| } | ||
|
|
||
| if let Ok(cwd) = std::env::current_dir() { | ||
| let candidate = cwd.join(TUI_REL_PATH); | ||
| if candidate.is_file() { | ||
| return Some(candidate); | ||
| } | ||
| } | ||
|
|
||
| None | ||
| } | ||
|
|
||
| fn resolve_source() -> TuiSource { | ||
| if let Some(script) = find_local_script() { | ||
| return TuiSource::LocalScript(script); | ||
| } | ||
| let spec = std::env::var(TUI_NPM_SPEC_ENV).unwrap_or_else(|_| DEFAULT_NPM_SPEC.to_string()); | ||
| TuiSource::Npx(spec) | ||
|
Comment on lines
+41
to
+45
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.
The new command advertises Useful? React with 👍 / 👎. |
||
| } | ||
|
|
||
| fn build_command(source: &TuiSource, args: &[String]) -> Result<Command> { | ||
| match source { | ||
| TuiSource::LocalScript(script) => { | ||
| let mut cmd = Command::new("node"); | ||
| cmd.arg(script).args(args); | ||
| Ok(cmd) | ||
| } | ||
| TuiSource::Npx(spec) => { | ||
| let mut cmd = Command::new("npx"); | ||
| cmd.arg("--yes") | ||
| .arg("--package") | ||
| .arg(spec) | ||
| .arg("--") | ||
| .arg(NPM_BIN_NAME) | ||
| .args(args); | ||
| Ok(cmd) | ||
| } | ||
| } | ||
| } | ||
|
Collaborator
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. so this doesn't actually run the current goose binary as the source of ACP, right?
Collaborator
Author
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. The TUI does. So we have some psuedo-cycles here... different commands but: goose tui -> runs TUI -> uses |
||
|
|
||
| pub fn handle_tui(args: Vec<String>) -> Result<()> { | ||
| let source = resolve_source(); | ||
|
|
||
| let goose_binary = std::env::current_exe() | ||
| .context("could not determine current goose executable to expose as GOOSE_BINARY")?; | ||
|
|
||
| let mut cmd = build_command(&source, &args)?; | ||
| cmd.env("GOOSE_BINARY", &goose_binary); | ||
|
|
||
| let descriptor = match &source { | ||
| TuiSource::LocalScript(p) => format!("node {}", p.display()), | ||
| TuiSource::Npx(spec) => format!("npx --package {} -- {}", spec, NPM_BIN_NAME), | ||
| }; | ||
|
|
||
| #[cfg(unix)] | ||
| { | ||
| use std::os::unix::process::CommandExt; | ||
| let err = cmd.exec(); | ||
| Err(anyhow!("failed to exec TUI ({descriptor}): {err}")) | ||
| } | ||
|
|
||
| #[cfg(not(unix))] | ||
| { | ||
| let status = cmd | ||
| .status() | ||
| .with_context(|| format!("failed to run `{descriptor}`"))?; | ||
| if !status.success() { | ||
| std::process::exit(status.code().unwrap_or(1)); | ||
| } | ||
| Ok(()) | ||
| } | ||
| } | ||
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.
what is the use case here? if I am developing the TUI, am I likely to use this path?
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.
Yeah I thought it could be helpful that when running
cargo run --bin goose -- tuiit also runs the tui from source