Skip to content

refactor(broker): replace helpers.rs with focused modules#907

Merged
willwashburn merged 2 commits into
mainfrom
codex/refactor-helpers-876
May 19, 2026
Merged

refactor(broker): replace helpers.rs with focused modules#907
willwashburn merged 2 commits into
mainfrom
codex/refactor-helpers-876

Conversation

@willwashburn
Copy link
Copy Markdown
Member

Closes #876

Summary

  • Removed the broad broker helpers.rs module and moved its code into domain-owned modules.
  • Grouped command parsing, ANSI/text utilities, terminal prompt detection, injection formatting, delivery verification, continuity parsing, worker activity detection, and Relaycast identity/DM cache logic by ownership.
  • Moved the helper unit tests alongside the code they validate.

Validation

  • cargo check -p agent-relay-broker
  • cargo test -p agent-relay-broker
  • cargo test --release
  • cargo fmt --check
  • cargo clippy -p agent-relay-broker -- -D warnings
  • npm run -w @agent-relay/sdk check

@willwashburn willwashburn requested a review from khaliqgant as a code owner May 19, 2026 02:57
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 19, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 87d0c5d3-6dfc-48c7-bbb6-51ff3647e7b3

📥 Commits

Reviewing files that changed from the base of the PR and between 8f92c06 and 505aa63.

📒 Files selected for processing (8)
  • crates/broker/src/broker/continuity.rs
  • crates/broker/src/relaycast/dm_participants.rs
  • crates/broker/src/runtime/event_loop.rs
  • crates/broker/src/runtime/init.rs
  • crates/broker/src/runtime/mod.rs
  • crates/broker/src/util/terminal.rs
  • crates/broker/src/worker/detection.rs
  • crates/broker/src/wrap.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • crates/broker/src/runtime/mod.rs
  • crates/broker/src/worker/detection.rs
  • crates/broker/src/util/terminal.rs

📝 Walkthrough

Walkthrough

Refactors the monolithic helpers.rs into focused modules: broker continuity/delivery/injection, CLI parsing, util ansi/terminal, relaycast dm/identity, and worker detection. Updates module wiring and replaces imports across the crate; adds trajectory records documenting the change.

Changes

Refactor broker helpers into focused utility modules by domain ownership

Layer / File(s) Summary
Module declarations and root wiring
crates/broker/src/main.rs, crates/broker/src/broker.rs, crates/broker/src/cli/mod.rs, crates/broker/src/relaycast/mod.rs, crates/broker/src/util/mod.rs
Introduce new root and submodule declarations (broker, cli, relaycast, util) and declare domain submodules.
Broker domain modules: continuity, delivery_verification, injection_format
crates/broker/src/broker/continuity.rs, crates/broker/src/broker/delivery_verification.rs, crates/broker/src/broker/injection_format.rs
Add continuity PTY parsing, delivery verification (throttling, pending tracking, echo checks, payload builders), and MCP injection formatting with system-reminder logic and tests.
CLI module: command parsing with shlex tokenization and flag injection
crates/broker/src/cli/command_parse.rs
Add parse_cli_command and normalize_cli_name with shlex-based tokenization, cursor→agent mapping, and flag injection/deduplication plus tests.
Util domain modules: ansi escape handling and terminal prompt detection
crates/broker/src/util/ansi.rs, crates/broker/src/util/terminal.rs
Add floor_char_boundary and strip_ansi; implement terminal detectors for permission/trust/editor/auto-suggestion prompts with tests.
Relaycast domain modules: dm_participants caching and identity comparison
crates/broker/src/relaycast/dm_participants.rs, crates/broker/src/relaycast/identity.rs
Introduce DmParticipantsCache with success/failure entries, TTLs, eviction; add agent_name_eq and is_self_name.
Worker detection module: activity marker inference from LLM output
crates/broker/src/worker/detection.rs
Add ActivityDetector selecting CLI-specific patterns, stripping ANSI and removing echoed text before matching; includes tests.
Import refactoring across codebase
crates/broker/src/{pty_worker.rs, readiness.rs, runtime/mod.rs, runtime/tests.rs, spawner.rs, swarm.rs, wait.rs, worker.rs, wrap.rs, runtime/init.rs, runtime/event_loop.rs}
Replace crate::helpers uses with targeted imports from new modules and retype DM participants cache to DmParticipantsCache.
Trajectory completion records
.trajectories/completed/2026-05/traj_jbo2x14y7ovt.json, .trajectories/completed/2026-05/traj_jbo2x14y7ovt.md, .trajectories/index.json
Add new completed trajectory files documenting "Fix issue 876" and update the trajectories index.

Estimated code review effort:
🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • khaliqgant
  • barryollama

Poem

🐰 In tangled helpers I once did dwell,

Now split by domain, each sings its own spell.
CLI hops, ANSI scrubs, relaycast knows its part—
A rabbit's small cheer for modular art. 🥕✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main refactoring change: moving from a monolithic helpers.rs to focused, domain-specific modules.
Description check ✅ Passed The PR description includes a concise summary of changes, validation steps performed, and references the closed issue. However, it lacks a 'Test Plan' section with checkboxes as specified in the repository template.
Linked Issues check ✅ Passed All acceptance criteria from issue #876 are met: helpers.rs is removed, functions are grouped into domain-specific modules with appropriate visibility (pub(crate)), tests are relocated alongside code, and validation confirms Rust tests pass.
Out of Scope Changes check ✅ Passed All changes are directly related to the refactoring objective. The PR removes helpers.rs and redistributes its functionality into focused modules (util/, broker/, relaycast/, cli/, worker/), with necessary import updates across the codebase.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/refactor-helpers-876

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (2)
.trajectories/completed/2026-05/traj_jbo2x14y7ovt.json (1)

51-51: ⚡ Quick win

Prefer repo-relative projectId over absolute local paths.

Line 51 stores a machine-specific absolute path (/Users/will/...), which leaks local environment details and makes trajectory artifacts less portable. Prefer a repo-relative identifier (or a stable logical project key) for committed metadata.

Proposed adjustment
-  "projectId": "/Users/will/Projects/AgentWorkforce/relay",
+  "projectId": ".",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.trajectories/completed/2026-05/traj_jbo2x14y7ovt.json at line 51, The
committed trajectory JSON contains a machine-specific absolute path in the
"projectId" field; update the projectId value to a repo-relative identifier or
stable logical key (e.g., "relay" or "./") instead of
"/Users/will/Projects/AgentWorkforce/relay". Locate the "projectId" key in the
.trajectories/completed JSON entry (the "projectId" property) and replace the
absolute local filesystem path with a portable repo-relative or canonical
project identifier, then re-save the artifact.
.trajectories/index.json (1)

985-990: ⚡ Quick win

Use a repository-relative path for the new trajectory index entry.

Line 990 records an absolute local filesystem path. For committed index metadata, a repo-relative path is safer and portable across contributors/machines.

Proposed adjustment
-      "path": "/Users/will/Projects/AgentWorkforce/relay/.trajectories/completed/2026-05/traj_jbo2x14y7ovt.json"
+      "path": ".trajectories/completed/2026-05/traj_jbo2x14y7ovt.json"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.trajectories/index.json around lines 985 - 990, The "traj_jbo2x14y7ovt"
index entry contains an absolute filesystem path in its "path" property; replace
that absolute path with a repository-relative path (for example
".trajectories/completed/2026-05/traj_jbo2x14y7ovt.json" or
"./.trajectories/..." consistent with other entries) so the index is portable
across machines, and ensure the "path" value format matches the rest of the
entries in the JSON.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/broker/src/broker/continuity.rs`:
- Around line 55-58: The parser currently falls back to unwrap_or(i + 2) when
computing bytes_consumed (assumes ACTION: is immediately after KIND:) which
under-consumes if blank/metadata lines appear; change the logic that computes
bytes_consumed so it uses the actual index found in the loop instead of i+2—use
the loop index j (or the index where you set body_start_line/action) as the
fallback. Concretely, in the code that iterates with for (j, line_at_j) in
lines.iter().enumerate().skip(i + 1) and sets action: Option<ContinuityAction>
and body_start_line: Option<usize>, replace the unwrap_or(i + 2) fallback with a
value derived from j or the discovered body_start_line/action index (e.g.,
bytes_consumed = body_start_line.unwrap_or(action_index_or_j)) so the
consumed-line count reflects where ACTION or the body actually begins rather
than assuming the next line.

In `@crates/broker/src/relaycast/dm_participants.rs`:
- Around line 9-10: get_dm_participants currently never caches failures so
repeated calls for the same cache_key trigger upstream requests on every
message; add a failure-backoff entry keyed by cache_key (separate from
DM_PARTICIPANT_CACHE_TTL) to throttle retries. Implement a new constant (e.g.
DM_PARTICIPANT_FAILURE_TTL) and on upstream failure insert a lightweight failure
marker into the same cache (respecting MAX_DM_CACHE_ENTRIES) so subsequent calls
check the cache first, return a failure/empty result or short-circuit until the
failure TTL expires, and ensure the failure path in get_dm_participants and
related logic (the cache lookup/insert points) use this marker rather than
always attempting the upstream call.

In `@crates/broker/src/util/terminal.rs`:
- Around line 61-63: The check trimmed.starts_with('\n') is unreachable because
trimmed was produced with trim_start() which removes leading newlines; change
the condition to inspect the original string before trimming (use
after_pattern.starts_with('\n')) so the editor-mode detection correctly detects
a leading newline and prevents incorrect auto-enter; update the if condition
that currently reads `if trimmed.is_empty() || trimmed.starts_with('\n')` to use
`after_pattern.starts_with('\n')` instead of checking trimmed for the newline.

In `@crates/broker/src/worker/detection.rs`:
- Around line 26-32: The current logic in detection.rs using the
relevant_output/clean_output/expected_echo flow only removes the first
occurrence of expected_echo, leaving duplicates that can still trigger activity;
change the handling so all echoed relay lines are removed (e.g., replace all
occurrences of expected_echo from clean_output or iteratively strip every match)
and return the fully-cleaned string into relevant_output so no remaining echoes
remain to cause activity markers.

---

Nitpick comments:
In @.trajectories/completed/2026-05/traj_jbo2x14y7ovt.json:
- Line 51: The committed trajectory JSON contains a machine-specific absolute
path in the "projectId" field; update the projectId value to a repo-relative
identifier or stable logical key (e.g., "relay" or "./") instead of
"/Users/will/Projects/AgentWorkforce/relay". Locate the "projectId" key in the
.trajectories/completed JSON entry (the "projectId" property) and replace the
absolute local filesystem path with a portable repo-relative or canonical
project identifier, then re-save the artifact.

In @.trajectories/index.json:
- Around line 985-990: The "traj_jbo2x14y7ovt" index entry contains an absolute
filesystem path in its "path" property; replace that absolute path with a
repository-relative path (for example
".trajectories/completed/2026-05/traj_jbo2x14y7ovt.json" or
"./.trajectories/..." consistent with other entries) so the index is portable
across machines, and ensure the "path" value format matches the rest of the
entries in the JSON.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 23da9c40-1506-47d6-8a9b-d32038560847

📥 Commits

Reviewing files that changed from the base of the PR and between 6378fdb and 8f92c06.

📒 Files selected for processing (27)
  • .trajectories/completed/2026-05/traj_jbo2x14y7ovt.json
  • .trajectories/completed/2026-05/traj_jbo2x14y7ovt.md
  • .trajectories/index.json
  • crates/broker/src/broker.rs
  • crates/broker/src/broker/continuity.rs
  • crates/broker/src/broker/delivery_verification.rs
  • crates/broker/src/broker/injection_format.rs
  • crates/broker/src/cli/command_parse.rs
  • crates/broker/src/cli/mod.rs
  • crates/broker/src/helpers.rs
  • crates/broker/src/main.rs
  • crates/broker/src/pty_worker.rs
  • crates/broker/src/readiness.rs
  • crates/broker/src/relaycast/dm_participants.rs
  • crates/broker/src/relaycast/identity.rs
  • crates/broker/src/relaycast/mod.rs
  • crates/broker/src/runtime/mod.rs
  • crates/broker/src/runtime/tests.rs
  • crates/broker/src/spawner.rs
  • crates/broker/src/swarm.rs
  • crates/broker/src/util/ansi.rs
  • crates/broker/src/util/mod.rs
  • crates/broker/src/util/terminal.rs
  • crates/broker/src/wait.rs
  • crates/broker/src/worker.rs
  • crates/broker/src/worker/detection.rs
  • crates/broker/src/wrap.rs
💤 Files with no reviewable changes (1)
  • crates/broker/src/helpers.rs

Comment thread crates/broker/src/broker/continuity.rs
Comment thread crates/broker/src/relaycast/dm_participants.rs
Comment thread crates/broker/src/util/terminal.rs Outdated
Comment thread crates/broker/src/worker/detection.rs Outdated
Copy link
Copy Markdown

@barryollama barryollama left a comment

Choose a reason for hiding this comment

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

Code Review: refactor(broker): replace helpers.rs with focused modules

Verdict: ✅ Approve

Summary

This PR successfully decomposes the monolithic helpers.rs (1,631 lines) into well-organized, domain-focused modules. This is a pure refactoring with no behavioral changes — code is moved as-is with tests co-located.

Structural Changes Reviewed

New Module Purpose Lines Tests
cli/command_parse.rs CLI command parsing, cursor→agent mapping 137
broker/continuity.rs Continuity command block parsing 135
broker/delivery_verification.rs Delivery verification, throttling 275
broker/injection_format.rs Message injection formatting, MCP hints 338
relaycast/dm_participants.rs DM participant caching with TTL 145
relaycast/identity.rs Case-insensitive agent name comparison 51
util/ansi.rs ANSI escape code stripping 97
util/terminal.rs Terminal prompt detection (vim, permissions, etc.) 371
worker/detection.rs Activity detection for Claude/Codex/Gemini 160

Verification Performed

  • cargo check -p agent-relay-broker — clean compilation
  • cargo test -p agent-relay-broker — 360 tests passed
  • cargo test --r (continuity tests) — 12 tests passed

Code Quality Observations

  • No logic changes: All code moved verbatim from helpers.rs
  • Tests co-located: Unit tests moved alongside implementation (e.g., cli/command_parse.rs tests validate the parsing)
  • Clean imports: All consuming modules updated to use new paths (use crate::cli::command_parse::..., etc.)
  • Module structure: Clean mod.rs files for cli/, broker/, relaycast/, util/, worker/

Suggestions (non-blocking)

  • The trajectory files (.trajectories/) are included — these provide audit trail of the refactoring process via the trail tool

Bottom Line

Clean, well-scoped refactoring that improves code organization without changing behavior. The module boundaries align with domain concepts (CLI parsing, delivery verification, terminal detection, etc.).

Reviewed by Hermes Agent

@willwashburn willwashburn merged commit 9b20510 into main May 19, 2026
39 checks passed
@willwashburn willwashburn deleted the codex/refactor-helpers-876 branch May 19, 2026 03:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(broker): replace helpers.rs with focused utility modules

2 participants