Documentation
¶
Index ¶
- Constants
- Variables
- type AuthorizedCommand
- type BoxMediaHandler
- type BoxMediaHandlerOptions
- type BoxMediaLocalTranscriber
- type BoxMediaRuleOptions
- type BoxMediaTLSConfig
- type BoxMediaTLSRuntime
- type BoxMediaTLSServer
- type BoxMediaTranscript
- type Bridge
- type BridgeOptions
- type ClaimDecision
- type ClaimKey
- type ClaimLedger
- type Denial
- type DeviceBindingOptions
- type DurableClaimLedger
- func (l *DurableClaimLedger) Claim(ctx context.Context, key ClaimKey, digest [32]byte, now time.Time) (ClaimDecision, error)
- func (l *DurableClaimLedger) Complete(ctx context.Context, key ClaimKey, digest [32]byte, result StoredResult, ...) error
- func (l *DurableClaimLedger) Lookup(ctx context.Context, key ClaimKey, now time.Time) (ClaimDecision, error)
- func (l *DurableClaimLedger) MarkIndeterminate(ctx context.Context, key ClaimKey, digest [32]byte, reason string, ...) error
- type HomeAssistant
- type HomeAssistantClient
- type HomeAssistantDispatchError
- type HomeAssistantOptions
- type HomeAssistantResult
- type HomeAssistantTarget
- type Policy
- type RuleOptions
- type StoredResult
- type TTSSynthesizer
- type TurnExecutionError
- type TurnRequest
- type TurnResult
Constants ¶
const ( BoxMediaTurnPath = "/v1/box-media/turn" BoxMediaDeviceIDHeader = "X-SpeechKit-Device-ID" BoxMediaPairingIDHeader = "X-SpeechKit-Pairing-ID" BoxMediaRequestIDHeader = "X-SpeechKit-Request-ID" BoxMediaInputSHA256Header = "X-SpeechKit-Input-Audio-SHA256" BoxMediaOutputSHA256Header = "X-SpeechKit-Output-Audio-SHA256" BoxMediaReplayHeader = "X-SpeechKit-Replayed" )
const ( ClaimDispatchNew = "dispatch_new" ClaimReplayCompleted = "replay_completed" ClaimIndeterminate = "indeterminate" ClaimDigestConflict = "digest_conflict" ClaimNotFound = "not_found" )
const ( ActionTurnOn = "turn_on" ActionTurnOff = "turn_off" ExpectedStateOn = "on" ExpectedStateOff = "off" PolicyErrorCodeDenied = "local_policy_denied" PolicyReasonRuleNotFound = "local_rule_not_found" PolicyReasonDeviceMismatch = "local_rule_device_mismatch" PolicyReasonRoomMismatch = "local_rule_room_mismatch" PolicyReasonTimeInvalid = "local_rule_time_invalid" PolicyReasonNotYetValid = "local_rule_not_yet_valid" PolicyReasonExpired = "local_rule_expired" PolicyReasonTextMismatch = "local_rule_text_mismatch" PolicyReasonLocaleMismatch = "local_rule_locale_mismatch" )
Variables ¶
var ( ErrBoxMediaBridgeRequired = errors.New("box media: device-agent bridge is required") ErrBoxMediaLocalSTTRequired = errors.New("box media: a proven local-only STT transcriber is required") ErrBoxMediaTokenInvalid = errors.New("box media: an independent pairing token is required") ErrBoxMediaRuleInvalid = errors.New("box media: the single transcript mapping is invalid") )
var ( ErrPolicyRuleInvalid = errors.New("device-agent local policy: invalid rule") ErrPolicyRuleDuplicate = errors.New("device-agent local policy: duplicate rule id") )
Functions ¶
This section is empty.
Types ¶
type AuthorizedCommand ¶
type AuthorizedCommand struct {
RuleID string `json:"rule_id"`
Utterance string `json:"utterance"`
Locale string `json:"locale"`
EntityID string `json:"entity_id"`
ExpectedState string `json:"expected_state"`
}
AuthorizedCommand is assembled exclusively from the configured rule after every binding has matched. Utterance is the canonical server-owned trigger, never the caller-provided string.
type BoxMediaHandler ¶
type BoxMediaHandler struct {
// contains filtered or unexported fields
}
BoxMediaHandler accepts one complete L16 turn over a dedicated HTTPS listener. It is intentionally not mounted by Bridge.Mount, keeping the existing exactly-four speechkit.device_agent.v1 routes unchanged.
func NewBoxMediaHandler ¶
func NewBoxMediaHandler(opts BoxMediaHandlerOptions) (*BoxMediaHandler, error)
func (*BoxMediaHandler) ServeHTTP ¶
func (h *BoxMediaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
type BoxMediaHandlerOptions ¶
type BoxMediaHandlerOptions struct {
Bridge *Bridge
LocalSTT BoxMediaLocalTranscriber
MediaPairingToken string
Rule BoxMediaRuleOptions
STTTimeout time.Duration
TurnTimeout time.Duration
}
type BoxMediaLocalTranscriber ¶
type BoxMediaLocalTranscriber interface {
LocalOnly() bool
TranscribeLocal(context.Context, []byte, string) (*BoxMediaTranscript, error)
}
BoxMediaLocalTranscriber deliberately differs from the general STT router: LocalOnly must attest that this dependency has no cloud or dynamic fallback. Production wiring passes the router's concrete Local() provider directly.
type BoxMediaRuleOptions ¶
type BoxMediaRuleOptions struct {
DeviceID string
PairingID string
RoomID string
Transcript string
CommandID string
Locale string
}
BoxMediaRuleOptions defines exactly one server-owned transcript-to-command mapping for the Phase-A representative light. There is no rule collection, fuzzy matching, search, intent inference, or fallback.
type BoxMediaTLSConfig ¶
BoxMediaTLSConfig is the explicit bootstrap contract for the dedicated Box listener. Certificate provisioning is intentionally out of scope: the host supplies an existing absolute-path key pair, and the Box must separately pin the issuing local CA. There is no plaintext listener or HTTP redirect mode.
type BoxMediaTLSRuntime ¶
type BoxMediaTLSRuntime struct {
// contains filtered or unexported fields
}
func (*BoxMediaTLSRuntime) Addr ¶
func (r *BoxMediaTLSRuntime) Addr() net.Addr
func (*BoxMediaTLSRuntime) Errors ¶
func (r *BoxMediaTLSRuntime) Errors() <-chan error
type BoxMediaTLSServer ¶
type BoxMediaTLSServer struct {
// contains filtered or unexported fields
}
BoxMediaTLSServer owns only the exact Box media handler. It never mounts the general SpeechKit mux, device-agent v1 routes, MCP, Gateway, or proxy paths.
func NewBoxMediaTLSServer ¶
func NewBoxMediaTLSServer(config BoxMediaTLSConfig, handler http.Handler) (*BoxMediaTLSServer, error)
func (*BoxMediaTLSServer) Start ¶
func (s *BoxMediaTLSServer) Start(ctx context.Context) (*BoxMediaTLSRuntime, error)
Start binds synchronously so configuration, certificate, and port failures are returned before any caller can claim the endpoint is available.
type BoxMediaTranscript ¶
BoxMediaTranscript is the bounded result returned by the host's local STT dependency. Provider identifies the local implementation for evidence only; it is never returned to the Box.
type Bridge ¶
type Bridge struct {
// contains filtered or unexported fields
}
func NewBridge ¶
func NewBridge(opts BridgeOptions) (*Bridge, error)
func (*Bridge) ExecuteTurn ¶
func (b *Bridge) ExecuteTurn(ctx context.Context, request TurnRequest) (*TurnResult, error)
ExecuteTurn runs the real, durable local HA G0 plus claim-bound TTS path without opening another authority surface. It deliberately reuses the existing v1 handlers in-process; the four public speechkit.device_agent.v1 routes and their JSON contracts remain unchanged.
type BridgeOptions ¶
type BridgeOptions struct {
ServerInstanceID string
Bindings []DeviceBindingOptions
HomeAssistant HomeAssistant
TTS TTSSynthesizer
TTSReady bool
Claims ClaimLedger
Policy *Policy
MaxRequestAge time.Duration
FutureSkew time.Duration
ProbeTimeout time.Duration
StateVerifyTimeout time.Duration
Now func() time.Time
}
type ClaimDecision ¶
type ClaimDecision struct {
Disposition string
Result *StoredResult
}
type ClaimLedger ¶
type ClaimLedger interface {
Claim(context.Context, ClaimKey, [32]byte, time.Time) (ClaimDecision, error)
Lookup(context.Context, ClaimKey, time.Time) (ClaimDecision, error)
Complete(context.Context, ClaimKey, [32]byte, StoredResult, time.Time) error
MarkIndeterminate(context.Context, ClaimKey, [32]byte, string, time.Time) error
}
ClaimLedger is a durable at-most-once ledger. Claim must commit a new row before returning ClaimDispatchNew. Implementations must never turn an existing nonterminal claim back into a dispatch decision.
type Denial ¶
type Denial struct {
ErrorCode string `json:"error_code"`
ReasonCode string `json:"reason_code"`
UserGuidance string `json:"user_guidance"`
}
Denial is the stable fail-closed reason envelope returned for every request that does not match one active local rule exactly.
type DeviceBindingOptions ¶
type DurableClaimLedger ¶
type DurableClaimLedger struct {
// contains filtered or unexported fields
}
DurableClaimLedger adapts the single-purpose SQLite ledger to the bridge contract. Handles exist only for claims won by this process; after a restart every previously nonterminal claim remains indeterminate and cannot be dispatched again.
func NewDurableClaimLedger ¶
func NewDurableClaimLedger(store *claimstore.Ledger) (*DurableClaimLedger, error)
func (*DurableClaimLedger) Claim ¶
func (l *DurableClaimLedger) Claim(ctx context.Context, key ClaimKey, digest [32]byte, now time.Time) (ClaimDecision, error)
func (*DurableClaimLedger) Complete ¶
func (l *DurableClaimLedger) Complete(ctx context.Context, key ClaimKey, digest [32]byte, result StoredResult, now time.Time) error
func (*DurableClaimLedger) Lookup ¶
func (l *DurableClaimLedger) Lookup(ctx context.Context, key ClaimKey, now time.Time) (ClaimDecision, error)
type HomeAssistant ¶
type HomeAssistantClient ¶
type HomeAssistantClient struct {
// contains filtered or unexported fields
}
func NewHomeAssistantClient ¶
func NewHomeAssistantClient(opts HomeAssistantOptions) (*HomeAssistantClient, error)
func (*HomeAssistantClient) Converse ¶
func (c *HomeAssistantClient) Converse(ctx context.Context, text, locale string) (*HomeAssistantResult, error)
func (*HomeAssistantClient) VerifyState ¶
func (c *HomeAssistantClient) VerifyState(ctx context.Context, entityID, expectedState string) error
VerifyState reads the documented Home Assistant state resource from the already-validated origin and proves both the entity identity and exact state.
type HomeAssistantDispatchError ¶
type HomeAssistantDispatchError struct {
ReasonCode string
Retryable bool
ActionExecuted string // no | unknown
Cause error
}
HomeAssistantDispatchError carries only stable bridge classification. It deliberately excludes response bodies and credentials from Error().
func (*HomeAssistantDispatchError) Error ¶
func (e *HomeAssistantDispatchError) Error() string
func (*HomeAssistantDispatchError) Unwrap ¶
func (e *HomeAssistantDispatchError) Unwrap() error
type HomeAssistantOptions ¶
type HomeAssistantResult ¶
type HomeAssistantResult struct {
ConversationID string
ResponseType string
Speech string
Language string
SuccessTargets []HomeAssistantTarget
FailedTargets []HomeAssistantTarget
ErrorCode string
ReasonCode string
ActionExecuted string // yes | no | not_applicable | unknown
}
type HomeAssistantTarget ¶
type HomeAssistantTarget struct {
Name string `json:"name"`
Type string `json:"type"`
ID string `json:"id,omitempty"`
}
HomeAssistantTarget is the documented target projection returned in the Conversation API response data.success and data.failed arrays.
type Policy ¶
type Policy struct {
// contains filtered or unexported fields
}
Policy is immutable after construction and therefore safe for concurrent authorization checks. An empty or nil Policy denies every request.
func NewPolicy ¶
func NewPolicy(options ...RuleOptions) (*Policy, error)
NewPolicy validates and copies a static local allowlist. Only reversible Tier-1 light turn_on/turn_off rules are accepted.
func (*Policy) Authorize ¶
func (p *Policy) Authorize(deviceID, roomID, ruleID, clientText, locale string, now time.Time) (AuthorizedCommand, *Denial)
Authorize resolves one request against one explicitly named local rule. It performs no NLP, fuzzy matching, intent inference, fallback, or rule search. A nil Denial means the command is authorized; otherwise the zero command is returned and callers must not dispatch an action.
type RuleOptions ¶
type RuleOptions struct {
RuleID string
DeviceID string
RoomID string
TriggerText string
Locale string
Action string
EntityID string
NotBefore time.Time
ExpiresAt time.Time
}
RuleOptions defines one static, server-owned G0 authorization rule. A rule is a local per-request allowlist entry, not a Workbench approval, Cloud standing grant, delegated identity, or federation capability.
type StoredResult ¶
type TTSSynthesizer ¶
type TurnExecutionError ¶
type TurnExecutionError struct {
StatusCode int
Envelope wire.ErrorEnvelope
}
TurnExecutionError preserves the stable error/reason/guidance envelope from the existing device-agent bridge when an in-process adapter executes a turn.
func (*TurnExecutionError) Error ¶
func (e *TurnExecutionError) Error() string
type TurnRequest ¶
type TurnRequest struct {
RequestID string
SessionID string
CommandID string
DeviceID string
PairingID string
RoomID string
PairingToken string
Text string
Locale string
InputSHA256 string
}
TurnRequest is the authenticated, host-side execution contract used by bounded media ingress adapters. PairingToken is consumed only for a constant-time binding check and is never serialized or returned.
InputSHA256 is optional for existing non-media callers. A media adapter must supply the lowercase digest it independently verified over the exact input bytes. The digest joins the durable HA claim, preventing a request ID from being reused with different audio.
type TurnResult ¶
type TurnResult struct {
Assist wire.AssistResponse
Audio []byte
Format string
SampleRate int
DurationMS int64
Provider string
Voice string
}
TurnResult combines the existing durable Home Assistant result with the existing claim-bound local TTS result. Audio is the validated provider payload returned by the v1 TTS implementation (currently WAV); media adapters remain responsible for their own final wire encoding.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package claimstore provides the durable at-most-once request ledger used by the local SpeechKit to Home Assistant bridge.
|
Package claimstore provides the durable at-most-once request ledger used by the local SpeechKit to Home Assistant bridge. |