# Installation Model Catalog ThothII has one operator-authored model source: `modelCatalog` in `deploy//thothii-installation.yaml`. It declares models used by interactive Pi sessions, metadata generation, and the internal embedding service. Workspace descriptors never declare providers, model allowlists, defaults, embeddings, dimensions, or vector-store settings. Do not edit `deploy/pi/models.json`, `deploy/pi/settings.json`, files under `generated/`, or provider/model environment defaults. Those former sources are retired. ## Minimal catalog ```yaml schemaVersion: 2 modelCatalog: defaults: session: zai/glm-5.3 metadataGeneration: zai/glm-5.3 embedding: id: ollama/qwen3-embedding:0.6b dimensions: 1024 providers: zai: endpoint: baseUrl: https://api.z.ai/api/coding/paas/v4 authentication: mode: secret_env apiKeyEnv: ZAI_API_KEY session: mode: openai_compatible metadataGeneration: litellmProvider: openai models: glm-5.3: label: GLM 5.3 session: reasoning: true contextWindow: 200000 maxTokens: 131072 metadataGeneration: {} ``` Provider and model entries are maps. The keys form the canonical identity `/`; `label` is only display text. A model is eligible for a use only when it contains that use block: - `session` makes it selectable for interactive sessions; - `metadataGeneration` makes it selectable for description generation; - `embedding` is a single installation-level model rather than a selectable list. `defaults.session` is required. `defaults.metadataGeneration` is required exactly when at least one metadata-generation model exists. A session manifest pins its canonical identity, so removing a model never silently changes an existing session: resume fails with `model_unavailable`. ## Session adapters Use `pi_builtin` for a model whose technical definition ships with Pi: ```yaml deepseek: authentication: mode: pi_auth session: mode: pi_builtin models: deepseek-v4-pro: session: {} ``` Use `openai_compatible` for an explicit compatible endpoint. Each eligible session model must then declare the technical limits Pi needs. `upstreamModel` is optional and is used only when the endpoint expects a model name different from the catalog key. Provider integrations remain declarative. Do not register providers from `harness/.pi/extensions/`; those extensions implement the workflow and human gates only. ## Authentication Every provider chooses one explicit mode: - `secret_env` names an approved key in the protected ThothII secret bundle through `apiKeyEnv`; - `pi_auth` uses Pi's protected authentication projection and is valid only for session-only `pi_builtin` providers; - `none` is valid only with an explicit keyless endpoint. Secret values never belong in installation YAML, generated files, logs, CLI arguments, or browser requests. The YAML contains only an environment-variable name or an authentication mode. Pi's protected credential file remains selected by the installation authentication configuration. ## Generated runtime projections Before Compose starts, `tht` validates the installation and atomically writes deterministic files under `deploy//generated/`: ```text generated/ ├── catalog.json ├── pi/ │ ├── models.json │ └── settings.json └── compose.models.yaml ``` The normalized catalog is consumed by the backend. The Pi files and Compose override are boundary adapters. They are not configuration sources and are excluded from backup. Restore regenerates them from the installation descriptor. Run all lifecycle commands from the project root and select the descriptor explicitly when more than one installation exists: ```bash INSTALLATION=/absolute/path/deploy/example/thothii-installation.yaml tht --installation "$INSTALLATION" start tht --installation "$INSTALLATION" doctor ``` After editing `modelCatalog` or provider credentials, apply the complete runtime projection with the normal installation lifecycle, then run the Pi checks: ```bash tht --installation "$INSTALLATION" start tht --installation "$INSTALLATION" pi doctor tht --installation "$INSTALLATION" pi test ``` `tht pi restart`, `tht pi update`, and `tht pi rollback` refuse to run while generated model projections differ from `modelCatalog`: those commands recreate only `core`, so they must never partially apply an embedding change. `tht pi update` changes the Pi version; it is not the configuration command. There is no `tht pi configure` and no separate apply command. ## Migrating a legacy installation The migrator reads the former installation `metadataGeneration` block and the two former Pi JSON files, but never modifies them. Supply the facts that cannot be inferred safely and write a separate candidate: ```bash tht --installation /absolute/path/legacy/thothii-installation.yaml installation migrate \ --output /absolute/path/thothii-installation.v2.yaml \ --session-default zai/glm-5.3 \ --embedding-id ollama/qwen3-embedding:0.6b \ --embedding-dimensions 1024 ``` Review the candidate, move the legacy source files out of the installation only after approval, then select the v2 descriptor. Ambiguous aliases, endpoint conflicts, or missing authentication facts produce field-level errors; the migrator does not guess. ## Troubleshooting | Symptom | Meaning | Action | | --- | --- | --- | | `migration_required` | A retired model source or installation schema is still present | Run the installation migrator and review its candidate | | Unknown session or metadata default | The canonical ID is missing the corresponding use block | Correct the provider/model key or add the intended use block | | Generated projection drift | Runtime files differ from the descriptor-derived bytes | Run `tht start` or `tht pi restart --yes --drain` | | `model_unavailable` on resume | The session's pinned model is no longer session-eligible | Restore that catalog entry or keep the session unavailable; do not remap it | | Provider smoke failure | Credentials, endpoint, or provider availability is invalid | Correct the protected credential or catalog endpoint, restart, then run `tht pi test` |