Feat: serve detailed app metadata from /list-apps in the dev server - #727
Open
AmaadMartin wants to merge 2 commits into
Open
Feat: serve detailed app metadata from /list-apps in the dev server#727AmaadMartin wants to merge 2 commits into
AmaadMartin wants to merge 2 commits into
Conversation
added 2 commits
August 6, 2026 08:21
The adk-web bundle renders an agent picker from `/list-apps?detailed=true`. The Python dev server serves that form; the JS dev server did not, so the picker had no descriptions. `AgentLoader.listAgentsDetailed()` returns one `AppInfo` per discovered agent, sorted by name. An agent that fails to load is logged and skipped. The route keeps its current array response for every other query value.
A failing assertion left the spy installed, which silenced error logging for every later test in the file.
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.
Please ensure you have read the contribution guide before creating a pull request.
Link to Issue or Description of Change
Link to an existing issue (if applicable):
N/A
Or, if no issue exists, describe the change:
Problem: The
adk-webagent picker reads each agent's description and root-agent name fromGET /list-apps?detailed=true. The Python dev server serves that form; the JS dev server ignores the parameter and always returns a bare array of names. A developer on the JS dev server therefore sees a picker with no descriptions.Solution:
AgentLoader.listAgentsDetailed()returns oneAppInfoper discovered agent, sorted by name, and the route returns{"apps": AppInfo[]}whendetailedistrueor1. The field names are camelCase to match the JSON the Python server emits, because the same front-end bundle consumes both. Every other value ofdetailedkeeps the current array response.Three deliberate differences from the Python
AppInfomodel:agentsis omitted.list_agents_detailed()never populates it, so it is always null on this route.languageis the literal type'typescript'. adk-js has no YAML agent format, and the source extension is not recoverable after compilation.isComputerUseis alwaysfalse. adk-js has no computer-use toolset to detect. The field stays because the shared bundle reads it.?detailed=<anything else>returns the legacy array rather than a 400. The legacy shape is the safe fallback for existing clients.The parser accepts
trueand1, which is this repo's convention for a stringly-typed boolean (getBooleanatdev/src/cli/cli.ts:91). FastAPI also acceptsyesandon, so the two servers differ on those two values. I chose the local convention becauseadk-webonly ever sendsdetailed=true, so the difference is not observable to the shared client.Collision check: I listed all 619 open PRs on the fork and diffed every PR that touches
dev/src/utils/agent_loader.tsordev/src/server/adk_api_server.ts(#633, #365, #726, #703, #674). None addslistAgentsDetailedor adetailedparameter.git log --all -S listAgentsDetailedis also empty. The overlap is file-level only, in different regions, so this branches frommain.Testing Plan
Please describe the tests that you ran to verify your changes. This is required for all PRs that are not small documentation or typo fixes.
Unit Tests:
[x] I have added or updated unit tests for my change.
[x] All unit tests pass locally.
I added 5 loader cases and 5 server cases. I edited no existing test. The
listAgentsDetailedstub added to the shared server mock is a fixture extension; the two existingList Appsassertions are unchanged, because they are the regression signal for the unchanged default response.Coverage: 100% of the new statements and 100% of the new branches, measured with
@vitest/coverage-v8over lines 484-508 ofagent_loader.tsand lines 250-266 ofadk_api_server.ts. Zero uncovered statements and zero uncovered branch paths in both ranges.Proof that the tests can fail. I ran 7 mutations and confirmed the named tests fail.
language: 'typescript'->'javascript'lists agents with detailed metadatafails:expected [...] to deep equally contain { name: 'described_agent', …(4) }rootAgentName->root_agent_name(parity guard)unwraps the root agent of an App:expected undefined to be 'agent_for_app'?? ''ondescriptiondefaults description to an empty stringfails:expected undefined to be ''try/catchskips and logs agents that fail to loadfails:Error: boomfor (const name of names.reverse())sorts detailed entries by namefails:expected [ 'agent3', 'agent2', 'agent1' ] to deeply equal [ 'agent1', 'agent2', 'agent3' ]Boolean(detailedParam)instead of the two literal comparisonsreturns the plain array when detailed=falseand...for an unrecognised detailed valuefail:expected { apps: [...] } to deeply equal [ 'testApp' ]{apps}envelopereturns detailed app info when detailed=trueandaccepts detailed=1fail:expected [...] to deeply equal { apps: [...] }Manual End-to-End (E2E) Tests:
Please provide instructions on how to manually test your changes, including any necessary setup or configuration.
I ran this against the 7 bundled samples. The detailed form returns the envelope, and
agent_with_toolreports"rootAgentName": "weather_time_agent"with its real description, which proves the unwrap and thatnameneed not equalrootAgentName. Samples that declare no description report"".I also captured the default response from
mainand from this branch on the same samples directory.diffreports the two are byte-identical:Over real HTTP,
?detailed=1returns the envelope, and?detailed=false,?detailed=yes,?detailed=, a repeated?detailed=true&detailed=true, and a nested?detailed[x]=1all return 200 with the legacy array.Checklist
[x] I have read the CONTRIBUTING.md document.
[x] I have performed a self-review of my own code.
[x] I have commented my code, particularly in hard-to-understand areas.
[x] I have added tests that prove my fix is effective or that my feature works.
[x] New and existing unit tests pass locally with my changes.