Skip to main content

Module config

Module config 

Source
Expand description

§Layout

Mirrors upstream’s nested layout, so a ~/.pi/agent/ directory can be copied to ~/.rpi/agent/ (or pointed at via RPI_CODING_AGENT_DIR) and “just works”. The agent/ layer matches pi’s getAgentDir():

~/.rpi/                 (RPI_CODING_AGENT_DIR env overrides the agent/ dir)
└── agent/
    ├── auth.json       # persisted credentials (mode 0o600 on Unix)
    ├── models.json     # user-defined provider/model catalog (hand-edited)
    ├── settings.json   # saved default provider/model/thinking + theme
    ├── trust.json      # per-cwd project trust decisions (read-only parity)
    ├── .setup_done     # first-time-setup sentinel (extras.rs)
    └── .earendil_seen  # earendil-announcement sentinel (extras.rs)

Flat-installed ~/.rpi/{auth.json,models.json} from older rpi releases are migrated under agent/ on the next launch by migrate_legacy_layout (best-effort, idempotent; only when the env override is unset).

§Concurrency

v1 is a single-process CLI, so we use atomic rename instead of upstream’s proper-lockfile: write a sibling temp file, fs::rename over the target, then chmod 0o600 on Unix (Windows chmod is a no-op, matching Node). Concurrent rpi auth login from two shells could lose one update — that’s accepted and documented; adding a file lock is deferred.

§Config-value expansion

resolve_config_value expands $ENV/${ENV}/!command inside apiKey/headers exactly like upstream’s resolve-config-value.ts — so a copied pi models.json/auth.json that references env vars or shell commands resolves the same way. Applied where rpi consumes those values (auth.json key, models.json bearer apiKey, provider/model headers).

Structs§

ModelDefinition
One model under a provider. id is required (mirrors TS ModelDefinition).
ModelsConfig
The models.json document. Mirrors TS { providers: Record<id, ProviderConfig> } (core/model-config.ts ModelsConfigSchema).
ProviderConfig
A provider entry in models.json. The fields mirror the TS ProviderConfig one-for-one; v1 honors base_url/api_key/headers/auth_header/models, and ignores api values other than anthropic-messages (documented).

Enums§

ConfigError
A config-layer error (path resolution, IO, JSON). Surfaced to the user by the auth subcommand / provider::resolve.
Credential
A stored credential. Mirrors the TS Credential union (packages/ai/src/auth/types.ts). The Oauth variant exists for forward compatibility but v1 never writes it (no OAuth device-code flow); resolve does not consume it.

Constants§

ANTHROPIC_DEFAULT_BASE_URL
The first-party Anthropic endpoint — used as the fallback base_url when a models.json provider omits it. Kept here (not imported from rpi_ai) so the config layer never depends on the provider’s private models module. Public so crate::provider::resolve can tell a gateway model (whose base_url differs from this) from a built-in Anthropic model.
CONFIG_DIR_ENV
Env var that overrides the whole config dir (mirrors upstream PI_CODING_AGENT_DIR). Absolute path; relative values are rejected.
CONFIG_DIR_NAME
The config directory name under the home dir. Upstream is .pi; rpi uses .rpi to avoid colliding with a native pi install on the same machine.
DEFAULT_PROVIDER_ID
The provider id under which rpi auth login stores the Anthropic key. Mirrors upstream’s fixed anthropic provider id.

Functions§

agent_dir
The rpi config directory (~/.rpi/agent by default, RPI_CODING_AGENT_DIR override). Creates nothing — purely a path computation. The agent/ layer mirrors upstream getAgentDir() (join(homedir(), CONFIG_DIR_NAME, "agent")) so a copied ~/.pi/agent/ directory reads in place. The env override points at the agent dir itself (same as pi’s PI_CODING_AGENT_DIR).
auth_path
~/.rpi/agent/auth.json.
default_anthropic_base_url
Same value as ANTHROPIC_DEFAULT_BASE_URL, as an owned String for the unwrap_or_else ergonomic used by provider_to_models and [crate::provider::models_json_provider_auth].
delete_credential
Remove provider_id from the store. Returns true if a credential was present (and is now gone), false if it was already absent. Always rewrites the file when the provider existed (so auth logout reflects the new state on disk even if the map isn’t empty).
load_models_config
Load ~/.rpi/models.json. Missing file ⇒ empty config (no error).
migrate_legacy_layout
One-time best-effort migration of a pre-nesting flat layout (~/.rpi/{auth.json,models.json,.setup_done,.earendil_seen}) into the nested ~/.rpi/agent/ layout. No-op when RPI_CODING_AGENT_DIR is set (never touch an explicit override), when the agent dir already exists, or when no flat files are present. Idempotent: a partial move resumes. Errors are swallowed (logged via the returned Result only so tests can observe); app::run ignores them so a migration hiccup never blocks startup.
models_path
~/.rpi/agent/models.json.
openai_provider_api_key
Resolve an OpenAI-compatible provider key from its explicit config or a known provider’s canonical environment variable. Arbitrary custom provider ids must declare apiKey: "$ENV": deriving an env name by normalizing the id would collapse distinct native-Pi identities such as a-b and a_b.
project_trust_decision
Return the stored trust decision for cwd. A missing entry (or an entry explicitly set to null) returns None; callers choose their safe default.
provider_is_anthropic_compatible
(anthropic-messages, or omitted/unknown). Unknown api is allowed through for forward-compat but flagged ignored-in-v1 in the docs. Public so crate::provider can scan models.json providers for an authHeader:true gateway bearer source.
provider_is_openai_completions
Whether a configured provider uses the OpenAI Chat Completions protocol.
provider_is_openai_responses
provider_to_models
Convert a (provider_id, ProviderConfig) pair into a list of library Models. Provider-level base_url/headers/auth_header fold into each model. Returns None for protocols that do not have a runtime provider.
read_auth
Read the auth store. Missing file ⇒ empty store (not an error). Malformed JSON ⇒ ConfigError::Json (we do not silently swallow a corrupt auth file).
read_trust
Read ~/.rpi/agent/trust.json. Missing file ⇒ empty store (not an error). Malformed JSON ⇒ ConfigError::Json. null decisions deserialize as None; absent entries are simply not present.
resolve_config_value
Resolve a config value (API key, header value) that may be a shell command, an env-var template, or a literal — mirroring pi’s resolveConfigValue.
resolve_config_value_uncached
Like resolve_config_value but uncached — mirrors pi’s resolveConfigValueUncached, used when a fresh resolution is required (e.g. headers, which pi resolves uncached so a rotating token is re-read).
resolve_headers
Resolve every header value via resolve_config_value_uncached; drop entries that resolve to None (mirrors pi resolveHeaders). Used on models.json headers maps before folding onto a model.
set_project_trust
Persist the trust decision for a project directory. The path is canonical when it exists, with an absolute fallback for a project being created.
settings_path
~/.rpi/agent/settings.json (saved default provider/model/thinking + theme).
trust_path
~/.rpi/agent/trust.json (per-cwd project trust decisions).
upsert_credential
Read-modify-write: upsert a credential for provider_id.
write_auth
Atomically write the whole auth store (ensures the dir exists, writes a temp sibling, renames over the target, then chmod 0o600 on Unix).

Type Aliases§

AuthStore
The auth store: providerId -> Credential. Mirrors upstream Record<providerId, Credential>.
TrustStore
The trust store: canonicalCwd -> decision (true/false/null). Mirrors pi’s TrustFile = Record<string, boolean | null | undefined> (trust-manager.ts). rpi reads this for layout parity (a copied pi trust.json parses + is located correctly) but does not gate any project resources behind trust in v1 — there is no trust prompt. Deferred.