Skip to content

Add ACP IO Nats Bridge#1

Draft
yordis wants to merge 16 commits intomainfrom
add-acp
Draft

Add ACP IO Nats Bridge#1
yordis wants to merge 16 commits intomainfrom
add-acp

Conversation

@yordis
Copy link
Member

@yordis yordis commented Feb 16, 2026

Signed-off-by: Yordis Prieto yordis.prieto@gmail.com

@coderabbitai
Copy link

coderabbitai bot commented Feb 16, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch add-acp

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.

@yordis yordis force-pushed the add-acp branch 27 times, most recently from ad93c4c to 5f2ba1e Compare February 18, 2026 18:03
@cursor
Copy link

cursor bot commented Feb 18, 2026

PR Summary

Medium Risk
Adds new network-facing proxying logic (stdio↔NATS) and telemetry initialization; while mostly additive, it introduces new runtime behavior around session/prompt coordination and error handling that could affect message delivery and shutdown semantics.

Overview
Introduces a new acp-nats crate that implements an ACP Agent bridge over NATS, including subject construction/parsing, request/notification forwarding, session lifecycle helpers (e.g., session.ready), prompt cancellation handling, and OpenTelemetry metrics instrumentation.

Adds a new acp-nats-stdio binary that runs the bridge over stdio, supports configurable ACP subject prefixes/env-based NATS config, graceful shutdown on signals, and optional OpenTelemetry + JSON logging to stderr and a platform log file.

Updates Cargo.lock to pull in the new crates and their dependency graph (notably clap, opentelemetry-otlp, reqwest/hyper/tonic, and updated transitive versions).

Written by Cursor Bugbot for commit 51f0ccf. This will update automatically on new commits. Configure here.

@yordis yordis force-pushed the add-acp branch 3 times, most recently from f3e3b9e to d8838ae Compare February 19, 2026 00:22
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Replace Arc with Rc for non-Send types used exclusively on spawn_local,
collapse nested if-let chains, remove ~900 lines of unused test builders
and handlers, and apply cargo fmt.
SIGINT and SIGTERM are expected operational events for graceful shutdown,
not conditions requiring attention.
Malformed payloads from external NATS sources are not internal server
errors — they indicate protocol mismatches, not issues requiring
on-call intervention.
If the configurable prefix contains "client" as a dot-separated token
(e.g. "org.client.app"), position() matched the wrong token and the
parser silently dropped valid messages. Using rposition() finds the
structural marker instead.
Re-check the cancel flag after registering the prompt response waiter.
Without this, a cancel arriving between the initial check and waiter
registration would be missed, causing the prompt to proceed and wait
until timeout.
match serde_json::from_slice::<SessionNotification>(payload) {
Ok(notification) => {
if let Err(e) = client.session_notification(notification).await {
error!(error = %e, "Failed to send session notification");
Copy link

Choose a reason for hiding this comment

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

Session notification failure logged at error level

Low Severity

error! is used for "Failed to send session notification," but this can occur during normal client disconnects, which are non-actionable. Per logging rules, error logs are treated as production issues that must be fixed. A warn level is more appropriate here since the failure may or may not require action.

Fix in Cursor Fix in Web

Triggered by team rule: Logging Level and Error Reporting Usage

- Extract duplicated session.ready publish logic into Bridge::spawn_session_ready
- Fix double remove_waiter in prompt timeout path
- Record metric on unexpected prompt channel close
- Fix HandlerType copy-paste bug (SessionNew was Authenticate)
- Reduce string allocations in metrics hot path
- Extract telemetry file layer init into try_open_log_file
- Document test builders as arbitrary fixtures
- Add Rc safety comment explaining !Send constraint
- Cancel handler now resolves pending prompt waiter with StopReason::Cancelled
- Replace raw -32603 literals with JSONRPC_INTERNAL_ERROR/JSONRPC_SERVER_ERROR constants
- Prompt timeout and channel-closed now return JSON-RPC errors instead of fake EndTurn
- Add catch_unwind guards on spawn_local tasks
- Warn on duplicate waiter replacement
- Validate empty session ID in parse_client_subject
- Remove dead code (unused wildcards module, #[allow(dead_code)])
- Add Metrics::with_meter() constructor, simplify test setup
- Add 3 new waiter tests (cancel, resolve, duplicate)
- Remove unnecessary Rc wrapping on RefCell fields
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

}

pub fn from_env_with_provider<E: ReadEnv>(env_provider: &E) -> Config {
let args = Args::parse();
Copy link

Choose a reason for hiding this comment

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

Args::parse() in tests reads real process arguments

Medium Severity

from_env_with_provider hardcodes Args::parse(), which reads from std::env::args(). In test binaries, those args include cargo-test flags (e.g., --nocapture, test name filters). Clap will reject unrecognized args and call process::exit(2), killing the entire test suite. The tests only pass when cargo test is invoked with zero extra arguments — running cargo test test_default_config or cargo test -- --nocapture will abort the process before any test runs.

Additional Locations (1)

Fix in Cursor Fix in Web

31 new tests covering Agent trait handler flows (initialize, authenticate,
new_session, load_session, set_session_mode, cancel, prompt, ext_method,
ext_notification) and Client-side handlers (ext_session_prompt_response,
session_update, all 8 RPC handlers with JSON round-trip).
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.

1 participant

Comments