Documentation
¶
Overview ¶
Package daemon owns the one local, read-only `datatug serve` process that AI-agent mods use so their cards can link to the DataTug web UI (spec/features/cli/daemon). The CLI is the owner of that process: it records it in a state directory (pidfile, record, log) and stops it with Stop.
Index ¶
Constants ¶
const ( // DefaultPort is the preferred agent port; MaxPort bounds the search for a free one. DefaultPort = 8989 MaxPort = 9009 // Host is the only address the daemon binds. Host = "127.0.0.1" // IdleTimeout is how long the daemon runs without a request before it exits. IdleTimeout = 2 * time.Hour // Fixed failure phrases: they never carry a path, URL or credential. ErrPhraseNoPort = "no free port between 8989 and 9009" ErrPhraseExited = "server exited during start" ErrPhraseTimeout = "server was not ready within 5s" ErrPhraseNoBinary = "cannot locate the datatug binary" ErrPhraseSpawn = "cannot launch the server" ErrPhraseState = "cannot write the daemon state directory" )
const ( KindTableMetadata = "table-metadata" KindTableRecords = "table-records" KindRecord = "record" // UISupport values: pending means the web UI has no route for the kind yet. UISupportAvailable = "available" UISupportPending = "pending" // DefaultUIBase is the hosted web UI; DATATUG_UI_BASE replaces it. DefaultUIBase = "https://datatug.app" UIBaseEnv = "DATATUG_UI_BASE" DefaultLimit = 50 MaxLimit = 1000 )
Link kinds, as printed by `daemon url`.
const ContractVersion = 1
ContractVersion is the shape version of the `daemon url` JSON: bumped on any incompatible change.
const DirEnv = "DATATUG_DAEMON_DIR"
DirEnv overrides the state directory (default ~/datatug/daemon).
const (
// MaxLinkLength bounds a link: the mod SDK draws at most this many characters.
MaxLinkLength = 2048
)
const WarningKeyNotScanned = "primary key not in scanned metadata: key not validated"
WarningKeyNotScanned is the warning of a record link to a table whose scan holds no primary-key information: the key is not validated.
const WarningNotScanned = "table metadata not scanned: link not validated"
WarningNotScanned is the one warning of a link that was not checked against the project's scanned metadata: the project has none for the source (never scanned, or it cannot be read).
Variables ¶
var ErrNotOwned = errors.New("no daemon started by this CLI")
ErrNotOwned is returned by Stop for a datatug API this CLI did not start.
Functions ¶
Types ¶
type ErrNotRunning ¶
type ErrNotRunning struct{ Phrase string }
ErrNotRunning is returned by Start, next to its Status, when no server runs.
func (ErrNotRunning) Error ¶
func (e ErrNotRunning) Error() string
type Link ¶
type Link struct {
Contract int `json:"contract"`
URL string `json:"url"`
Kind string `json:"kind"`
Running bool `json:"running"`
UISupport string `json:"uiSupport"`
// Warnings is always present ([] when empty) so the shape is stable.
Warnings []string `json:"warnings"`
}
Link is the deep link of one card.
func BuildLink ¶
func BuildLink(st Status, req LinkRequest) (Link, error)
BuildLink builds the deep link of contract deep-link-contract for the agent reported by st: identity in the path, view parameters (limit, schema) in the query, the record key in the fragment so it is never sent to the web host. It never reaches the network.
type LinkRequest ¶
type LinkRequest struct {
Project, Env, DB, Table, Schema string
View bool
Records bool
Limit int
Record string // primary key as a JSON object
// Code is the one-time code of the agent (agentaccess.MintCode), put first in the fragment of
// every link; "" when the agent has none to give.
Code string
// Metadata reads the scanned relations named Table (nil when the project holds none): the link is
// checked against them, and carries a warning when there is nothing to check against. It runs
// last, after every check of the request itself; a nil function is no metadata.
Metadata func() *Metadata
}
LinkRequest names one card's target.
type Manager ¶
type Manager struct {
Dir string
Exe func() (string, error)
Probe func(port int) (version string, ok bool)
// Dial says whether something accepts a TCP connection on 127.0.0.1:port. It sends no
// HTTP request, so it never counts as activity for the server's idle timer.
Dial func(port int) bool
PortFree func(port int) bool
Alive func(pid int) bool
// Owns says whether pid is a `datatug serve` on port (guards against a reused pid).
Owns func(pid, port int) bool
Terminate func(pid int) error
// Spawn starts the detached server and returns its pid and a channel closed when it exits.
Spawn func(exe string, args []string, logPath string) (pid int, exited <-chan struct{}, err error)
Now func() time.Time
Sleep func(time.Duration)
// StartWait bounds the readiness wait; Poll is its interval.
StartWait time.Duration
Poll time.Duration
}
Manager holds the state directory and every seam over the OS, so tests drive the whole lifecycle without a real process or port.
func (*Manager) Start ¶
Start ensures the daemon runs. The returned Status is always set; the error is ErrNotRunning when no server could be brought up.
func (*Manager) Status ¶
Status reports the daemon without starting or stopping anything, and without sending an HTTP request to a server this CLI started (a request would reset its idle timer): the record, the pid and a TCP connect decide (no process-command check, which can fail in a sandbox and, on Windows, is an HTTP probe). A datatug API this CLI did not start (no record of it) is the one case that costs a single agent-info request, because a TCP connect cannot tell it from a foreign listener on the port.
type Metadata ¶ added in v0.92.0
type Metadata struct{ Relations []Relation }
Metadata is the scanned relations of one source, as the project declares them. A nil *Metadata means the project holds none (the source was never scanned); relations are those of the one name asked for, so an empty one is a scanned source without that name.
type NotFoundError ¶ added in v0.92.0
type NotFoundError struct{ Msg string }
NotFoundError is a link to a table or view that the project's scanned metadata does not list (exit code 3). It names the kind of problem only, never the name asked for.
func (NotFoundError) Error ¶ added in v0.92.0
func (e NotFoundError) Error() string
type Record ¶
type Record struct {
PID int `json:"pid"`
Port int `json:"port"`
URL string `json:"url"`
StartedAt time.Time `json:"startedAt"`
StartedBy string `json:"startedBy"`
Version string `json:"version"`
Binary string `json:"binary"`
IdleTimeout string `json:"idleTimeout"`
}
Record is what the CLI persists about the daemon it started (daemon.json).
type Relation ¶ added in v0.92.0
Relation is one scanned table or view: its schema ("" for a schemaless source), its name and, for a table, its primary-key column names (none when the scan holds no key information).
type Status ¶
type Status struct {
Running bool `json:"running"`
URL string `json:"url"`
UIBase string `json:"uiBase"`
Port int `json:"port"`
PID int `json:"pid"`
StartedBy string `json:"startedBy"`
StartedAt string `json:"startedAt,omitempty"`
Version string `json:"version"`
LogFile string `json:"logFile"`
IdleTimeout string `json:"idleTimeout"`
Error string `json:"error,omitempty"`
}
Status is the machine-readable state printed by `daemon status|start`.
type UsageError ¶
type UsageError struct{ Msg string }
UsageError is a bad `daemon url` input (exit code 2).
func (UsageError) Error ¶
func (e UsageError) Error() string