- Update CI (unit-test.yml, pr-test.yml) to use yaoapp/tai:1.2.0 with new default ports (gRPC:19100, HTTP:8099, VNC:16080, Docker:12375) - Add explicit 0.0.0.0 bind for containerized Tai instances - Fix sandbox/v2 grpc.go default port fallback (9100 → 19100) - Fix tai/tunnel/proxy.go fallback ports (8080→8099, 6080→16080) - Sync tai SDK and sandbox/v2 documentation with implementation - Add new docs: api.md, registry.md, tunnel.md Made-with: Cursor
3.8 KiB
Package api
HTTP handlers for Tai node registration, heartbeat, and unregistration. Built on Gin, these handlers are mounted on the Yao server to allow remote Tai instances to register themselves.
Routes
| Method | Path | Handler | Description |
|---|---|---|---|
POST |
/tai-nodes/register |
HandleRegister |
Register a Tai node |
POST |
/tai-nodes/heartbeat |
HandleHeartbeat |
Update heartbeat timestamp |
DELETE |
/tai-nodes/register/:tai_id |
HandleUnregister |
Remove a Tai node |
All endpoints require a Bearer token in the Authorization header. Tokens are validated via the Yao OAuth service.
Authentication
Authorization: Bearer <access_token>
The token is validated against oauth.OAuth.AuthenticateToken(). On success, an AuthInfo is extracted containing Subject, UserID, ClientID, Scope, TeamID, and TenantID. The ClientID is used for ownership checks on heartbeat and unregister.
Endpoints
POST /tai-nodes/register
Registers a new Tai node in the global registry.
Request Body:
{
"tai_id": "tai-abc123",
"machine_id": "m-001",
"version": "1.2.0",
"addr": "192.168.1.100",
"ports": {"grpc": 19100, "http": 8099, "vnc": 16080, "docker": 12375},
"capabilities": {"docker": true, "host_exec": true},
"system": {
"os": "linux",
"arch": "amd64",
"hostname": "docker-host-01",
"num_cpu": 16,
"total_mem": 34359738368
}
}
| Field | Type | Required | Description |
|---|---|---|---|
tai_id |
string | yes | Unique identifier for this Tai instance |
machine_id |
string | no | Host machine identifier |
version |
string | no | Tai version string |
addr |
string | no | Reachable address of the Tai server |
ports |
map[string]int | no | Service ports (grpc, http, vnc, docker, k8s) |
capabilities |
map[string]bool | no | Supported features (docker, k8s, host_exec) |
system |
object | no | Host system information |
Response (200):
{
"status": "registered",
"tai_id": "tai-abc123",
"remote_ip": "203.0.113.50"
}
Errors:
| Code | Condition |
|---|---|
| 400 | Missing tai_id or invalid JSON body |
| 401 | Missing or invalid Bearer token |
| 500 | Registry not initialized |
POST /tai-nodes/heartbeat
Updates the LastPing timestamp for a registered node. The node's ClientID must match the token's ClientID.
Request Body:
{
"tai_id": "tai-abc123"
}
Response (200):
{
"status": "ok"
}
Errors:
| Code | Condition |
|---|---|
| 400 | Missing tai_id or invalid JSON body |
| 401 | Missing or invalid Bearer token |
| 403 | tai_id belongs to a different client |
| 404 | tai_id not found in registry |
| 500 | Registry not initialized |
DELETE /tai-nodes/register/:tai_id
Removes a registered node. The node's ClientID must match the token's ClientID.
Response (200):
{
"status": "unregistered"
}
Errors:
| Code | Condition |
|---|---|
| 400 | Missing tai_id path parameter |
| 401 | Missing or invalid Bearer token |
| 403 | tai_id belongs to a different client |
| 404 | tai_id not found in registry |
| 500 | Registry not initialized |
Node Mode
Nodes registered via this HTTP API are marked with Mode: "direct". This means the Yao server can reach the Tai instance directly over the network. For tunnel-mode nodes (registered via WebSocket), see registry.md.
Health Check
The registry runs a background health checker (started via Registry.StartHealthCheck). Direct-mode nodes that miss heartbeats beyond the configured timeout are marked "offline". Nodes that remain offline longer than the cleanup threshold are automatically unregistered.