Documentation
¶
Index ¶
- func ExtractCanonicalKeys(partsJSON []byte, agentID string) []string
- func NewRouter(cfg RouterConfig) http.Handler
- func PublishRunTerminal(ctx context.Context, pubsub *realtime.PubSub, agentID, runID uuid.UUID, ...)
- func RealIP(cfg *RealIPConfig) func(http.Handler) http.Handler
- func SubdomainProxy(agentDomain string, database *db.DB, s3 *storage.S3Client, ...) http.Handler
- func SynthesizeOrphanToolResults(ctx context.Context, q *dbq.Queries, runID uuid.UUID, status string, ...)
- type AuthHandler
- func (h *AuthHandler) Activate(w http.ResponseWriter, r *http.Request)
- func (h *AuthHandler) ChangePassword(w http.ResponseWriter, r *http.Request)
- func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request)
- func (h *AuthHandler) Me(w http.ResponseWriter, r *http.Request)
- func (h *AuthHandler) Refresh(w http.ResponseWriter, r *http.Request)
- func (h *AuthHandler) Status(w http.ResponseWriter, r *http.Request)
- type CaddyAskHandler
- type ProvidersHandler
- func (h *ProvidersHandler) Create(w http.ResponseWriter, r *http.Request)
- func (h *ProvidersHandler) Delete(w http.ResponseWriter, r *http.Request)
- func (h *ProvidersHandler) List(w http.ResponseWriter, r *http.Request)
- func (h *ProvidersHandler) ListCatalogModels(w http.ResponseWriter, r *http.Request)
- func (h *ProvidersHandler) ListCatalogProviders(w http.ResponseWriter, r *http.Request)
- func (h *ProvidersHandler) Update(w http.ResponseWriter, r *http.Request)
- type RealIPConfig
- type RouterConfig
- type UsersHandler
- func (h *UsersHandler) Create(w http.ResponseWriter, r *http.Request)
- func (h *UsersHandler) Delete(w http.ResponseWriter, r *http.Request)
- func (h *UsersHandler) List(w http.ResponseWriter, r *http.Request)
- func (h *UsersHandler) ListSelectable(w http.ResponseWriter, r *http.Request)
- func (h *UsersHandler) UpdateRole(w http.ResponseWriter, r *http.Request)
- type WSHandler
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ExtractCanonicalKeys ¶
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 (*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 (h *AuthHandler) Me(w http.ResponseWriter, r *http.Request)
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 ¶
func (h *CaddyAskHandler) Ask(w http.ResponseWriter, r *http.Request)
type ProvidersHandler ¶
type ProvidersHandler struct {
// contains filtered or unexported fields
}
func NewProvidersHandler ¶
func NewProvidersHandler(database *db.DB, enc *crypto.Encryptor) *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 (h *ProvidersHandler) List(w http.ResponseWriter, r *http.Request)
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
// Encryption (for provider API keys)
Encryptor *crypto.Encryptor
// 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 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.
Source Files
¶
- agent.go
- agent_http.go
- agent_llm.go
- agent_mcp.go
- agent_print.go
- agent_proxy.go
- agent_run.go
- agent_search.go
- agent_session.go
- agent_storage.go
- agent_webfetch.go
- agents.go
- auth.go
- bridges.go
- caddy.go
- capabilities.go
- conv_mutex.go
- conversations.go
- credentials.go
- credentials_mcp.go
- deliver.go
- event_publisher.go
- health.go
- helpers.go
- identity.go
- middleware.go
- models.go
- providers.go
- proxy.go
- realip.go
- relay.go
- router.go
- run_finalize.go
- runs.go
- settings.go
- users.go
- webhook_ingress.go
- ws.go