Documentation
¶
Overview ¶
Package jev is a dependency-free client for the TypeSafe AI System One API and its Jev model.
Jev answers typed questions about a piece of state and returns calibrated probabilities. It generates no text, so every answer is a value your code can branch on directly.
Send state and named questions:
client, err := jev.New(jev.WithAPIKey(os.Getenv(jev.APIKeyEnv)))
if err != nil {
return err
}
response, err := client.SystemOne(ctx, "I was charged twice.", jev.Questions{
"billing": jev.Noul{Instructions: "Is this about billing?"},
})
if err != nil {
return err
}
probability, _ := response.NoulOf("billing")
The three question types are Noul (yes/no), Choice (one label out of many) and Score (a rating against ordered levels). Each has a matching answer type reached through SystemOneResponse.NoulOf, SystemOneResponse.ChoiceOf and SystemOneResponse.ScoreOf.
This is an unofficial client, maintained independently of TypeSafe AI. The wire contract follows https://docs.typesafe.ai/api.
Example ¶
Route a support ticket on three questions asked in one request.
package main
import (
"context"
"fmt"
"log"
jev "github.com/KKloudTarus/taurus-jev-sdk-go"
)
func main() {
client, err := jev.New()
if err != nil {
log.Fatal(err)
}
response, err := client.SystemOne(context.Background(),
map[string]any{"subject": "Duplicate charge", "body": "I was charged twice. Please help."},
jev.Questions{
"billing": jev.Noul{Instructions: "Is this about billing?"},
"tone": jev.Choice{
Instructions: "What is the tone?",
Criteria: map[string]any{"angry": "upset or hostile", "calm": nil},
},
"urgency": jev.Score{
Instructions: "How urgent is this?",
Criteria: []any{"Can wait", "This week", "Today"},
},
})
if err != nil {
log.Fatal(err)
}
if probability, ok := response.NoulOf("billing"); ok && probability > 0.9 {
fmt.Println("route to billing")
}
if tone, ok := response.ChoiceOf("tone"); ok {
fmt.Println("tone:", tone.Choice, "confidence:", tone.Confidence)
}
if urgency, ok := response.ScoreOf("urgency"); ok && urgency.Score > 1.5 {
fmt.Println("escalate")
}
}
Output:
Index ¶
- Constants
- Variables
- func RetryableStatus(status int) bool
- func SystemOneAs[T any](ctx context.Context, client *Client, state any, questions Questions, ...) (T, error)
- type APIError
- type Answer
- type CallOption
- type Choice
- type ChoiceAnswer
- type Client
- func (c Client) GoString() string
- func (c Client) LogValue() slog.Value
- func (c *Client) Models(ctx context.Context, options ...CallOption) ([]Model, error)
- func (c Client) String() string
- func (c *Client) SystemOne(ctx context.Context, state any, questions Questions, options ...CallOption) (*SystemOneResponse, error)
- type ConnectionError
- type Model
- type Noul
- type NoulAnswer
- type NoulCriteria
- type Option
- func WithAPIKey(key string) Option
- func WithBaseURL(baseURL string) Option
- func WithHTTPClient(httpClient *http.Client) Option
- func WithHeader(name, value string) Option
- func WithLogger(logger *slog.Logger) Option
- func WithModel(model string) Option
- func WithRetry(policy RetryPolicy) Option
- func WithTimeout(timeout time.Duration) Option
- type Question
- type Questions
- type RawQuestion
- type ResponseValidationError
- type RetryPolicy
- type Score
- type ScoreAnswer
- type SystemOneResponse
- func (r *SystemOneResponse) ChoiceOf(name string) (ChoiceAnswer, bool)
- func (r *SystemOneResponse) Choices() map[string]ChoiceAnswer
- func (r *SystemOneResponse) NoulOf(name string) (float64, bool)
- func (r *SystemOneResponse) Nouls() map[string]NoulAnswer
- func (r *SystemOneResponse) ScoreOf(name string) (ScoreAnswer, bool)
- func (r *SystemOneResponse) Scores() map[string]ScoreAnswer
- func (r *SystemOneResponse) Unknown() map[string]Answer
- func (r *SystemOneResponse) UnmarshalJSON(data []byte) error
- type Usage
Examples ¶
Constants ¶
const ( AnswerNoul = "noul" AnswerChoice = "choice" AnswerScore = "score" )
Answer types the API defines today. An answer carrying any other type is kept raw rather than rejected.
const ( // DefaultBaseURL is the API root used when none is configured. DefaultBaseURL = "https://api.typesafe.ai" // DefaultModel is the model alias used when none is configured. DefaultModel = "jev-latest" // APIKeyEnv holds the API key. APIKeyEnv = "TYPESAFE_API_KEY" // BaseURLEnv overrides the API root. BaseURLEnv = "TYPESAFE_BASE_URL" // ModelEnv overrides the default model. ModelEnv = "TYPESAFE_DEFAULT_MODEL" )
Wire constants and environment variables.
const DefaultTimeout = 30 * time.Second
DefaultTimeout bounds one HTTP attempt when no timeout is configured.
const Version = "0.1.0"
Version is this client's release, sent in the User-Agent header.
Variables ¶
var ( // ErrNoAPIKey is returned by New when no key is configured. ErrNoAPIKey = errors.New("jev: no API key") // ErrInvalidConfig is returned by New for an unusable option. ErrInvalidConfig = errors.New("jev: invalid configuration") // ErrInvalidRequest marks input rejected before any request is sent. ErrInvalidRequest = errors.New("jev: invalid request") // ErrInvalidResponse marks a success status whose body did not match the // documented schema. ErrInvalidResponse = errors.New("jev: invalid response") // ErrConnection marks a request that never produced an HTTP response. ErrConnection = errors.New("jev: connection failed") // ErrTimeout marks a call that ran out of time. ErrTimeout = errors.New("jev: request timed out") ErrBadRequest = errors.New("jev: bad request") // 400 ErrAuthentication = errors.New("jev: authentication failed") // 401 ErrPermissionDenied = errors.New("jev: permission denied") // 403 ErrNotFound = errors.New("jev: not found") // 404 ErrUnprocessableEntity = errors.New("jev: unprocessable entity") // 422 ErrRateLimit = errors.New("jev: rate limit exceeded") // 429 ErrOverloaded = errors.New("jev: service overloaded") // 529 ErrInternalServer = errors.New("jev: server error") // 5xx )
Sentinel errors for classification with errors.Is. Details live on APIError, ConnectionError and ResponseValidationError, reached with errors.As.
Functions ¶
func RetryableStatus ¶
RetryableStatus reports whether a status is worth retrying: 408, 429 and any 5xx, including the non-standard 529 the API uses for overload.
func SystemOneAs ¶
func SystemOneAs[T any](ctx context.Context, client *Client, state any, questions Questions, options ...CallOption) (T, error)
SystemOneAs answers named questions and decodes the body into T, for a response shape this version does not model or a narrower one you declare yourself. It is a function rather than a method because Go methods take no type parameters.
Example ¶
Decode a response shape this version does not model, such as a field added to the API after this release.
package main
import (
"context"
"fmt"
"log"
jev "github.com/KKloudTarus/taurus-jev-sdk-go"
)
func main() {
client, err := jev.New()
if err != nil {
log.Fatal(err)
}
type response struct {
Model string `json:"model"`
Answers struct {
Spam struct {
Noul float64 `json:"noul"`
} `json:"spam"`
} `json:"answers"`
}
result, err := jev.SystemOneAs[response](context.Background(), client,
"Buy cheap watches now", jev.Questions{"spam": jev.Noul{Instructions: "Is this spam?"}})
if err != nil {
log.Fatal(err)
}
fmt.Println(result.Answers.Spam.Noul > 0.9)
}
Output:
Types ¶
type APIError ¶
type APIError struct {
// Status is the HTTP status code.
Status int
// Message is the server's explanation, extracted from the error body.
Message string
// Body is the response body, truncated to 8 KiB. Any configured credential
// is masked, as in Message.
Body []byte
// RequestID is the x-typesafe-request-id header, empty when absent.
RequestID string
// Endpoint is the method and URL, without credentials or query.
Endpoint string
// RetryAfter is the server's requested wait, zero when not supplied.
RetryAfter time.Duration
}
APIError is an unsuccessful HTTP response. Classify it with errors.Is against the status sentinels, and read the details after errors.As.
Example ¶
Classify a failure before deciding whether to fall back or to fail the request.
package main
import (
"context"
"errors"
"fmt"
"log"
jev "github.com/KKloudTarus/taurus-jev-sdk-go"
)
func main() {
client, err := jev.New()
if err != nil {
log.Fatal(err)
}
_, err = client.SystemOne(context.Background(), "state", jev.Questions{"q": jev.Noul{}})
switch {
case err == nil:
case errors.Is(err, jev.ErrRateLimit), errors.Is(err, jev.ErrOverloaded):
// Retries are already exhausted here; shed load instead.
fmt.Println("degrade to the rule-based path")
case errors.Is(err, jev.ErrAuthentication):
log.Fatal("check TYPESAFE_API_KEY")
case errors.Is(err, jev.ErrTimeout):
fmt.Println("give up on this ticket for now")
default:
var apiErr *jev.APIError
if errors.As(err, &apiErr) {
fmt.Printf("status %d, request %s: %s\n", apiErr.Status, apiErr.RequestID, apiErr.Message)
}
}
}
Output:
func (*APIError) Is ¶
Is reports whether this status matches a sentinel. A 529 matches both ErrOverloaded and ErrInternalServer.
type Answer ¶
type Answer struct {
// Type is the wire discriminator.
Type string
// Noul is set when Type is [AnswerNoul].
Noul *NoulAnswer
// Choice is set when Type is [AnswerChoice].
Choice *ChoiceAnswer
// Score is set when Type is [AnswerScore].
Score *ScoreAnswer
// Raw is the answer object exactly as the server sent it.
Raw json.RawMessage
// contains filtered or unexported fields
}
Answer holds exactly one of Noul, Choice or Score, selected by Type.
An answer whose type this version does not model leaves all three nil and keeps Raw, so a primitive added to the API later does not fail the response your service is already handling. A malformed answer is rejected instead: SystemOneResponse reports it as a ResponseValidationError naming the field, so a broken payload is never mistaken for a future primitive.
func (Answer) MarshalJSON ¶
MarshalJSON writes the answer exactly as the server sent it, so a decoded response round-trips through encoding/json.
func (*Answer) UnmarshalJSON ¶
UnmarshalJSON selects the variant named by the type discriminator. A type this version does not model keeps its bytes in Raw; a malformed payload is recorded and reported by the enclosing response, which knows the question name.
type CallOption ¶
type CallOption interface {
// contains filtered or unexported methods
}
CallOption overrides client configuration for a single call. The interface is closed; use the Using* constructors.
func UsingExtraBody ¶
func UsingExtraBody(fields map[string]any) CallOption
UsingExtraBody merges top-level fields into the request body after state, model and questions are set. Last write wins, and values replace rather than merge. Use it to reach a field this version does not model.
func UsingHeader ¶
func UsingHeader(name, value string) CallOption
UsingHeader adds a header to this call.
func UsingModel ¶
func UsingModel(model string) CallOption
UsingModel overrides the model for this call.
func UsingRetry ¶
func UsingRetry(policy RetryPolicy) CallOption
UsingRetry overrides the retry policy for this call.
func UsingTimeout ¶
func UsingTimeout(timeout time.Duration) CallOption
UsingTimeout bounds each HTTP attempt of this call. The value must be positive. Use RetryPolicy.Budget, or the context, to bound the whole call.
type Choice ¶
type Choice struct {
// Instructions is what the model should decide. Optional.
Instructions any
// Criteria holds the labels to choose between. Required.
Criteria map[string]any
}
Choice selects one label. Criteria maps each label to a description, or to nil for a label interpreted by its name alone.
The number of labels is bounded by the API, not by this client, so a limit raised server side needs no SDK upgrade.
See https://docs.typesafe.ai/primitives/choice.
func (Choice) MarshalJSON ¶
MarshalJSON builds the wire object by hand so an unset field is absent rather than null, while a nil description inside Criteria stays an explicit null.
type ChoiceAnswer ¶
type ChoiceAnswer struct {
// Choice is the label with the highest probability.
Choice string `json:"choice"`
// Confidence in the selection, from 0 to 1.
Confidence float64 `json:"confidence"`
// Probabilities per label, summing to approximately 1.
Probabilities map[string]float64 `json:"probabilities"`
}
ChoiceAnswer is the selected label with the distribution behind it.
func (*ChoiceAnswer) UnmarshalJSON ¶
func (a *ChoiceAnswer) UnmarshalJSON(data []byte) error
UnmarshalJSON rejects a payload missing any required field, so an absent label or confidence is reported rather than decoded as an empty string or a zero probability.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a TypeSafe AI API client. It is safe for concurrent use and should be created once and shared, so connections are pooled.
Its String and LogValue methods mask the API key, so printing or logging a client cannot disclose the credential.
func New ¶
New creates a client. It reads TYPESAFE_API_KEY, TYPESAFE_BASE_URL and TYPESAFE_DEFAULT_MODEL, each overridable by an option.
It returns ErrNoAPIKey when no key is configured and ErrInvalidConfig for an unusable option.
Example (Options) ¶
Tune retries and logging for a request path with a tight latency budget.
package main
import (
"log"
"log/slog"
"os"
"time"
jev "github.com/KKloudTarus/taurus-jev-sdk-go"
)
func main() {
client, err := jev.New(
jev.WithAPIKey(os.Getenv(jev.APIKeyEnv)),
jev.WithModel("jev-latest"),
jev.WithTimeout(2*time.Second),
jev.WithRetry(jev.RetryPolicy{
MaxRetries: 1,
InitialBackoff: 100 * time.Millisecond,
MaxBackoff: time.Second,
Jitter: 0.25,
Budget: 3 * time.Second,
RetryStatus: jev.RetryableStatus,
RespectRetryAfter: true,
RetryConnection: true,
}),
jev.WithLogger(slog.Default()),
)
if err != nil {
log.Fatal(err)
}
_ = client
}
Output:
func (*Client) SystemOne ¶
func (c *Client) SystemOne(ctx context.Context, state any, questions Questions, options ...CallOption) (*SystemOneResponse, error)
SystemOne answers named questions about state.
State is the content every question refers to: a string, or any value that encodes to a JSON object or array. Each answer is keyed by its question name.
Errors are classified with errors.Is against ErrRateLimit, ErrTimeout and the other sentinels; details come from errors.As into *APIError, *ConnectionError or *ResponseValidationError.
type ConnectionError ¶
type ConnectionError struct {
// Endpoint is the method and URL, without credentials or query.
Endpoint string
// Timeout reports whether the failure was a deadline rather than a refusal.
Timeout bool
// contains filtered or unexported fields
}
ConnectionError is a request that never produced an HTTP response.
Every string this type exposes is redacted, including the one reached through Unwrap. The chain stops at a sanitized node, so an error reporter that walks Unwrap cannot reach the raw transport error, while errors.Is and errors.As still see through to it.
func (*ConnectionError) Error ¶
func (e *ConnectionError) Error() string
func (*ConnectionError) Is ¶
func (e *ConnectionError) Is(target error) bool
Is reports whether the target is ErrConnection, or ErrTimeout when the failure was a deadline.
func (*ConnectionError) Unwrap ¶
func (e *ConnectionError) Unwrap() error
Unwrap returns the sanitized transport error. Its message is redacted and it has no Unwrap of its own, so the raw error is not reachable by walking the chain. errors.Is and errors.As still reach the original cause.
type Model ¶
type Model struct {
// Name or alias accepted by a request's model field.
Name string `json:"name"`
// Description of the model and its capabilities.
Description string `json:"description"`
// ReleaseDate formatted as YYYY-MM-DD.
ReleaseDate string `json:"release_date"`
}
Model describes one model available to the account.
type Noul ¶
type Noul struct {
// Instructions is the question or statement to evaluate, as a string, a map
// or a slice. Optional.
Instructions any
// Criteria clarifies the two outcomes. Optional.
Criteria *NoulCriteria
}
Noul asks a yes/no question. The answer is the probability that the statement is true, from 0 to 1.
See https://docs.typesafe.ai/primitives/noul.
func (Noul) MarshalJSON ¶
MarshalJSON builds the wire object by hand so an unset field is absent rather than null; the API reads an explicit null as a supplied value.
type NoulAnswer ¶
type NoulAnswer struct {
// Noul runs from 0 to 1. Values near 0.5 mean the model is undecided.
Noul float64 `json:"noul"`
}
NoulAnswer is the probability that a yes/no statement is true.
func (*NoulAnswer) UnmarshalJSON ¶
func (a *NoulAnswer) UnmarshalJSON(data []byte) error
UnmarshalJSON rejects a payload missing the required field. Decoding into a plain float would turn an absent probability into 0, which reads as a maximally confident no.
type NoulCriteria ¶
NoulCriteria describes what counts as a yes and what counts as a no. Either field may be a string, a map or a slice. Leave a field nil to send nothing.
type Option ¶
type Option func(*Client)
Option configures a Client in New. Explicit options win over environment variables.
func WithAPIKey ¶
WithAPIKey sets the API key, overriding TYPESAFE_API_KEY.
func WithBaseURL ¶
WithBaseURL sets the API root, overriding TYPESAFE_BASE_URL. It must be an absolute https URL, or http for a loopback host, and must carry no credentials, query or fragment.
func WithHTTPClient ¶
WithHTTPClient supplies the HTTP client. The SDK does not close it and does not change its transport, timeout or redirect policy, so a client supplied here is responsible for its own connection pool and for not following a redirect that would carry the Authorization header to another host.
func WithHeader ¶
WithHeader adds a header to every request. Authentication, Accept, the SDK identification headers and the SDK's own retry-count header are set afterwards and cannot be overridden.
func WithLogger ¶
WithLogger enables logging. Requests log at debug, retries at info. Headers are never logged and any configured credential is masked.
func WithRetry ¶
func WithRetry(policy RetryPolicy) Option
WithRetry replaces the retry policy. Use NoRetry to send one attempt.
func WithTimeout ¶
WithTimeout bounds each HTTP attempt. It composes with WithHTTPClient rather than replacing it: the timeout is applied through the request context, so a supplied client keeps its transport, and its own Timeout still applies alongside this one. Use RetryPolicy.Budget to bound a call across its retries.
The value must be positive.
type Questions ¶
Questions maps a name you choose to the question asked under it. The same names key the answers in the response.
type RawQuestion ¶
type RawQuestion struct {
// Type is the wire discriminator. Required.
Type string
// Fields are the remaining members of the question object. A "type" key
// here is ignored in favor of Type.
Fields map[string]any
}
RawQuestion sends a question shape this version does not model, such as a primitive added to the API after this release. Fields are written verbatim alongside the type discriminator.
Its answer arrives with Known() false and its payload in Answer.Raw.
func (RawQuestion) MarshalJSON ¶
func (q RawQuestion) MarshalJSON() ([]byte, error)
MarshalJSON writes Fields verbatim with Type as the discriminator. A "type" key in Fields is ignored, so the discriminator cannot be overwritten.
type ResponseValidationError ¶
type ResponseValidationError struct {
// FieldPath is the dotted path to the offending field, such as
// "answers.tone.confidence". It is empty when the whole body is unusable.
FieldPath string
// Status is the HTTP status code, which was a success.
Status int
// Body is the response body, truncated to 8 KiB and redacted.
Body []byte
// RequestID is the x-typesafe-request-id header, empty when absent.
RequestID string
// Endpoint is the method and URL, without credentials or query.
Endpoint string
// contains filtered or unexported fields
}
ResponseValidationError is a success status whose body did not match the documented schema. FieldPath names the first offending field, so a truncated or degraded response is reported instead of decoding to a zero value.
func (*ResponseValidationError) Error ¶
func (e *ResponseValidationError) Error() string
func (*ResponseValidationError) Is ¶
func (e *ResponseValidationError) Is(target error) bool
Is reports whether the target is ErrInvalidResponse.
type RetryPolicy ¶
type RetryPolicy struct {
// MaxRetries is the number of retries after the initial attempt.
MaxRetries int
// InitialBackoff is the first delay, doubled each attempt up to MaxBackoff.
// Zero disables backoff.
InitialBackoff time.Duration
// MaxBackoff caps every delay between attempts, including one a server asks
// for through retry-after. Zero disables backoff.
MaxBackoff time.Duration
// Jitter is the fraction of each delay randomly subtracted, from 0 to 1. It
// applies to a server-supplied wait as well, so callers that received the
// same retry-after do not wake at the same instant.
Jitter float64
// Budget is the total wall-clock allowance for one call including delays.
// Zero disables the limit. An attempt is not started when the delay before
// it would exhaust the budget.
Budget time.Duration
// RetryStatus reports whether a status code should be retried. Nil retries
// no status.
RetryStatus func(status int) bool
// RespectRetryAfter honors the retry-after and retry-after-ms headers,
// clamped by MaxBackoff and jittered.
RespectRetryAfter bool
// RetryConnection retries a request that produced no HTTP response.
RetryConnection bool
}
RetryPolicy controls how a failed attempt is retried. The zero value retries nothing; start from DefaultRetry and adjust.
func DefaultRetry ¶
func DefaultRetry() RetryPolicy
DefaultRetry retries 408, 429 and 5xx twice, plus connection failures, with jittered exponential backoff from 500ms to 5s and a 30s total budget.
type Score ¶
type Score struct {
// Instructions is what the model should rate. Optional.
Instructions any
// Criteria holds the ordered level descriptions. Required, at least one.
Criteria []any
}
Score rates the state against ordered levels. A level's position is its score, counting from zero.
See https://docs.typesafe.ai/primitives/score.
func (Score) MarshalJSON ¶
MarshalJSON builds the wire object by hand so an unset field is absent rather than null.
type ScoreAnswer ¶
type ScoreAnswer struct {
// Score is the probability-weighted average level, so it may fall between
// two integer levels.
Score float64 `json:"score"`
// Confidence in the score, from 0 to 1.
Confidence float64 `json:"confidence"`
// Legend maps each level to the criterion that defined it.
Legend map[int]any `json:"legend"`
// Probabilities per level, summing to approximately 1.
Probabilities map[int]float64 `json:"probabilities"`
}
ScoreAnswer is the expected score with the rubric it was scored against.
Legend and Probabilities are keyed by integer level. The wire format sends those keys as JSON strings; encoding/json converts them back.
func (*ScoreAnswer) UnmarshalJSON ¶
func (a *ScoreAnswer) UnmarshalJSON(data []byte) error
UnmarshalJSON rejects a payload missing any required field, so an absent score or rubric is reported rather than decoded as zero.
type SystemOneResponse ¶
type SystemOneResponse struct {
// Model that answered, which may differ from the alias that was requested.
Model string `json:"model"`
// Answers keyed by question name.
Answers map[string]Answer `json:"answers"`
// Usage for this evaluation.
Usage Usage `json:"usage"`
// RequestID is the x-typesafe-request-id header. Quote it in a support
// report.
RequestID string `json:"-"`
// Status is the HTTP status code the response arrived with.
Status int `json:"-"`
// Header is the response header, for values this version does not model.
Header http.Header `json:"-"`
// RawBody is the response body exactly as it arrived.
RawBody json.RawMessage `json:"-"`
}
SystemOneResponse holds one answer per question, keyed by the names supplied in the request.
func (*SystemOneResponse) ChoiceOf ¶
func (r *SystemOneResponse) ChoiceOf(name string) (ChoiceAnswer, bool)
ChoiceOf returns the choice answer for a question. The second result is false when the name is absent or answered by another primitive.
Example ¶
Confidence is the point of a System One model: a low-confidence answer is a signal to ask a person rather than to guess.
package main
import (
"fmt"
jev "github.com/KKloudTarus/taurus-jev-sdk-go"
)
func main() {
var response *jev.SystemOneResponse // from client.SystemOne
tone, ok := response.ChoiceOf("tone")
switch {
case !ok:
fmt.Println("no answer for that question")
case tone.Confidence < 0.6:
fmt.Println("uncertain, send to a human reviewer")
default:
fmt.Println("acting on", tone.Choice)
}
}
Output:
func (*SystemOneResponse) Choices ¶
func (r *SystemOneResponse) Choices() map[string]ChoiceAnswer
Choices returns every choice answer, keyed by question name.
func (*SystemOneResponse) NoulOf ¶
func (r *SystemOneResponse) NoulOf(name string) (float64, bool)
NoulOf returns the probability for a yes/no question. The second result is false when the name is absent or answered by another primitive.
func (*SystemOneResponse) Nouls ¶
func (r *SystemOneResponse) Nouls() map[string]NoulAnswer
Nouls returns every yes/no answer, keyed by question name.
func (*SystemOneResponse) ScoreOf ¶
func (r *SystemOneResponse) ScoreOf(name string) (ScoreAnswer, bool)
ScoreOf returns the score answer for a question. The second result is false when the name is absent or answered by another primitive.
func (*SystemOneResponse) Scores ¶
func (r *SystemOneResponse) Scores() map[string]ScoreAnswer
Scores returns every score answer, keyed by question name.
func (*SystemOneResponse) Unknown ¶
func (r *SystemOneResponse) Unknown() map[string]Answer
Unknown returns every answer whose type this version does not model, keyed by question name. Their payloads are available through Answer.Raw.
func (*SystemOneResponse) UnmarshalJSON ¶
func (r *SystemOneResponse) UnmarshalJSON(data []byte) error
UnmarshalJSON enforces the fields the API documents as required, so a truncated or degraded body is reported rather than decoded into zero values.