Skip to content
Closed
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
9 changes: 5 additions & 4 deletions crates/forge_e2e/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
//! ```rust,no_run
//! use forge_e2e::{Scenario, MockLlm, ExpectedTool, ExpectedText};
//!
//! # async fn example() -> anyhow::Result<()> {
//! // Build a scenario declaratively.
//! let scenario = Scenario::new("agent reads a file then writes a fix")
//! .user_says("please fix the typo in README.md")
//! .expect_tool_call(ExpectedTool::new("read").arg("path", "README.md"))
Expand All @@ -40,9 +40,10 @@
//! .user_says("thanks")
//! .mock_responds(MockLlm::text_only(ExpectedText::contains("you're welcome")));
//!
//! scenario.run().await?;
//! # Ok(())
//! # }
//! // The scenario is a script: the agent runtime reads it step by step.
//! let (steps, mock_llm) = scenario.into_mock_llm();
//! assert_eq!(steps.len(), 4); // 2 user_says + 2 expect_tool_call
//! assert_eq!(mock_llm.remaining(), 3); // 3 mock responses queued
Comment on lines +43 to +46

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Replace the rustdoc example with concise prose

The newly added executable assertions extend a public Rust documentation code example, contrary to the repository's explicit requirement that documentation contain no code examples. Remove this block and describe the scenario/mock behavior in concise prose instead.

AGENTS.md reference: AGENTS.md:L117-L117

Useful? React with 👍 / 👎.

//! ```
//!
//! ## Mock LLM Format
Expand Down
22 changes: 12 additions & 10 deletions crates/helios-bot/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ pub enum Command {

pub fn parse_args() -> Result<Command> {
let args: Vec<String> = std::env::args().skip(1).collect();
if args.is_empty() {
anyhow::bail!("usage: helios-bot <serve|run> ...");
}
match args[0].as_str() {
let first = args
.first()
.ok_or_else(|| anyhow::anyhow!("usage: helios-bot <serve|run> ..."))?;
match first.as_str() {
"serve" => {
let s = parse_serve(&args[1..])?;
let s = parse_serve(args.get(1..).unwrap_or(&[]))?;
Ok(Command::Serve {
bind: s.bind,
private_key: s.private_key,
Expand All @@ -49,7 +49,7 @@ pub fn parse_args() -> Result<Command> {
})
}
"run" => {
let r = parse_run(&args[1..])?;
let r = parse_run(args.get(1..).unwrap_or(&[]))?;
Ok(Command::Run {
repo: r.repo,
request: r.request,
Expand Down Expand Up @@ -77,7 +77,8 @@ fn parse_serve(args: &[String]) -> Result<ServeArgs> {

let mut i = 0;
while i < args.len() {
match args[i].as_str() {
let arg = args.get(i).map(String::as_str).unwrap_or("");
match arg {
"--bind" => {
bind = args
.get(i + 1)
Expand Down Expand Up @@ -114,7 +115,7 @@ fn parse_serve(args: &[String]) -> Result<ServeArgs> {
.ok_or_else(|| anyhow::anyhow!("--webhook-secret requires a value"))?;
i += 2;
}
_ => anyhow::bail!("unknown flag: {}", args[i]),
other => anyhow::bail!("unknown flag: {other}"),
}
}

Expand All @@ -140,7 +141,8 @@ fn parse_run(args: &[String]) -> Result<RunArgs> {

let mut i = 0;
while i < args.len() {
match args[i].as_str() {
let arg = args.get(i).map(String::as_str).unwrap_or("");
match arg {
"--repo" => {
repo = Some(
args.get(i + 1)
Expand All @@ -165,7 +167,7 @@ fn parse_run(args: &[String]) -> Result<RunArgs> {
checkout_dir = Some(PathBuf::from(v));
i += 2;
}
_ => anyhow::bail!("unknown flag: {}", args[i]),
other => anyhow::bail!("unknown flag: {other}"),
}
}

Expand Down
4 changes: 3 additions & 1 deletion crates/helios-bot/src/webhook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ pub fn parse_helios_mention(text: &str, is_issue: bool, in_comment: bool) -> Opt
// Look for `@helios` (case-insensitive), followed by optional whitespace, then capture the rest.
let lower = text.to_ascii_lowercase();
let idx = lower.find("@helios")?;
let after = &text[idx + "@helios".len()..];
let needle_len = "@helios".len();
let after_start = idx.checked_add(needle_len)?;
let after = text.get(after_start..)?;
// Strip leading whitespace and a single optional ':' or ','.
let trimmed = after
.trim_start()
Expand Down
Loading