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

config

package
v0.4.5 Latest Latest
Warning

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

Go to latest
Published: Oct 16, 2026 License: MIT Imports: 32 Imported by: 0

Documentation

Overview

Session-lifetime composed-config cache: the single read source for one run.

Composes the global and per-project settings layers into one effective config (95).

Locates the project root by walking upward for the innermost .codemeld/settings.yaml marker.

Loads and validates settings/template YAML, classifying load failures.

Derives and validates <project>/.codemeld/settings.local.yaml, the per-user layer codemeld writes.

Validates settings.yaml against the embedded JSON Schema, reporting the dotted offending key.

Index

Constants

View Source
const (
	KeyPermissions   = "permissions"
	KeyModelActive   = "model.active"
	KeyModelLastUsed = "model.last_used"
	// KeyAuthOpenAIChatGPT is the codemeld-owned, global-only ChatGPT session
	// state stored under auth.openai-chatgpt. Pass a yaml-marshalable mapping value
	// to set it, or the AuthDelete sentinel to remove it (logout).
	KeyAuthOpenAIChatGPT = "auth.openai-chatgpt"
	KeyAttribution       = "attribution"
	KeySharedTempFolders = "confinement.shared_temp_folders"
	KeyRetentionDays     = "sessions.retention_days"
)

Codemeld-owned YAML keys per §Reserved Values "Codemeld-owned YAML keys".

View Source
const (
	KeyOpenRouterRoutingDataCollection = "provider.openrouter.routing.data_collection"
	KeyOpenRouterRoutingSort           = "provider.openrouter.routing.sort"
	KeyOpenRouterRoutingMaxPrice       = "provider.openrouter.routing.max_price"
)
View Source
const (
	// DiscoveredModelsVersion is the current models.yaml schema version. It is written
	// on every store and lets future readers migrate or reject incompatible shapes.
	DiscoveredModelsVersion = 1
)
View Source
const KeyProviderPrefix = "provider."

Variables

View Source
var AuthDelete any = authDeleteValue{}

AuthDelete is the newValue sentinel passed to Persist/RewriteKey with KeyAuthOpenAIChatGPT to delete the stored ChatGPT session instead of writing one. Deleting an absent session is a no-op success that creates no file.

View Source
var ErrReservedProviderID = errors.New("provider.openai-chatgpt is reserved; its credentials are stored under auth.openai-chatgpt, not as a provider entry")

ErrReservedProviderID is returned by RewriteKey/Persist when a caller tries to write provider.openai-chatgpt. That provider id is built-in and reserved; a user-defined provider.openai-chatgpt entry is rejected at load, and its session credentials are stored only under auth.openai-chatgpt. The writer refuses it regardless of caller so the credential-write path is fail-closed.

Functions

func BlockedPathAdd

func BlockedPathAdd(home, item, heading string) any

func BlockedPathRemove

func BlockedPathRemove(home, path string, occurrence int) any

func Compose

func Compose(globalLayer, projectLayer map[string]any, localLayer ...map[string]any) (map[string]any, error)

localLayer is optional so the one production caller can adopt the third layer without changing shape; passing none composes exactly what two layers composed before.

func CopyLayer

func CopyLayer(raw map[string]any) map[string]any

CopyLayer deep-copies a decoded settings layer so a snapshot retained past composition shares no structure with the map Compose merges.

func DiscoveredModelsPath

func DiscoveredModelsPath(globalSettingsPath string) string

DiscoveredModelsPath returns the path of the shared discovered-model store for the given global settings file. The store sits beside settings.yaml in the global config directory. An empty settings path yields "" so a caller with no known settings location skips the store. The path is local only — reading or writing it performs no network I/O; writer and reader derive their target from this same helper so they cannot drift.

func EnforceGlobalOnly

func EnforceGlobalOnly(perProjectPath string, perProject map[string]any) error

EnforceGlobalOnly reports the first global-only key found in a decoded per-project settings map. The returned error's text matches the settings loader's schema-validation shape ("<file>: schema validation failed at <key>: <detail>") so callers render it with FormatLoadError under SchemaValidationError. It returns nil when the map carries no global-only key. Run it only on per-project maps after LoadYAML succeeds; the global file legitimately holds these keys.

func FormatLoadError

func FormatLoadError(path string, cat LoadFailure, err error, consequence LoadConsequence) string

FormatLoadError renders the stderr message for a non-LoadOK category, returning "" for LoadOK. The category tokens are an internal classification and never appear in the result.

func FormatYAMLParseFailure

func FormatYAMLParseFailure(src []byte, err error, consequence LoadConsequence) string

FormatYAMLParseFailure renders the same body FormatLoadError builds for a parse failure, without the path attribution, for a caller whose own error type supplies that attribution.

func LayerPermissions

func LayerPermissions(raw map[string]any, kind permissions.LayerKind) ([]permissions.PermissionEntry, error)

LayerPermissions stamps provenance as the layer is read — before anything is concatenated or deduplicated — so it can never be claimed by the file's own content.

func LocalSettingsLockPath

func LocalSettingsLockPath(projectRoot string) string

func LocalSettingsPath

func LocalSettingsPath(projectRoot string) string

LocalSettingsPath returns the per-user settings file inside the project root the active discovery.boundary already resolved. It stats nothing and never walks.

func LocateProjectRoot

func LocateProjectRoot(cwd string, mode string) (root string, layers []string, warnings []string, err error)

LocateProjectRoot resolves the project root for the given discovery boundary mode. cwd is the launch directory (the walk anchor), normalized to an absolute cleaned path; layers holds the discovered .codemeld/settings.yaml path (at most one). In project-root mode the walk skips non-anchor unreadable directories with a warning and stops at the innermost ancestor with a marker, falling back to the anchor if none match; an unreadable anchor yields a *AnchorReadError. Discovery is read-only.

func PermissionDelete

func PermissionDelete(dedupKey permissions.DedupKey) any

PermissionDelete is the newValue passed to Persist/RewriteKey with KeyPermissions to remove the permission entry whose identity matches dedupKey, instead of appending one. Removing an entry that is absent — no file, no permissions: key, or no matching entry — is a no-op success that creates no file.

func RewriteKey

func RewriteKey(path, key string, newValue any) (fsutil.AtomicWriteStep, fserrors.Category, error)

RewriteKey persists one codemeld-owned YAML key (KeyPermissions, KeyModelActive, KeyModelLastUsed, KeyAuthOpenAIChatGPT, KeyAttribution, or a KeyProviderPrefix+name provider entry) into the file at path, preserving every other top-level or nested key, comment, and adjacent whitespace byte-for-byte per step (3). newValue is a permissions.PermissionEntry for KeyPermissions, or any yaml.Marshal-able payload (typically yaml.MapSlice with provider/id/effort in that order) for the two model keys. For a KeyProviderPrefix+name key newValue is a yaml.Marshal-able provider.ProviderEntry shape, schema-validated before any write; writing provider.openai-chatgpt is refused (ErrReservedProviderID). Returns (zero, zero, nil) on success; fsutil.WriteAtomic's (step, cat, err) unchanged on atomic-write failure; or (fsutil.LoadStep, best-effort cat, err) for any pre-write failure with the on-disk file untouched.

func UpdateDiscoveredModelsProvider

func UpdateDiscoveredModelsProvider(path, providerID string, entry DiscoveredProvider) error

UpdateDiscoveredModelsProvider sets providerID's entry to models in the store at path, preserving every other provider's entry, and republishes the whole store owner-only and atomically under a sidecar lock. The read-merge-write happens under the lock so concurrent updates to different providers cannot lose each other's rows. It stamps the current schema version. An empty path is a no-op (nil error) so a caller with no known settings location silently skips persistence.

func UpdateDiscoveredModelsProviderThen

func UpdateDiscoveredModelsProviderThen(path, providerID string, entry DiscoveredProvider, then func() error) error

UpdateDiscoveredModelsProviderThen sets providerID's store entry, runs then while still holding the discovered-models lock, and restores the exact prior store bytes if then fails. This lets callers pair the store write with a later durable write without allowing concurrent store updates to be clobbered by rollback.

func Validate

func Validate(yamlBytes []byte, filePath string) error

Validate checks settings.yaml bytes against the embedded JSON Schema, using filePath only in error messages. Cross-reference checks (model.active / model.last_used) are intentionally not performed here.

func ValidatePermissionEntries

func ValidatePermissionEntries(path string, raw map[string]any) error

ValidatePermissionEntries rejects a layer holding an entry the schema admits but ParseEntry does not. Cache builds its permission view from the composed config, where deduplication can drop an invalid layer entry behind an equivalent one from another layer, so the entry has to be parsed at its source to be rejected at all.

func WarnIfBroaderThan0600

func WarnIfBroaderThan0600(path string)

WarnIfBroaderThan0600 emits one advisory stderr warning when the file's mode exposes any group/other bit. The global settings file holds plaintext credentials — provider API keys and, under, ChatGPT session tokens (auth.openai-chatgpt) — so the warning names both rather than API keys alone. Advisory only: the file is never rewritten or chmod'd. Suppressed on Windows and when the file is absent. The final component is inspected without following it, so a settings path that is a symbolic link — which the readers reject rather than follow — never produces a warning derived from its target's mode.

Types

type AnchorReadError

type AnchorReadError struct {
	Operation string
	Anchor    string
	Category  fserrors.Category
	Err       error
}

AnchorReadError reports that the walk anchor (the launch CWD) could not be listed, so the upward walk never started.

func (*AnchorReadError) Error

func (e *AnchorReadError) Error() string

func (*AnchorReadError) Unwrap

func (e *AnchorReadError) Unwrap() error

type Cache

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

Cache is the single, session-lifetime read source for composed configuration. It is built once from the composed config and never re-reads files so external edits to the on-disk YAML are deliberately invisible for the run (Non-Goals: "no live config reload during a running session"). In-process permission grants and model selections made via the write-back methods are visible to subsequent reads immediately but are not persisted to disk by those methods, and there is no general reload API.

ToggleFavorite, SetAttribution, and SetSharedTempFolders are the exceptions: they durably write the global settings layer through the locked writer and replace the cached value only from that write's confirmed result.

func NewCache

func NewCache(composed map[string]any, projectRoot string, layerPaths []string, home ...string) (*Cache, error)

func (*Cache) AgentInstructionsMaxFileBytes

func (c *Cache) AgentInstructionsMaxFileBytes() int

AgentInstructionsMaxFileBytes returns agent_instructions.max_file_bytes (default 65536).

func (*Cache) AgentMaxConcurrency

func (c *Cache) AgentMaxConcurrency() int

AgentMaxConcurrency returns agent.max_concurrency (default 3).

func (*Cache) AppendPermission

func (c *Cache) AppendPermission(e permissions.PermissionEntry)

AppendPermission adds an in-memory permission grant so it is visible to subsequent Permissions reads without re-reading config. The entry is taken already-typed: session-scoped grants that the on-disk parser rejects are stored here directly rather than round-tripped through it.

func (*Cache) Attribution

func (c *Cache) Attribution() bool

func (*Cache) DeclaredCommands

func (c *Cache) DeclaredCommands() []permissions.DeclaredCommand

func (*Cache) Discovery

func (c *Cache) Discovery() string

Discovery returns the discovery.boundary mode (default launch-dir-only when omitted).

func (*Cache) Favorites

func (c *Cache) Favorites() []Favorite

func (*Cache) LayerPaths

func (c *Cache) LayerPaths() []string

LayerPaths returns a copy of the ordered settings-layer paths that composed the session config; mutating it does not change the cache.

func (*Cache) LayeredPermissions

func (c *Cache) LayeredPermissions() []permissions.PermissionEntry

func (*Cache) MaxToolOutputBytes

func (c *Cache) MaxToolOutputBytes() int

MaxToolOutputBytes returns sessions.max_tool_output_bytes (default 65536, minimum 256).

func (*Cache) ModeDefault

func (c *Cache) ModeDefault() (mode string, configured bool)

ModeDefault returns the resolved launch default interaction mode (mode.default) and whether the key was present in the composed config. When the key is absent or not a string the mode falls back to "build" with configured=false; callers map the boolean to the interaction_mode source (false -> "default", true -> "config"). Enum validity of the value is enforced upstream by the settings schema and downstream by the interaction_mode event, mirroring how Discovery returns the raw boundary string without re-validating the enum.

func (*Cache) ModelActiveRaw

func (c *Cache) ModelActiveRaw() (any, bool)

ModelActiveRaw returns a copy of the raw model.active value and whether it is set. The value is left unvalidated for the model package's shape and cross-reference checks.

func (*Cache) ModelLastUsedRaw

func (c *Cache) ModelLastUsedRaw() (any, bool)

ModelLastUsedRaw returns a copy of the raw model.last_used value and whether it is set, left unvalidated for the model package's checks.

func (*Cache) OpenRouterDataCollection

func (c *Cache) OpenRouterDataCollection() string

func (*Cache) OpenRouterMaxPrice

func (c *Cache) OpenRouterMaxPrice(model string) (provider.MaxPrice, bool)

func (*Cache) OpenRouterSort

func (c *Cache) OpenRouterSort() string

func (*Cache) Permissions

func (c *Cache) Permissions() []permissions.PermissionEntry

Permissions returns a copy of the in-memory permission list (composed on-disk grants plus any session grants appended this run); mutating it does not change the cache.

func (*Cache) ProgramLookup

func (c *Cache) ProgramLookup() string

func (*Cache) ProjectRoot

func (c *Cache) ProjectRoot() string

ProjectRoot returns the resolved project root used for this session.

func (*Cache) Provider

func (c *Cache) Provider(name string) (provider.ProviderEntry, bool)

Provider returns a copy of the named provider entry and whether it is configured. The boolean distinguishes a missing provider from one configured with empty values, which model validation relies on.

func (*Cache) ProviderRetry

func (c *Cache) ProviderRetry() RetrySettings

ProviderRetry returns the resolved provider.retry auto-retry settings, filled with the hard-coded defaults for any omitted key. Enum/range validity is enforced upstream by the settings schema; this mirrors the other accessors' "return the configured value or the default" contract.

func (*Cache) Providers

func (c *Cache) Providers() map[string]provider.ProviderEntry

Providers returns a copy of every configured provider entry keyed by name; mutating the returned map or its entries does not change the cache.

func (*Cache) ReloadDiscoveredCatalog

func (c *Cache) ReloadDiscoveredCatalog()

func (*Cache) RemovePermission

func (c *Cache) RemovePermission(e permissions.PermissionEntry) bool

RemovePermission drops the first in-memory permission grant whose identity (DedupKey) matches e — the in-memory half of a grant revoke and the counterpart of AppendPermission — and reports whether it removed one. A caller that records a revoke needs that result: a false means the table never held the grant (a stale or duplicate request), so nothing was revoked to record. It matches a session grant the same way (the DedupKey carries grant_kind). Like AppendPermission it takes no lock of its own: a production caller mutating the live grant table must serialize this through the same holder that guards AppendPermission (bootstrap's syncGrants) so a concurrent prompt-gate append cannot race the removal. Previously returned Permissions slices are unaffected because Permissions clones before returning.

func (*Cache) RetentionDays

func (c *Cache) RetentionDays() int

RetentionDays returns sessions.retention_days (default 30).

func (*Cache) SelectableCatalog

func (c *Cache) SelectableCatalog() provider.Catalog

SelectableCatalog returns the merged selectable-provider catalog for this run: the configured provider.<name> entries plus the built-in providers that declare selectable models outside the provider: map (the OpenAI ChatGPT provider). It is the single cross-reference source for model validation, resume recovery, and no-selectable diagnostics, so a provider: openai-chatgpt selection validates against the built-in catalog rather than provider.openai-chatgpt.models. The returned catalog's accessors copy their entries, so the cached session view cannot be mutated through it.

func (*Cache) SetAttribution

func (c *Cache) SetAttribution(on bool) (PersistReason, fserrors.Category, error)

SetAttribution writes attribution to the global settings layer and, only once that write has succeeded, updates the session value Attribution reports. attribution is global-only (see firstGlobalOnlyViolation), so layerPaths[0] is both the sole source and the sole write target.

func (*Cache) SetLayeredPermissions

func (c *Cache) SetLayeredPermissions(entries []permissions.PermissionEntry)

SetLayeredPermissions labels each effective grant with the nearest layer holding it, which is not the surviving copy's layer: deduplication keeps the farthest one. A session grant appended later carries no layer.

func (*Cache) SetModelActiveRaw

func (c *Cache) SetModelActiveRaw(v any)

SetModelActiveRaw replaces the cached raw model.active value so later reads see the new selection immediately. It updates only this value; shape validation stays in the model package and persistence in the shared persistence path.

func (*Cache) SetModelLastUsedRaw

func (c *Cache) SetModelLastUsedRaw(v any)

SetModelLastUsedRaw replaces the cached raw model.last_used value visible to later reads immediately; validation and persistence stay elsewhere.

func (*Cache) SetOpenRouterConnection

func (c *Cache) SetOpenRouterConnection(baseURL, apiKey string)

func (*Cache) SetOpenRouterDataCollection

func (c *Cache) SetOpenRouterDataCollection(v string) (PersistReason, fserrors.Category, error)

func (*Cache) SetOpenRouterMaxPrice

func (c *Cache) SetOpenRouterMaxPrice(model string, p provider.MaxPrice) (PersistReason, fserrors.Category, error)

func (*Cache) SetOpenRouterSort

func (c *Cache) SetOpenRouterSort(v string) (PersistReason, fserrors.Category, error)

The cache never holds "default": the client sends any non-empty Sort as provider.sort.

func (*Cache) SetProvider

func (c *Cache) SetProvider(id string, entry provider.ProviderEntry)

SetProvider adds or replaces one composed provider entry and rebuilds the selectable catalog from the updated set, so a provider connected mid-session (via /connect, after its durable settings write) becomes selectable through the existing catalog surfaces — the model picker and /model — without a restart. It is the single-entry analogue of what NewCache does for the whole provider block: the rebuild runs through the same provider.BuildCatalog path, so a built-in selectable id (openai-chatgpt) still wins over a settings-shaped entry of the same name, and a configured provider with no settings model list picks up the ids discovered into the system-owned models.yaml store — so a /connect that writes models.yaml before this call makes those ids selectable now, with no restart. This does not persist anything — durable writes stay in config.Persist.

func (*Cache) SetRetentionDays

func (c *Cache) SetRetentionDays(days int) (PersistReason, fserrors.Category, error)

func (*Cache) SetSharedTempFolders

func (c *Cache) SetSharedTempFolders(allow bool) (PersistReason, fserrors.Category, error)

func (*Cache) SharedTempFolders

func (c *Cache) SharedTempFolders() (allowed, answered bool)

func (*Cache) ToggleFavorite

func (c *Cache) ToggleFavorite(target Favorite, want bool) ([]Favorite, PersistReason, fserrors.Category, error)

func (*Cache) VCSPreferred

func (c *Cache) VCSPreferred() string

VCSPreferred returns vcs.preferred, or "" when unset.

func (*Cache) VCSPriority

func (c *Cache) VCSPriority() []string

VCSPriority returns a copy of the vcs.priority tie-break order (default [git, hg, jj]); mutating it does not change the cache.

func (*Cache) WebResearch

func (c *Cache) WebResearch() WebResearchSettings

func (*Cache) WebResearchAPIKey

func (c *Cache) WebResearchAPIKey() string

The API key must not be logged, emitted, or included in errors or tool results.

type DiscoveredModel

type DiscoveredModel struct {
	ID              string         `yaml:"id"`
	DisplayName     string         `yaml:"display_name,omitempty"`
	ContextWindow   int64          `yaml:"context_window,omitempty"`
	InputModalities []string       `yaml:"input_modalities,omitempty"`
	Capabilities    map[string]any `yaml:"capabilities,omitempty"`
}

DiscoveredModel is one discovered model's whitelisted selection/capability metadata. Capabilities holds provider-specific fields (e.g. reasoning levels, verbosity) as a generic map so this package needs no provider-specific types. Producers should place only safe, non-secret values there; as a backstop the write path redacts secret-shaped keys and values (see sanitizeProvider) so auth material cannot reach the on-disk store.

type DiscoveredModelsStore

type DiscoveredModelsStore struct {
	Version   int                           `yaml:"version"`
	Providers map[string]DiscoveredProvider `yaml:"providers"`
}

DiscoveredModelsStore is the codemeld-owned, persisted discovered-model store. It is keyed by provider id so several providers share one file, and it carries only selection/capability metadata — never API keys, auth headers, prompts, or raw provider responses. The shape is deliberately generic (plain strings, ints, and a free-form capabilities map) so provider and bootstrap packages can populate it without internal/config depending on them.

func ReadDiscoveredModels

func ReadDiscoveredModels(path string) (DiscoveredModelsStore, error)

type DiscoveredProvider

type DiscoveredProvider struct {
	RefreshedAt string            `yaml:"refreshed_at,omitempty"`
	Source      string            `yaml:"source,omitempty"`
	Models      []DiscoveredModel `yaml:"models"`
}

DiscoveredProvider is one provider's discovered model list plus optional, secret-free refresh metadata. RefreshedAt/Source are advisory only; consumers must still tolerate their absence.

type Favorite

type Favorite struct {
	Provider string
	ID       string
}

Favorite is one favorited provider/model pair as stored in ordered model.favorites entries. Identity is exact string equality on both fields, so the same model ID offered by two providers stays two distinct favorites.

type LoadConsequence

type LoadConsequence string

LoadConsequence states what the failure did to the run in progress. The formatter cannot derive it: the same category aborts a launch from one caller and is only reported by another.

const LaunchAborted LoadConsequence = "codemeld did not start"

type LoadFailure

type LoadFailure string

LoadFailure classifies a settings/template load outcome; its string values are the category tokens reported on stderr.

const (
	LoadOK                LoadFailure = "none"
	UnreadableFile        LoadFailure = "unreadable_file"
	YAMLParseError        LoadFailure = "yaml_parse_error"
	SchemaValidationError LoadFailure = "schema_validation_error"
)

func LoadYAML

func LoadYAML(path string) (doc *ast.File, raw map[string]any, cat LoadFailure, err error)

LoadYAML reads and validates a settings or VCS-template YAML file, returning the comment-preserving AST and decoded raw map on success, or a non-LoadOK category and the underlying error on failure.

func LoadYAMLBytes

func LoadYAMLBytes(b []byte, path string) (doc *ast.File, raw map[string]any, cat LoadFailure, err error)

LoadYAMLBytes validates settings or VCS-template YAML the caller has already read. path names the source for diagnostics only and is never opened.

func ValidateGlobalSettingsBytes

func ValidateGlobalSettingsBytes(b []byte, path string) (raw map[string]any, cat LoadFailure, err error)

ValidateGlobalSettingsBytes applies every global-layer rule to settings bytes the caller has already read under its own bound. path names the source for diagnostics only and is never opened, so a caller that reads through a hardened descriptor keeps that guarantee.

func ValidateLocalSettingsBytes

func ValidateLocalSettingsBytes(b []byte, path string) (raw map[string]any, cat LoadFailure, err error)

func ValidateProjectSettingsBytes

func ValidateProjectSettingsBytes(b []byte, path string) (raw map[string]any, cat LoadFailure, err error)

type OpenRouterMaxPrice

type OpenRouterMaxPrice struct {
	Model string
	Price provider.MaxPrice
}

type PermissionDeleteOp

type PermissionDeleteOp struct {
	Key     permissions.DedupKey
	Removed bool
}

type PersistReason

type PersistReason string

PersistReason classifies the outcome of a Persist call in the vocabulary shared with the permission/model persist-failure events. ReasonNone covers a successful write; every other value is a distinct failure path.

const (
	ReasonNone             PersistReason = "none"
	ReasonLockTimeout      PersistReason = "lock_timeout"
	ReasonLockAcquireError PersistReason = "lock_acquire_error"
	ReasonRereadParseError PersistReason = "reread_parse_error"
	ReasonRereadIOError    PersistReason = "reread_io_error"
	ReasonWriteError       PersistReason = "write_error"
	ReasonRenameError      PersistReason = "rename_error"
	ReasonParentDirError   PersistReason = "parent_dir_error"
)

func Persist

func Persist(targetPath, key string, newValue any) (reason PersistReason, errCat fserrors.Category, err error)

Persist is the single internal chokepoint for every folder/global permission write and every model.active/model.last_used write, implementing the protocol: ensure the parent directory, take a 2-second advisory lock on the dedicated sidecar lock file (targetPath+".lock"), re-read and validate the latest contents, byte-preservingly merge newValue into key, write atomically, and release the lock. newValue is the matching payload RewriteKey expects for key. For KeyPermissions that is either a permissions.PermissionEntry to append an entry or a PermissionDelete(dedupKey) sentinel to remove one — both take this same sidecar-lock + re-read-validate + atomic-replace path. The model keys take a yaml-marshalable value.

The lock is held on the sidecar — never on targetPath itself — because every write replaces the settings file's inode via atomic rename, which would orphan a lock taken on that inode and break mutual exclusion for three or more concurrent writers. The lock does NOT create the settings file; an absent settings file is created by RewriteKey's atomic write under the held lock ("Create-file-if-absent").

On success it returns (ReasonNone, "", nil). On failure it returns the reason, the error category, and the underlying error. lock_timeout and reread_parse_error carry no category (the failure did not originate in an OS file syscall); every other failure carries the category observed by the helper that hit the OS error. For reason reread_parse_error, reread_io_error, lock_timeout, or lock_acquire_error the merge/write is skipped entirely and the existing file is left untouched (special branch).

targetPath is treated as final: callers snapshot the project-root path when the triggering prompt is raised ("write-target snapshot") and pass it in Persist does not re-resolve project root. The TUI notice and the persist-failure event are the caller's responsibility, so Persist performs no logging or event emission of its own.

func PersistLocal

func PersistLocal(projectRoot, key string, newValue any) (created bool, reason PersistReason, errCat fserrors.Category, err error)

PersistLocal is the single write path into the local settings file. created reports a write that made the file, derived from stats taken either side of the write rather than from inside Persist's lock window, so two processes creating it at once may both report it.

type RetrySettings

type RetrySettings struct {
	Enabled     bool
	MaxAttempts int
	BaseDelayMs int
	MaxDelayMs  int
}

RetrySettings is the resolved provider.retry auto-retry configuration: whether auto-retry is enabled, the total attempt cap (including the first), and the exponential-backoff base and cap in milliseconds. The per-turn retry wall-clock budget is not a settings knob — it has a fixed default applied at the turn layer.

type WebResearchSettings

type WebResearchSettings struct {
	Enabled        bool
	MaxResults     int
	TimeoutSeconds int
}

WebResearchSettings excludes the API key so formatted settings cannot disclose it.

Jump to

Keyboard shortcuts

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