Files
talk/internal/api/types.go
T

154 lines
5.2 KiB
Go
Raw Normal View History

package api
// Request/response types of the daemon HTTP contract (binding fields). The
// CLI and other consumers (MCP) use the same types: one source, no contract
// drift between daemon and client.
// SpeakRequest is the body of POST /speak.
type SpeakRequest struct {
// Text is the announcement text (required).
Text string `json:"text"`
// Priority: low | normal | high (default normal when empty).
Priority string `json:"priority,omitempty"`
// Provider pins the provider chain (--provider).
Provider string `json:"provider,omitempty"`
// Voice pins a voice ID (--voice).
Voice string `json:"voice,omitempty"`
// Lang pins the language de | en (empty = automatic detection).
Lang string `json:"lang,omitempty"`
// Now lets the announcement jump ahead of all waiting ones (--now).
Now bool `json:"now,omitempty"`
}
// SpeakResponse is the response of POST /speak: 202 {"id":"..."}; with mute
// active 202 {"id":"","muted":true} (announcement discarded; documented
// behaviour, not an error). Discarded spam is reported just as
// documented: 202 {"id":"","discarded":"rate_limit"|"quiet_hours"}, plus
// "toast":true when the quiet-hours announcement was replaced by a
// notification (quiet_mode = "toast").
type SpeakResponse struct {
ID string `json:"id"`
Muted bool `json:"muted,omitempty"`
// Discarded is the discard reason ("rate_limit" | "quiet_hours"); empty
// when the announcement was admitted.
Discarded string `json:"discarded,omitempty"`
// Toast reports the replacement by a notification.
Toast bool `json:"toast,omitempty"`
// Truncated reports that the text was cut to queue.max_text and
// admitted that way (the law against read-aloud long answers).
Truncated bool `json:"truncated,omitempty"`
}
// CurrentItem describes the running item in GET /status.
type CurrentItem struct {
ID string `json:"id"`
Text string `json:"text"`
Priority string `json:"priority"`
Now bool `json:"now"`
}
// StatusResponse is the response of GET /status: queue length, current item
// (null when idle), mute state, active provider, daemon version. QueueIDs
// lists the waiting IDs in processing order; the CLI needs them for its
// --wait polling. The law state (rate_limit, quiet_hours) and mcp/cors
// (compat fields: MCP endpoint present, configured CORS origins) are
// additive.
type StatusResponse struct {
Version string `json:"version"`
Queue int `json:"queue"`
QueueIDs []string `json:"queue_ids,omitempty"`
Current *CurrentItem `json:"current"`
Muted bool `json:"muted"`
Provider string `json:"provider"`
RateLimit *RateLimitState `json:"rate_limit,omitempty"`
QuietHours *QuietHoursState `json:"quiet_hours,omitempty"`
Limits *LimitsState `json:"limits,omitempty"`
// MCP reports that the daemon offers the MCP endpoint (always true; the
// field exists for an additive compat view of clients/browsers).
MCP bool `json:"mcp"`
// Cors is the configured CORS allow list of POST /speak (empty [] =
// door closed). Always present (even when empty), not omitempty.
Cors []string `json:"cors"`
}
// RateLimitState is the rate-limit state in GET /status.
type RateLimitState struct {
// Interval is the configured minimum spacing as a duration string
// ("30s"; "0s" = unlimited).
Interval string `json:"interval"`
// AllowHighBurst reports whether priority=high may violate it.
AllowHighBurst bool `json:"allow_high_burst"`
// NextSlot is the next free announcement slot as an RFC3339 timestamp;
// null when playback would be allowed immediately (or unlimited).
NextSlot *string `json:"next_slot"`
}
// LimitsState holds the length and age laws in GET /status.
type LimitsState struct {
// MaxText is the upper bound of the announcement length in characters
// (0 = unlimited).
MaxText int `json:"max_text"`
// MaxAge is the longest wait in the queue as a duration string ("2m0s";
// "0s" = unlimited).
MaxAge string `json:"max_age"`
}
// QuietHoursState is the quiet-hours state in GET /status.
type QuietHoursState struct {
// Window is the configured window ("18:00-08:00"; "" = disabled).
Window string `json:"window"`
// Active reports whether local time is currently inside the window.
Active bool `json:"active"`
// Mode is the configured quiet-hours mode ("discard" | "toast").
Mode string `json:"mode"`
// Until is the window end as an RFC3339 timestamp when active;
// otherwise null.
Until *string `json:"until"`
}
// PendingOrCurrent reports whether the announcement with the ID is still
// waiting or currently playing; the basis of the CLI's --wait polling. If
// it is neither waiting nor playing, it is done (or cancelled); in both
// cases the caller has nothing left to wait for.
func (s StatusResponse) PendingOrCurrent(id string) bool {
if s.Current != nil && s.Current.ID == id {
return true
}
for _, qid := range s.QueueIDs {
if qid == id {
return true
}
}
return false
}
// CancelResponse is the response of POST /cancel.
type CancelResponse struct {
Cancelled int `json:"cancelled"`
}
// MuteResponse is the response of POST /mute and POST /unmute.
type MuteResponse struct {
Muted bool `json:"muted"`
}
// ShutdownResponse is the response of POST /shutdown.
type ShutdownResponse struct {
OK bool `json:"ok"`
}