Skip to content
Merged
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: 9 additions & 0 deletions crates/cli/src/doctor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use std::time::Duration;

use nemo_relay::observability::plugin_component::OBSERVABILITY_PLUGIN_KIND;
use nemo_relay::plugin::{DiagnosticLevel, PluginConfig, validate_plugin_config};
use nemo_relay_adaptive::plugin_component::register_adaptive_component;
use serde::Serialize;
use serde_json::Value;
use tokio::time::timeout;
Expand Down Expand Up @@ -592,6 +593,14 @@ async fn collect_observability(gateway: &GatewayConfig) -> Vec<Check> {
return checks;
}
};
if let Err(error) = register_adaptive_component() {
checks.push(Check {
name: "Adaptive plugin",
status: Status::Fail,
details: format!("registration failed: {error}"),
});
return checks;
}
let report = validate_plugin_config(&plugin_config);
if report.diagnostics.is_empty() {
checks.push(Check {
Expand Down
37 changes: 37 additions & 0 deletions crates/cli/tests/coverage/doctor_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,43 @@ async fn collect_observability_warns_for_missing_atif_dir_without_creating_it()
assert!(!missing.exists());
}

#[tokio::test]
async fn collect_observability_registers_adaptive_before_validation() {
let gateway = GatewayConfig {
plugin_config: Some(serde_json::json!({
"version": 1,
"components": [
{
"kind": "observability",
"enabled": true,
"config": { "version": 1 }
},
{
"kind": "adaptive",
"enabled": false,
"config": {
"policy": {
"unknown_component": "warn",
"unknown_field": "warn",
"unsupported_value": "error"
}
}
}
]
})),
..GatewayConfig::default()
};

let checks = collect_observability(&gateway).await;

assert!(
!checks.iter().any(|check| check
.details
.contains("plugin component kind 'adaptive' is unsupported")),
"doctor should register adaptive before plugin validation: {checks:?}"
);
}

#[test]
fn format_agents_human_lists_supported_and_separates_detected() {
let agents = vec![
Expand Down
2 changes: 1 addition & 1 deletion docs/nemo-relay-cli/about.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ NeMo Relay CLI support is experimental and observability-focused.
| Claude Code | ✅ Yes | ❌ No | ❌ No | Observability only; no known issues. |
| Codex | ✅ Yes | ❌ No | ❌ No | Observability only; some hooks needed for full feature coverage are missing. |
| Hermes Agent | ✅ Yes | ❌ No | ❌ No | Observability only; no known issues. |
| Cursor | ✅ Yes | ❌ No | ❌ No | Observability only; missing hooks under `cursor-agent` limit feature coverage. |
| Cursor | 🚧 Partial | ❌ No | ❌ No | Observability only; highly experimental |

## Guides

Expand Down
14 changes: 14 additions & 0 deletions docs/nemo-relay-cli/cursor.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,20 @@ repository ships a Cursor hook bundle under `integrations/coding-agents/cursor/`
because this integration does not assume an official Cursor plugin package
format.

<Error>
Cursor support is highly experimental and limited. NeMo Relay can install or
temporarily patch Cursor hooks, but it cannot automatically route Cursor model
traffic through the gateway. Complete LLM observability requires manual Cursor
provider/proxy configuration, including any required API keys, and that
configuration is outside NeMo Relay's control.

Cursor subagents may choose or inherit models independently from the top-level
session. If those subagent calls bypass the NeMo Relay gateway, their LLM
requests and responses will not appear in NeMo Relay events even when hook
events are present.

</Error>

Cursor GUI or IDE sessions can provide agent, subagent, tool, shell, MCP, file,
and response lifecycle events through `.cursor/hooks.json`. Complete LLM
lifecycle observability additionally requires Cursor model traffic to route
Expand Down
12 changes: 12 additions & 0 deletions integrations/coding-agents/cursor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ This package is a Cursor hook bundle, not an official Cursor plugin package. It
contains `.cursor/hooks.json` entries that forward canonical Cursor hook JSON to
`nemo-relay` at `/hooks/cursor`.

> [!CAUTION]
> Cursor support is highly experimental and limited. NeMo Relay can install or
> temporarily patch Cursor hooks, but it cannot automatically route Cursor model
> traffic through the gateway. Complete LLM observability requires manual Cursor
> provider/proxy configuration, including any required API keys, and that
> configuration is outside NeMo Relay's control.
>
> Cursor subagents may choose or inherit models independently from the top-level
> session. If those subagent calls bypass the NeMo Relay gateway, their LLM
> requests and responses will not appear in NeMo Relay events even when hook
> events are present.

Cursor GUI or IDE sessions can provide agent, subagent, tool, shell, MCP, file,
and response lifecycle events through `.cursor/hooks.json`. Complete LLM
lifecycle observability additionally requires Cursor model traffic to route
Expand Down
Loading