feat(platform-ui): add Platform UI dashboard + developer playground#93
Merged
Conversation
A new React/Vite app at examples/platform-ui/ that gives developers a
visual control plane for an OTAIP instance, plus the read-only telemetry
endpoints on the existing OTA Fastify server it consumes.
This is NOT the OTA reference app. The OTA app is a flight-booking
demo; this one is OTAIP's own dashboard — agent registry, adapter
status, health sidebar, and an interactive Playground.
Reuses existing utilities per the brief (no rebuild):
- discoverAgents() from packages/cli/src/agent-discovery.ts
- generateCatalog() shape from packages/core/src/tool-interface
Backend (examples/ota):
- New routes /api/platform/{agents,adapters,health,stats} returning
read-only telemetry. Per-route rate limit raised to 5000/min so
dashboard polling never trips the global 100/min cap.
- New routes /api/playground/{catalog,search,agent,adapter}. catalog
surfaces every discovered agent plus an executable_ids whitelist.
search wraps SearchService against the configured adapter. agent
dispatches into a curated whitelist (v1: 0.1 AirportCodeResolver);
non-whitelisted IDs return 501 with a clear hint instead of pretending
to run. adapter exposes search/price/isAvailable directly.
- onRequest hook tracks last-request timestamp for the health endpoint.
- Tests: 12 new cases across platform.test.ts + playground.test.ts,
Fastify inject() + MockOtaAdapter following the existing search.test.ts
shape.
discoverAgents move:
- packages/core gains src/discovery/agent-discovery.ts (verbatim from
CLI, with a more robust repoRoot() that walks up to pnpm-workspace.yaml
rather than counting directories).
- packages/cli/src/agent-discovery.ts shrinks to a re-export — every
existing import path keeps working, behaviour unchanged.
Frontend (examples/platform-ui):
- Vite + React 18 + TS strict + Tailwind + react-router-dom.
- Dashboard: 4 stat cards, agent table with filter/sort/group-by-domain,
adapter cards keyed off env vars, health sidebar polled every 15s.
- Playground: split-panel layout with Search/Agent/Adapter mode tabs,
Formatted/Raw/Timeline response tabs, last-10 request history with
one-click replay. JSON viewer is a hand-rolled <pre> + copy button —
no heavyweight syntax-highlighter dep, matching the brief's "no
heavy component library" rule.
- Vite proxies /api → http://localhost:3000 (override via OTA_SERVER_URL),
so dev mode is same-origin and CORS is a non-issue.
Out of scope (intentional):
- Production packaging (Fastify serving the built dist/) — Vite dev-only
this round.
- Generic agent execution. Whitelist starts at one; the surface to add
more is a single object literal in playground-service.ts.
Verification:
- pnpm --filter @otaip/platform-ui typecheck → clean.
- pnpm exec vitest run examples/ota → 100/100 across 9 files.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 6, 2026
telivity-otaip
added a commit
that referenced
this pull request
May 7, 2026
chore(release): v0.7.2 — Duffel Cars + auto-publish + post-#93 fix
ntbpy
pushed a commit
to ntbpy/AI_Agent_otaip
that referenced
this pull request
May 11, 2026
fix Patch bump off v0.7.1. Three pieces: - TelivityAI#99 @otaip/adapter-duffel adds Cars (search → quote → book → get → cancel) under /cars/. Same Bearer auth, AbortSignal threading on request(). 8 open DOMAIN_QUESTIONs captured in docs/knowledge-base/cars.md. - TelivityAI#97 unbreaks the Release workflow's Count agents step that TelivityAI#93's CLI re-export indirection broke. Every push-to-main since TelivityAI#93 had been failing silently — that's why v0.7.1's tag was created but the workspace npm bumps lagged behind for a while. - TelivityAI#98 switches gh release create to RELEASE_PAT so the release: published event propagates to the Publish workflow. This is the first release that should auto-publish to npm without a manual workflow_dispatch. Workspace-wide bump: 17 package.json files 0.7.1 → 0.7.2 (@otaip/adapter-duffel was already at 0.7.2 from TelivityAI#99). Going forward, the next release is v0.7.3. See CHANGELOG.md for details. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
A new React/Vite app at
examples/platform-ui/plus the read-only telemetry endpoints that back it. Two views:0.1AirportCodeResolver) execute end-to-end; everything else returns a clear 501 with a "not yet wired" hint.search/price/isAvailableagainst the configured adapter.Response viewer has Formatted / Raw / Timeline tabs and a last-10 in-memory request history with one-click replay.
Why
OTAIP currently ships an OTA reference app (
examples/ota) — a booking demo. There was no UI for OTAIP itself: no view of the agent registry, no view of adapter configuration, no way to poke at agents. This PR adds that — Stripe Dashboard-style control plane for travel AI agents.Backend changes
@otaip/coregainssrc/discovery/agent-discovery.ts(moved verbatim from CLI; tweakedrepoRoot()to walk up topnpm-workspace.yamlrather than counting directories — more robust for both source and built consumers).@otaip/cliagent-discovery.tsshrinks to a re-export from@otaip/core; every existing import path keeps working./api/platform/*(read-only telemetry, rate limit raised to 5 000/min so dashboard polling can't trip the global 100/min cap) and/api/playground/*(execution surface, AJV body schemas on every state-mutating route). OneonRequesthook updates the dashboard's last-request timestamp.platform.test.ts+playground.test.ts, Fastifyinject()+MockOtaAdaptermirroring the existingsearch.test.tsshape.Frontend changes
examples/platform-ui/— Vite + React 18 + TypeScript strict + Tailwind + react-router-dom. ~30 files: tooling (6), src components (8), src pages (2), src API client (2), styling/config (4). Tailwind only — no MUI/Ant per the brief's "no heavyweight component library" rule. JSON viewer is a hand-rolled<pre>+ copy button (no syntax-highlighter dep).Vite proxies
/api→http://localhost:3000in dev (override withOTA_SERVER_URL), so the browser sees same-origin and the existing CORS_ORIGIN env-var path stays untouched.Curated agent whitelist
Generic agent execution requires
PipelineOrchestrator+PipelineSessionplumbing for every agent that has a Zod-typed contract. Doing that for 70+ agents would mean importing every package at boot. Instead the catalog endpoint surfaces all agents (so the picker works) but theexecutable_idsset starts at one —0.1AirportCodeResolver, the agent CLAUDE.md cites as the canonical reference pattern. Non-whitelisted IDs render a clear "not yet wired for playground execution" banner in the form area; submitting returns501with a pointer to the catalog. Adding more agents is a single object-literal entry inplayground-service.ts.Out of scope
dist/). Acceptance criteria stop atpnpm devend-to-end; deferred.bookexposed through the playground — intentionally read-only.Test plan
pnpm --filter @otaip/platform-ui typecheck— clean.pnpm --filter @otaip/ota-example typecheck— clean.pnpm --filter @otaip/cli typecheck— clean (uses the re-exported discoverAgents).pnpm exec vitest run examples/ota— 100 passed across 9 files (88 existing + 12 new).pnpm --filter @otaip/ota-example devthenpnpm --filter @otaip/platform-ui dev. Open http://localhost:5173:pnpm cli agents.DUFFEL_API_KEY/HOTELBEDS_API_KEYenv state.0.1with{"code":"JFK","code_type":"iata"}returns the resolved JFK record.🤖 Generated with Claude Code