Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
c97b1a0
feat(agoratoken): little-endian packing primitives
plutoless Jul 6, 2026
52a35da
feat(agoratoken): AccessToken2 builder with RTC+RTM services
plutoless Jul 6, 2026
7775d15
fix(agoratoken): handle rand failure explicitly; drop vacuous service…
plutoless Jul 6, 2026
0f9f6bd
feat(convoai): register convoai playground command skeleton
plutoless Jul 6, 2026
bcc253c
feat(convoai): startup resolution, channel/uid validation, convoai re…
plutoless Jul 6, 2026
b7cd90e
feat(convoai): /api/get_config combined-token handler with loopback g…
plutoless Jul 6, 2026
e6ff587
fix(convoai): case-insensitive loopback host check; uid=0 fallthrough…
plutoless Jul 6, 2026
69bff98
feat(convoai): embed assets, port selection, serve with graceful shut…
plutoless Jul 6, 2026
940e410
fix(convoai): handle SIGTERM, add ReadHeaderTimeout, correct port com…
plutoless Jul 6, 2026
1345bbe
feat(convoai): wire block and JSON startup envelope
plutoless Jul 6, 2026
69087d7
refactor(convoai): remove unreachable render.go case; document inline…
plutoless Jul 6, 2026
387454c
chore(convoai): frontend scaffold and source-hash tool
plutoless Jul 6, 2026
43d9d75
chore(convoai): bundle agora-rtm instead of CDN externalization
plutoless Jul 6, 2026
4fa253a
feat(convoai): frontend harness (join, transcript, meters, status)
plutoless Jul 7, 2026
3f67b7b
perf(convoai): serve gzip assets, embed compressed-only; drop dead ty…
plutoless Jul 7, 2026
951977a
test(convoai): playground build/check make targets and embedded-app i…
plutoless Jul 7, 2026
b645bf4
docs: document convoai playground command and error codes
plutoless Jul 7, 2026
8c99f7c
chore: ignore playgroundhash build artifact
plutoless Jul 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ coverage.out
# Built CLI binaries
agora
agora-cli-go
playgroundhash

# IDE and editor files
.idea/
Expand All @@ -23,3 +24,6 @@ _site/
# Python bytecode
__pycache__/
*.py[cod]

# Frontend dependencies (never commit node_modules)
frontend/node_modules/
15 changes: 13 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: build test lint lint-go lint-fmt snapshot snapshot-error-codes release release-snapshot docs-commands docs-commands-check docs-preview
.PHONY: build test lint lint-go lint-fmt snapshot snapshot-error-codes release release-snapshot docs-commands docs-commands-check docs-preview playground-build playground-check

# Build a local agora binary with stripped paths.
build:
Expand All @@ -11,7 +11,7 @@ test:
# Aggregate lint target. Runs gofmt, golangci-lint (if installed), the
# error-code coverage audit, and the docs/commands.md drift check. Use
# this in CI and pre-commit.
lint: lint-fmt lint-go snapshot-error-codes docs-commands-check
lint: lint-fmt lint-go snapshot-error-codes docs-commands-check playground-check

lint-fmt:
@unformatted="$$(gofmt -l .)"; \
Expand Down Expand Up @@ -73,3 +73,14 @@ docs-commands-check:
# Uses an empty local baseurl so assets resolve from http://localhost:4000/.
docs-preview:
./scripts/preview-pages-site.sh

# Build the embedded playground frontend and stamp the source hash.
# Requires Node/npm (only needed to regenerate the committed webassets).
playground-build:
cd frontend && npm ci && npm run build
go run ./cmd/playgroundhash -write

# Drift guard (pure Go, runs in lint): fails if frontend/ changed without
# rebuilding the committed webassets. Fix by running `make playground-build`.
playground-check:
go run ./cmd/playgroundhash -check
73 changes: 73 additions & 0 deletions cmd/playgroundhash/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Command playgroundhash computes a stable hash over the frontend/ source
// inputs. `-write` stamps it into webassets/SOURCE_HASH; `-check` compares.
package main

import (
"crypto/sha256"
"encoding/hex"
"flag"
"fmt"
"os"
"path/filepath"
"sort"
"strings"
)

func main() {
write := flag.Bool("write", false, "write SOURCE_HASH")
check := flag.Bool("check", false, "check SOURCE_HASH")
flag.Parse()

sum, err := hashFrontend("frontend")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
}
target := filepath.Join("internal", "cli", "playground", "webassets", "SOURCE_HASH")
switch {
case *write:
if err := os.WriteFile(target, []byte(sum+"\n"), 0o644); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
}
case *check:
got, err := os.ReadFile(target)
if err != nil || strings.TrimSpace(string(got)) != sum {
fmt.Fprintln(os.Stderr, "frontend/ changed but webassets not rebuilt. Run `make playground-build`.")
os.Exit(1)
}
default:
fmt.Println(sum)
}
}

func hashFrontend(root string) (string, error) {
var files []string
err := filepath.Walk(root, func(p string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
if info.Name() == "node_modules" || info.Name() == "dist" {
return filepath.SkipDir
}
return nil
}
files = append(files, p)
return nil
})
if err != nil {
return "", err
}
sort.Strings(files)
h := sha256.New()
for _, f := range files {
b, err := os.ReadFile(f)
if err != nil {
return "", err
}
fmt.Fprintf(h, "%s\n", f)
h.Write(b)
}
return hex.EncodeToString(h.Sum(nil)), nil
}
19 changes: 19 additions & 0 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,25 @@ Update persisted CLI defaults
| `--output` | `output` | `pretty` | persist default output mode (pretty or json) |
| `--telemetry-enabled` | `bool` | — | persist telemetry preference; use --telemetry-enabled=false to disable |

### `agora convoai`

Conversational AI developer tools

_No local flags. Inherited parent and global flags still apply; run `agora <command> --help` for the full flag set._

### `agora convoai playground`

Start a local frontend to talk to your Conversational AI agent

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--agent-uid` | `int64` | — | reserved agent uid printed in the wire block (0 = generate) |
| `--channel` | `string` | — | RTC channel to join (required; use the same value for your agent) |
| `--no-open` | `bool` | — | do not open the browser automatically |
| `--port` | `int` | `8787` | local server port (auto-increments if busy unless explicitly set) |
| `--ttl` | `string` | `1h` | token lifetime |
| `--uid` | `int64` | — | browser RTC uid (0 = generate a non-zero uid) |

### `agora doctor`

Diagnose the local Agora CLI install (PATH, version, network, auth, MCP host)
Expand Down
8 changes: 8 additions & 0 deletions docs/error-codes.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@ These codes appear inside `data.checks[].issues[].code` and (for blocking issues
| `APP_CREDENTIALS_MISSING` | 1 | The selected project has no app ID / app certificate yet. | Run the command from `suggestedCommand` (`agora project show --project <id>`) to re-fetch credentials; if still missing, enable the app certificate in Console (`agora open --target console`). |
| `TOKEN_CAPABILITY_DISABLED` | (warning) | The project has token issuance disabled. | Enable token issuance in Console. |

### Conversational AI (`convoai playground`)

| Code | Exit | Meaning | Recovery |
|------|------|---------|----------|
| `CHANNEL_INVALID` | 1 | The `--channel` value is empty, exceeds 64 bytes, or contains an unsupported character. | Pass a non-empty channel name using only alphanumeric characters, hyphens, and underscores, up to 64 bytes. |
| `TTL_INVALID` | 1 | The `--ttl` value is not a valid positive Go duration (e.g. `1h`, `30m`). | Pass a positive duration such as `1h` or `30m`. |
| `CONVOAI_NOT_READY` | 1 | The selected project does not have Conversational AI enabled. | Run `agora project feature enable convoai` and retry. |

### Skills (curated workflows)

| Code | Exit | Meaning | Recovery |
Expand Down
3 changes: 3 additions & 0 deletions frontend/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# agora-agent-uikit ships workspace:* peer dep specifiers (pnpm monorepo);
# npm requires legacy-peer-deps mode to resolve them without error.
legacy-peer-deps=true
12 changes: 12 additions & 0 deletions frontend/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Agora Convoai Playground</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Loading
Loading