web

package
v0.13.0 Latest Latest
Warning

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

Go to latest
Published: Aug 6, 2026 License: MIT Imports: 30 Imported by: 0

Documentation

Overview

Package web: app-contract search endpoint (ADR-0028). GET /_search?q= returns the caller's user-scoped matches; platformd fans out to every app and groups the results.

Package web is the server scaffold every app runs on (docs/design/architecture.md). It owns listening, identity enforcement, /healthz, request logging, and graceful shutdown, so apps contain zero infrastructure code — just routes.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Changed

func Changed(login string)

Changed announces that the user's data in THIS app changed: local /_live subscribers re-render, and platformd is nudged (fire-and-forget) so dashboard cards refresh too. Call after every mutation — handlers, tools, and intents alike.

func DashboardCard

func DashboardCard(mux *http.ServeMux, provider CardProvider)

DashboardCard mounts GET /_card, the optional app-contract endpoint the dashboard pulls per-user summaries from. Call inside web.Run's register:

web.DashboardCard(mux, func(ctx, user) (templ.Component, error) { … })

func EnableChat

func EnableChat(mux *http.ServeMux, slug string, provider ChatProvider)

EnableChat mounts POST /_chat and turns on the AppShell chat panel. Call once inside web.Run's register function:

web.EnableChat(mux, "journal", func(ctx, user) (string, error) { … })

The chat is agentic over the app's own web.Tool registrations.

func EnableChatWithTools

func EnableChatWithTools(mux *http.ServeMux, slug string, provider ChatProvider, toolSource ToolSource, extra ...llm.Option)

EnableChatWithTools is EnableChat with an explicit tool source. Extra llm options are applied to every chat completion — platformd's dashboard chat uses this for llm.WithBuiltins (ADR-0024); apps normally pass none.

func IdempotencyKey added in v0.13.0

func IdempotencyKey(ctx context.Context) (string, bool)

func Intent

func Intent(mux *http.ServeMux, appTitle string, def IntentDef)

Intent mounts GET /_intents/<name> (prefilled, editable confirm page) and POST /_intents/<name> (execute → redirect). Other apps link here via the registry; the confirm step doubles as the edit step.

func Live

func Live(mux *http.ServeMux, fragment func(ctx context.Context, user auth.User) (templ.Component, error))

Live mounts GET /_live: a Datastar SSE stream that re-renders the app's live region on every Changed(login) and patches it in place. Pages subscribe from a stable wrapper element:

<div data-init="@get('/_live')">
  <div id="<slug>-live">…initial render…</div>
</div>

fragment must render the element with that same id.

func Notify

func Notify(login string)

Notify wakes this process's /_live subscribers for a user without touching the plane — platformd's /notify endpoint feeds cross-process changes in through here.

func Run

func Run(slug string, register func(mux *http.ServeMux))

Run serves the app named slug on the port from its manifest — the normal entrypoint for apps. Production units override the address with -listen <tailscale-ip>:<port> (docs/adr/0011-split-host-deployment.md).

func Search(mux *http.ServeMux, provider SearchProvider)

Search mounts GET /_search, the optional app-contract endpoint the dashboard search box and the platform `search` tool fan out to. Call inside web.Run's register.

func Serve

func Serve(slug string, defaultPort int, register func(mux *http.ServeMux))

Serve is Run with an explicit default port, for platform processes that have no app manifest (platformd). Every route registered by register is behind auth.Middleware; /healthz is not. Blocks until SIGINT/SIGTERM, then drains for up to 5s.

func Skills

func Skills(mux *http.ServeMux, skillsFS fs.FS) error

Skills registers the app's bundled skills (ADR-0026): skillsFS holds <name>/SKILL.md files with `name:` and `description:` frontmatter — the same format as the repo's agent skills. It mounts GET /_skills (the parsed set, JSON) and registers one `load_skill` tool whose description carries the index, so every surface with the app's tools — its own chat, the dashboard chat (as <slug>_skill), external MCP clients — can load a skill's full instructions on demand. Call inside web.Run's register, before EnableChat.

func Tool

func Tool(mux *http.ServeMux, def ToolDef)

Tool registers an LLM-callable action: POST /_tools/<name> executes it (auth'd like everything), and GET /_tools lists all definitions for the aggregators. Call inside web.Run's register.

Types

type AutomationMode added in v0.13.0

type AutomationMode string
const (
	AutomationForbidden  AutomationMode = "forbidden"
	AutomationReadOnly   AutomationMode = "read_only"
	AutomationIdempotent AutomationMode = "idempotent"
)

type AutomationPolicy added in v0.13.0

type AutomationPolicy struct{ Mode AutomationMode }

type CardProvider

type CardProvider func(ctx context.Context, user auth.User) (templ.Component, error)

CardProvider renders the app's live dashboard-card fragment for a user (ADR-0017): content only — no AppShell, no forms; cheap queries, never LLM calls (the dashboard waits behind a short timeout).

type ChatProvider

type ChatProvider func(ctx context.Context, user auth.User) (string, error)

ChatProvider returns the current user's relevant app data as text — the context the in-app chat answers from (ADR-0015). Keep it recent and bounded (e.g. last 30 days), not a full dump.

type IntentDef

type IntentDef struct {
	Name    string // must match an [[intents]] name in app.toml
	Title   string // confirm-page heading, e.g. "Create Todo"
	Prompt  string // label over the editable payload, e.g. "Task description"
	Handler func(ctx context.Context, user auth.User, text string) (redirect string, err error)
}

IntentDef wires a manifest-declared intent (docs/adr/0018-cross-app-intents.md) to its handler. Handler returns the in-app URL to land on after execution (the created thing, or "/").

type SSE

SSE is the Datastar server-sent-events generator apps use for live UI (patch elements/signals from handlers). Kept as an alias so apps import only pkg/web; the AppShell already loads the matching datastar.js.

func NewSSE

func NewSSE(w http.ResponseWriter, r *http.Request) *SSE

NewSSE starts a Datastar SSE response for r.

type SearchProvider added in v0.2.0

type SearchProvider func(ctx context.Context, user auth.User, q string) ([]SearchResult, error)

SearchProvider returns the user's results matching q. It MUST scope to the user and MUST be a cheap DB query — never an LLM call (platformd waits behind a short timeout).

type SearchResult added in v0.2.0

type SearchResult struct {
	Title     string `json:"title"`
	Snippet   string `json:"snippet,omitempty"`
	URL       string `json:"url,omitempty"`
	Timestamp string `json:"timestamp,omitempty"`
}

SearchResult is one hit an app returns for a query. Only Title is required; URL is app-relative and best-effort deep (a bare "/" home link is acceptable). See docs/specs/app-search.md.

type SkillDef

type SkillDef struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	Body        string `json:"body"`
}

SkillDef is one bundled skill: procedural knowledge for chat, loaded on demand (ADR-0026).

type ToolDef

type ToolDef struct {
	Name        string
	Description string
	Schema      map[string]any // JSON Schema for the arguments object
	Automation  AutomationPolicy
	Handler     func(ctx context.Context, user auth.User, args json.RawMessage) (string, error)
}

ToolDef is a user-scoped action the app exposes to LLMs (ADR-0021): agentic chat calls these through the gateway, and the platform MCP server exposes them to external clients as <slug>_<name>. Handlers must scope everything by the given user — same discipline as HTTP handlers.

type ToolSource

type ToolSource func(ctx context.Context, user auth.User) []llm.Tool

ToolSource supplies the tools a chat may use (ADR-0021). Apps get their own registered tools automatically via EnableChat; platformd's dashboard chat aggregates every app's.

Jump to

Keyboard shortcuts

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