Repository navigation
Conversation
Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
…lchain risk Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
…ent) Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
… payload uses a number, not a string) Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
…he single-threaded MCP runtime Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe pull request adds a ChangesFlare docs integration
Sequence Diagram(s)sequenceDiagram
participant MCPClient
participant AgentflareMcp
participant UreqFetcher
participant DocsStore
MCPClient->>AgentflareMcp: Submit flare_docs action
AgentflareMcp->>UreqFetcher: Fetch docs.rs rustdoc JSON in spawn_blocking
UreqFetcher-->>AgentflareMcp: Return compressed response
AgentflareMcp->>DocsStore: Parse and persist document
DocsStore-->>AgentflareMcp: Return document result
AgentflareMcp-->>MCPClient: Return JSON response
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (1)
src/mcp_server/flare_docs.rs (1)
78-97: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winUnbounded blocking fetch: a stalled docs.rs response can hang this tool call for up to 5 minutes.
UreqFetcheris configured with a 300s read timeout (percrates/flare-docs/src/fetch.rs), andfetch_and_store_via_spawn_blockingawaits thespawn_blockingtask with no additional deadline. A slow/stalled docs.rs response leaves the calling agent/session blocked on this MCP tool call for up to five minutes with no partial feedback.Consider wrapping the
spawn_blockingawait intokio::time::timeoutwith a shorter, tool-appropriate bound (e.g. 30-60s), returning a clear timeout error instead of silently hanging.⏱️ Sketch of a bounded fetch
- let fetched = tokio::task::spawn_blocking(move || { - let fetcher = UreqFetcher::new(); - fetcher.fetch(&url) - }) - .await - .map_err(|e| ErrorData::internal_error(format!("fetch task panicked: {e}"), None))? - .map_err(|e| ErrorData::internal_error(e.to_string(), None))?; + let fetched = tokio::time::timeout( + std::time::Duration::from_secs(60), + tokio::task::spawn_blocking(move || { + let fetcher = UreqFetcher::new(); + fetcher.fetch(&url) + }), + ) + .await + .map_err(|_| ErrorData::internal_error("docs.rs fetch timed out".to_string(), None))? + .map_err(|e| ErrorData::internal_error(format!("fetch task panicked: {e}"), None))? + .map_err(|e| ErrorData::internal_error(e.to_string(), None))?;🤖 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 `@src/mcp_server/flare_docs.rs` around lines 78 - 97, Update fetch_and_store_via_spawn_blocking to wrap the spawn_blocking task await in tokio::time::timeout using a shorter tool-appropriate deadline, such as 30–60 seconds. Preserve the existing panic and fetch-error mappings, and return a clear internal timeout error when the deadline expires.
🤖 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 @.superpowers/sdd/progress.md:
- Line 144: Update the documentation text in the progress note so the Rust
attribute #[tool] is wrapped in inline-code backticks, preventing the Markdown
heading rule from interpreting it as a heading.
In `@crates/flare-docs/src/fetch.rs`:
- Around line 22-23: Replace the unbounded response buffering and
decompress_zstd implementation with a shared bounded reader helper: reject
declared Content-Length values above the compressed-size limit, cap chunked
reads, and stream zstd output while enforcing the decompressed-size limit.
Preserve FetchError mapping and add tests covering both compressed and
decompressed limit violations.
In `@crates/flare-docs/src/rustdoc.rs`:
- Around line 42-48: Update the docs extraction flow in the function returning
`Ok(docs)` to distinguish valid `docs: null` from malformed responses: require
`index[root_key]` and its string `docs` field to be present, and return an error
when either is missing or non-string. Preserve `Some` for valid strings and
`None` only when the existing docs value is explicitly null, preventing
`store_fetched` from caching a placeholder for invalid responses.
In `@src/cli/docs.rs`:
- Around line 10-31: Update the documentation comment for the DocsCmd::Get
variant to describe its actual behavior through the shared fetch_and_store path,
distinguishing it from Refresh only if the implementation does so. Do not change
command behavior or the Refresh documentation.
In `@src/mcp_server/flare_docs.rs`:
- Line 1: Separate the package-based get and refresh flows in the flare_docs
handler and the corresponding CLI docs logic. Make get read the cached docs
entry from DocsStore at docsrs/{package}/{version} without fetching, while
refresh continues through the network fetch-and-store path; preserve the
existing behavior for other request modes.
- Around line 50-63: Update the `refresh` branch in the request handler so it
does not simply call `fetch_and_store_via_spawn_blocking` with the same behavior
as `get`; add or pass a force-refresh option through the relevant helper path to
bypass cached package data, while preserving the existing `get` behavior and
validation.
---
Nitpick comments:
In `@src/mcp_server/flare_docs.rs`:
- Around line 78-97: Update fetch_and_store_via_spawn_blocking to wrap the
spawn_blocking task await in tokio::time::timeout using a shorter
tool-appropriate deadline, such as 30–60 seconds. Preserve the existing panic
and fetch-error mappings, and return a clear internal timeout error when the
deadline expires.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: f6ebd991-c7af-473f-a43e-a8ca054d2e18
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (12)
.superpowers/sdd/progress.mdCargo.tomlcrates/flare-docs/Cargo.tomlcrates/flare-docs/src/fetch.rscrates/flare-docs/src/lib.rscrates/flare-docs/src/rustdoc.rscrates/flare-docs/src/store.rssrc/cli/docs.rssrc/cli/mod.rssrc/mcp_server.rssrc/mcp_server/flare_docs.rssrc/mcp_server/types.rs
…edless-return) Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
…a placeholder Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.superpowers/sdd/progress.md (1)
1-7: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winRemove or clearly separate the unrelated historical section.
The header says the previous stale plan content was reset, but lines 203-448 still contain the unrelated gateway-search plan history. This makes the progress document ambiguous and can mislead future readers or automation. Remove that section or place it under an explicitly labeled archive.
🤖 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 @.superpowers/sdd/progress.md around lines 1 - 7, Remove the unrelated gateway-search plan history from the progress document, specifically the stale section spanning the historical content after the current plan header. If retaining it, move it under a clearly labeled archive section so the active 2026-07-23-flare-docs-implementation-plan content remains unambiguous.
🤖 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.
Outside diff comments:
In @.superpowers/sdd/progress.md:
- Around line 1-7: Remove the unrelated gateway-search plan history from the
progress document, specifically the stale section spanning the historical
content after the current plan header. If retaining it, move it under a clearly
labeled archive section so the active 2026-07-23-flare-docs-implementation-plan
content remains unambiguous.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 4175b3eb-31f3-44e2-80b0-b05ffaffa592
📒 Files selected for processing (8)
.superpowers/sdd/progress.mdcrates/flare-docs/src/fetch.rscrates/flare-docs/src/lib.rscrates/flare-docs/src/rustdoc.rscrates/flare-docs/src/store.rssrc/mcp_server.rssrc/mcp_server/flare_docs.rssrc/mcp_server/types.rs
🚧 Files skipped from review as they are similar to previous changes (7)
- crates/flare-docs/src/lib.rs
- src/mcp_server/types.rs
- src/mcp_server/flare_docs.rs
- crates/flare-docs/src/store.rs
- src/mcp_server.rs
- crates/flare-docs/src/rustdoc.rs
- crates/flare-docs/src/fetch.rs
…, cap fetch timeout - fetch.rs: cap compressed (32MB) and decompressed (512MB) response bytes so a malicious/misbehaving docs.rs response can't exhaust process memory - get/refresh: get now reads DocsStore first and only fetches on a cache miss; refresh always re-fetches (was previously an alias for get, always live-fetching and never actually reading the cache) - flare_docs MCP tool: bound the spawn_blocking docs.rs fetch with a 60s timeout so a stalled response can't freeze the whole MCP tool call for up to 5 minutes - progress.md: drop stale unrelated gateway-search plan history Agentflare-Agent: claude-code_2-1-218_agent Agentflare-Branch: task/325 Agentflare-Item: 325
…on-blocking-fetch test (#344) * fix(flare-docs): caller-vs-service error mapping, search limit cap, non-blocking-fetch test Addresses the actionable subset of the PR #316 whole-branch review follow-ups (item #327): - 404/bad package name now returns invalid_params instead of internal_error. FetchError gains a structured Status(u16) variant (ureq::Error::Status was previously flattened into a string), and a ClientError trait lets blocking_fetch discriminate 4xx (caller's fault) from 5xx/transport/timeout (ours). npm's NoTypes counts as caller-caused too. - search limit is capped at 50, enforced inside DocsStore::search so the MCP tool and the CLI both inherit it rather than each guarding separately. - the non-2xx re-check in UreqFetcher::fetch is documented as deliberate rather than dead: ureq only auto-errors on >= 400, so 1xx/3xx still arrive as Ok. It now returns the same structured Status variant. - committed regression test for the spawn_blocking fix (83f76ad), which was previously only proven by an ad-hoc uncommitted script. Verified it fails ("only 0 ticks elapsed") when the fetch is made inline. Two of the six findings needed no change: the zstd output cap already landed (MAX_DECOMPRESSED_BYTES + read_capped), and CLI `get` now has its own cache-checking arm, so its "or read from cache" help text is accurate. * fix(flare-docs): don't map retryable 4xx to invalid_params; honour list limit Self-review follow-ups on this branch: - 408 and 429 are 4xx but retryable — the request was well-formed and the caller needs to back off, not fix its arguments. Mapping them to invalid_params told an agent to correct a request that was never wrong. They now stay internal_error. - the `limit` schema documents a ceiling for both search and list, but the list action ignored the field entirely, so the documented cap was a promise the tool did not keep. list still returns every cached document by default; an explicit limit is now honoured and capped. Description reworded to state both behaviours exactly. * fix(flare-docs): only attach the other-ecosystem hint to a genuine miss CodeRabbit finding on PR #344, and broader than reported: the hint reads "\"X\" was not found on docs.rs/npm", but blocking_fetch appended it to every failure. A 503, a corrupt tarball, a store error, or a package that exists and simply ships no types all produced a message asserting the package does not exist. In the NoTypes case it directly contradicted the sentence it was appended to. ClientError gains is_package_missing(), kept separate from is_client_error() because they answer different questions -- a package with no types is the caller's problem yet is not missing. Only a 404 now earns the hint. * docs(flare-docs): note retryable 4xx in the blocking_fetch classification contract
Summary
Adds
flare-docs, a new crate that fetches third-party package documentation on demand (Rust crates via docs.rs's official JSON API for Phase 1), exposed via a newflare_docsMCP tool (action=search|get|list|refresh) and anagentflare docs <search|get|list|refresh>CLI subcommand. Reusesagentflare-store's existing document/blob storage (SQLite + FTS5) in its own dedicated global DB file (~/.agentflare/flare-docs.db,project_id="global"), separate from the shared~/.agentflare/store.db.ureq(this repo's house-standard client, already used in 6+ other crates), notokio/async-traitinsideflare-docsitselfflare_docsMCP tool offloads the network fetch viatokio::task::spawn_blockingso a slow/hung docs.rs response can't freeze the (single-threaded) MCP serverPROJECT_ID="global"sentinel enforced everywhere through a singleDocsStorefacade — no path bypasses it or touches the shared storeDesign note: the fetch client went through two pivots before landing on
ureq—wreq(browser-fingerprint-aware) was dropped after it dragged in BoringSSL/NASM/CMake native-build fragility on Windows;reqwestworked but wasn't house-standard. Also fixed along the way: the docs.rs rustdoc-JSON resolver initially assumed"root"is always a JSON string — the real payload uses a JSON number — caught via a live network smoke test and fixed with end-to-end verification against realserdedocs.Test plan
cargo test --workspace— 744 passed, 0 failed, 1 ignoredcargo test -p flare-docs— full crate suite greenagentflare docs get serde --version latestreturns real serde documentationflare_docs getno longer blocks concurrentflare_docs listcallsKnown follow-ups (logged, not blocking): 404s map to
internal_errorinstead ofinvalid_params;limitis unbounded; zstd decompression has no output-size cap; CLIget's help text implies cache-awareness it doesn't have yet (TTL/cache-check deferred); a dead status-recheck in the fetch client; no committed regression test for the spawn_blocking concurrency property (only an ad-hoc manual script).Summary by CodeRabbit
agentflare docsCLI commands for search, list, get, and refresh with pretty-printed JSON.flare_docs) backed by a local, cacheable store (including in-memory mode).