feat(middleware): resolve per-target CDP capability profiles for agent sessions - #448
Open
V3RON wants to merge 1 commit into
Open
feat(middleware): resolve per-target CDP capability profiles for agent sessions#448V3RON wants to merge 1 commit into
V3RON wants to merge 1 commit into
Conversation
…t sessions Rozenite's five built-in agent domains were designed against React Native's CDP surface, and Lynx exposes a different one: no `Network` domain at all, no React DevTools backend, and a Perfetto-based `Tracing` domain that shares Chrome's method names but not its protocol. Every session advertised all five regardless of target, so an agent could only discover the gap by calling — and two of the three ways it fails are silent, because a device answers an unknown method with an empty success just as readily as with `-32601`. Each session now resolves a capability profile from its target's platform. Unsupported tools are never registered; unavailable domains stay listed with an availability, a reason and a fallback, so the gap is legible rather than looking like a typo; and calling one fails during resolution with that explanation instead of a protocol error. Three fixes to the CDP command channel are platform-agnostic: a device error now names the method it refused, waits on device events are bounded, and `stopTrace` refuses to finalise an empty trace artifact instead of reporting a successful capture of nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pj8YXsJh4mMsJ1HpJEr7B5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Rozenite for Agents now knows which built-in domains the connected target can actually back, instead of advertising all five on every session.
Each session resolves a capability profile from its target's platform. Unsupported tools are never registered, so
list-toolsis honest.Unavailable domains stay visible in
rozenite agent domains, which gains anavailabilitycolumn (supported/degraded/unsupported) and afallback— both default fields, not--verboseones.Calling an unsupported tool now fails during resolution with the reason and a next step, before anything reaches the wire:
On a Lynx target that means
console, plugin domains, app tools andmemory.takeHeapSnapshotare supported;memoryis degraded (allocation sampling removed);network,reactandperformanceare unavailable with reasons.Three fixes to the CDP command channel apply to every platform:
UnsupportedCdpMethodErrorfor-32601) instead of arriving as a stringified error object.stopTracerefuses to finalise a zero-event trace artifact instead of reporting a successful capture of nothing.Agent docs gain a
platformsfrontmatter field, platform-availability sections onnetwork,react,performanceandmemory, and a newlynxorientation doc.Related Issue
Closes #447
Context
The five built-in domains were designed against React Native's CDP surface. Lynx's is different, verified against
LynxDevToolNG::RegisterAgents(the domains a Lynx device answers at all) andprimjs'ssrc/inspector/protocols.cc(the method table behind the domains Lynx forwards into the JS engine): noNetworkdomain is registered, no React DevTools backend exists,Tracingis Perfetto-based rather than Chrome-based, andHeapProfilerimplements snapshots but not sampling.The design follows from the fact that "unsupported" is three behaviours on the wire, and only one is loud: an unregistered domain answers
-32601; an unknown method inside an engine-backed domain answers with an empty success, so the call resolves and the awaited event never comes; and a same-named-different-protocol domain succeeds while producing the wrong thing. The latter two cannot be detected from a response, which is why this is resolved from a profile before the call rather than translated from an error after it.Some decisions worth a reviewer's attention:
Runtime.executionContextCreated); that is left as a future refinement rather than a foundation.networkoutright would makerozenite agent network listRequestsfail withUnknown domain "network". Did you mean…?, which reads to an agent as a typo to correct rather than a platform limit to route around.undefinedand treats every domain as supported — exactly the previous behaviour. No lockstep upgrade.withCapabilityFilterreturns the original service untouched when nothing is filtered.callToolis guarded as well asgetTools, since the call-tool route reaches tools by exact name.platformconfig is the default;@rozenite/lynx-devadditionally stampsrozenite: { platform: 'lynx' }on each/json/listpage, whichmetro-discoverycarries ontoMetroTargetand which wins per target. Metro never emits that key and every other consumer ignores unknown ones, so it is additive.Two gaps I'd rather name than leave implicit:
memoryandnetwork— the domains whose services construct cheaply in a test.reactandperformancehave no tool-level entries today so nothing is currently unguarded, but adding one there would not be caught.UITree/Template/ Lynx's ownPerformanceandMemoryis now a profile entry away, but it is new surface area rather than a fix and stayed out of scope.Testing
Automated, from the repository root after
git fetch origin main:pnpm checks:affected— typecheck, lint and format across 102 tasks, all passing.pnpm test:affected— 63/63 tasks passing.pnpm release:plan— confirms the version plan.New tests in
packages/middleware/src/__tests__/agent-capabilities.test.tscover the React Native profile declaring no gaps, a drift guard asserting the Lynx table names only tools the services actually expose, whole-domain versus tool-level gap reporting, filtering on bothgetToolsandcallTool, and the untouched-service fast path.Three existing tests changed deliberately: the two
agent-command-outputdomain-listing assertions carry the new default columns (their mocks now include adegradedand anunsupporteddomain so the columns are exercised), andskills-registrycounts the newlynxdoc.Not manually verified against a physical Lynx device — the Lynx behaviour encoded in the profile is sourced from the upstream C++ registration and dispatch tables cited above rather than from a live session.
Generated by Claude Code