Repository navigation
feat(agent): native Fusion dual-lane routing - #180
Conversation
Implement Devin Fusion-style lead/sidekick orchestration with compaction-boundary model switching, fusion_delegate briefs, config/CLI toggles, lane cost stats, tool-error escalation, and cached Devin model discovery.
📝 WalkthroughWalkthroughFusion dual-lane routing is added with CLI/config activation, sidekick delegation, compaction-boundary model switching, per-lane usage reporting, session persistence, cached Devin model discovery, and updated documentation. ChangesFusion mode
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant CLI
participant AgentRuntime
participant FusionState
participant SidekickPlugin
participant SessionStore
CLI->>AgentRuntime: enable Fusion
AgentRuntime->>FusionState: initialize lead lane
AgentRuntime->>SidekickPlugin: invoke fusion_delegate
SidekickPlugin-->>AgentRuntime: sidekick result and usage
AgentRuntime->>FusionState: record lane usage
AgentRuntime->>FusionState: route after compaction
FusionState-->>AgentRuntime: switch or escalate route
AgentRuntime->>SessionStore: persist Fusion usage on done
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6b497c10e6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
There was a problem hiding this comment.
Criterion
Details
| Benchmark suite | Current: d344969 | Previous: c5ffb54 | Ratio |
|---|---|---|---|
fib/jit_mlua_hook |
6676950 ns/iter (± 240059) |
13537489 ns/iter (± 113823) |
0.49 |
fib/jit_watchdog |
2232773 ns/iter (± 8417) |
2391653 ns/iter (± 85615) |
0.93 |
fib/jit_none |
2220790 ns/iter (± 80006) |
2480470 ns/iter (± 59112) |
0.90 |
fib/interp_mlua_hook |
8160912 ns/iter (± 248296) |
10726266 ns/iter (± 34794) |
0.76 |
fib/interp_watchdog |
4374187 ns/iter (± 27532) |
4397759 ns/iter (± 153339) |
0.99 |
fib/interp_none |
4317048 ns/iter (± 50101) |
4339951 ns/iter (± 132998) |
0.99 |
buffer_rw/jit_mlua_hook |
583680 ns/iter (± 1172) |
1229792 ns/iter (± 4955) |
0.47 |
buffer_rw/jit_watchdog |
191960 ns/iter (± 308) |
191361 ns/iter (± 2861) |
1.00 |
buffer_rw/jit_none |
191942 ns/iter (± 213) |
191631 ns/iter (± 3267) |
1.00 |
buffer_rw/interp_mlua_hook |
1046479 ns/iter (± 11776) |
1591909 ns/iter (± 10648) |
0.66 |
buffer_rw/interp_watchdog |
581826 ns/iter (± 2348) |
582572 ns/iter (± 9478) |
1.00 |
buffer_rw/interp_none |
582037 ns/iter (± 14279) |
581875 ns/iter (± 9246) |
1.00 |
splash_render_120x40 |
79217 ns/iter (± 2084) |
80560 ns/iter (± 269) |
0.98 |
splash_render_200x60 |
172792 ns/iter (± 17685) |
119966 ns/iter (± 8677) |
1.44 |
This comment was automatically generated by workflow using github-action-benchmark.
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_b58ac6ff-1d45-4261-9855-1881864cc77a) |
|
cursor review |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_742c0c0a-1017-4dff-972f-8b275973cfea) |
- Merge origin/main into feat/n00n-fusion - Remove unneeded wildcard pattern and use clone_from - Collapse nested if statements with let-chains - Mark usage_stats #[must_use] and move constants before statements - Allow large LogRecord variant (serialization-only enum)
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_79eb07e2-2b34-4745-8fb3-bcce6c87d005) |
|
cursor review |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_a6674792-3ef8-467c-a6d0-59aa152f6fec) |
|
cursor review |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_cfbcf31b-8581-43c0-aad3-b9173ac9ed66) |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_463f6877-b212-4bc5-8fd1-4e3a00192fdd) |
…baseline - n00n-docgen SECTIONS was missing the new fusion_delegate tool. - Regenerate n00n-token-profile cold_start baseline for 28 tools.
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_1cf4f7f4-e2d7-465a-bbe6-5de50f682058) |
There was a problem hiding this comment.
Actionable comments posted: 12
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
n00n-agent/src/agent/run.rs (1)
909-933: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winCompaction cost is attributed to the wrong lane.
apply_fusion_route(which can flipfusion_state.lane) runs beforeself.record_usage(usage, cost). Sincerecord_usageattributes usage/cost to whateverstate.lanecurrently is, the compaction call's own usage/cost ends up credited to the lane the agent just switched to, not the lane that was actually active while compaction executed. This corrupts the per-lane cost/usage stats that are a core deliverable of this PR.🐛 Proposed fix — record usage before switching lanes
- if self.config.fusion.enabled { - let route = self.fusion_state.as_mut().map(|state| { - let recent_errors = state.recent_tool_errors(); - let route = crate::fusion::route_after_compact(state, &summary, recent_errors); - state.clear_recent_tool_errors(); - route - }); - if let Some(route) = route { - self.apply_fusion_route(route); - } - } - let cost = usage.cost(&compact_model.pricing, false); - self.record_usage(usage, cost); + let cost = usage.cost(&compact_model.pricing, false); + self.record_usage(usage, cost); + if self.config.fusion.enabled { + let route = self.fusion_state.as_mut().map(|state| { + let recent_errors = state.recent_tool_errors(); + let route = crate::fusion::route_after_compact(state, &summary, recent_errors); + state.clear_recent_tool_errors(); + route + }); + if let Some(route) = route { + self.apply_fusion_route(route); + } + }🤖 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 `@n00n-agent/src/agent/run.rs` around lines 909 - 933, Record the compaction usage and cost via record_usage before the fusion routing block can call apply_fusion_route. Keep route_after_compact and lane switching behavior unchanged, ensuring the compaction attribution uses the lane active during compact_history rather than the newly selected lane.
🤖 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 `@n00n-agent/src/agent/run.rs`:
- Around line 865-868: Update the model registry access in the tier lookup
around model_registry() and spec_for_tier_any to handle RwLock read failures
explicitly instead of calling .ok(). Use a named fallback for the poisoned-lock
case and emit sanitized structured logging containing the lock error, while
preserving the existing lookup behavior for successfully acquired read guards.
- Around line 839-897: Update apply_fusion_route for both the lead and sidekick
branches so a provider-construction failure from from_model_with_openai_options
rejects the route change instead of updating self.model while retaining the old
self.provider. Surface the failure with structured logging, and only assign the
new model and update fusion state after both model and provider construction
succeed.
In `@n00n-agent/src/fusion/mod.rs`:
- Around line 213-233: Replace the inline thresholds in route_after_compact with
named constants: define a constant for the sidekick-failure escalation limit of
2 and another for the delegation cap of 8, then use those constants in the
existing comparisons while preserving the current routing behavior.
In `@n00n-docgen/src/gen_config.rs`:
- Around line 225-230: Replace the new writeln!().unwrap() calls in the
documentation-generation block with non-panicking output handling, preferably by
appending the static agent.fusion section via push_str; otherwise propagate
write errors explicitly. Ensure this block complies with the production deny
rules for unwrap_used without changing the generated documentation.
In `@n00n-providers/src/providers/devin.rs`:
- Around line 1157-1184: Define constants for each cognition.ai metadata key
immediately after the imports, then update the metadata lookups in the provider
parsing logic to use those constants instead of inline strings, including
supportsImages, contextWindow, maxOutputTokens, pricing, free, and promo.
- Around line 1153-1156: Update the model discovery loop around
ModelInfo::id_only to accept only non-empty string option.value values that pass
the existing model-ID validation rules; skip invalid or malformed entries before
creating ModelInfo. Log skipped provider configuration entries using sanitized
details, without treating them as executable input or disrupting discovery of
valid options.
In `@n00n-ui/src/app/mod.rs`:
- Around line 1611-1638: Update the fusion metadata persistence around the
AgentEvent::Done handler to write stats only when chat_idx == 0, mapping
fusion.as_ref() into StoredFusionUsage while preserving the existing field
conversions. Explicitly clear self.state.session.meta.fusion when a main-run
completion has fusion: None, and add tests covering subagent completion not
persisting stats and non-fusion completion clearing stale stats.
- Around line 1633-1635: Centralize the persisted lane labels used by the
final_lane mapping: add or reuse a canonical `FusionLane::as_str()` method or
shared constants, then update the `match stats.final_lane` in the surrounding
code to reference it instead of inline `"lead"` and `"sidekick"` strings.
Preserve the existing storage labels exactly.
In `@site/docs/content/tools/_index.md`:
- Around line 342-349: Complete the fusion_delegate parameter table in the
Additional tools section by adding rows for the required delegation inputs,
including the goal, constraints, and definition of done described in the lead
text. Document each parameter’s type, required status, and expected content so
readers know what to pass.
In `@src/cli.rs`:
- Around line 196-198: Make the fusion flag available to the agent run path by
either marking the existing Cli::fusion argument global or adding a
corresponding field to AgentCommand::Run; then update run dispatch to propagate
the parsed value into AgentRunOptions. Ensure `n00n agent run --fusion` is
accepted and enables fusion routing.
In `@src/print.rs`:
- Around line 471-480: Update the fusion statistics output in the eprintln!
block and the corresponding output path around the alternate reporting block to
include complete per-lane statistics: lead and sidekick token usage plus
final_lane, while preserving the existing cost and count fields and formatting
consistently with the Fusion reporting contract.
In `@src/sdk_mode.rs`:
- Around line 1073-1075: Update the AgentEvent::Done handling to preserve and
pass the fusion data into handle_done instead of discarding it, then calculate
total_cost_usd using separate lead_cost and sidekick_cost values so usage after
a sidekick switch is priced correctly. Add a test covering mixed lead/sidekick
lane pricing.
---
Outside diff comments:
In `@n00n-agent/src/agent/run.rs`:
- Around line 909-933: Record the compaction usage and cost via record_usage
before the fusion routing block can call apply_fusion_route. Keep
route_after_compact and lane switching behavior unchanged, ensuring the
compaction attribution uses the lane active during compact_history rather than
the newly selected lane.
🪄 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: ASSERTIVE
Plan: Pro Plus
Run ID: 6fadc704-2e67-4226-95cc-fb7847e80188
📒 Files selected for processing (27)
changelog.d/180.added.mdn00n-agent/src/agent/compaction.rsn00n-agent/src/agent/run.rsn00n-agent/src/fusion/mod.rsn00n-agent/src/lib.rsn00n-agent/src/types.rsn00n-config/src/lib.rsn00n-docgen/src/gen_config.rsn00n-docgen/src/gen_tools.rsn00n-lua/src/api/agent.rsn00n-lua/src/loader.rsn00n-providers/src/providers/devin.rsn00n-storage/src/sessions.rsn00n-token-profile/baselines/cold_start.jsonn00n-ui/src/agent/agent_loop.rsn00n-ui/src/app/mod.rsn00n-ui/src/app/tests.rsplugins/fusion/init.luasite/docs/content/configuration/_index.mdsite/docs/content/tools/_index.mdspecs/008-fusion-mode/plan.mdsrc/cli.rssrc/cmd/agent.rssrc/cmd/mod.rssrc/cmd/tui.rssrc/print.rssrc/sdk_mode.rs
📜 Review details
⏰ Context from checks skipped due to timeout. (14)
- GitHub Check: MSRV (1.97)
- GitHub Check: Docs
- GitHub Check: Coverage
- GitHub Check: Test
- GitHub Check: Rustdoc
- GitHub Check: Test (Windows)
- GitHub Check: Build (Windows)
- GitHub Check: Test (macOS)
- GitHub Check: Lint (macOS)
- GitHub Check: Build
- GitHub Check: Lint
- GitHub Check: Lint (Windows)
- GitHub Check: Criterion
- GitHub Check: Analyze (rust)
🧰 Additional context used
📓 Path-based instructions (6)
**/*
📄 CodeRabbit inference engine (AGENTS.md)
**/*: Non-trivial or multi-file changes should use a dedicated git worktree and new branch; do not modify unrelated user changes, force-push, or push to main.
Ship finished work with a clear Conventional Commit message, a pushed branch, and a draft pull request; never add AI-agent attribution to authored content.
Before investigating unfamiliar failures or third-party behavior, research documented behavior first and distinguish unrelated baseline failures from regressions in the touched surface.
Use structural tools before broad searches: prefercodegraphorarborfor cross-file relationships,indexbefore reading files, targeted reads, parallel calls, andcode_executionfor filtering large outputs.
Files:
changelog.d/180.added.mdn00n-ui/src/agent/agent_loop.rsspecs/008-fusion-mode/plan.mdn00n-docgen/src/gen_config.rsn00n-lua/src/loader.rsn00n-lua/src/api/agent.rssite/docs/content/configuration/_index.mdsrc/cmd/mod.rssrc/cmd/tui.rsplugins/fusion/init.luan00n-docgen/src/gen_tools.rssrc/cli.rsn00n-agent/src/lib.rsn00n-agent/src/types.rsn00n-token-profile/baselines/cold_start.jsonn00n-ui/src/app/mod.rssrc/sdk_mode.rssite/docs/content/tools/_index.mdn00n-storage/src/sessions.rssrc/cmd/agent.rsn00n-providers/src/providers/devin.rsn00n-agent/src/fusion/mod.rsn00n-agent/src/agent/compaction.rsn00n-ui/src/app/tests.rssrc/print.rsn00n-agent/src/agent/run.rsn00n-config/src/lib.rs
**/*.rs
📄 CodeRabbit inference engine (AGENTS.md)
**/*.rs: Workspace Rust lint rules are mandatory: deny unsafe code, productionunwrap_used,expect_used,panic,todo!,unimplemented!,dbg!, wildcard imports, and silent-default error handling.
Do not add unsafe code, FFI, global mutable state,static mut, or unchecked transmute-like behavior without written review and an explicit crate-level lint exception.
Use explicit error handling withResult<T, E>rather than panics; propagate typed errors with?,ok_or_else, andmap_err.
Usethiserrorfor library and domain-specific errors, andcolor-eyreat binary edges.
Do not silently discard errors with.ok(),unwrap_or,unwrap_or_default, or equivalent defaults; return an error, reject the operation, or use an explicitly named fallback with sanitized structured logging.
Follow Rust idioms, use descriptive variable and function names, avoid unnecessary state and bloat, and keep each line justified.
Import types at the top of the file, use short imported names instead of inline qualified paths, and place constants immediately after imports.
Do not use inline magic numbers or strings; deriveCopyonly for structs with one primitive field.
Use structured logging with useful fields and provide helpful, sanitized error messages.
Do not commit credentials, API keys, tokens, cookies, authorization headers, or user data, and do not log raw provider payloads, prompts, credentials, or session data.
Validate and authorize HTTP, file, queue, configuration/environment, LLM output, and provider callbacks before mutation or persistence.
Tool execution requires allowlisted tools, scoped credentials, explicit user context, audit events, and refusal or denial tests.
Write meaningful, non-tautological, non-flaky tests; avoid arbitrary sleeps, and define shared constant error/status messages for assertions.
Files:
n00n-ui/src/agent/agent_loop.rsn00n-docgen/src/gen_config.rsn00n-lua/src/loader.rsn00n-lua/src/api/agent.rssrc/cmd/mod.rssrc/cmd/tui.rsn00n-docgen/src/gen_tools.rssrc/cli.rsn00n-agent/src/lib.rsn00n-agent/src/types.rsn00n-ui/src/app/mod.rssrc/sdk_mode.rsn00n-storage/src/sessions.rssrc/cmd/agent.rsn00n-providers/src/providers/devin.rsn00n-agent/src/fusion/mod.rsn00n-agent/src/agent/compaction.rsn00n-ui/src/app/tests.rssrc/print.rsn00n-agent/src/agent/run.rsn00n-config/src/lib.rs
**/*.{rs,toml}
📄 CodeRabbit inference engine (AGENTS.md)
All crates must opt into the workspace lint configuration with
[lints] workspace = true; the root workspace lint configuration is authoritative.
Files:
n00n-ui/src/agent/agent_loop.rsn00n-docgen/src/gen_config.rsn00n-lua/src/loader.rsn00n-lua/src/api/agent.rssrc/cmd/mod.rssrc/cmd/tui.rsn00n-docgen/src/gen_tools.rssrc/cli.rsn00n-agent/src/lib.rsn00n-agent/src/types.rsn00n-ui/src/app/mod.rssrc/sdk_mode.rsn00n-storage/src/sessions.rssrc/cmd/agent.rsn00n-providers/src/providers/devin.rsn00n-agent/src/fusion/mod.rsn00n-agent/src/agent/compaction.rsn00n-ui/src/app/tests.rssrc/print.rsn00n-agent/src/agent/run.rsn00n-config/src/lib.rs
**/*.{rs,ron,json,toml,yaml,yml}
📄 CodeRabbit inference engine (AGENTS.md)
Treat LLM and provider output as untrusted input; validate it against schemas, domain constraints, and source evidence before persistence or action.
Files:
n00n-ui/src/agent/agent_loop.rsn00n-docgen/src/gen_config.rsn00n-lua/src/loader.rsn00n-lua/src/api/agent.rssrc/cmd/mod.rssrc/cmd/tui.rsn00n-docgen/src/gen_tools.rssrc/cli.rsn00n-agent/src/lib.rsn00n-agent/src/types.rsn00n-token-profile/baselines/cold_start.jsonn00n-ui/src/app/mod.rssrc/sdk_mode.rsn00n-storage/src/sessions.rssrc/cmd/agent.rsn00n-providers/src/providers/devin.rsn00n-agent/src/fusion/mod.rsn00n-agent/src/agent/compaction.rsn00n-ui/src/app/tests.rssrc/print.rsn00n-agent/src/agent/run.rsn00n-config/src/lib.rs
site/docs/**/*
📄 CodeRabbit inference engine (AGENTS.md)
User documentation should be warm, simple, concise, easy for non-native English speakers, story-oriented, and contain no em-dashes, emojis, or AI-like tone.
Files:
site/docs/content/configuration/_index.mdsite/docs/content/tools/_index.md
plugins/**/*.lua
📄 CodeRabbit inference engine (AGENTS.md)
Built-in Lua plugins belong under
./pluginsand should use the repository's plugin tooling and conventions.
Files:
plugins/fusion/init.lua
🪛 markdownlint-cli2 (0.23.0)
changelog.d/180.added.md
[warning] 1-1: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
site/docs/content/tools/_index.md
[warning] 349-349: Files should end with a single newline character
(MD047, single-trailing-newline)
🔇 Additional comments (24)
n00n-token-profile/baselines/cold_start.json (1)
7-20: LGTM!n00n-agent/src/types.rs (1)
882-883: LGTM!n00n-lua/src/api/agent.rs (1)
1384-1388: LGTM!n00n-ui/src/agent/agent_loop.rs (1)
430-434: LGTM!n00n-ui/src/app/tests.rs (1)
532-532: LGTM!Also applies to: 1892-1897, 1910-1915, 2024-2029, 2222-2229, 3449-3449, 3494-3500
n00n-storage/src/sessions.rs (1)
195-220: LGTM!Also applies to: 653-653
n00n-config/src/lib.rs (1)
67-67: LGTM!Also applies to: 142-148, 236-236, 254-254, 289-289, 490-498, 530-541, 868-868, 1110-1128, 1168-1200, 2409-2409
n00n-agent/src/lib.rs (1)
7-7: LGTM!Also applies to: 21-22
n00n-agent/src/fusion/mod.rs (2)
46-138: 🎯 Functional CorrectnessConfirm permanent escalation is intentional.
sidekick_failuresis only ever incremented (record_sidekick_failure), never reset. Once it reaches the threshold,route_after_compactwill returnEscalateToLeadfor every subsequent compaction, permanently disabling sidekick delegation for the rest of the session. Please confirm this "no recovery" behavior is intended (vs. e.g. decaying the failure count over time or per new user turn).
1-12: LGTM!Also applies to: 140-302
site/docs/content/tools/_index.md (1)
10-10: LGTM!Also applies to: 321-341
specs/008-fusion-mode/plan.md (1)
1-47: LGTM!changelog.d/180.added.md (1)
1-1: LGTM!n00n-agent/src/agent/run.rs (1)
8-9: LGTM!Also applies to: 27-30, 55-63, 167-280, 543-550, 668-676, 688-705
n00n-agent/src/agent/compaction.rs (1)
72-82: LGTM!Also applies to: 131-140, 175-205
src/cmd/agent.rs (2)
318-318: 🎯 Functional CorrectnessVerify all
AgentRunOptionsliterals andprepare_agent_envcallers.These required API changes are updated in the shown paths, but any test, integration, or omitted internal caller using the old shape will fail to compile. Search all
AgentRunOptions { ... }literals andprepare_agent_env(...)calls before merging.Also applies to: 334-339
364-366: LGTM!Also applies to: 420-420, 628-628
src/cmd/mod.rs (1)
97-97: LGTM!src/cmd/tui.rs (1)
111-113: LGTM!site/docs/content/configuration/_index.md (1)
61-61: LGTM!Also applies to: 113-119, 188-194
plugins/fusion/init.lua (2)
90-103: 🔒 Security & PrivacyEnforce model and cost policy before honoring tool overrides.
input.model,input.model_tier, andinput.auto_tierare tool-controlled inputs passed directly tosubagent.launch. Unless that API enforces an allowlist, provider scope, user authorization, and budget limits, the lead can bypass the configured cost-aware sidekick route.As per coding guidelines, validate and authorize untrusted LLM output and tool execution before taking action.
Source: Coding guidelines
123-128: 🎯 Functional CorrectnessVerify that
fusion_delegateis gated when Fusion is disabled.The bundled plugin registers this tool unconditionally, and no
agent.fusion.enabledcheck appears in the handler. If the host does not filter it separately, ordinary sessions can still launch sidekicks and incur Fusion costs even though Fusion is disabled.n00n-lua/src/loader.rs (1)
102-105: LGTM!n00n-docgen/src/gen_tools.rs (1)
52-52: LGTM!
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
…l docs The non-Unix agent_stub.rs AgentRunOptions was missing the new fusion field, causing Windows builds to fail. Add the field so the struct matches the Unix AgentRunOptions and the call sites in src/cmd/mod.rs. Also regenerate site/docs/content/tools/_index.md after adding fusion_delegate to the docgen sections.
…erver Keep FusionUsageStats/AgentMode imports and pass fusion into prepare_agent_env while preserving main's fork/setsid detach for background agent servers.
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_fc665082-7595-4712-a82e-89b080461454) |
Use push('\n') in docgen and register fusion_delegate with schema= so
the tool exposes its params to the model and gen-docs-check passes.
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_4327d7bc-c09f-4166-b681-b54d9a180399) |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_288436ac-8468-48c4-b01d-569154875eba) |
When Model::from_spec succeeds but from_model_with_openai_options fails, self.model was updated while self.provider kept the old value, leaving an inconsistent pair. Now provider and model are only updated after both operations succeed.
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_d010feef-c43b-4ada-8668-81b5ebef0919) |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_43aca762-9995-405f-acf3-0228a5f13d24) |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_df64f6d0-056a-48bc-965f-d20b52ce392d) |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_5f8e5e86-4372-4e09-9c8b-938ea814fb5c) |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_16ffe0c9-4902-4ce0-9361-b4d2969de799) |
Refresh cold_start baseline and start the cursor pace timer before the first frame read to avoid flaky FIRST_FRAME_PACE assertions.
Summary
fusion_delegate, with model switches at compaction boundaries.--fusion/always_fusion/[agent.fusion]config; Rust routing core (classify_delegation,route_after_compact); per-lane usage stats onAgentEvent::Done.fusion.config_optionsfor model discovery; docs regenerated for the new tool and config fields.Linear
Test plan
cargo test -p n00n-agent --lib fusion::testscargo clippy --all --tests -- -D warningsn00n --fusion -m <frontier-model> "delegate grep work via fusion_delegate"list_modelsuses cache after first sessionNote
Medium Risk
Changes core agent run loop, compaction boundaries, provider/model switching, and cost accounting across TUI, print, and SDK surfaces; failures degrade with warnings but mis-routing could affect model choice and spend.
Overview
Introduces Fusion dual-lane routing: a frontier lead model handles planning and judgment while a cheaper sidekick tier runs mechanical work, toggled via
--fusion,always_fusion, and[agent.fusion](includingsidekick_tier).The agent loop gains a
n00n-agent/src/fusion/routing core—lexicalclassify_delegation,route_after_compact(with tool-error escalation), per-lane usage/cost tracking, and model/provider switches only after auto-compaction using the compaction summary. Lane changes refresh dynamic system prompts and rebuild tools via newSystem::replace_last_dynamic.fusion_delegateis a bundled Lua plugin that launches an isolated subagent brief; successful delegations attribute sidekick telemetry to the sidekick lane while the main session stays on lead.AgentEvent::Donenow optionally carriesfusionstats; the TUI persists them on session meta, and print/SDK paths use lead+sidekick cost totals instead of repricing all tokens on the lead model.compact_historyreturns the summary string for routing.Also: Devin
list_modelsprefers cached ACPconfig_options, docs/changelog for the new tool and config, and token-profile baseline bumps for the extra builtin tool.Reviewed by Cursor Bugbot for commit 19441da. Bugbot is set up for automated code reviews on this repo. Configure here.