feat(tui): open a Linked Resources screen on bare project status - #2215
feat(tui): open a Linked Resources screen on bare project status#2215AlexanderRichey wants to merge 2 commits into
Conversation
A bare `agentcore project status` in a terminal now opens an interactive
Linked Resources view: each agent the project declares (spec.runtimes and
spec.harnesses) is a top-level group holding its deployed Runtime/Harness
and linked Memories, with everything unattributable kept visible under a
shared "project" group. Enter on a deployed Runtime, Harness, Memory,
Gateway, or Gateway Target forwards to its existing detail page;
local-only rows are dimmed and non-selectable. Any user-supplied flag,
--json, or a non-TTY invocation keeps the headless JSON report unchanged.
Detail screens fetch in the region pinned on their context, which is the
ambient one — not necessarily the project target's. Root now scopes the
context per navigation from { state: { region } }, so the status screen
lands detail pages in the target's region while history-back restores the
launch context (escape keeps working at every level).
The vendored TreeView gains a focusMarker prop (the ❯ selection style the
rest of the TUI uses) and per-node annotations; `status` joins the project
router's supported TUI commands so the menu lists it as interactive.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMPY8yuo2z5Vhrmyte1Lk2
|
Claude Security Review: no high-confidence findings. (run) |
There was a problem hiding this comment.
AgentCore Harness Review
Verdict: Changes requested
Nice piece of work overall — the grouping logic is clearly documented, TreeView gets a small, principled extension, and the dispatch/test coverage for TTY vs. non-TTY is thorough. One substantive issue about the region-forwarding mechanism, plus a couple of smaller things.
Region drops on forward navigation from a detail screen
src/components/Root.tsx (AppRoutes, ~lines 146–153) resolves the effective region from location.state.region for every route, and src/handlers/project/status/screen.tsx:1786 seeds that state when opening a detail page. Because state is per-history-entry, that works for the initial status → detail hop and for esc back — but any further forward navigation from the detail screen re-enters AppRoutes with a location.state that doesn't carry region, so the destination silently falls back to the launch (ambient) region:
src/handlers/runtime/get/screen.tsx:66— the "endpoints", "versions", and "detail (json)" actions callnavigate(action.to(runtimeId), { state: … })withoutregion. Only theinvokeaction sets state at all, and even then it's{ returnOnEscape: true }, not{ region }.src/handlers/memory/get/screen.tsx:71andsrc/handlers/harness/get/screen.tsx:78— actiononSelecthandlers callnavigate(action.to(id))with no state at all.src/handlers/gateway/target/get/…— same shape.
So the concrete case is: on a project deployed to us-west-2 with ambient region us-east-1, status → runtime detail fetches in us-west-2 (correct, and covered by a test), but then picking "endpoints" / "versions" / "invoke" / "json" from that page fetches in us-east-1 and the user sees "not found" or gets pointed at the wrong resource. Same for memory→segments/…, harness→endpoints/versions/etc., gateway→targets.
A few options for the author:
- Have every detail screen that owns an action list forward the current
regionfrom itslocation.stateonto itsnavigate({ state })calls. Simple and localized, but easy to forget for future screens. - Persist the region higher up (e.g. a small "session region" ref/context set by the status screen when it forwards, cleared when the user leaves via the project menu), so downstream screens don't have to plumb state.
- Encode the region in the URL for the detail routes that need it and read it from
useParams(route-first approach — no reliance on history state at all).
Whichever direction is chosen, please add a screen test that drills at least one level past the detail page (e.g. status → runtime detail → endpoints list) and asserts the region on the resulting core-client call.
Minor
src/handlers/project/status/screen.tsx:1734— the description string passed toProjectGate("the project's linked resources on target default") hardcodesdefault, but theTARGET_NAME = "default"constant is right above; consider interpolating it so the two can't drift. TheLayoutrender below already usesstatus.data.target.namefor the same string, so the gate/loading path is the only inconsistency. Not blocking.src/handlers/project/status/screen.tsx:1685— every memory inspec.memoriesis claimed by every runtime agent, butclaim()still callsclaimed.addon each pass. That's fine functionally (Set dedupes), but the intent — "a memory is claimed once it appears under any runtime" — is worth a one-liner comment for the next reader; the neighboring block-comment already explains the why of the grouping rule but not this detail.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## refactor #2215 +/- ##
============================================
- Coverage 97.07% 97.06% -0.02%
============================================
Files 544 547 +3
Lines 37866 38215 +349
============================================
+ Hits 36760 37093 +333
- Misses 1106 1122 +16 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
… state The cross-region link from project status to a detail page now travels as ?region= on the detail route, resolved by a useCoreOpts hook the detail screens share: a truthy region in the query string wins, otherwise the context's ambient region applies as before. This drops the AppRoutes wrapper from Root (and the whole-file re-indent it caused) — Root gains only the status route — and makes the override visible in the route itself. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AMPY8yuo2z5Vhrmyte1Lk2
|
Claude Security Review: no high-confidence findings. (run) |
What
agentcore project statuswas headless-only. A bare invocation in a terminal now opens an interactive Linked Resources screen; any user-supplied flag,--json, or a non-TTY invocation keeps producing exactly the current headless JSON report.spec.runtimes(code agents) andspec.harnesses(managed harness agents) is a top-level group holding the agent's deployed Runtime/Harness and its linked Memories. Resources not attributable to an agent (gateways, credentials, config bundles, …) stay visible under a sharedprojectgroup, with the resolver's nested children (gateway → targets, policy engine → policies, payment manager → connectors) carried through.local-only, and non-selectable; deployed types without a detail screen explain themselves instead of navigating.Design decisions
buildStatusNodes): every declared memory groups under every runtime agent, because the CDK L3 injects aMEMORY_<NAME>_IDenv var for each declared memory into every runtime. A harness's memory ref lives in its ownharness.json, not in the project spec the report is built from, so harness groups list the harness itself and unclaimed memories fall back to the shared group.?region=<target region>, and the detail screens resolve theirCoreOptionsthrough a shareduseCoreOptshook: a truthy region in the query string wins, otherwise the context's region applies as before. History-back naturally restores the previous screen, so escape works at every level, and the override is visible in the route itself.TreeViewis used for the grouped view, extended with afocusMarkerprop (the❯selection style the rest of the TUI uses instead of inverse video) and per-node muted annotations; icons are off so it matches the existing visual language.statusjoins the project router'ssupportedTuiCommands, so theagentcore projectmenu lists it above the "command line only" divider, and the route is mounted inRoot.tsx.Testing
src/handlers/project/status/: screen tests viarenderScreen(grouping, shared group, local-only skipping, forwarding to Runtime/Memory/Harness detail with region assertions, escape at each level, hint rows, collapse/expand, error state, empty project, outside-a-project guidance) plus handler tests pinning the TTY/non-TTY/--json/explicit-flag dispatch.tsc,oxlint,prettier --checkclean.myFirstAgent+myFirstAgentMemory+ an added harness, deployed to us-west-2 with ambient region us-east-1 (the mismatch case), and drove the real TUI in a PTY: the tree grouped the memory under the agent, enter landed on live Runtime (READY), Memory (ACTIVE), and Harness (READY) detail pages fetched in us-west-2, and escape walked back cleanly. Headless--jsonverified unchanged; stack torn down afterwards (DELETE_COMPLETE, noStatusE2Eresources remain).🤖 Generated with Claude Code
https://claude.ai/code/session_01AMPY8yuo2z5Vhrmyte1Lk2