output

package
v0.1.0-rc.1 Latest Latest
Warning

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

Go to latest
Published: Apr 19, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package output renders catalog.Row values into the spec §4 JSON envelope.

The full envelope always carries the same keys (null when absent); preset trimming is applied by stripping keys before encoding. The rendering path is allocation-conscious but not micro-optimized — the hot path in M1 is the single-row lookup, not streaming output.

Index

Constants

This section is empty.

Variables

View Source
var ErrDropped = errors.New("output: row dropped by preset filter")

ErrDropped signals that Pipeline intentionally emitted nothing — e.g. an aggregated row with IncludeAggregated=false. Callers should skip the row without treating this as a fatal error.

Functions

func ApplyFields

func ApplyFields(doc map[string]any, expr string) map[string]any

ApplyFields projects doc down to the requested comma-separated dot paths. Paths are split on `.`; numeric segments index into `[]any`. Missing paths are silently dropped. When multiple paths share a prefix they merge into the same parent. An empty expression returns doc unchanged.

func ApplyJQ

func ApplyJQ(doc any, expr string) (any, error)

ApplyJQ runs a gojq expression against doc. Zero iterator outputs return nil; one returns that value directly; multiple return a `[]any` of all results. Parse/runtime errors are wrapped with a "jq:" prefix.

func EmitDryRun

func EmitDryRun(w io.Writer, p DryRunPlan) error

EmitDryRun writes the stable dry-run envelope to w.

func EmitEstimate

func EmitEstimate(w io.Writer, r estimate.Result, opts Options) error

EmitEstimate writes the result as JSON/YAML/TOML per Options.Format. For TOML, the envelope is re-wrapped as { "rows": items, ... } per the repo TOML convention (CLAUDE.md "TOML quirks").

func Encode

func Encode(doc any, format string, pretty bool) ([]byte, error)

Encode serializes doc to the requested format.

  • "json" / "": compact by default, indented when pretty. Always terminated with a single newline.
  • "yaml": yaml.v3 marshal; pretty is a no-op (yaml is always formatted). yaml.v3 already emits a trailing newline so we do not add another.
  • "toml": go-toml/v2. TOML cannot represent a top-level array, so any slice-typed doc is wrapped as {"rows": doc} before marshaling.

Unknown formats return an error.

func EncodeEnvelope

func EncodeEnvelope(w io.Writer, env Envelope, pretty bool) error

EncodeEnvelope writes the envelope as JSON to w. When pretty is false the encoding is compact (json.Encoder defaults); when true it's indented with two spaces. Always writes a trailing newline. Retained for M1 callers until Task 10 migrates them to Pipeline.

func Log

func Log(w io.Writer, event string, fields map[string]any)

Log emits one JSON object per call to w with a ts/event header. Intended for --verbose stderr tracing; errors marshaling are swallowed because verbose output is best-effort.

func Pipeline

func Pipeline(r catalog.Row, opts Options) ([]byte, error)

Pipeline is the single entry point used by every data-path command. It preset-projects, applies --fields, applies --jq, and encodes in one call. Callers writing multiple rows call Pipeline once per row so JSON output streams as NDJSON.

func ShouldColorize

func ShouldColorize(w io.Writer, opts Options) bool

ShouldColorize reports whether human-facing output emitted to w may include ANSI color. It returns false when the caller set --no-color (consumed into Options.NoColor upstream from NO_COLOR / SKU_NO_COLOR), when w is not an *os.File, or when the underlying file descriptor is not a TTY. Data-format output paths never call this — agents always receive uncolored bytes.

Types

type DryRunPlan

type DryRunPlan struct {
	Command      string         `json:"command"`
	ResolvedArgs map[string]any `json:"resolved_args"`
	Shards       []string       `json:"shards"`
	TermsHash    string         `json:"terms_hash,omitempty"`
	SQL          string         `json:"sql,omitempty"`
	Preset       string         `json:"preset"`
}

DryRunPlan carries the resolved query plan emitted by commands when --dry-run is set. The rendered JSON follows spec §4 "Dry-run output".

type Envelope

type Envelope struct {
	Provider string    `json:"provider,omitempty"`
	Service  string    `json:"service,omitempty"`
	SKUID    string    `json:"sku_id,omitempty"`
	Resource *Resource `json:"resource,omitempty"`
	Location *Location `json:"location,omitempty"`
	Price    []Price   `json:"price,omitempty"`
	Terms    *Terms    `json:"terms,omitempty"`
	Health   *Health   `json:"health,omitempty"`
	Source   *Source   `json:"source,omitempty"`
	Raw      any       `json:"raw,omitempty"`
}

Envelope is the top-level §4 output object. Field ordering is enforced by the struct layout; json.Encoder writes keys in declaration order.

func Project

func Project(env Envelope, p Preset, kind string) Envelope

Project trims a full Envelope to the preset's declared field set, folding in kind-specific extras where the preset depends on kind. Today only the compare preset uses kind — agent/price/full are kind-agnostic.

func Render

func Render(r catalog.Row, p Preset) Envelope

Render builds an Envelope for a single catalog.Row at the given preset. Retained as a convenience helper; the primary choke point is Pipeline.

type EstimateEnvelope

type EstimateEnvelope struct {
	Items        []EstimateItem       `json:"items" yaml:"items" toml:"-"`
	MonthlyTotal EstimateMonthlyTotal `json:"monthly_total" yaml:"monthly_total" toml:"monthly_total"`
}

EstimateEnvelope is the §4 shape for `sku estimate`.

type EstimateItem

type EstimateItem struct {
	Item         string  `json:"item" yaml:"item" toml:"item"`
	Kind         string  `json:"kind" yaml:"kind" toml:"kind"`
	SKUID        string  `json:"sku_id,omitempty" yaml:"sku_id,omitempty" toml:"sku_id,omitempty"`
	Provider     string  `json:"provider" yaml:"provider" toml:"provider"`
	Service      string  `json:"service" yaml:"service" toml:"service"`
	Resource     string  `json:"resource" yaml:"resource" toml:"resource"`
	Region       string  `json:"region,omitempty" yaml:"region,omitempty" toml:"region,omitempty"`
	HourlyUSD    float64 `json:"hourly_usd,omitempty" yaml:"hourly_usd,omitempty" toml:"hourly_usd,omitempty"`
	Quantity     float64 `json:"quantity,omitempty" yaml:"quantity,omitempty" toml:"quantity,omitempty"`
	QuantityUnit string  `json:"quantity_unit,omitempty" yaml:"quantity_unit,omitempty" toml:"quantity_unit,omitempty"`
	MonthlyUSD   float64 `json:"monthly_usd" yaml:"monthly_usd" toml:"monthly_usd"`
}

EstimateItem is one line-item in the output envelope.

type EstimateMonthlyTotal

type EstimateMonthlyTotal struct {
	Amount   float64 `json:"amount" yaml:"amount" toml:"amount"`
	Currency string  `json:"currency" yaml:"currency" toml:"currency"`
}

EstimateMonthlyTotal is the monthly-total block carried in the envelope.

type Health

type Health struct {
	Uptime30d              *float64 `json:"uptime_30d,omitempty"`
	LatencyP50Ms           *int64   `json:"latency_p50_ms,omitempty"`
	LatencyP95Ms           *int64   `json:"latency_p95_ms,omitempty"`
	ThroughputTokensPerSec *float64 `json:"throughput_tokens_per_sec,omitempty"`
	ObservedAt             *int64   `json:"observed_at,omitempty"`
}

Health is the §4 health block (LLM-populated).

type Location

type Location struct {
	ProviderRegion   *string `json:"provider_region"`
	NormalizedRegion *string `json:"normalized_region"`
	AvailabilityZone *string `json:"availability_zone"`
}

Location is the §4 location block.

type Options

type Options struct {
	Preset            Preset
	Format            string
	Pretty            bool
	Fields            string
	JQ                string
	IncludeRaw        bool
	IncludeAggregated bool
	NoColor           bool
}

Options configures the output Pipeline. Zero values are filled by WithDefaults: empty Preset becomes PresetAgent, empty Format becomes "json".

func (Options) WithDefaults

func (o Options) WithDefaults() Options

WithDefaults returns a copy of o with zero fields filled in.

type Preset

type Preset string

Preset enumerates the output-shape presets. Agent and Full are fully implemented in M1; Price and Compare get kind-aware projections in M2.

const (
	PresetAgent   Preset = "agent"
	PresetPrice   Preset = "price"
	PresetFull    Preset = "full"
	PresetCompare Preset = "compare"
)

Output preset constants.

type Price

type Price struct {
	Amount    float64 `json:"amount"`
	Currency  string  `json:"currency"`
	Unit      string  `json:"unit"`
	Dimension string  `json:"dimension"`
	Tier      *string `json:"tier"`
}

Price is a single price dimension as emitted in the output.

type Resource

type Resource struct {
	Kind             string         `json:"kind,omitempty"`
	Name             string         `json:"name,omitempty"`
	VCPU             *int64         `json:"vcpu,omitempty"`
	MemoryGB         *float64       `json:"memory_gb,omitempty"`
	StorageGB        *float64       `json:"storage_gb,omitempty"`
	GPUCount         *int64         `json:"gpu_count,omitempty"`
	ContextLength    *int64         `json:"context_length,omitempty"`
	MaxOutputTokens  *int64         `json:"max_output_tokens,omitempty"`
	Capabilities     []string       `json:"capabilities,omitempty"`
	DurabilityNines  *int64         `json:"durability_nines,omitempty"`
	AvailabilityTier *string        `json:"availability_tier,omitempty"`
	Attributes       map[string]any `json:"attributes,omitempty"`
}

Resource is the §4 resource block.

type Source

type Source struct {
	CatalogVersion string `json:"catalog_version"`
	FetchedAt      string `json:"fetched_at,omitempty"`
	UpstreamID     string `json:"upstream_id,omitempty"`
	Freshness      string `json:"freshness,omitempty"`
}

Source is the §4 source block.

type Terms

type Terms struct {
	Commitment    string  `json:"commitment"`
	Tenancy       *string `json:"tenancy,omitempty"`
	OS            *string `json:"os,omitempty"`
	SupportTier   *string `json:"support_tier,omitempty"`
	Upfront       *string `json:"upfront,omitempty"`
	PaymentOption *string `json:"payment_option,omitempty"`
}

Terms is the §4 terms block. Empty-string sentinels become nil pointers.

Jump to

Keyboard shortcuts

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