Documentation
¶
Overview ¶
Package tripadvice wraps the operator-configured AI provider to generate plain-language observations about a Rivian trip plan: charging stop summary, arrival SoC commentary, adapter warnings, and drive-mode suggestions when the plan looks sub-optimal.
Structure mirrors internal/recap: side-effect-free buildPrompt, stateless Generate, structured JSON output the SPA renders as a card below the route table.
Index ¶
Constants ¶
const DefaultDCFCRateUSD = 0.46
DefaultDCFCRateUSD is the per-kWh fallback used in the rare case where the cost estimator runs without a route (pre-network-table API consumers, tests). The real per-stop pricing flows through the Networks table in networks.go.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Context ¶
type Context struct {
OriginLabel string
DestinationLabel string
// DriveMode is the mode the user explicitly chose, or "" for
// "let the planner pick". Included so the model can say "you
// planned in Conserve mode" rather than treating it as a mystery.
DriveMode string
StartingSoC float64
HasAdapter bool
// Weather at the origin at departure time. nil when the operator
// has not enabled the weather feature (recap.weather_enabled).
Weather *weather.Snapshot
// TirePressurebars holds [FL, FR, RL, RR] in bar from the live
// vehicle state. Zero values mean unavailable for that corner.
TirePressureBars [4]float64
// PackKWh is the observed battery capacity in kWh from the vehicle
// record. 0 means unknown.
PackKWh float64
// TirePlacardPSI is the user-configured door-jamb cold-fill
// pressure from the vehicle profile. 0 means unconfigured; the
// prompt then falls back to a generic "below placard" framing
// instead of citing a specific number.
TirePlacardPSI float64
// HomePricePerKWh is the user's at-home charging cost in
// HomeCurrency (typically USD). 0 means unconfigured — the cost
// section degrades to a pure-DCFC estimate.
HomePricePerKWh float64
HomeCurrency string
// GasPricePerGallon × distance / ComparisonMPG drives the gas-
// equivalent chip. Both must be > 0 for the chip to render.
GasPricePerGallon float64
ComparisonMPG float64
// DCFCNetworks is the user's edited price book from Settings.
// Pass nil or empty to use the built-in defaults from dcfcrates.
// Per-stop rates honour each row's MemberActive flag so the
// estimate's user-totals match what the user has actually
// signed up for.
DCFCNetworks []dcfcrates.NetworkOverride
}
Context bundles user-supplied labels and request parameters that would otherwise be unavailable in the plan response itself.
type CostEstimate ¶
type CostEstimate struct {
Currency string `json:"currency"`
DCFCSpend float64 `json:"dcfc_spend"`
DCFCSpendUserMember float64 `json:"dcfc_spend_user_member"`
DCFCSpendAllMember float64 `json:"dcfc_spend_all_member"`
HomeEquivalent float64 `json:"home_equivalent"`
// GasEquivalent is what the same distance would cost in an ICE
// vehicle at the user's configured gas price + MPG. Zero when
// either input is unset.
GasEquivalent float64 `json:"gas_equivalent"`
GasPricePerGallon float64 `json:"gas_price_per_gallon"`
GasMPG float64 `json:"gas_mpg"`
// DCFCRateUsed is the avg per-kWh guest rate weighted by energy.
// Falls back to DefaultDCFCRateUSD when no waypoints priced.
DCFCRateUsed float64 `json:"dcfc_rate_used"`
DCFCRateUsedUserMember float64 `json:"dcfc_rate_used_user_member"`
DCFCRateUsedAllMember float64 `json:"dcfc_rate_used_all_member"`
// HomeRateUsed is the user's configured at-home rate, 0 when
// unconfigured.
HomeRateUsed float64 `json:"home_rate_used"`
// Breakdown lists each priced stop. Empty when no DCFC stops
// were on the route (all-from-home trip).
Breakdown []CostStop `json:"breakdown,omitempty"`
}
CostEstimate is a deterministic, code-computed projection of trip cost. Four views the user cares about:
- DCFCSpend (guest): what a walk-up driver pays.
- DCFCSpendUserMember: cost given the user's active memberships (toggled in Settings). Equal to DCFCSpend when the user has no memberships on.
- DCFCSpendAllMember: hypothetical "you have every plan" floor, so the strip can hint "you could save $X more by joining Tesla Supercharging Membership".
- HomeEquivalent: every kWh at the home meter rate.
Breakdown is the per-stop attribution that drives the totals, so the SPA can show "1× EA · 1× Tesla SC · 1× RAN".
func EstimateRoute ¶ added in v0.18.85
func EstimateRoute(r *rivian.TripRoute, tc Context) CostEstimate
EstimateRoute projects DCFC spend + home-rate-equivalent for a single route. Exported so the /api/trips/plan handler can attach a cost to every route in the response without making the SPA round- trip through the AI advice endpoint just to see numbers.
type CostStop ¶ added in v0.18.83
type CostStop struct {
NetworkSlug string `json:"network_slug"`
NetworkName string `json:"network_name"`
ChargerName string `json:"charger_name"`
EnergyKWh float64 `json:"energy_kwh"`
GuestRate float64 `json:"guest_rate"`
UserRate float64 `json:"user_rate"`
AllMemberRate float64 `json:"all_member_rate"`
MemberPlan string `json:"member_plan,omitempty"`
}
CostStop is one waypoint's contribution to the DCFC total.
type Parsed ¶
type Parsed struct {
Headline string `json:"headline"`
Cost []string `json:"cost"`
Efficiency []string `json:"efficiency"`
Weather []string `json:"weather"`
Vehicle []string `json:"vehicle"`
}
Parsed is the structured JSON shape the model emits. Each list holds 1-3 short sentences; sections with nothing useful to say stay empty rather than emitting filler.
type Result ¶
type Result struct {
// Raw is the model's reply, stored and forwarded as-is.
Raw string
Parsed *Parsed
Model string
InputTokens int64
OutputTokens int64
// Cost is computed deterministically in Go (not by the LLM) so
// the dollar figure is always accurate. The LLM gets the same
// numbers in the prompt and writes the commentary around them.
Cost CostEstimate
}
Result is what Generate returns to the handler.
func Generate ¶
func Generate(ctx context.Context, a *ai.Analyzer, plan *rivian.TripPlan, tc Context) (Result, error)
Generate calls the AI provider with a compact trip-plan summary and returns structured advice. The context's deadline should be generous (30s+) — sit in the AI-bound route group, not the timed one.