thalovant

package module
v0.3.4 Latest Latest
Warning

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

Go to latest
Published: Aug 14, 2026 License: MIT Imports: 28 Imported by: 0

README

Thalovant Go SDK

Go SDK for connecting services, CLIs, devices, and agents to Thalovant hubs.

The control API is used to discover hubs and provision a client identity. After that, the SDK talks directly to the hub data plane over HTTPS, WSS, or MQTTS.

Full docs: https://docs.thalovant.com/developers/sdks/go/

What You Need

  • A Thalovant account with API access for authenticated control-plane actions.
  • A hub id or slug.
  • A client identity for that hub. You can create one through the API or use one downloaded from the dashboard.

Install

Use Go 1.25 or newer so the SDK receives supported upstream networking security fixes.

go get github.com/thalovant/thalovant-go-sdk

Quick Start

package main

import (
	"context"
	"fmt"

	thalovant "github.com/thalovant/thalovant-go-sdk"
)

func main() {
	ctx := context.Background()
	control := thalovant.NewDefaultControlPlane("")

	// Public hub discovery does not require auth.
	publicHubs, err := control.ListPublicHubs(ctx, 12, "")
	if err != nil {
		panic(err)
	}
	for _, raw := range publicHubs["data"].([]any) {
		hub := raw.(map[string]any)
		fmt.Println(hub["id"], hub["slug"], hub["title"])
	}

	// Auth is required when creating a client identity.
	if _, err := control.Login(ctx, "you@example.com", "password", ""); err != nil {
		panic(err)
	}

	result, err := control.CreateClientIdentityForHubID(ctx, "hub-id", thalovant.BootstrapIdentityOptions{
		Name:               "go-demo-client",
		PreferredProtocols: []thalovant.HubProtocol{thalovant.ProtocolWSS, thalovant.ProtocolHTTPS, thalovant.ProtocolMQTT},
	})
	if err != nil {
		panic(err)
	}

	client, err := thalovant.NewClientWithOptions(result.Identity, thalovant.ClientOptions{
		Protocol: thalovant.ProtocolWSS,
	})
	if err != nil {
		panic(err)
	}
	defer client.Close(ctx)

	info, err := client.ConnectWithInfo(ctx)
	if err != nil {
		panic(err)
	}
	fmt.Println("connected in", info.ConnectMS, "ms")

	reply, err := client.Ask(ctx, "Tell me a short clean joke.", thalovant.RequestOptions{})
	if err != nil {
		panic(err)
	}
	fmt.Println(reply.Text)
}

NewDefaultControlPlane uses https://api.thalovant.com. Use NewControlPlane only for local development or a self-hosted control plane.

Login With MFA

Accounts with multi-factor authentication enabled are rejected with HTTP 401 {"code": "mfa_required"} by a plain Login call. Use LoginWithOptions to pass a TOTP code, or a recovery code when the authenticator is unavailable:

control := thalovant.NewDefaultControlPlane("")

// With a TOTP code from an authenticator app.
_, err := control.LoginWithOptions(ctx, "you@example.com", "password", thalovant.LoginOptions{
	OTPCode: "123456",
})

// Or with a one-time recovery code.
_, err = control.LoginWithOptions(ctx, "you@example.com", "password", thalovant.LoginOptions{
	RecoveryCode: "your-recovery-code",
})

LoginOptions.Scope matches the scope argument of Login. Empty fields are omitted from the request body, so LoginWithOptions with a zero-value LoginOptions behaves exactly like Login without a scope.

Sign In With the Browser (Device Flow)

Accounts without a password (for example Google sign-in) use the device flow. LoginWithBrowser prints a verification URL and a short user code, opens the browser on a best-effort basis, and polls until you approve the request:

control := thalovant.NewDefaultControlPlane("")

token, err := control.LoginWithBrowser(ctx, thalovant.DeviceLoginOptions{
	Scopes:     []string{"hubs:read", "clients:write"}, // optional
	ClientName: "my-cli",                               // optional label in the dashboard
})
if err != nil {
	panic(err)
}
fmt.Println("signed in, token id:", token["token_id"])

On approval the returned access_token is a durable scoped API token; it is stored on control.AccessToken exactly like Login, so subsequent control-plane calls are authenticated. The server may expand the echoed scopes during normalization.

Options:

  • OpenBrowser: *bool, defaults to true when nil. Set it to a false pointer on headless hosts; the plain verification URL and code are always shown.
  • Prompt: func(grant map[string]any) replaces the default stdout message. The grant carries verification_uri, user_code, and verification_uri_complete.
  • Timeout: total approval wait, 15 minutes when zero.

Failures are distinct sentinel errors: errors.Is(err, thalovant.ErrDeviceAccessDenied) when the request is denied in the browser, thalovant.ErrDeviceCodeExpired when the code expires unapproved (call LoginWithBrowser again for a new code), and thalovant.ErrTimeout when the wait elapses. Context cancellation is honored between polls.

CI: Direct API Token Auth

Non-interactive environments should skip login entirely and construct the control plane with a pre-provisioned API token, such as one issued by LoginWithBrowser on a workstation:

control := thalovant.NewDefaultControlPlane(os.Getenv("THALOVANT_API_TOKEN"))

page, err := control.ListHubs(ctx, 50, "", "")

ControlPlane.AccessToken is an exported field, so an existing instance can also be pointed at a token directly: control.AccessToken = token.

Keep result.Identity secret. It contains the client credentials used by the hub. Do not log result.Summary(true).

List Your Hubs

Authenticated accounts can list owned or visible hubs:

control := thalovant.NewDefaultControlPlane("")
_, _ = control.Login(ctx, "you@example.com", "password", "")

page, err := control.ListHubs(ctx, 50, "", "")
if err != nil {
	panic(err)
}
for _, raw := range page["data"].([]any) {
	hub := raw.(map[string]any)
	fmt.Println(hub["id"], hub["slug"], hub["title"])
}

Workspace Analytics

Authenticated accounts can read the same overview used by the dashboard:

overview, err := control.GetAnalyticsOverview(ctx, thalovant.AnalyticsOverviewOptions{
	Range: "7d",
	HubID: "hub-id",
})
if err != nil {
	panic(err)
}
fmt.Println(overview["totals"])

Durable Memory

Private Daily Desk and workspace assistants can manage explicit opt-in memory:

memory, err := control.CreateMemoryItem(ctx, map[string]any{
	"scope":   "workspace",
	"kind":    "preference",
	"content": "Prefer America/Toronto for scheduling.",
	"tags":    []string{"timezone"},
})
if err != nil {
	panic(err)
}
fmt.Println(memory["id"])

items, err := control.ListMemoryItems(ctx, thalovant.MemoryListOptions{
	Scope: "workspace",
	Query: "timezone",
})
if err != nil {
	panic(err)
}
fmt.Println(items["data"])

Use An Existing Identity

For local development, store one or more identities in the protected SDK config:

mkdir -p ~/.config/thalovant
chmod 700 ~/.config/thalovant
$EDITOR ~/.config/thalovant/config.yaml
chmod 600 ~/.config/thalovant/config.yaml
profile: prod
profiles:
  prod:
    identity:
      access_key: ...
      password: ...
      site_id: demo-agent
      default_master: https://jokes.thalovant.io
      data_plane_endpoints:
        wss: wss://jokes.thalovant.io/public
        https: https://jokes.thalovant.io/public
        mqtt: mqtts://mqtt.thalovant.com:8883
      mqtt:
        endpoint: mqtts://mqtt.thalovant.com:8883
        username: ...
        password: ...
        topic_prefix: hubs/hub-id/clients/client-id
        tls: true
client, err := thalovant.NewClientFromConfig("", "prod")
if err != nil {
	panic(err)
}
defer client.Close(ctx)

reply, err := client.Ask(ctx, "What can this hub do?", thalovant.RequestOptions{})
if err != nil {
	panic(err)
}
fmt.Println(reply.Text)

SDKs reject config files that are readable or writable by other users on Linux and macOS. Keep this file out of git.

Raw identity files are supported too:

client, err := thalovant.NewClientFromFile("_identity.json")

Environment variables are supported too:

client, err := thalovant.NewClientFromEnv()

Protocols

Hubs may expose one or more public data-plane protocols:

  • wss: secure realtime WebSocket, the default public path and SDK preference.
  • https: request/response HTTP protocol exposed as HTTPS.
  • mqtt: broker-mediated MQTT over TLS. Requires per-client broker credentials.

Inspect what an identity supports:

identity := result.Identity

fmt.Println(identity.EnabledProtocols())
fmt.Println(identity.EndpointFor(thalovant.ProtocolWSS))
fmt.Println(identity.EndpointFor(thalovant.ProtocolHTTPS))
fmt.Println(identity.EndpointFor(thalovant.ProtocolMQTT))
if identity.MQTT != nil {
	fmt.Println(identity.MQTT.Endpoint)
}

Connect with a specific protocol:

for _, protocol := range []thalovant.HubProtocol{
	thalovant.ProtocolWSS,
	thalovant.ProtocolHTTPS,
	thalovant.ProtocolMQTT,
} {
	if !identity.SupportsProtocol(protocol) {
		continue
	}
	if protocol == thalovant.ProtocolMQTT && identity.MQTT == nil {
		continue
	}

	client, err := thalovant.NewClientWithOptions(identity, thalovant.ClientOptions{Protocol: protocol})
	if err != nil {
		panic(err)
	}
	reply, err := client.Ask(ctx, fmt.Sprintf("Reply over %s.", protocol), thalovant.RequestOptions{})
	_ = client.Close(ctx)
	if err != nil {
		panic(err)
	}
	fmt.Println(protocol, reply.Text)
}

Use client.ConnectWithInfo(ctx) when you need connection telemetry for benchmarks or health dashboards. The returned snapshot includes phase, socket/open time, handshake time, total connect time, and last error.

Use client.Query(ctx, ...) for the direct HiveMind query frame path when the hub supports it. It avoids broad bus fanout and is the preferred request/reply API for low-latency app integrations.

reply, err := client.Query(ctx, "What time is it in Toronto?", thalovant.QueryOptions{})

MQTT identities include a broker endpoint, username, password, TLS flag, and topic prefix. The broker credentials are scoped to that client and should be treated like a password. Public identities should use mqtts://; the SDK also honors an explicit tls: true flag from the identity.

Conversations

Use a conversation when related turns should share one session.

conversation := client.Conversation(thalovant.ConversationOptions{Lang: "en-us"})

first, err := conversation.Ask(ctx, "Remember that my favorite color is blue.", thalovant.RequestOptions{})
if err != nil {
	panic(err)
}
second, err := conversation.Ask(ctx, "What color did I mention?", thalovant.RequestOptions{})
if err != nil {
	panic(err)
}

fmt.Println(first.Text)
fmt.Println(second.Text)

Client Context

Context lets skills know which app, device, user, or channel made the request.

requestContext := thalovant.BuildClientContext(nil, thalovant.ClientContextOptions{
	UserID:       "user-42",
	UserName:     "Ada",
	AuthProvider: "oidc",
	Roles:        []string{"member"},
	Platform:     "kiosk",
	Source:       "checkout-kiosk",
	Channel:      "chat",
})

reply, err := client.Ask(ctx, "Show the next instruction.", thalovant.RequestOptions{
	Context: requestContext,
})

Actions And Exact Inputs

Use actions for button payloads and codes for exact typed or scanned values.

conversation := client.Conversation(thalovant.ConversationOptions{SessionID: "work-session"})

_ = conversation.SendAction(ctx, `/choose{"id":"42"}`, thalovant.ActionOptions{Title: "Choose item"})
_ = conversation.SendCode(ctx, "SN-001-XYZ", thalovant.CodeOptions{Kind: "qr", Label: "serial"})

Rich Responses

Replies can include text, choices, tables, images, or attachments.

items := reply.DisplayItems(600)
for _, item := range items {
	if item.Kind == "text" {
		fmt.Println(item.Text)
	}
}

Common Issues

  • missing access token: call control.Login(...) or control.LoginWithBrowser(...) before private control-plane actions, or pass an access token to NewControlPlane.
  • HTTP 401 with "code": "mfa_required": the account has MFA enabled; use control.LoginWithOptions(...) with an OTPCode or RecoveryCode.
  • The account has no password (Google sign-in): use control.LoginWithBrowser(...), or mint a durable token once and pass it to NewDefaultControlPlane in CI.
  • API access requires a paid plan: upgrade the workspace before using the SDK control-plane API to provision private resources.
  • unsupported protocol: the hub does not expose that protocol, or the identity was created before that protocol was enabled.
  • MQTT fails immediately: create or download a fresh client identity after MQTT is enabled. MQTT needs the per-client Identity.MQTT credentials.
  • A request times out: set RequestOptions{Timeout: ...}.
  • HTTP 429 with "code": "token_rate_limited": the API token exceeded its plan's per-minute request rate (60 requests per minute on the free plan). The response carries a Retry-After header and a matching retry_after_seconds; wait that long and resend.
  • HTTP 429 with "code": "token_quota_exceeded": the API token exhausted its plan's daily or monthly call quota. The body names which in quota (daily or monthly) alongside limit and used, and Retry-After points at the next UTC day or month boundary.

Both 429s apply to token-authenticated control-plane calls and are returned as errors wrapping ErrAPI, with the status and response body in the message. The SDK does not retry automatically: Retry-After is authoritative, so honor it before resending. Per-plan limits are listed in the dashboard and at https://docs.thalovant.com/developers/sdks/go/.

API Shape

  • NewDefaultControlPlane(accessToken)
  • NewControlPlane(apiURL, accessToken) for local or self-hosted control planes
  • control.Login(ctx, email, password, scope)
  • control.LoginWithOptions(ctx, email, password, LoginOptions{Scope: ..., OTPCode: ..., RecoveryCode: ...})
  • control.LoginWithBrowser(ctx, DeviceLoginOptions{Scopes: ..., ClientName: ..., OpenBrowser: ..., Prompt: ..., Timeout: ...})
  • control.ListPublicHubs(ctx, limit, cursor)
  • control.GetPublicHub(ctx, hubRef)
  • control.ListHubs(ctx, limit, cursor, ownerID)
  • control.GetHub(ctx, hubID)
  • control.GetOperation(ctx, operationID)
  • control.GetAnalyticsOverview(ctx, options)
  • control.ListMemoryItems(ctx, options)
  • control.GetMemorySummary(ctx, ownerID)
  • control.CreateMemoryItem(ctx, payload)
  • control.GetMemoryItem(ctx, memoryID)
  • control.UpdateMemoryItem(ctx, memoryID, payload)
  • control.DeleteMemoryItem(ctx, memoryID)
  • control.CreateClientIdentityForHubID(ctx, hubID, options)
  • IdentityFromConfig(path, profile)
  • IdentityFromFile(path)
  • NewClientFromConfig(path, profile)
  • NewClientFromFile(path)
  • NewClientFromEnv()
  • NewClientWithOptions(identity, ClientOptions{Protocol: ...})
  • client.ConnectWithInfo(ctx)
  • client.ConnectionInfo()
  • client.Query(ctx, text, options)
  • client.Ask(ctx, text, options)
  • client.SendUtterance(ctx, text, options)
  • client.SendAction(ctx, payload, options)
  • client.SendCode(ctx, value, options)
  • client.Conversation(options)

Development

go test ./...

Documentation

Index

Constants

View Source
const (
	EventRecognizerLoopUtterance = "recognizer_loop:utterance"
	EventSpeak                   = "speak"
	EventOvosUtteranceSpeak      = "ovos.utterance.speak"
	EventUtteranceHandled        = "ovos.utterance.handled"
	EventIntentFailure           = "complete_intent_failure"
	EventPolicyDenied            = "hive.policy.denied"
	EventQueryTimeout            = "hive.query.timeout"
	DefaultUserAgent             = "ThalovantGoSDK/0.3.4"
)
View Source
const (
	DefaultControlAPIURL    = "https://api.thalovant.com"
	DefaultControlUserAgent = "ThalovantGoSDK/0.3.4"

	// DefaultDeviceLoginTimeout bounds how long LoginWithBrowser waits for the
	// user to approve the sign-in request in the browser.
	DefaultDeviceLoginTimeout = 15 * time.Minute
)
View Source
const DefaultConfigFilename = "config.yaml"

Variables

View Source
var (
	ErrIdentity   = errors.New("thalovant identity error")
	ErrConnection = errors.New("thalovant connection error")
	ErrTimeout    = errors.New("thalovant timeout")
	ErrRuntime    = errors.New("thalovant runtime error")
	ErrAPI        = errors.New("thalovant api error")
	ErrProtocol   = errors.New("thalovant unsupported protocol")

	// ErrDeviceAccessDenied reports that the browser device sign-in request
	// was denied by the user.
	ErrDeviceAccessDenied = errors.New("thalovant device sign-in denied")
	// ErrDeviceCodeExpired reports that the device sign-in code expired
	// before it was approved.
	ErrDeviceCodeExpired = errors.New("thalovant device sign-in code expired")
)
View Source
var DefaultProtocolPreference = []HubProtocol{ProtocolWSS, ProtocolHTTPS, ProtocolMQTT}

Functions

func DecryptBinary added in v0.2.5

func DecryptBinary(key string, payload []byte) ([]byte, error)

func DecryptFromJSON

func DecryptFromJSON(key string, raw string) (string, error)

func DefaultConfigPath added in v0.2.11

func DefaultConfigPath() (string, error)

func EncodeHiveBinaryFrame added in v0.2.5

func EncodeHiveBinaryFrame(message HiveMessage) ([]byte, error)

func EncryptAsBinary added in v0.2.5

func EncryptAsBinary(key string, plaintext []byte) ([]byte, error)

func EncryptAsJSON

func EncryptAsJSON(key string, plaintext string) (string, error)

func EndpointFromDomain added in v0.2.1

func EndpointFromDomain(domain string, protocol HubProtocol) string

func EventMatchesContext

func EventMatchesContext(event Event, expected Context) bool

func NewRequestID

func NewRequestID() string

func NewSessionID

func NewSessionID() string

func RequestIDFromContext

func RequestIDFromContext(context Context) string

func RichMediaFromData

func RichMediaFromData(data Data) map[string]any

func RuntimeCryptoKey

func RuntimeCryptoKey(raw string) []byte

func SessionIDFromContext

func SessionIDFromContext(context Context) string

func StripSSML

func StripSSML(text string) string

Types

type ActionOptions

type ActionOptions struct {
	Title     string
	Lang      string
	Context   Context
	SessionID string
	RequestID string
}

type AnalyticsOverviewOptions added in v0.2.13

type AnalyticsOverviewOptions struct {
	Admin     bool
	Range     string
	Bucket    string
	OwnerID   string
	HubID     string
	ClientID  string
	Country   string
	Message   string
	Utterance string
	Intent    string
	TimeStart string
	TimeEnd   string
	Weekday   *int
	Hour      *int
}

type BootstrapIdentityOptions added in v0.2.2

type BootstrapIdentityOptions struct {
	Name               string
	SiteID             string
	Spec               map[string]any
	OwnerID            string
	Active             *bool
	PreferredProtocols []HubProtocol
	IdempotencyKey     string
}

type BootstrapIdentityResult added in v0.2.2

type BootstrapIdentityResult struct {
	Identity Identity
	Hub      map[string]any
	Client   map[string]any
	Endpoint *SelectedHubEndpoint
}

func (BootstrapIdentityResult) SelectedProtocol added in v0.2.2

func (r BootstrapIdentityResult) SelectedProtocol() HubProtocol

func (BootstrapIdentityResult) Summary added in v0.2.2

func (r BootstrapIdentityResult) Summary(includeSecrets bool) map[string]any

type Client

type Client struct {
	Identity       Identity
	Transport      RuntimeTransport
	ConnectTimeout time.Duration
}

func NewClient

func NewClient(identity Identity) *Client

func NewClientFromConfig added in v0.2.11

func NewClientFromConfig(path string, profile string) (*Client, error)

func NewClientFromEnv

func NewClientFromEnv() (*Client, error)

func NewClientFromFile

func NewClientFromFile(path string) (*Client, error)

func NewClientWithOptions added in v0.2.2

func NewClientWithOptions(identity Identity, opts ClientOptions) (*Client, error)

func (*Client) Ask

func (c *Client) Ask(ctx context.Context, text string, opts RequestOptions) (Reply, error)

func (*Client) Close

func (c *Client) Close(ctx context.Context) error

func (*Client) Connect

func (c *Client) Connect(ctx context.Context) error

func (*Client) ConnectWithInfo added in v0.2.14

func (c *Client) ConnectWithInfo(ctx context.Context) (TransportConnectionInfo, error)

func (*Client) ConnectionInfo added in v0.2.14

func (c *Client) ConnectionInfo() TransportConnectionInfo

func (*Client) Conversation

func (c *Client) Conversation(opts ConversationOptions) Conversation

func (*Client) Emit

func (c *Client) Emit(ctx context.Context, eventType string, data Data, eventContext Context) error

func (*Client) Healthcheck

func (c *Client) Healthcheck() TransportHealth

func (*Client) Query added in v0.2.15

func (c *Client) Query(ctx context.Context, text string, opts QueryOptions) (Reply, error)

func (*Client) SendAction

func (c *Client) SendAction(ctx context.Context, payload string, opts ActionOptions) error

func (*Client) SendCode

func (c *Client) SendCode(ctx context.Context, value string, opts CodeOptions) error

func (*Client) SendUtterance

func (c *Client) SendUtterance(ctx context.Context, text string, opts RequestOptions) error

type ClientContextOptions

type ClientContextOptions struct {
	UserID       string
	UserName     string
	AuthToken    string
	AuthProvider string
	AuthClaims   map[string]any
	Roles        []string
	Platform     string
	Source       string
	Destination  string
	Channel      string
	DeviceID     string
	Locale       string
	Metadata     map[string]any
	SessionID    string
}

type ClientOptions added in v0.2.2

type ClientOptions struct {
	Protocol       HubProtocol
	ConnectTimeout time.Duration
}

type CodeOptions

type CodeOptions struct {
	Kind      string
	Label     string
	Lang      string
	Context   Context
	SessionID string
	RequestID string
}

type Context

type Context map[string]any

func BuildClientContext

func BuildClientContext(base Context, opts ClientContextOptions) Context

func ContextWithCorrelation

func ContextWithCorrelation(raw Context, sessionID, siteID, lang, requestID string) Context

func MergeContext

func MergeContext(base, extra Context) Context

type ControlPlane added in v0.2.2

type ControlPlane struct {
	APIURL      string
	AccessToken string
	UserAgent   string
	HTTPClient  *http.Client
}

func NewControlPlane added in v0.2.2

func NewControlPlane(apiURL string, accessToken string) *ControlPlane

func NewDefaultControlPlane added in v0.2.8

func NewDefaultControlPlane(accessToken string) *ControlPlane

func (*ControlPlane) CreateClient added in v0.2.2

func (c *ControlPlane) CreateClient(ctx context.Context, payload map[string]any, idempotencyKey string) (map[string]any, error)

func (*ControlPlane) CreateClientIdentity added in v0.2.2

func (c *ControlPlane) CreateClientIdentity(ctx context.Context, hub map[string]any, opts BootstrapIdentityOptions) (BootstrapIdentityResult, error)

func (*ControlPlane) CreateClientIdentityForHubID added in v0.2.2

func (c *ControlPlane) CreateClientIdentityForHubID(ctx context.Context, hubID string, opts BootstrapIdentityOptions) (BootstrapIdentityResult, error)

func (*ControlPlane) CreateMemoryItem added in v0.2.13

func (c *ControlPlane) CreateMemoryItem(ctx context.Context, payload map[string]any) (map[string]any, error)

func (*ControlPlane) DeleteMemoryItem added in v0.2.13

func (c *ControlPlane) DeleteMemoryItem(ctx context.Context, memoryID string) error

func (*ControlPlane) GetAnalyticsOverview added in v0.2.13

func (c *ControlPlane) GetAnalyticsOverview(ctx context.Context, opts AnalyticsOverviewOptions) (map[string]any, error)

func (*ControlPlane) GetHub added in v0.2.2

func (c *ControlPlane) GetHub(ctx context.Context, hubID string) (map[string]any, error)

func (*ControlPlane) GetMemoryItem added in v0.2.13

func (c *ControlPlane) GetMemoryItem(ctx context.Context, memoryID string) (map[string]any, error)

func (*ControlPlane) GetMemorySummary added in v0.2.13

func (c *ControlPlane) GetMemorySummary(ctx context.Context, ownerID string) (map[string]any, error)

func (*ControlPlane) GetOperation added in v0.2.16

func (c *ControlPlane) GetOperation(ctx context.Context, operationID string) (OperationResource, error)

func (*ControlPlane) GetPublicHub added in v0.2.6

func (c *ControlPlane) GetPublicHub(ctx context.Context, hubRef string) (map[string]any, error)

func (*ControlPlane) ListHubs added in v0.2.2

func (c *ControlPlane) ListHubs(ctx context.Context, limit int, cursor string, ownerID string) (map[string]any, error)

func (*ControlPlane) ListMemoryItems added in v0.2.13

func (c *ControlPlane) ListMemoryItems(ctx context.Context, opts MemoryListOptions) (map[string]any, error)

func (*ControlPlane) ListPublicHubs added in v0.2.6

func (c *ControlPlane) ListPublicHubs(ctx context.Context, limit int, cursor string) (map[string]any, error)

func (*ControlPlane) Login added in v0.2.2

func (c *ControlPlane) Login(ctx context.Context, email string, password string, scope string) (map[string]any, error)

func (*ControlPlane) LoginWithBrowser added in v0.3.3

func (c *ControlPlane) LoginWithBrowser(ctx context.Context, opts DeviceLoginOptions) (map[string]any, error)

LoginWithBrowser signs in through the browser device flow and stores the returned API token. This is the sign-in path for accounts without a password (for example Google sign-in). It requests a device authorization, tells the user to visit verification_uri and enter the short user_code (set DeviceLoginOptions.Prompt to present it yourself), opens the browser at verification_uri_complete on a best-effort basis unless DeviceLoginOptions.OpenBrowser is false, and polls until the request is approved, denied, expired, the timeout elapses, or ctx is cancelled.

On approval the returned access_token is a durable scoped API token and is stored on ControlPlane.AccessToken exactly like Login. Denial, expiry, and timeout are reported as ErrDeviceAccessDenied, ErrDeviceCodeExpired, and ErrTimeout respectively.

func (*ControlPlane) LoginWithOptions added in v0.3.2

func (c *ControlPlane) LoginWithOptions(ctx context.Context, email string, password string, opts LoginOptions) (map[string]any, error)

func (*ControlPlane) RequireRuntimeProtocol added in v0.2.2

func (c *ControlPlane) RequireRuntimeProtocol(result BootstrapIdentityResult, protocol HubProtocol) (*SelectedHubEndpoint, error)

func (*ControlPlane) UpdateMemoryItem added in v0.2.13

func (c *ControlPlane) UpdateMemoryItem(ctx context.Context, memoryID string, payload map[string]any) (map[string]any, error)

type Conversation

type Conversation struct {
	Client  *Client
	Options ConversationOptions
}

func (Conversation) Ask

func (c Conversation) Ask(ctx context.Context, text string, opts RequestOptions) (Reply, error)

func (Conversation) Query added in v0.2.15

func (c Conversation) Query(ctx context.Context, text string, opts QueryOptions) (Reply, error)

func (Conversation) SendAction

func (c Conversation) SendAction(ctx context.Context, payload string, opts ActionOptions) error

func (Conversation) SendCode

func (c Conversation) SendCode(ctx context.Context, value string, opts CodeOptions) error

func (Conversation) SendUtterance

func (c Conversation) SendUtterance(ctx context.Context, text string, opts RequestOptions) error

type ConversationOptions

type ConversationOptions struct {
	SessionID string
	Lang      string
	Context   Context
}

type Data

type Data map[string]any

func UtterancePayload

func UtterancePayload(text, lang string) Data

type DeviceLoginOptions added in v0.3.3

type DeviceLoginOptions struct {
	Scopes      []string
	ClientName  string
	OpenBrowser *bool
	Prompt      func(grant map[string]any)
	Timeout     time.Duration
}

DeviceLoginOptions carries optional device-flow sign-in inputs for LoginWithBrowser. Scopes and ClientName are forwarded to the device authorization request when set; the server may expand the echoed scopes during normalization. OpenBrowser defaults to true when nil. Prompt, when set, receives the device authorization payload instead of the default message printed to stdout. Timeout bounds the whole approval wait and defaults to DefaultDeviceLoginTimeout when zero.

type DisplayItem

type DisplayItem struct {
	Kind    string
	Text    string
	Data    any
	Title   string
	Payload string
	URL     string
	Silent  bool
}

func DisplayItemsFromEventData

func DisplayItemsFromEventData(data Data, eventName string, maxTextChars int) []DisplayItem

type Event

type Event struct {
	Name    string
	Data    Data
	Context Context
	Raw     any
}

func (Event) DisplayItems

func (e Event) DisplayItems(maxTextChars int) []DisplayItem

func (Event) DisplayText

func (e Event) DisplayText() string

func (Event) IsFailure

func (e Event) IsFailure() bool

func (Event) RequestID

func (e Event) RequestID() string

func (Event) RichMedia

func (e Event) RichMedia() map[string]any

func (Event) SessionID

func (e Event) SessionID() string

func (Event) Text

func (e Event) Text() string

func (Event) Utterances

func (e Event) Utterances() []string

type HTTPTransport

type HTTPTransport struct {
	Identity     Identity
	UserAgent    string
	PollInterval time.Duration
	HTTPClient   *http.Client
	BusEvents    chan Event
	HiveEvents   chan HiveMessage
	// contains filtered or unexported fields
}

func NewHTTPTransport

func NewHTTPTransport(identity Identity) *HTTPTransport

func (*HTTPTransport) Authorization

func (t *HTTPTransport) Authorization() string

func (*HTTPTransport) BaseURL

func (t *HTTPTransport) BaseURL() string

func (*HTTPTransport) Connect

func (t *HTTPTransport) Connect(ctx context.Context) error

func (*HTTPTransport) ConnectionInfo added in v0.2.14

func (t *HTTPTransport) ConnectionInfo() TransportConnectionInfo

func (*HTTPTransport) Disconnect

func (t *HTTPTransport) Disconnect(ctx context.Context) error

func (*HTTPTransport) EmitBus

func (t *HTTPTransport) EmitBus(ctx context.Context, eventType string, data Data, eventContext Context) error

func (*HTTPTransport) Events added in v0.2.4

func (t *HTTPTransport) Events() <-chan Event

func (*HTTPTransport) Healthcheck

func (t *HTTPTransport) Healthcheck() TransportHealth

func (*HTTPTransport) HiveMessages added in v0.2.15

func (t *HTTPTransport) HiveMessages() <-chan HiveMessage

func (*HTTPTransport) IsHandshakeComplete

func (t *HTTPTransport) IsHandshakeComplete() bool

func (*HTTPTransport) PollOnce

func (t *HTTPTransport) PollOnce(ctx context.Context) error

func (*HTTPTransport) SendHiveMessage added in v0.2.15

func (t *HTTPTransport) SendHiveMessage(ctx context.Context, message HiveMessage, encrypt bool) error

type HiveMessage

type HiveMessage struct {
	MsgType      string         `json:"msg_type"`
	Payload      map[string]any `json:"payload"`
	Metadata     map[string]any `json:"metadata"`
	Route        []any          `json:"route"`
	Node         any            `json:"node"`
	TargetSiteID any            `json:"target_site_id"`
	TargetPubKey any            `json:"target_pubkey"`
	SourcePeer   any            `json:"source_peer"`
}

func DecodeHiveBinaryFrame added in v0.2.5

func DecodeHiveBinaryFrame(payload []byte) (HiveMessage, error)

type HubDataPlaneEndpoints added in v0.2.1

type HubDataPlaneEndpoints struct {
	HTTPS string `json:"https,omitempty"`
	WSS   string `json:"wss,omitempty"`
	MQTT  string `json:"mqtt,omitempty"`
}

func DataPlaneEndpointsFromHub added in v0.2.1

func DataPlaneEndpointsFromHub(hub map[string]any) HubDataPlaneEndpoints

func DataPlaneEndpointsFromMap added in v0.2.1

func DataPlaneEndpointsFromMap(values map[string]any) HubDataPlaneEndpoints

func (HubDataPlaneEndpoints) EndpointFor added in v0.2.1

func (e HubDataPlaneEndpoints) EndpointFor(protocol HubProtocol) string

func (HubDataPlaneEndpoints) HTTPBase added in v0.2.1

func (e HubDataPlaneEndpoints) HTTPBase(fallbackMaster string, fallbackPort int, fallbackPath string) string

func (HubDataPlaneEndpoints) Map added in v0.2.1

func (e HubDataPlaneEndpoints) Map(redactCredentials bool) map[string]string

type HubProtocol added in v0.2.1

type HubProtocol string
const (
	ProtocolWSS   HubProtocol = "wss"
	ProtocolHTTPS HubProtocol = "https"
	ProtocolMQTT  HubProtocol = "mqtt"
)

type HubProtocolSettings added in v0.2.1

type HubProtocolSettings struct {
	WSS  bool `json:"wss"`
	HTTP bool `json:"http"`
	MQTT bool `json:"mqtt"`
}

func DefaultHubProtocolSettings added in v0.2.1

func DefaultHubProtocolSettings() HubProtocolSettings

func ProtocolSettingsFromMap added in v0.2.1

func ProtocolSettingsFromMap(values map[string]any) HubProtocolSettings

func (HubProtocolSettings) EnabledProtocols added in v0.2.1

func (s HubProtocolSettings) EnabledProtocols() []HubProtocol

func (HubProtocolSettings) IsEnabled added in v0.2.1

func (s HubProtocolSettings) IsEnabled(protocol HubProtocol) bool

func (HubProtocolSettings) SpecMap added in v0.2.1

func (s HubProtocolSettings) SpecMap() map[string]any

type Identity

type Identity struct {
	AccessKey          string                 `json:"access_key"`
	Password           string                 `json:"password"`
	CryptoKey          string                 `json:"crypto_key,omitempty"`
	SiteID             string                 `json:"site_id"`
	DefaultMaster      string                 `json:"default_master"`
	DefaultPort        int                    `json:"default_port"`
	DefaultPath        string                 `json:"default_path,omitempty"`
	PublicKey          string                 `json:"public_key,omitempty"`
	Metadata           map[string]any         `json:"metadata,omitempty"`
	DataPlaneEndpoints HubDataPlaneEndpoints  `json:"data_plane_endpoints,omitempty"`
	Protocols          HubProtocolSettings    `json:"protocols,omitempty"`
	MQTT               *MqttBrokerCredentials `json:"mqtt,omitempty"`
}

func IdentityFromConfig added in v0.2.11

func IdentityFromConfig(path string, profile string) (Identity, error)

func IdentityFromEnv

func IdentityFromEnv(prefix string) (Identity, error)

func IdentityFromFile

func IdentityFromFile(path string) (Identity, error)

func IdentityFromMap

func IdentityFromMap(values map[string]any) (Identity, error)

func (Identity) EnabledProtocols added in v0.2.1

func (i Identity) EnabledProtocols() []HubProtocol

func (Identity) EndpointBase

func (i Identity) EndpointBase() string

func (Identity) EndpointFor added in v0.2.1

func (i Identity) EndpointFor(protocol HubProtocol) string

func (Identity) Summary

func (i Identity) Summary() map[string]any

func (Identity) SupportsProtocol added in v0.2.1

func (i Identity) SupportsProtocol(protocol HubProtocol) bool

type LoginOptions added in v0.3.2

type LoginOptions struct {
	Scope        string
	OTPCode      string
	RecoveryCode string
}

LoginOptions carries optional login inputs. Scope overrides the default token scopes. OTPCode and RecoveryCode satisfy an MFA challenge; the API rejects MFA-enabled accounts with HTTP 401 {"code": "mfa_required"} when neither is provided.

type MQTTTransport added in v0.2.4

type MQTTTransport struct {
	Identity   Identity
	UserAgent  string
	Topics     MqttTopicSet
	BusEvents  chan Event
	HiveEvents chan HiveMessage
	// contains filtered or unexported fields
}

func NewMQTTTransport added in v0.2.4

func NewMQTTTransport(identity Identity) (*MQTTTransport, error)

func (*MQTTTransport) Connect added in v0.2.4

func (t *MQTTTransport) Connect(ctx context.Context) error

func (*MQTTTransport) ConnectionInfo added in v0.2.14

func (t *MQTTTransport) ConnectionInfo() TransportConnectionInfo

func (*MQTTTransport) Disconnect added in v0.2.4

func (t *MQTTTransport) Disconnect(ctx context.Context) error

func (*MQTTTransport) EmitBus added in v0.2.4

func (t *MQTTTransport) EmitBus(ctx context.Context, eventType string, data Data, eventContext Context) error

func (*MQTTTransport) Events added in v0.2.4

func (t *MQTTTransport) Events() <-chan Event

func (*MQTTTransport) Healthcheck added in v0.2.4

func (t *MQTTTransport) Healthcheck() TransportHealth

func (*MQTTTransport) HiveMessages added in v0.2.15

func (t *MQTTTransport) HiveMessages() <-chan HiveMessage

func (*MQTTTransport) IsHandshakeComplete added in v0.2.4

func (t *MQTTTransport) IsHandshakeComplete() bool

func (*MQTTTransport) SendHiveMessage added in v0.2.15

func (t *MQTTTransport) SendHiveMessage(ctx context.Context, message HiveMessage, encrypt bool) error

type MemoryListOptions added in v0.2.13

type MemoryListOptions struct {
	Scope          string
	Kind           string
	OwnerID        string
	HubID          string
	Query          string
	IncludeDeleted bool
	IncludeExpired bool
	Limit          int
	Offset         int
}

type MqttBrokerCredentials added in v0.2.3

type MqttBrokerCredentials struct {
	Endpoint    string `json:"endpoint"`
	Username    string `json:"username"`
	Password    string `json:"password"`
	TopicPrefix string `json:"topic_prefix,omitempty"`
	HubID       string `json:"hub_id,omitempty"`
	C2STopic    string `json:"c2s_topic,omitempty"`
	S2CTopic    string `json:"s2c_topic,omitempty"`
	StatusTopic string `json:"status_topic,omitempty"`
	HashTopics  bool   `json:"hash_topics,omitempty"`
	QOS         byte   `json:"qos,omitempty"`
	TLS         bool   `json:"tls"`
}

func MqttBrokerCredentialsFromMap added in v0.2.3

func MqttBrokerCredentialsFromMap(raw any) *MqttBrokerCredentials

func (MqttBrokerCredentials) Map added in v0.2.3

func (m MqttBrokerCredentials) Map(includeSecrets bool) map[string]any

type MqttTopicSet added in v0.2.4

type MqttTopicSet struct {
	C2S    string
	S2C    string
	Status string
}

func MQTTTopicsForIdentity added in v0.2.4

func MQTTTopicsForIdentity(identity Identity) (MqttTopicSet, error)

type OperationResource added in v0.2.16

type OperationResource struct {
	ID            string             `json:"id"`
	Kind          string             `json:"kind"`
	AggregateType string             `json:"aggregate_type"`
	AggregateID   *string            `json:"aggregate_id"`
	Status        OperationStatus    `json:"status"`
	Details       map[string]any     `json:"details"`
	GitCommitSHA  *string            `json:"git_commit_sha"`
	ErrorCode     *string            `json:"error_code"`
	ErrorMessage  *string            `json:"error_message"`
	CreatedAt     string             `json:"created_at"`
	UpdatedAt     string             `json:"updated_at"`
	CommittedAt   *string            `json:"committed_at"`
	AppliedAt     *string            `json:"applied_at"`
	ReadyAt       *string            `json:"ready_at"`
	TerminalAt    *string            `json:"terminal_at"`
	Links         map[string]*string `json:"links"`
}

type OperationStatus added in v0.2.16

type OperationStatus string
const (
	OperationRequested OperationStatus = "requested"
	OperationCommitted OperationStatus = "committed"
	OperationApplied   OperationStatus = "applied"
	OperationReady     OperationStatus = "ready"
	OperationFailed    OperationStatus = "failed"
	OperationTimedOut  OperationStatus = "timed_out"
)

type QueryOptions added in v0.2.15

type QueryOptions struct {
	Timeout   time.Duration
	Lang      string
	Context   Context
	SessionID string
	RequestID string
	QueryID   string
}

type Reply

type Reply struct {
	Text         string
	Utterances   []string
	Handled      bool
	OK           bool
	SessionID    string
	RequestID    string
	Events       []Event
	FailureEvent *Event
}

func (Reply) DisplayItems

func (r Reply) DisplayItems(maxTextChars int) []DisplayItem

func (Reply) DisplayText

func (r Reply) DisplayText() string

type RequestOptions

type RequestOptions struct {
	Timeout   time.Duration
	Lang      string
	Context   Context
	SessionID string
	RequestID string
}

type RuntimeTransport added in v0.2.4

type RuntimeTransport interface {
	Connect(ctx context.Context) error
	Disconnect(ctx context.Context) error
	Healthcheck() TransportHealth
	ConnectionInfo() TransportConnectionInfo
	EmitBus(ctx context.Context, eventType string, data Data, eventContext Context) error
	Events() <-chan Event
}

type SelectedHubEndpoint added in v0.2.2

type SelectedHubEndpoint struct {
	Protocol HubProtocol `json:"protocol"`
	Endpoint string      `json:"endpoint"`
}

func SelectDataPlaneEndpoint added in v0.2.2

func SelectDataPlaneEndpoint(endpoints HubDataPlaneEndpoints, protocols HubProtocolSettings, preferred []HubProtocol) *SelectedHubEndpoint

type TransportConnectionInfo added in v0.2.14

type TransportConnectionInfo struct {
	Phase           TransportConnectionPhase `json:"phase"`
	StartedAt       time.Time                `json:"started_at,omitempty"`
	ConnectedAt     time.Time                `json:"connected_at,omitempty"`
	TransportOpenMS float64                  `json:"transport_open_ms,omitempty"`
	SocketOpenMS    float64                  `json:"socket_open_ms,omitempty"`
	HandshakeMS     float64                  `json:"handshake_ms,omitempty"`
	ConnectMS       float64                  `json:"connect_ms,omitempty"`
	LastError       string                   `json:"last_error,omitempty"`
}

type TransportConnectionPhase added in v0.2.14

type TransportConnectionPhase string
const (
	ConnectionIdle       TransportConnectionPhase = "idle"
	ConnectionConnecting TransportConnectionPhase = "connecting"
	ConnectionHandshake  TransportConnectionPhase = "handshake"
	ConnectionReady      TransportConnectionPhase = "ready"
	ConnectionClosed     TransportConnectionPhase = "closed"
	ConnectionError      TransportConnectionPhase = "error"
)

type TransportHealth

type TransportHealth struct {
	Connected         bool
	HandshakeComplete bool
	TransportAlive    bool
	LastError         string
	Connection        TransportConnectionInfo
}

type WSSTransport added in v0.2.4

type WSSTransport struct {
	Identity   Identity
	UserAgent  string
	BusEvents  chan Event
	HiveEvents chan HiveMessage
	// contains filtered or unexported fields
}

func NewWSSTransport added in v0.2.4

func NewWSSTransport(identity Identity) *WSSTransport

func (*WSSTransport) Authorization added in v0.2.4

func (t *WSSTransport) Authorization() string

func (*WSSTransport) Connect added in v0.2.4

func (t *WSSTransport) Connect(ctx context.Context) error

func (*WSSTransport) ConnectionInfo added in v0.2.14

func (t *WSSTransport) ConnectionInfo() TransportConnectionInfo

func (*WSSTransport) Disconnect added in v0.2.4

func (t *WSSTransport) Disconnect(_ context.Context) error

func (*WSSTransport) EmitBus added in v0.2.4

func (t *WSSTransport) EmitBus(ctx context.Context, eventType string, data Data, eventContext Context) error

func (*WSSTransport) Events added in v0.2.4

func (t *WSSTransport) Events() <-chan Event

func (*WSSTransport) Healthcheck added in v0.2.4

func (t *WSSTransport) Healthcheck() TransportHealth

func (*WSSTransport) HiveMessages added in v0.2.15

func (t *WSSTransport) HiveMessages() <-chan HiveMessage

func (*WSSTransport) IsHandshakeComplete added in v0.2.4

func (t *WSSTransport) IsHandshakeComplete() bool

func (*WSSTransport) SendHiveMessage added in v0.2.15

func (t *WSSTransport) SendHiveMessage(ctx context.Context, message HiveMessage, encrypt bool) error

Jump to

Keyboard shortcuts

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