Help us shape the future of Go! Take the 2026 Go Developer Survey

config

package
v2.0.0 Latest Latest
Warning

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

Go to latest
Published: Oct 9, 2026 License: MIT Imports: 27 Imported by: 0

Documentation

Overview

Package config provides configuration management for Celeste CLI.

Package config provides configuration management for Celeste CLI. This file handles session persistence (conversation history).

Package config — personality slider persistence.

Sliders modulate Celeste's voice inside whatever register is active. They do NOT select registers, override invariants, or touch canonical collection files. They compose ON TOP of the persona baseline at position 6 in the assembly order (after voice_and_tone, before active register body).

Persistence: ~/.celeste/slider.yaml (or slider.json — we use JSON to match the existing config pattern). Loaded at startup, written on every slider change via the /persona TUI panel.

Package config provides configuration management for Celeste CLI. This file provides thin wrappers around ctxmgr for token estimation and model limit queries. Session-specific helpers that depend on config types (SessionMessage, Session) remain here.

Package config — user identity persistence.

Stores who Celeste is currently talking to so she calibrates her relationship dynamic appropriately. Without this, she defaults to addressing everyone as Kusanagi (twin/Onii-chan), which is wrong for other users.

Persistence: ~/.celeste/user.json Set via: /user <name> in TUI, or edit the file directly.

Index

Constants

View Source
const (
	EnvAPIKey      = "CELESTE_API_KEY"
	EnvAPIEndpoint = "CELESTE_API_ENDPOINT"
	EnvTarotToken  = "TAROT_AUTH_TOKEN"
)

Environment overrides. Precedence is environment > config file. They apply to this run only: ApplyEnvOverrides is called by the entry points that run a session (chat, message, agent, serve), never by the loads that are saved back, so a variable's value is never written to disk.

View Source
const (
	ModeOff    = "off"
	ModeShadow = "shadow" // ask and log, never act
	ModeOn     = "on"
)

Steering modes (2.0 W3, #175). Every mechanism is off or in shadow mode by default and fails open; an unknown value is the default.

View Source
const (
	SourceConfigured = "configured"
	SourceReported   = "reported by the server"
	SourceModel      = "model default"
	SourceFallback   = "fallback"
)

Where ResolveContextLimitSource's window came from.

View Source
const DefaultMaxToolIterations = 25

DefaultMaxToolIterations is the chat's turn cap (#144 renamed it from claw_max_tool_iterations; migrate.go maps the old key).

View Source
const DefaultProvider = "sakana"

DefaultProvider seeds a brand-new install that has no config file yet. It only names a provider in the registry — the BaseURL and model come from there, so retiring/renaming a model is a one-line registry edit, never a hunt across config.go, main.go templates, and the registry that diverge over time.

View Source
const DefaultTimeoutSeconds = 60

DefaultTimeoutSeconds is the request timeout a new profile gets: how long a request may receive nothing from the provider before it fails.

View Source
const DefaultTypingSpeed = 60

DefaultTypingSpeed is typing_speed's default, in characters per second (3 characters per 50ms animation tick).

View Source
const LocalFirstByteSeconds = 1800

LocalFirstByteSeconds is how long a request to a local server may wait for the first byte of the reply (GetFirstByteTimeout). Prefill sends nothing: on a loaded machine a 32K prompt on a 14B model took ~563 s to the first byte, and a full re-prefill after plan mode 11.5 min (#359).

View Source
const LocalTimeoutSeconds = 600

LocalTimeoutSeconds replaces DefaultTimeoutSeconds for a server on this machine or the local network (providers.IsLocalEndpoint). A local model sends nothing while it reads the prompt: a cold 16K-token first turn on a 14B model took longer than 300 s.

View Source
const WebFetchAllowPrivateEnv = "CELESTE_WEB_FETCH_ALLOW_PRIVATE"

WebFetchAllowPrivateEnv set to 1 lets web_fetch reach non-public addresses.

Variables

View Source
var ErrNoHome = errors.New("no home directory: set HOME (USERPROFILE on Windows) to an absolute path")

ErrNoHome is HomeDir's error when there is no usable home directory.

View Source
var MigrationWarn = func(msg string) { fmt.Fprintln(os.Stderr, "celeste: "+msg) }

MigrationWarn prints the one-line note for each migrated key. Tests replace it.

View Source
var ModelLimits = ctxmgr.ModelLimits

ModelLimits is kept as an alias for backward compatibility. Canonical data lives in ctxmgr.ModelLimits.

View Source
var ModelPricing = map[string]PricingTier{

	"gpt-4.1-nano":      {0.15, 0.60},
	"grok-build-0.1":    {1.00, 2.00},
	"grok-4-1-fast":     {0.20, 0.50},
	"claude-sonnet-4":   {3.00, 15.00},
	"gemini-2.0-flash":  {0.10, 0.40},
	"venice-uncensored": {0.20, 0.90},
}

ModelPricing is the legacy pricing table for backwards compatibility. The canonical pricing source is costs/pricing.go (costs.ModelPricing). This table is used by the stats dashboard for historical cost estimates.

Functions

func ApplyEnvOverrides

func ApplyEnvOverrides(cfg *Config)

ApplyEnvOverrides lets CELESTE_API_KEY, CELESTE_API_ENDPOINT and TAROT_AUTH_TOKEN replace the loaded api_key, base_url and tarot_auth_token. An unset or blank variable changes nothing.

func CalculateCost

func CalculateCost(model string, inputTokens, outputTokens int) float64

CalculateCost calculates the estimated cost based on token usage and model pricing

func CheckHome

func CheckHome() error

CheckHome is HomeDir's check for the start of a celeste command.

func DefaultModelForBaseURL

func DefaultModelForBaseURL(baseURL string) string

DefaultModelForBaseURL resolves the default model for a config from its own provider (detected via the registry), falling back to the seed provider's model when the URL is unknown. This is the dynamic resolution that replaces a hard-coded model string.

func EnableLocalWindowProbe

func EnableLocalWindowProbe()

EnableLocalWindowProbe installs the caching HTTP probe.

func EstimateMessageTokens

func EstimateMessageTokens(msg SessionMessage) int

EstimateMessageTokens counts tokens in a message.

func EstimateSessionTokens

func EstimateSessionTokens(session *Session) int

EstimateSessionTokens counts total tokens in session.

func EstimateSessionTokensByRole

func EstimateSessionTokensByRole(session *Session) (int, int, int)

EstimateSessionTokensByRole calculates separate input/output token counts. Returns (promptTokens, completionTokens, totalTokens).

func EstimateTokens

func EstimateTokens(text string) int

EstimateTokens approximates token count (delegates to ctxmgr).

func FormatCost

func FormatCost(cost float64) string

FormatCost formats a cost value as a currency string

func FormatNumber

func FormatNumber(n int) string

FormatNumber formats a number with thousand separators

func FormatTokenCount

func FormatTokenCount(tokens int) string

FormatTokenCount formats token count with K/M suffix (delegates to ctxmgr).

func GenerateNameFromMessage

func GenerateNameFromMessage(content string) string

GenerateNameFromMessage creates a session name from first user message. Extracts first 40-50 chars, intelligently truncates at word boundary.

func GetAnalyticsPath

func GetAnalyticsPath() string

GetAnalyticsPath returns the path to the analytics file

func GetExportDir

func GetExportDir() string

GetExportDir returns the path to the exports directory

func HomeDir

func HomeDir() (string, error)

HomeDir returns the user's home directory, or ErrNoHome when it is unset, empty or relative. It fails closed: joining ".celeste" onto an empty or relative home would read config, skills, hooks and permission rules from the current directory, which may be an untrusted checkout.

func ListConfigs

func ListConfigs() ([]string, error)

ListConfigs returns all available config names.

func LocalWindowNoWait

func LocalWindowNoWait(on bool, onChange func())

LocalWindowNoWait switches the installed probe to never wait (on) or back. The TUI turns it on once its prompt is composed: its Update and View must do no I/O, so an endpoint the probe has no answer for yet gets the fallback at once, the server is asked in the background, and onChange runs (on that goroutine) when an answer changes a window.

func LookupModelLimit

func LookupModelLimit(model string) (int, bool)

LookupModelLimit reports the limit and whether the model is known (delegates to ctxmgr). Callers validating a user-configured window need the second value: for an unknown model the limit is a fallback, not knowledge.

func MigrateConfigDir

func MigrateConfigDir()

MigrateConfigDir migrates every config*.json profile in the config directory once, up front. Call it from the chat startup path before the Bubble Tea alt screen opens (main.go's runChatTUI): by the time a running chat switches profiles (/endpoint, SwitchEndpoint), every file is already migrated, so migrateFile is a no-op instead of printing notes into the alt screen on every switch (#144 W6b review, I1(a)). Notes still go to MigrationWarn, which is stderr at this point — the alt screen isn't open yet. Load and LoadNamed still call migrateFile defensively; this just does the work for every profile before either of them needs to.

func NamedConfigPath

func NamedConfigPath(name string) string

NamedConfigPath returns the path for a named config file. If name is empty, returns the default config path.

func Paths

func Paths() (configDir, configFile, secretsFile, skillsFile string)

Paths returns the configuration directory and file paths.

func ProbeLocalWindow

func ProbeLocalWindow(ctx context.Context, hc *http.Client, baseURL, apiKey, model string) int

ProbeLocalWindow asks the server at baseURL (an OpenAI-compatible base, usually ending in /v1) for the context window it runs model with, and returns 0 when it does not say. apiKey, when set, is sent as a Bearer token (a llama.cpp or LM Studio server started with a key answers only with it); callers send it to a local host only. It tries Ollama's running models and the model's num_ctx, llama.cpp's /props, then LM Studio's model entry. A model's trained maximum (Ollama's model_info, LM Studio's max_context_length) is never used: the server runs it with less.

func RedactSecretCommand

func RedactSecretCommand(line string) string

RedactSecretCommand returns line with the key of a set-key command replaced by ***, and any other line unchanged. Input history, which is saved with the session and its exports, keeps only the redacted form.

func ResolveContextLimit

func ResolveContextLimit(baseURL, model string, override int, apiKey string) (limit int, known bool)

ResolveContextLimit returns the effective context window and whether that number is actually knowledge.

An explicit override always wins. A local endpoint whose server reports its window (the probe EnableLocalWindowProbe installs) gets that. Otherwise local endpoints get ctxmgr.LocalDefaultLimit even when the model name is in the table: a local server names its model whatever it likes, so a hit is coincidence. That mattered in practice — a fresh profile inherits the seed default's model (fugu), so pointing it at a local server produced a confident 1,000,000-token budget for a server that might have 8k. Unknown hosted models get the table's 128k default (#201).

func ResolveContextLimitSource

func ResolveContextLimitSource(baseURL, model string, override int, apiKey string) (int, string)

ResolveContextLimitSource is ResolveContextLimit with where the number came from (`celeste config` shows it). apiKey is the endpoint's key: a local server started with one answers the probe only with it.

func ResolveDefaultName

func ResolveDefaultName() string

ResolveDefaultName returns the name of the config.<name>.json file flagged "default": true, or "" if none is flagged (or the dir is unreadable). Files are scanned in directory order; the first match wins.

func SameProject

func SameProject(a, b string) bool

SameProject reports whether two workspaces are the same project: the same git root, or the same directory when neither is in a repository (2.0 W4 ruling 1). An empty workspace is no project.

func Save

func Save(config *Config) error

Save saves configuration to file.

func SaveCollections

func SaveCollections(cfg *Config) error

SaveCollections writes cfg's collections block back to the file cfg was loaded from: the named profile LoadNamed read, or config.json. Only the "collections" key changes; every other key stays as the file has it, so nothing a load merged in (config.json's sandbox, skills.json and secrets.json values, defaults) is copied into the wrong file (#324).

func SaveNamed

func SaveNamed(name string, config *Config) error

SaveNamed writes the config to a named profile file (config.<name>.json). Named profiles store everything inline, including the API key — that is how LoadNamed reads them — so unlike Save there is no separate secrets file. An empty name falls back to the default Save path.

func SaveSecrets

func SaveSecrets(config *Config) error

SaveSecrets saves API key to secrets file (backward compatibility).

func SaveSkillsConfig

func SaveSkillsConfig(skillsConfig *Config) error

SaveSkillsConfig saves skill-specific configuration to skills.json.

func SetDefaultProfile

func SetDefaultProfile(name string) error

SetDefaultProfile marks config.<name>.json as the default profile and clears the flag on every other named profile, so exactly one stays flagged.

func SetLocalWindowProbe

func SetLocalWindowProbe(fn func(baseURL, apiKey, model string) int)

SetLocalWindowProbe installs fn as the probe ResolveContextLimit asks about a local endpoint with no context_limit; nil removes it. fn returns the window in tokens, or 0 when the server did not say.

func SliderPath

func SliderPath() string

SliderPath returns the path to the slider config file.

func SnapToAnchor

func SnapToAnchor(value int) int

SnapToAnchor returns the nearest anchor index (0-3) for a slider value 0-10. Anchors are at 0, 3, 7, 10.

func UniqueNanoID

func UniqueNanoID() string

UniqueNanoID is the current time in nanoseconds from clock.Now, which never repeats in this process: Windows' clock is coarse, and two sessions with one ID overwrite each other's file.

func UnknownContextNotice

func UnknownContextNotice(model string, limit int) string

UnknownContextNotice returns the one-time warning for a model whose window was guessed, and "" on every later call for the same model (#201).

func UserPath

func UserPath() string

UserPath returns the path to the user identity file.

func ValidateProfileName

func ValidateProfileName(name string) error

ValidateProfileName reports whether name can name a profile file, config.<name>.json in ~/.celeste: a plain file-name part, with no path separator, drive or stream colon, NUL, or dot segment. A name read from elsewhere (a resumed session's endpoint) otherwise could load or write a file outside the config directory.

func WebFetchPrivateAllowed

func WebFetchPrivateAllowed() bool

WebFetchPrivateAllowed reports whether web_fetch may reach loopback, private-network, link-local and other non-public addresses: CELESTE_WEB_FETCH_ALLOW_PRIVATE=1, or "web_fetch_allow_private": true in the config this session was started with.

func WorkspaceConfigPath

func WorkspaceConfigPath(workspace string) string

WorkspaceConfigPath is a workspace's own config file.

Types

type AlchemyConfig

type AlchemyConfig struct {
	APIKey         string
	DefaultNetwork string
	TimeoutSeconds int
}

AlchemyConfig holds Alchemy API configuration.

type BlockmonConfig

type BlockmonConfig struct {
	AlchemyAPIKey       string
	WebhookURL          string
	DefaultNetwork      string
	PollIntervalSeconds int
}

BlockmonConfig holds blockchain monitoring configuration.

type CollectionsConfig

type CollectionsConfig struct {
	Enabled           bool     `json:"enabled"`
	ActiveCollections []string `json:"active_collections"`
	AutoEnable        bool     `json:"auto_enable"`
}

CollectionsConfig holds collections settings

type Config

type Config struct {
	// API settings
	APIKey  string `json:"api_key"`
	BaseURL string `json:"base_url"`
	Model   string `json:"model"`
	// AgentModel is the model used for agent / orchestrate / subagent work
	// (free tool-selection). Chat/TTS use Model. Empty falls back to Model.
	// Lets you pin a reasoning/tool-capable model for agent work while keeping a
	// cheap non-reasoning model for chat (model-router guardrail, task e8775b91).
	AgentModel string `json:"agent_model,omitempty"`
	// SmallModel is a cheaper model for housekeeping calls such as context
	// compaction summaries (#174). Empty falls back to Model.
	SmallModel string `json:"small_model,omitempty"`
	// PinModel turns live model resolution off: the configured models are
	// sent as written even if the provider no longer lists them. Same as
	// CELESTE_PIN_MODEL=1.
	PinModel bool `json:"pin_model,omitempty"`
	// WebFetchAllowPrivate lets web_fetch reach loopback, private-network,
	// link-local and other non-public addresses, which it refuses by default.
	// For local docs servers. Same as CELESTE_WEB_FETCH_ALLOW_PRIVATE=1.
	WebFetchAllowPrivate bool `json:"web_fetch_allow_private,omitempty"`
	// JevPrune turns on TypeSafe Jev as a judge for context pruning (#175).
	// "shadow" asks Jev in the background and only logs what it would have
	// pruned; "on" (2.0 W3) elides the least-needed results first, asking
	// Jev inside the loop (2.5 s cap, rules on any error); anything else is
	// off. Redacted excerpts of old tool results go to TypeSafe. The key
	// comes from TYPESAFE_API_KEY or ~/.celeste/typesafe.key.
	JevPrune string `json:"jev_prune,omitempty"`
	// JevGate asks Jev whether a tool call is destructive, exfiltrates data
	// or goes beyond what was asked (2.0 W3): "shadow" logs, "on" turns an
	// allowed call into an Ask (never the reverse). Off by default.
	JevGate string `json:"jev_gate,omitempty"`
	// JevRoute picks /orchestrate's lane with a Jev choice question (2.0
	// W3): "shadow" logs, "on" uses it. Off by default.
	JevRoute string `json:"jev_route,omitempty"`
	// Oracle picks the judge for steering questions (2.0 W3):
	// "heuristic" (default), "llm" (the small model) or "jev". The
	// watchdog ballot asks it.
	Oracle string `json:"oracle,omitempty"`
	// StreamRules: "shadow" (default) matches stream rules and logs, "on"
	// acts, "off" skips them (2.0 W3).
	StreamRules string `json:"stream_rules,omitempty"`
	// Watchdog: the ballot every 3 turns (2.0 W3): "off" (default),
	// "shadow" (asked and logged) or "on" (steers).
	Watchdog string `json:"watchdog,omitempty"`
	// CompletionGate (agent runs, 2.0 W3): "shadow" (default) keeps the
	// substring TASK_COMPLETE check and logs where the gate differs; "on"
	// lets the gate decide.
	CompletionGate string `json:"completion_gate,omitempty"`
	Timeout        int    `json:"timeout"`                 // seconds
	ContextLimit   int    `json:"context_limit,omitempty"` // Optional: Override context window size

	// Google Cloud authentication (for Gemini/Vertex AI)
	GoogleCredentialsFile string `json:"google_credentials_file,omitempty"` // Path to service account JSON file
	GoogleUseADC          bool   `json:"google_use_adc,omitempty"`          // Use Application Default Credentials

	// Runtime-detected provider (not persisted to config file)
	Provider string `json:"-"` // Detected from BaseURL at runtime

	// Default marks this named config as the one loaded when no -config flag
	// is given. Exactly one file should set it; the first match wins.
	Default bool `json:"default,omitempty"`

	// Confirm mode: when true, Celeste proposes actions before executing
	// write/generate operations. When false, she auto-executes.
	ConfirmActions bool `json:"confirm_actions,omitempty"`

	// ElevenLabs TTS settings
	ElevenLabsAPIKey  string `json:"elevenlabs_api_key,omitempty"`
	ElevenLabsVoiceID string `json:"elevenlabs_voice_id,omitempty"`

	// Streaming settings
	SimulateTyping bool `json:"simulate_typing"`
	TypingSpeed    int  `json:"typing_speed"` // chars per second

	// MaxToolIterations caps the model turns in one chat turn's tool loop.
	MaxToolIterations int `json:"max_tool_iterations,omitempty"`

	// Venice.ai settings (for NSFW mode)
	VeniceAPIKey     string `json:"venice_api_key,omitempty"`
	VeniceBaseURL    string `json:"venice_base_url,omitempty"`
	VeniceModel      string `json:"venice_model,omitempty"`       // Chat model (venice-uncensored)
	VeniceImageModel string `json:"venice_image_model,omitempty"` // Image model (lustify-sdxl)

	// Tarot settings
	TarotFunctionURL string `json:"tarot_function_url,omitempty"`
	TarotAuthToken   string `json:"tarot_auth_token,omitempty"`

	// Twitter settings
	TwitterBearerToken       string `json:"twitter_bearer_token,omitempty"`
	TwitterAPIKey            string `json:"twitter_api_key,omitempty"`
	TwitterAPISecret         string `json:"twitter_api_secret,omitempty"`
	TwitterAccessToken       string `json:"twitter_access_token,omitempty"`
	TwitterAccessTokenSecret string `json:"twitter_access_token_secret,omitempty"`

	// Weather settings
	WeatherDefaultZipCode string `json:"weather_default_zip_code,omitempty"`

	// Twitch settings
	TwitchClientID        string `json:"twitch_client_id,omitempty"`
	TwitchClientSecret    string `json:"twitch_client_secret,omitempty"`
	TwitchDefaultStreamer string `json:"twitch_default_streamer,omitempty"`

	// YouTube settings
	YouTubeAPIKey         string `json:"youtube_api_key,omitempty"`
	YouTubeDefaultChannel string `json:"youtube_default_channel,omitempty"`

	// IPFS settings
	IPFSProvider       string `json:"ipfs_provider,omitempty"` // "infura", "pinata", "custom"
	IPFSAPIKey         string `json:"ipfs_api_key,omitempty"`
	IPFSAPISecret      string `json:"ipfs_api_secret,omitempty"`
	IPFSProjectID      string `json:"ipfs_project_id,omitempty"` // Infura specific
	IPFSGatewayURL     string `json:"ipfs_gateway_url,omitempty"`
	IPFSTimeoutSeconds int    `json:"ipfs_timeout_seconds,omitempty"`

	// Alchemy settings
	AlchemyAPIKey         string `json:"alchemy_api_key,omitempty"`
	AlchemyDefaultNetwork string `json:"alchemy_default_network,omitempty"`
	AlchemyTimeoutSeconds int    `json:"alchemy_timeout_seconds,omitempty"`

	// Blockchain monitoring settings
	BlockmonAlchemyAPIKey       string `json:"blockmon_alchemy_api_key,omitempty"`
	BlockmonWebhookURL          string `json:"blockmon_webhook_url,omitempty"`
	BlockmonDefaultNetwork      string `json:"blockmon_default_network,omitempty"`
	BlockmonPollIntervalSeconds int    `json:"blockmon_poll_interval_seconds,omitempty"`

	// Wallet security settings
	WalletSecurityEnabled      bool   `json:"wallet_security_enabled,omitempty"`
	WalletSecurityPollInterval int    `json:"wallet_security_poll_interval,omitempty"` // seconds
	WalletSecurityAlertLevel   string `json:"wallet_security_alert_level,omitempty"`   // "low", "medium", "high", "critical"

	// Collections configuration (xAI only)
	XAIManagementAPIKey string             `json:"xai_management_api_key,omitempty"`
	Collections         *CollectionsConfig `json:"collections,omitempty"`
	XAIFeatures         *XAIFeaturesConfig `json:"xai_features,omitempty"`

	// Orchestrator settings
	Orchestrator *OrchestratorConfig `json:"orchestrator,omitempty"`

	// Sandbox is the OS sandbox for bash (2.0 W4); see Sandbox.
	Sandbox *Sandbox `json:"sandbox,omitempty"`
	// contains filtered or unexported fields
}

Config holds all configuration for Celeste CLI.

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns a config with default values. Provider-specific bits (BaseURL, model) resolve from the provider registry rather than being pinned here; only behavioural defaults live in this struct.

func Load

func Load() (*Config, error)

Load loads configuration from file and environment.

func LoadNamed

func LoadNamed(name string) (*Config, error)

LoadNamed loads configuration from a named config file. If name is empty, loads the default config.

func LoadNamedWithEnv

func LoadNamedWithEnv(name string) (*Config, error)

LoadNamedWithEnv is LoadNamed plus the environment overrides, for the entry points that run a session.

func LoadSkillsConfig

func LoadSkillsConfig() (*Config, error)

LoadSkillsConfig loads skill-specific configuration from skills.json.

func (*Config) CompletionGateMode

func (c *Config) CompletionGateMode() string

CompletionGateMode is completion_gate: "shadow" (default) keeps the substring TASK_COMPLETE check and logs where the gate disagrees, "on" lets the gate decide.

func (*Config) GetFirstByteTimeout

func (c *Config) GetFirstByteTimeout() time.Duration

GetFirstByteTimeout returns how long a request may wait for the first byte of the reply. For a local endpoint it is LocalFirstByteSeconds, or GetTimeout when that is longer; once data flows, GetTimeout applies between chunks. Hosted providers use GetTimeout for both.

func (*Config) GetTimeout

func (c *Config) GetTimeout() time.Duration

GetTimeout returns the request timeout. It is a stall timeout: a request fails when nothing arrives for this long, however long the reply takes in all (llm.MaxRequestDuration bounds that). A local endpoint whose timeout is unset or still the generic default gets LocalTimeoutSeconds; any other value is the user's and is kept.

func (*Config) JevGateMode

func (c *Config) JevGateMode() string

JevGateMode is jev_gate: "off" (default), "shadow" or "on".

func (*Config) JevPruneMode

func (c *Config) JevPruneMode() string

JevPruneMode is jev_prune: "off" (default), "shadow" or "on".

func (*Config) JevRouteMode

func (c *Config) JevRouteMode() string

JevRouteMode is jev_route: "off" (default), "shadow" or "on".

func (*Config) ModelPinned

func (c *Config) ModelPinned() bool

ModelPinned reports whether model resolution is off for this config: "pin_model": true in the config, or CELESTE_PIN_MODEL=1 in the environment. A pinned model is sent as configured, served or not.

func (*Config) OracleMode

func (c *Config) OracleMode() string

OracleMode is oracle: "heuristic" (default), "llm" or "jev".

func (*Config) ResolveAgentModel

func (c *Config) ResolveAgentModel() string

ResolveAgentModel returns the model to use for agent / orchestrate / subagent work: AgentModel if set, otherwise the chat Model. This is the router seam — callers entering agent mode use this instead of Model.

func (*Config) ResolveServedModel

func (c *Config) ResolveServedModel(ctx context.Context, baseURL, apiKey, model string) (resolved, note string)

ResolveServedModel resolves one model on its own endpoint (an orchestrator lane's), unless this config pins models. It may block on the network.

func (*Config) ResolveServedModels

func (c *Config) ResolveServedModels(ctx context.Context) (notes []string)

ResolveServedModels replaces Model, AgentModel and SmallModel with what the provider serves now, but only those celeste is sure are gone (providers.ResolveFromMemory). It loads the provider's catalog first (the cache, or one bounded fetch) and checks unlisted models where the provider can answer, so it may block on the network. It changes this in-memory config only; nothing is saved. The notes say what was replaced.

func (*Config) ResolveServedModelsCached

func (c *Config) ResolveServedModelsCached() (notes []string, pending bool)

ResolveServedModelsCached is ResolveServedModels from what this process already knows, with no I/O, for the TUI's Update. pending is true when a ResolveServedModels (in a tea.Cmd) would know more.

func (*Config) ResolveSmallModel

func (c *Config) ResolveSmallModel() string

ResolveSmallModel returns the model for housekeeping calls (compaction summaries): SmallModel if set, otherwise the chat Model.

func (*Config) StreamRulesMode

func (c *Config) StreamRulesMode() string

StreamRulesMode is stream_rules: "shadow" (default) matches and logs, "on" acts, "off" skips matching.

func (*Config) WatchdogMode

func (c *Config) WatchdogMode() string

WatchdogMode is watchdog: "off" (default), "shadow" or "on".

type ConfigLoader

type ConfigLoader struct {
	// contains filtered or unexported fields
}

ConfigLoader provides configuration values to tools.

func NewConfigLoader

func NewConfigLoader(config *Config) *ConfigLoader

NewConfigLoader creates a new config loader.

func (*ConfigLoader) GetAlchemyConfig

func (l *ConfigLoader) GetAlchemyConfig() (AlchemyConfig, error)

GetAlchemyConfig returns Alchemy API configuration.

func (*ConfigLoader) GetBlockmonConfig

func (l *ConfigLoader) GetBlockmonConfig() (BlockmonConfig, error)

GetBlockmonConfig returns blockchain monitoring configuration.

func (*ConfigLoader) GetIPFSConfig

func (l *ConfigLoader) GetIPFSConfig() (IPFSConfig, error)

GetIPFSConfig returns IPFS configuration.

func (*ConfigLoader) GetTarotConfig

func (l *ConfigLoader) GetTarotConfig() (TarotConfig, error)

GetTarotConfig returns tarot configuration.

func (*ConfigLoader) GetTwitchConfig

func (l *ConfigLoader) GetTwitchConfig() (TwitchConfig, error)

GetTwitchConfig returns Twitch API configuration.

func (*ConfigLoader) GetVeniceConfig

func (l *ConfigLoader) GetVeniceConfig() (VeniceConfig, error)

GetVeniceConfig returns Venice.ai configuration.

func (*ConfigLoader) GetWalletSecurityConfig

func (l *ConfigLoader) GetWalletSecurityConfig() (WalletSecuritySettingsConfig, error)

GetWalletSecurityConfig returns wallet security monitoring configuration.

func (*ConfigLoader) GetWeatherConfig

func (l *ConfigLoader) GetWeatherConfig() (WeatherConfig, error)

GetWeatherConfig returns weather skill configuration.

func (*ConfigLoader) GetYouTubeConfig

func (l *ConfigLoader) GetYouTubeConfig() (YouTubeConfig, error)

GetYouTubeConfig returns YouTube API configuration.

type ContextTracker

type ContextTracker struct {
	Session          *Session
	Model            string
	MaxTokens        int
	CurrentTokens    int
	PromptTokens     int
	CompletionTokens int

	// Thresholds (kept for backward compatibility)
	WarnThreshold     float64 // 0.75
	CautionThreshold  float64 // 0.85
	CriticalThreshold float64 // 0.95

	// Tracking
	LastWarningLevel string
	CompactionCount  int
	TruncationCount  int

	// Underlying budget (exported so callers can use it directly if needed)
	Budget *ctxmgr.TokenBudget
}

ContextTracker monitors token usage and context window status for a session. It is a thin wrapper around ctxmgr.TokenBudget, keeping the same external API so that tui/app.go and commands/ callers do not need wholesale changes.

func NewContextTracker

func NewContextTracker(session *Session, model string, contextLimitOverride ...int) *ContextTracker

NewContextTracker creates a new context tracker for a session. It initialises an internal ctxmgr.TokenBudget.

func (*ContextTracker) EstimateMessagesUntilLimit

func (ct *ContextTracker) EstimateMessagesUntilLimit(avgTokensPerMsg int) int

EstimateMessagesUntilLimit estimates how many messages can be sent before hitting the warning threshold.

func (*ContextTracker) GetContextSummary

func (ct *ContextTracker) GetContextSummary() string

GetContextSummary returns a formatted summary of context usage.

func (*ContextTracker) GetRemainingTokens

func (ct *ContextTracker) GetRemainingTokens() int

GetRemainingTokens returns the number of tokens remaining before limit.

func (*ContextTracker) GetUsagePercentage

func (ct *ContextTracker) GetUsagePercentage() float64

GetUsagePercentage returns the percentage of context window used (0.0 to 1.0).

func (*ContextTracker) GetWarningLevel

func (ct *ContextTracker) GetWarningLevel() string

GetWarningLevel returns the current warning level based on usage percentage. Uses the tracker's own CurrentTokens/MaxTokens rather than delegating to the budget, because external code may set CurrentTokens directly.

func (*ContextTracker) ShouldCompact

func (ct *ContextTracker) ShouldCompact() bool

ShouldCompact returns true if auto-compaction should be triggered.

func (*ContextTracker) UpdateTokens

func (ct *ContextTracker) UpdateTokens(prompt, completion, total int)

UpdateTokens updates token counts from API response.

type DailyStats

type DailyStats struct {
	Date         string  `json:"date"`
	SessionCount int     `json:"session_count"`
	MessageCount int     `json:"message_count"`
	TokenCount   int     `json:"token_count"`
	Cost         float64 `json:"cost"`
}

DailyStats tracks usage for a specific day

type Exporter

type Exporter struct {
	// contains filtered or unexported fields
}

Exporter handles session export to various formats

func NewExporter

func NewExporter(session *Session) *Exporter

NewExporter creates a new exporter for a session

func (*Exporter) ExportToFile

func (e *Exporter) ExportToFile(format string) (string, error)

ExportToFile is a convenience method that exports and saves in one call

func (*Exporter) SaveToFile

func (e *Exporter) SaveToFile(content string, format string) (string, error)

SaveToFile saves the exported content to a file

func (*Exporter) ToCSV

func (e *Exporter) ToCSV() (string, error)

ToCSV exports the session as CSV (one row per message) Format: timestamp,role,content,tokens,model,cost

func (*Exporter) ToJSON

func (e *Exporter) ToJSON() (string, error)

ToJSON exports the session as pretty-printed JSON

func (*Exporter) ToMarkdown

func (e *Exporter) ToMarkdown() (string, error)

ToMarkdown exports the session as Markdown with frontmatter

type GlobalAnalytics

type GlobalAnalytics struct {
	TotalSessions int     `json:"total_sessions"`
	TotalMessages int     `json:"total_messages"`
	TotalTokens   int     `json:"total_tokens"`
	TotalCost     float64 `json:"total_cost"`

	// Per-provider breakdown
	ProviderUsage map[string]*ProviderStats `json:"provider_usage"`

	// Per-model breakdown
	ModelUsage map[string]*ModelStats `json:"model_usage"`

	// Time-based tracking (YYYY-MM-DD -> stats)
	DailyUsage map[string]*DailyStats `json:"daily_usage"`

	LastUpdated time.Time `json:"last_updated"`
}

GlobalAnalytics tracks cumulative usage across all sessions

func LoadGlobalAnalytics

func LoadGlobalAnalytics() (*GlobalAnalytics, error)

LoadGlobalAnalytics loads analytics from ~/.celeste/analytics.json

func NewGlobalAnalytics

func NewGlobalAnalytics() *GlobalAnalytics

NewGlobalAnalytics creates a new empty analytics tracker

func (*GlobalAnalytics) GetTopModelNames

func (ga *GlobalAnalytics) GetTopModelNames(n int) []struct {
	Name  string
	Stats ModelStats
}

GetTopModelNames returns the top N model names with their stats

func (*GlobalAnalytics) GetTopProviders

func (ga *GlobalAnalytics) GetTopProviders() []struct {
	Name  string
	Stats ProviderStats
}

GetTopProviders returns providers sorted by usage

func (*GlobalAnalytics) GetWeeklyUsage

func (ga *GlobalAnalytics) GetWeeklyUsage() []DailyStats

GetWeeklyUsage returns usage stats for the last 7 days

func (*GlobalAnalytics) Save

func (ga *GlobalAnalytics) Save() error

Save persists analytics to ~/.celeste/analytics.json

func (*GlobalAnalytics) UpdateFromSession

func (ga *GlobalAnalytics) UpdateFromSession(session *Session)

UpdateFromSession updates analytics with data from a session

type IPFSConfig

type IPFSConfig struct {
	Provider       string
	APIKey         string
	APISecret      string
	ProjectID      string
	GatewayURL     string
	TimeoutSeconds int
}

IPFSConfig holds IPFS configuration.

type LaneConfig

type LaneConfig struct {
	Primary         string `json:"primary"`
	PrimaryBaseURL  string `json:"primary_base_url,omitempty"`
	PrimaryAPIKey   string `json:"primary_api_key,omitempty"`
	Reviewer        string `json:"reviewer,omitempty"`
	ReviewerBaseURL string `json:"reviewer_base_url,omitempty"`
	ReviewerAPIKey  string `json:"reviewer_api_key,omitempty"`
}

LaneConfig holds the primary and optional reviewer model for one task lane. PrimaryBaseURL/PrimaryAPIKey and ReviewerBaseURL/ReviewerAPIKey allow cross-provider orchestration (e.g. xAI primary + OpenAI reviewer) without changing the main config.

type ModelStats

type ModelStats struct {
	SessionCount int     `json:"session_count"`
	MessageCount int     `json:"message_count"`
	InputTokens  int     `json:"input_tokens"`
	OutputTokens int     `json:"output_tokens"`
	Cost         float64 `json:"cost"`
}

ModelStats tracks usage for a specific model

type OrchestratorConfig

type OrchestratorConfig struct {
	Lanes        map[string]LaneConfig `json:"lanes,omitempty"`
	DefaultLane  string                `json:"default_lane,omitempty"`
	DebateRounds int                   `json:"debate_rounds,omitempty"`
}

OrchestratorConfig controls multi-model orchestration behaviour.

type PricingTier

type PricingTier struct {
	InputCostPerMillion  float64
	OutputCostPerMillion float64
}

PricingTier represents the cost per million tokens for input and output

func GetModelPricing

func GetModelPricing(model string) (PricingTier, bool)

GetModelPricing returns the pricing tier for a model, if available

type ProviderBlocks

type ProviderBlocks struct {
	Provider string            `json:"provider"`
	Digest   string            `json:"digest,omitempty"`
	Blocks   []json.RawMessage `json:"blocks"`
}

ProviderBlocks is a message's content exactly as one provider returned it (2.0 F3): Anthropic thinking, redacted_thinking, text, tool_use and compaction blocks; OpenAI Responses output items. Provider is the key of the backend that produced them (llm.ProviderKey). Digest ties them to the message's provider-neutral Content and ToolCalls at the moment they were attached (tui.AttachProviderBlocks); tui.ReplayBlocks replays them only while both still match.

Blocks are canonical JSON: compact and HTML-escaped, the form encoding/json itself writes, so a save/load cycle returns the same bytes. A ProviderBlocks is never modified after it is attached; an edit replaces the message's pointer with nil.

func NewProviderBlocks

func NewProviderBlocks(provider string, blocks []json.RawMessage) (*ProviderBlocks, error)

NewProviderBlocks canonicalizes a reply's blocks. It returns nil, nil for no blocks, and an error for an empty provider or a block that is not a JSON object.

func (*ProviderBlocks) UnmarshalJSON

func (p *ProviderBlocks) UnmarshalJSON(data []byte) error

UnmarshalJSON re-canonicalizes each block, undoing the indentation that MarshalIndent (sessions, agent checkpoints) puts inside raw JSON. A value that does not decode becomes the zero ProviderBlocks, which is never replayed: damaged blocks must not fail a session or checkpoint load.

type ProviderStats

type ProviderStats struct {
	SessionCount int     `json:"session_count"`
	MessageCount int     `json:"message_count"`
	TokenCount   int     `json:"token_count"`
	Cost         float64 `json:"cost"`
}

ProviderStats tracks usage for a specific provider

type Sandbox

type Sandbox struct {
	Enabled  *bool    `json:"enabled,omitempty"`  // run bash under the OS sandbox
	Writable []string `json:"writable,omitempty"` // more writable directories (relative: to the workspace)
	Network  *bool    `json:"network,omitempty"`  // false cuts the network
}

Sandbox is the "sandbox" object in ~/.celeste/config.json (the user's, trusted) and in a workspace's .celeste/config.json (the repository's: its tightening applies always, its loosening only once trusted). A nil field keeps the default.

func LoadWorkspaceSandbox

func LoadWorkspaceSandbox(workspace string) (s *Sandbox, path, body string, err error)

LoadWorkspaceSandbox reads the "sandbox" object of workspace's .celeste/config.json. s is nil when the file or the key is absent. body is s as canonical JSON (sorted keys, no unknown fields), what trust approvals hash. The file's other keys are ignored.

func (*Sandbox) Loosens

func (s *Sandbox) Loosens() bool

Loosens reports whether s, coming from a repository, would weaken the sandbox: "enabled": false, "network": true or extra writable paths. Those apply only once the file is trusted; "enabled": true and "network": false tighten and always apply.

type Session

type Session struct {
	ID         string           `json:"id"`
	Name       string           `json:"name,omitempty"`
	CreatedAt  time.Time        `json:"created_at"`
	UpdatedAt  time.Time        `json:"updated_at"`
	Messages   []SessionMessage `json:"messages"`
	NSFWMode   bool             `json:"nsfw_mode,omitempty"`
	Metadata   map[string]any   `json:"metadata,omitempty"`
	TokenCount int              `json:"token_count,omitempty"` // Estimated token count
	Model      string           `json:"model,omitempty"`       // Track model for limits

	// NEW: Enhanced tracking
	UsageMetrics *UsageMetrics `json:"usage_metrics,omitempty"` // Detailed usage tracking
	Provider     string        `json:"provider,omitempty"`      // Provider (openai, venice, etc)
	MaxContext   int           `json:"max_context,omitempty"`   // Model's max context window

	// Workspace is the absolute directory the chat ran in (2.0 W4 ruling
	// 1): `celeste resume` and /session list show this project's
	// sessions first. Older sessions have none.
	Workspace string `json:"workspace,omitempty"`
}

Session represents a saved conversation session.

func LoadSession

func LoadSession(sessionID int64) (*Session, error)

LoadSession is a global helper to load a session by numeric ID

func SortForWorkspace

func SortForWorkspace(sessions []Session, ws string) (mine, others []Session)

SortForWorkspace splits sessions into ws's project's and the rest, each newest first (2.0 W4 ruling 2).

func (*Session) ClearMessages

func (s *Session) ClearMessages()

ClearMessages clears all messages from the session.

func (*Session) GetCommandHistory

func (s *Session) GetCommandHistory() []string

GetCommandHistory retrieves the input command history from session metadata.

func (*Session) GetEndpoint

func (s *Session) GetEndpoint() string

GetEndpoint retrieves the endpoint from session metadata.

func (*Session) GetMessages

func (s *Session) GetMessages() []SessionMessage

GetMessages returns all session messages.

func (*Session) GetMessagesRaw

func (s *Session) GetMessagesRaw() interface{}

GetMessagesRaw returns messages as interface{} (for TUI interface compatibility).

func (*Session) GetModel

func (s *Session) GetModel() string

GetModel retrieves the model from session metadata.

func (*Session) GetModelPinned

func (s *Session) GetModelPinned() bool

GetModelPinned reports a saved /set-model --force pin.

func (*Session) GetModelUnverified

func (s *Session) GetModelUnverified() bool

GetModelUnverified reports what SetModelUnverified stored.

func (*Session) GetNSFWMode

func (s *Session) GetNSFWMode() bool

GetNSFWMode retrieves the NSFW mode from session.

func (*Session) GetProvider

func (s *Session) GetProvider() string

GetProvider retrieves the provider name from the session.

func (*Session) GetWorkspace

func (s *Session) GetWorkspace() string

GetWorkspace is the directory the session ran in ("" for older sessions).

func (*Session) InitializeUsageMetrics

func (s *Session) InitializeUsageMetrics()

InitializeUsageMetrics ensures the session has usage metrics initialized.

func (*Session) SetCommandHistory

func (s *Session) SetCommandHistory(history []string)

SetCommandHistory stores the input command history in session metadata, with set-key commands' keys redacted.

func (*Session) SetEndpoint

func (s *Session) SetEndpoint(endpoint string)

SetEndpoint stores the current endpoint in session metadata.

func (*Session) SetMessagesRaw

func (s *Session) SetMessagesRaw(msgs interface{})

SetMessagesRaw sets messages from interface{} (for TUI interface compatibility).

func (*Session) SetModel

func (s *Session) SetModel(model string)

SetModel stores the current model in session metadata.

func (*Session) SetModelPinned

func (s *Session) SetModelPinned(pinned bool)

SetModelPinned records a /set-model --force pin, so a resume keeps the model instead of resolving it.

func (*Session) SetModelUnverified

func (s *Session) SetModelUnverified(unverified bool)

SetModelUnverified records that the session's model is a /set-model --force name no catalog listed, so a resume does not show it as valid.

func (*Session) SetNSFWMode

func (s *Session) SetNSFWMode(enabled bool)

SetNSFWMode stores the NSFW mode in session.

func (*Session) SetName

func (s *Session) SetName(name string)

SetName updates the session name.

func (*Session) SetWorkspace

func (s *Session) SetWorkspace(ws string)

SetWorkspace records the directory the session runs in.

func (*Session) Summarize

func (s *Session) Summarize() SessionSummary

Summarize returns a summary of the session.

func (*Session) SummarizeRaw

func (s *Session) SummarizeRaw() interface{}

SummarizeRaw returns summary as interface{} (for TUI interface compatibility).

func (*Session) UpdateUsageMetrics

func (s *Session) UpdateUsageMetrics(inputTokens, outputTokens int)

UpdateUsageMetrics updates the session's usage metrics with new token data.

type SessionManager

type SessionManager struct {
	// contains filtered or unexported fields
}

SessionManager manages session persistence.

func NewSessionManager

func NewSessionManager() *SessionManager

NewSessionManager creates a new session manager.

func (*SessionManager) AddMessage

func (m *SessionManager) AddMessage(session *Session, role, content string)

AddMessage adds a message to the session and saves.

func (*SessionManager) AddMessageWithTokens

func (m *SessionManager) AddMessageWithTokens(session *Session, role, content string, inputTokens, outputTokens int)

AddMessageWithTokens adds a message to the session with token tracking.

func (*SessionManager) Clear

func (m *SessionManager) Clear() error

Clear deletes all sessions.

func (*SessionManager) Delete

func (m *SessionManager) Delete(id string) error

Delete deletes a session by ID.

func (*SessionManager) GetCurrentID

func (m *SessionManager) GetCurrentID() string

GetCurrentID returns the current session ID.

func (*SessionManager) List

func (m *SessionManager) List() ([]Session, error)

List returns all saved sessions.

func (*SessionManager) Load

func (m *SessionManager) Load(id string) (*Session, error)

Load loads a session by ID.

func (*SessionManager) LoadLatest

func (m *SessionManager) LoadLatest() (*Session, error)

LoadLatest loads the most recent session.

func (*SessionManager) MergeSessions

func (m *SessionManager) MergeSessions(session1, session2 *Session) *Session

MergeSessions combines messages from two sessions chronologically.

func (*SessionManager) NewSession

func (m *SessionManager) NewSession() *Session

NewSession creates a new session with a unique ID.

func (*SessionManager) Save

func (m *SessionManager) Save(session *Session) error

Save saves a session to disk.

type SessionMessage

type SessionMessage struct {
	Role      string    `json:"role"`
	Content   string    `json:"content"`
	Timestamp time.Time `json:"timestamp"`

	// Tool traffic (#174): without it a resumed session replays only the
	// prose, so the model loses what it read and did.
	ToolCalls  []SessionToolCall `json:"tool_calls,omitempty"`   // assistant: calls made
	ToolCallID string            `json:"tool_call_id,omitempty"` // tool: call answered
	Name       string            `json:"name,omitempty"`         // tool: function name

	// Hidden messages are sent to the model but not rendered (directives,
	// compaction summaries). Compacted messages were replaced by a summary:
	// rendered in the scrollback but no longer sent.
	Hidden    bool `json:"hidden,omitempty"`
	Compacted bool `json:"compacted,omitempty"`

	// ProviderBlocks is the message as the provider returned it (2.0 F3),
	// saved only while it still matches Content and ToolCalls.
	ProviderBlocks *ProviderBlocks `json:"provider_blocks,omitempty"`
}

SessionMessage represents a message in a session.

type SessionSummary

type SessionSummary struct {
	ID           string         `json:"id"`
	Name         string         `json:"name,omitempty"`
	MessageCount int            `json:"message_count"`
	CreatedAt    time.Time      `json:"created_at"`
	UpdatedAt    time.Time      `json:"updated_at"`
	FirstMessage string         `json:"first_message,omitempty"`
	Metadata     map[string]any `json:"metadata,omitempty"`
	Workspace    string         `json:"workspace,omitempty"`
}

SessionSummary provides a brief overview of a session.

type SessionToolCall

type SessionToolCall struct {
	ID               string `json:"id"`
	Name             string `json:"name"`
	Arguments        string `json:"arguments"`
	ThoughtSignature []byte `json:"thought_signature,omitempty"`
}

SessionToolCall is a tool call recorded on an assistant message.

type SliderConfig

type SliderConfig struct {
	// Flirt controls how forward / teasing she is.
	// 0=professional, 3=playful, 7=flirty, 10=aggressive-flirt
	Flirt int `json:"flirt"`

	// Warmth controls affection level.
	// 0=cold/distant, 3=polite, 7=warm, 10=openly-affectionate
	Warmth int `json:"warmth"`

	// Register controls speech style.
	// 0=clipped-operator, 3=standard, 7=theatrical, 10=uwu/baby-talk
	Register int `json:"register"`

	// Lewdness controls content eligibility. Only has effect when
	// R18Enabled is true — without R18, lewdness > 0 is a no-op.
	// 0=SFW, 3=suggestive, 7=explicit-tease, 10=R18
	Lewdness int `json:"lewdness"`

	// R18Enabled is the independent toggle. Provider-agnostic — it
	// controls what Celeste ATTEMPTS, not what the backend allows.
	// Default false. Orthogonal to every slider.
	R18Enabled bool `json:"r18_enabled"`

	// Presets stores user-saved named slider combos.
	Presets map[string]SliderPreset `json:"presets,omitempty"`
}

SliderConfig holds the user's personality slider state. Each slider is an int 0-10. Anchor points at 0/3/7/10 snap to authored prompt snippets; intermediate values snap to nearest anchor.

func DefaultSliderConfig

func DefaultSliderConfig() *SliderConfig

DefaultSliderConfig returns the factory-default slider state. Moderate across the board, R18 off.

func LoadSliders

func LoadSliders() *SliderConfig

LoadSliders loads the slider config from disk. Returns defaults if the file doesn't exist or is malformed.

func (*SliderConfig) LoadPreset

func (s *SliderConfig) LoadPreset(name string) bool

LoadPreset restores slider values from a named preset.

func (*SliderConfig) Reset

func (s *SliderConfig) Reset()

Reset restores factory defaults (preserves presets).

func (*SliderConfig) Save

func (s *SliderConfig) Save() error

Save writes the slider config to disk.

type SliderPreset

type SliderPreset struct {
	Flirt      int  `json:"flirt"`
	Warmth     int  `json:"warmth"`
	Register   int  `json:"register"`
	Lewdness   int  `json:"lewdness"`
	R18Enabled bool `json:"r18_enabled"`
}

SliderPreset is a named snapshot of slider values.

type TarotConfig

type TarotConfig struct {
	FunctionURL string
	AuthToken   string
}

TarotConfig holds tarot function configuration.

type TwitchConfig

type TwitchConfig struct {
	ClientID        string
	ClientSecret    string
	DefaultStreamer string
}

TwitchConfig holds Twitch API configuration.

type UsageMetrics

type UsageMetrics struct {
	TotalInputTokens  int       `json:"total_input_tokens"`
	TotalOutputTokens int       `json:"total_output_tokens"`
	TotalTokens       int       `json:"total_tokens"`
	EstimatedCost     float64   `json:"estimated_cost"`
	CompactionCount   int       `json:"compaction_count"`
	TruncationCount   int       `json:"truncation_count"`
	MessageCount      int       `json:"message_count"`
	ConversationStart time.Time `json:"conversation_start"`
	ConversationEnd   time.Time `json:"conversation_end"`
}

UsageMetrics tracks token usage and cost for a session

func NewUsageMetrics

func NewUsageMetrics() *UsageMetrics

NewUsageMetrics creates a new usage metrics instance

func (*UsageMetrics) GetAverageTokensPerMessage

func (um *UsageMetrics) GetAverageTokensPerMessage() float64

GetAverageTokensPerMessage returns the average tokens per message

func (*UsageMetrics) GetCostPerMessage

func (um *UsageMetrics) GetCostPerMessage() float64

GetCostPerMessage returns the average cost per message

func (*UsageMetrics) GetDuration

func (um *UsageMetrics) GetDuration() time.Duration

GetDuration returns the duration of the conversation

func (*UsageMetrics) IncrementMessageCount

func (um *UsageMetrics) IncrementMessageCount()

IncrementMessageCount increments the message counter

func (*UsageMetrics) Update

func (um *UsageMetrics) Update(inputTokens, outputTokens int, model string)

Update updates the usage metrics with new token counts

type UserIdentity

type UserIdentity struct {
	// Name is the user's display name. Empty means use the default title.
	Name string `json:"name"`

	// Title is the abyss-themed fallback when Name is empty.
	// Default: "Summoner" — they invoked Celeste via the CLI.
	Title string `json:"title,omitempty"`
}

UserIdentity holds the current user's identity for prompt calibration.

func DefaultUserIdentity

func DefaultUserIdentity() *UserIdentity

DefaultUserIdentity returns the factory default — an unnamed summoner.

func LoadUser

func LoadUser() *UserIdentity

LoadUser loads the user identity from disk. Returns default if the file doesn't exist or is malformed.

func (*UserIdentity) DisplayName

func (u *UserIdentity) DisplayName() string

DisplayName returns the name to use when addressing the user. Returns Name if set, otherwise Title.

func (*UserIdentity) IsKusanagi

func (u *UserIdentity) IsKusanagi() bool

IsKusanagi returns true if the user has identified as Kusanagi.

func (*UserIdentity) Save

func (u *UserIdentity) Save() error

Save writes the user identity to disk.

type VeniceConfig

type VeniceConfig struct {
	APIKey     string
	BaseURL    string
	Model      string // Chat model (venice-uncensored)
	ImageModel string // Image generation model (lustify-sdxl, animewan, hidream, wai-Illustrious)
	Upscaler   string
}

VeniceConfig holds Venice.ai configuration.

type WalletSecuritySettingsConfig

type WalletSecuritySettingsConfig struct {
	Enabled      bool
	PollInterval int    // seconds
	AlertLevel   string // minimum severity to alert on
}

WalletSecuritySettingsConfig holds wallet security settings.

type WeatherConfig

type WeatherConfig struct {
	DefaultZipCode string
}

WeatherConfig holds weather skill configuration.

type XAIFeaturesConfig

type XAIFeaturesConfig struct {
	EnableWebSearch bool `json:"enable_web_search"`
	EnableXSearch   bool `json:"enable_x_search"`
}

XAIFeaturesConfig holds xAI-specific feature flags

type YouTubeConfig

type YouTubeConfig struct {
	APIKey         string
	DefaultChannel string
}

YouTubeConfig holds YouTube API configuration.

Jump to

Keyboard shortcuts

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