api

package
v0.2.16 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 7, 2026 License: AGPL-3.0 Imports: 68 Imported by: 0

Documentation

Overview

Env var endpoints for both agent-internal sync and operator UI. Agent-internal handlers live on agentHandler (same as MCP/connection upserts); operator-facing handlers live on credentialHandler (same shape as the rest of the credential surface).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ExtractCanonicalKeys

func ExtractCanonicalKeys(partsJSON []byte, agentID string) []string

ExtractCanonicalKeys reads `s3ref:K` sentinels from the stored goai-shaped parts JSON (image.image / file.data fields) and returns the canonical `llm/agents/<agentID>/K` keys. The sentinel survives the goai.Content marshal roundtrip since it's just a string in Image/Data.

func NewRouter

func NewRouter(cfg RouterConfig) http.Handler

func PublishRunTerminal added in v0.2.8

func PublishRunTerminal(ctx context.Context, pubsub *realtime.PubSub, agentID, runID uuid.UUID, status, errMsg string)

PublishRunTerminal publishes the appropriate WebSocket event for a run's terminal state. Mirrors what publishRunEvents emits from the agent's NDJSON stream so frontends and bridges see one event regardless of which path the run took to terminal — happy path (NDJSON), cancel (CancelRun closes the stream early), the agent's detached r.Complete POST after the stream died, or the sweeper for stuck rows.

Maps airlock-side status strings to WS event types:

  • "error" / "failed" / "timeout" → run.error
  • everything else (success, tool_errors, cancelled, suspended) → run.complete

Idempotent at the client: chat.ts ignores events for runIDs already finalized locally, so a duplicate from the happy-path NDJSON + this helper is harmless.

func RealIP

func RealIP(cfg *RealIPConfig) func(http.Handler) http.Handler

RealIP returns middleware that overwrites r.RemoteAddr with the client's real IP extracted from X-Real-IP or X-Forwarded-For, but only when the direct connection comes from a trusted proxy.

func SubdomainProxy

func SubdomainProxy(agentDomain string, database *db.DB, s3 *storage.S3Client, dispatcher *trigger.Dispatcher, jwtSecret, publicURL string, logger *zap.Logger, inner http.Handler) http.Handler

SubdomainProxy wraps the main router and intercepts requests whose Host header matches {slug}.{agentDomain}. Matching requests are authenticated according to the route's access level and reverse-proxied to the agent's container. Non-matching requests fall through to inner.

func SynthesizeOrphanToolResults added in v0.2.8

func SynthesizeOrphanToolResults(ctx context.Context, q *dbq.Queries, runID uuid.UUID, status string, logger *zap.Logger)

SynthesizeOrphanToolResults inserts a synthetic role=tool message for every tool-call this run emitted that doesn't have a paired tool-result row. Required for the next LLM turn: provider APIs (Anthropic, OpenAI) reject inputs where an assistant's tool_use isn't followed by a tool_result with the matching id. Common after cancel, deadline-exceeded, panic mid-tool, or any path where the agent didn't get to write the tool's result before terminating.

The synthesized output text is derived from the run's terminal status so the LLM has some signal about why the tool didn't complete:

  • "cancelled" → "Cancelled by user."
  • "timeout" → "Tool timed out."
  • else → "Tool execution failed."

Best-effort: failures are logged but don't block the caller. The SessionLoad lazy-synthesis path is the safety net if this misses.

Types

type AuthHandler

type AuthHandler struct {
	// contains filtered or unexported fields
}

func NewAuthHandler

func NewAuthHandler(database *db.DB, jwtSecret, activationCodeFile string, logger *zap.Logger) *AuthHandler

func (*AuthHandler) Activate

func (h *AuthHandler) Activate(w http.ResponseWriter, r *http.Request)

Activate performs one-time setup: creates the tenant and first admin user. Returns 409 if a tenant already exists.

func (*AuthHandler) ChangePassword

func (h *AuthHandler) ChangePassword(w http.ResponseWriter, r *http.Request)

ChangePassword updates the current user's password and clears the must_change_password flag.

func (*AuthHandler) Login

func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request)

func (*AuthHandler) Me

func (*AuthHandler) Refresh

func (h *AuthHandler) Refresh(w http.ResponseWriter, r *http.Request)

func (*AuthHandler) Status

func (h *AuthHandler) Status(w http.ResponseWriter, r *http.Request)

Status returns whether the system has been activated (tenant exists). The activation code itself is generated on airlock startup (see ensureActivationCode in cmd/airlock/main.go) — this handler only reports state, never mutates it.

type CaddyAskHandler

type CaddyAskHandler struct {
	// contains filtered or unexported fields
}

CaddyAskHandler validates on-demand TLS requests from Caddy. Caddy calls GET /caddy/ask?domain=foo.stage.airlock.run before issuing a certificate. We return 200 if the subdomain belongs to a known agent, 403 otherwise.

func (*CaddyAskHandler) Ask

type ProvidersHandler

type ProvidersHandler struct {
	// contains filtered or unexported fields
}

func NewProvidersHandler

func NewProvidersHandler(database *db.DB, enc secrets.Store) *ProvidersHandler

func (*ProvidersHandler) Create

func (h *ProvidersHandler) Create(w http.ResponseWriter, r *http.Request)

func (*ProvidersHandler) Delete

func (h *ProvidersHandler) Delete(w http.ResponseWriter, r *http.Request)

func (*ProvidersHandler) List

func (*ProvidersHandler) ListCatalogModels

func (h *ProvidersHandler) ListCatalogModels(w http.ResponseWriter, r *http.Request)

func (*ProvidersHandler) ListCatalogProviders

func (h *ProvidersHandler) ListCatalogProviders(w http.ResponseWriter, r *http.Request)

func (*ProvidersHandler) Update

func (h *ProvidersHandler) Update(w http.ResponseWriter, r *http.Request)

type RealIPConfig

type RealIPConfig struct {
	// TrustedProxies is a list of CIDR ranges whose X-Forwarded-For / X-Real-IP
	// headers are trusted. If empty, no headers are trusted and r.RemoteAddr is
	// used as-is. A single entry of "*" trusts all sources.
	TrustedProxies []*net.IPNet

	// TrustAll is set when the configured value is "*".
	TrustAll bool

	// Limit is how many rightmost entries in X-Forwarded-For to walk.
	// Default: 1 (single proxy).
	Limit int
}

RealIPConfig configures the real IP extraction middleware.

func ParseRealIPConfig

func ParseRealIPConfig(trustedProxies string, limit int) *RealIPConfig

ParseRealIPConfig builds a RealIPConfig from the raw env values. trustedProxies is a comma-separated list of CIDRs or "*". limit is the number of proxy hops (minimum 1).

func (*RealIPConfig) Enabled

func (c *RealIPConfig) Enabled() bool

Enabled returns true if any proxy trust is configured.

type RouterConfig

type RouterConfig struct {
	DB        *db.DB
	JWTSecret string

	// Real-time
	Hub     *realtime.Hub
	PubSub  *realtime.PubSub
	Handler *realtime.Handler

	// Secrets store. Today wraps a local AES-GCM encryptor; the interface
	// is forward-compatible with a Vault-backed implementation.
	Secrets secrets.Store

	// S3 storage
	S3Client *storage.S3Client

	// Build service
	BuildService *builder.BuildService

	// Public URL (for OAuth callbacks, auth URLs)
	PublicURL string

	// OAuth client
	OAuthClient *oauth.Client

	// Telegram driver (for bridge validation via getMe)
	TelegramDriver *trigger.TelegramDriver

	// Discord driver (for bridge validation via /users/@me)
	DiscordDriver *trigger.DiscordDriver

	// Trigger system
	Dispatcher    *trigger.Dispatcher
	Scheduler     *trigger.Scheduler
	BridgeManager *trigger.BridgeManager

	// Container manager
	Containers container.ContainerManager

	// Prompt proxy (for web conversations)
	PromptProxy *trigger.PromptProxy

	// Agent subdomain routing (e.g. "airlock.host" → {slug}.airlock.host)
	AgentDomain string

	// LLM debugging proxy (e.g. telescope -watch)
	LLMProxyURL string

	// Dev escape hatch: force base64 attachment delivery regardless of
	// provider URL capability. Useful when the public URL isn't reachable
	// from the model provider (e.g. localhost without a tunnel).
	ForceInlineAttachments bool

	// Path to the on-disk activation code file — cleared after Activate
	// succeeds so the one-time secret doesn't linger on disk.
	ActivationCodeFile string

	// Reverse proxy real IP extraction
	RealIP *RealIPConfig

	// Logger
	Logger *zap.Logger
}

type SetEnvVarValueRequest added in v0.2.12

type SetEnvVarValueRequest struct {
	Value string `json:"value"`
}

SetEnvVarValueRequest is the body for POST /api/v1/agents/{agentID}/env-vars/{slug}.

type UsersHandler

type UsersHandler struct {
	// contains filtered or unexported fields
}

func NewUsersHandler

func NewUsersHandler(database *db.DB) *UsersHandler

func (*UsersHandler) Create

func (h *UsersHandler) Create(w http.ResponseWriter, r *http.Request)

Create creates a new user with a temporary password.

func (*UsersHandler) Delete

func (h *UsersHandler) Delete(w http.ResponseWriter, r *http.Request)

Delete removes a user.

func (*UsersHandler) List

func (h *UsersHandler) List(w http.ResponseWriter, r *http.Request)

List returns all users.

func (*UsersHandler) ListSelectable

func (h *UsersHandler) ListSelectable(w http.ResponseWriter, r *http.Request)

ListSelectable returns a slim user directory (id/email/display_name) for member-picker dropdowns. Available to any authenticated user — agent admins who aren't tenant admins (e.g. managers, or users promoted to agent admin) still need to see candidates to invite.

func (*UsersHandler) UpdateRole

func (h *UsersHandler) UpdateRole(w http.ResponseWriter, r *http.Request)

UpdateRole changes a user's tenant role.

type WSHandler

type WSHandler struct {
	// contains filtered or unexported fields
}

WSHandler upgrades HTTP connections to WebSocket.

func NewWSHandler

func NewWSHandler(database *db.DB, hub *realtime.Hub, handler *realtime.Handler, jwtSecret string, logger *zap.Logger) *WSHandler

NewWSHandler creates a new WebSocket upgrade handler.

func (*WSHandler) Upgrade

func (h *WSHandler) Upgrade(w http.ResponseWriter, r *http.Request)

Upgrade handles GET /ws?token=<jwt> — validates the token, upgrades to WebSocket, and auto-subscribes the connection to every agent the user has access to (via agent_members). The client does not issue subscribe messages; authorization is enforced at connect time from durable DB state.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL