Skip to content

feat: add agora convoai playground dev frontend command#50

Open
plutoless wants to merge 18 commits into
mainfrom
feat/convoai-playground
Open

feat: add agora convoai playground dev frontend command#50
plutoless wants to merge 18 commits into
mainfrom
feat/convoai-playground

Conversation

@plutoless

Copy link
Copy Markdown
Collaborator

Summary

Adds agora convoai playground --channel <name>: a local dev harness that serves an embedded web frontend so a developer can talk to a Conversational AI agent they run separately (e.g. a Python script on the Agora Agents SDK). Point your agent at the same App ID and --channel, open the browser, and converse — with a live transcript, audio meters, and connection status.

  • Local token minting — new self-contained internal/agoratoken implements Agora's AccessToken2 (007) builder (RTC + RTM services in one combined token), stdlib crypto only, verified byte-for-byte against Agora's official reference builder.
  • HTTP server — binds 127.0.0.1 only, serves the embedded SPA + GET /api/get_config (mirrors the quickstart's {code,data} contract). Loopback Host-header guard, same-origin (no CORS), graceful SIGINT/SIGTERM shutdown, auto-incrementing port (default 8787).
  • Embedded frontend — a thin Vite/React harness built on Agora's official agora-agent-uikit + agora-agent-client-toolkit (join, mic, agent audio, AgoraVoiceAI transcript/metrics/state), go:embed-ed and gzip-served (binary embeds only the ~1.5 MB compressed bundle).
  • Startup preconditions — online project resolution; certificate required; fails fast with agora project feature enable convoai if Conversational AI isn't enabled (never auto-enables). Prints a "wire your agent" block (App ID + channel + reserved agent uid) and never prints the certificate.
  • Build integrity — frontend source in frontend/; make playground-build regenerates the committed webassets/; a pure-Go SOURCE_HASH drift guard (make playground-check) is wired into make lint. go build needs no Node.

Notes / trade-offs

  • agora-rtc-sdk-ng and agora-rtm are bundled (no reliable RTM UMD CDN build; RTC SDK's named ESM exports don't map cleanly to a UMD global). CDN-externalizing the RTC SDK remains a possible future size optimization.
  • End-to-end voice/transcript against a live agent is not covered by CI (needs Agora creds + a running agent); correctness rests on the byte-exact token vector, unit/integration tests, and the maintained uikit/toolkit.

Test Plan

  • go test ./... (token-builder golden-vector + decode tests, /api/get_config handler tests incl. loopback guard, embedded-app integration test, frontend conversation unit test)
  • make snapshot-error-codes, make docs-commands-check, make playground-check all pass
  • go build ./... / go vet ./... clean
  • Manual: run agora convoai playground --channel <name> against a convoai-ready project, start a Python agent on the same channel, confirm audio + live transcript both ways

🤖 Generated with Claude Code

plutoless and others added 18 commits July 6, 2026 16:09
Implements the version-007 Agora AccessToken2 builder producing a single
token carrying both an RTC service (join + publish privileges) and an RTM
service (login privilege), with a golden-vector test verified against the
AgoraIO/Tools reference implementation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds the `agora convoai playground` command group with all required flags
(--channel, --port, --uid, --agent-uid, --ttl, --no-open) and a stub
RunE body; later tasks will fill in the server/token logic.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…adiness

Add pure helper functions (validateChannelName, resolveUID, resolveAgentUID,
parseTTLSeconds, featureEnabled) plus resolvePlaygroundSession which resolves
the active project, enforces an app certificate, and gates on the convoai
feature being enabled before returning a populated playgroundSession.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…uard

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…down

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… startup output

The "convoai playground" case added to render.go's pretty switch is dead code:
printPlaygroundStartup only calls renderResult in JSON mode, where renderResult
returns early via emitEnvelope before reaching the switch. Deleted the case and
added a comment to convoai.go explaining why printPlaygroundStartup owns pretty
rendering inline (the multi-line wire block doesn't fit printBlock's shape).

JSON envelope unaffected: renderResult's JSON guard emits the envelope with
data before the switch, so removing the pretty case doesn't affect JSON output.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…pe file

- Vite: deleteOriginFile: true so large JS/CSS become .gz-only in webassets (1.5 MB embedded vs 7.3 MB before)
- Go: replace http.FileServer with gzip-aware newStaticHandler that serves raw files directly or .gz siblings with Content-Encoding: gzip; nil assets still returns 404
- Remove duplicate "Waiting for agent to join…" inline div (kept in StatusBar)
- Delete unused frontend/src/types/conversation.ts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ntegration test

- Add playground-build and playground-check Makefile targets matching the docs-commands pattern
- Wire playground-check into the lint aggregate target alongside docs-commands-check
- Add TestConvoaiPlaygroundServesEmbeddedApp: verifies real embedded assets are served (not the placeholder) and /api/get_config returns a 007 token
- Re-stamp webassets/SOURCE_HASH (prior task deleted frontend/src/types/conversation.ts without updating the hash)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant