Skip to content

feat(dev): Agent Inspector HTTP layer (server, security, assets) - #2082

Open
tejaskash wants to merge 6 commits into
feat/dev-supervisorfrom
feat/inspector-http-layer
Open

feat(dev): Agent Inspector HTTP layer (server, security, assets)#2082
tejaskash wants to merge 6 commits into
feat/dev-supervisorfrom
feat/inspector-http-layer

Conversation

@tejaskash

Copy link
Copy Markdown
Contributor

What

First of three stacked PRs re-authoring the Agent Inspector from feat/agent-inspector against current refactor APIs. This one lands the HTTP contract and SPA delivery only — a pure request to response handler the dev command will compose with io/startHttpServer. It is not yet reachable from the CLI.

Stacked on #2041 (feat/dev-supervisor); retarget to refactor once that merges.

Scope

  • src/core/dev/inspector/{types,respond,server,testkit}.ts — DI interfaces (InspectorSupervisor, InspectorTraces, InspectorAssets, InspectorDeps), response helpers, and createInspectorHandler.
  • src/core/dev/inspectorAssets.ts — reads the staged SPA through AssetSource with an AGENT_INSPECTOR_PATH override and a node_modules fallback.
  • src/io/packagedAssets.ts — raw file reads and package-dir resolution, so node:fs/node:module stay out of core/dev.
  • scripts/build.tsstageInspectorAssets() copies @aws/agent-inspector/dist-assets into the asset tree before bundle and compile.

Routes registered this PR: GET /api/status, POST /api/start, GET /api/traces, GET /api/traces/:id, static SPA (with index.html fallback), and a graceful { success:false, error } 404 for everything else. Agent-proxy routes (invocations, MCP, A2A, resources) and the CLI wiring land in the following PRs, so no stub routes appear here.

Security model

Loopback-only Host check (accepts localhost, 127.0.0.1, [::1]), server-side Origin allowlist (plus the Vite :5173 dev origins), X-Agentcore-Local required on POSTs, CORS preflight, and a CSP on served HTML.

Design notes vs the reference branch

  • Route matching hardened: exact /api/traces for the list route and slice + decodeURIComponent for :id, so /api/tracesXYZ no longer matches the list route and encoded ids decode. Covered by tests.
  • Boundary of concern: filesystem and package resolution moved into src/io/packagedAssets.ts; inspectorAssets.ts no longer imports node:fs/node:module.
  • Trace list capped to the newest 200 per poll, matching TraceStore.list's existing limit contract, since each summary carries full spans/logs.
  • Security-guard rejection cases parameterized with test.each.

Verification

  • bun test src/core/dev/inspector + inspectorAssets.test.ts — 26 pass.
  • Full bun test (1812 pass), bun run typecheck, bun run lint:check, bun run format:check all green.
  • bun run build stages the four SPA files into src/assets/agent-inspector/ (gitignored) and mirrors them into dist/assets/.

project dev without --agent now runs all of the project's runtimes at once:
a DevSupervisor owns per-agent lifecycle (sequential port resolution — a
concurrent race would put two agents on one port), merges every runner's
output into one agent-attributed stream ([name] prefixes; an agent field in
NDJSON), and keeps the session alive when one agent crashes. Selecting a
single runtime (--agent, or a one-runtime project) keeps the direct path
where a crash still fails the command.
…setup

A child that stays alive without ever binding its port previously blocked
every later runtime (starts are sequential) until interrupted; readiness now
gives up after 120s and fails that start. Setup failures before the pump
exists (port resolution, environment) now remove their parent-abort listener
like every other exit path, so Inspector retries of a failing agent cannot
accumulate listeners.
The #1980 rebase carried a single-runtime host check (runtime.build) into
the multi-agent dev handler, where the variable is the runtimes array. Bind
all interfaces when any selected runtime runs in a container.
…batch

events() spliced the queue, yielded each event, then installed its wake
callback and blocked. A push landing during the yields ran while wake was
undefined, so its wake was a no-op, and the newly installed waiter never
noticed the queued event until the next push or shutdown. Re-check the queue
inside the wait so a queued event resolves immediately.
Port the reference WebUIServer as a pure request to response handler the
dev command composes with io/startHttpServer. This lands the HTTP contract
and SPA delivery only; agent-proxy routes (invocations, MCP, A2A, resources)
and the CLI wiring follow in later PRs.

- security: loopback-only Host check (incl. IPv6 [::1]), server-side origin
  allowlist, X-Agentcore-Local on POSTs, CORS preflight, CSP on served HTML
- routes: GET /api/status, POST /api/start, GET /api/traces[/:id], static SPA
  with index.html fallback, graceful JSON 404 for everything else
- exact-match trace routing with decodeURIComponent :id extraction
- InspectorAssets reads the staged SPA through AssetSource with an
  AGENT_INSPECTOR_PATH override and node_modules fallback; raw filesystem and
  package resolution live in src/io/packagedAssets, keeping node:fs/node:module
  out of core/dev
- build stages @aws/agent-inspector/dist-assets into the asset tree before
  bundle and compile
@github-actions github-actions Bot added the size/xl PR size: XL label Aug 24, 2026
@github-actions github-actions Bot added agentcore-harness-reviewing AgentCore Harness review in progress and removed agentcore-harness-reviewing AgentCore Harness review in progress labels Aug 24, 2026
@tejaskash
tejaskash force-pushed the feat/dev-supervisor branch from 94eed9a to fc5db62 Compare August 24, 2026 17:49
- serve static assets over a zero-copy Buffer view of the cached bytes
- hoist the constant CORS headers to module scope; the per-request origin
  pick reduces to origin || primary now that the guard runs first
- drop the single-use InspectorAssetReader alias; inline read's signature
- hoist the asset TextEncoder to module scope
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Aug 24, 2026
@tejaskash
tejaskash force-pushed the feat/dev-supervisor branch 2 times, most recently from 9904ee1 to 0a77c0c Compare August 25, 2026 15:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xl PR size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant