{
  "$defs": {
    "CatalogAuditEntry": {
      "additionalProperties": false,
      "properties": {
        "service": {
          "title": "Service",
          "type": "string"
        },
        "seedable": {
          "title": "Seedable",
          "type": "boolean"
        },
        "model_deterministic": {
          "title": "Model Deterministic",
          "type": "boolean"
        },
        "image_tag_mutable": {
          "title": "Image Tag Mutable",
          "type": "boolean"
        },
        "notes": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Notes"
        }
      },
      "required": [
        "service",
        "seedable",
        "model_deterministic",
        "image_tag_mutable"
      ],
      "title": "CatalogAuditEntry",
      "type": "object"
    },
    "CatalogField": {
      "additionalProperties": false,
      "description": "One request parameter, rendered as one form control.",
      "properties": {
        "name": {
          "title": "Name",
          "type": "string"
        },
        "type": {
          "enum": [
            "text",
            "textarea",
            "number",
            "slider",
            "select",
            "bool",
            "file",
            "json"
          ],
          "title": "Type",
          "type": "string"
        },
        "label": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Label"
        },
        "required": {
          "default": true,
          "title": "Required",
          "type": "boolean"
        },
        "optional": {
          "default": false,
          "title": "Optional",
          "type": "boolean"
        },
        "togglable": {
          "default": false,
          "description": "When true, the consumer renders this field with an OFF-by-default enable switch; while off the control is disabled (excluded from submission) AND the field's default is NOT injected, so it is genuinely not sent until the user opts in. Requires optional=true. Used to keep advanced override fields (e.g. inline clone references) from silently overriding primary controls.",
          "title": "Togglable",
          "type": "boolean"
        },
        "default": {
          "default": null,
          "title": "Default"
        },
        "min": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Min"
        },
        "max": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Max"
        },
        "step": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Step"
        },
        "options": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/FieldOption"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Options"
        },
        "source_url": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Source Url"
        },
        "source_jsonpath": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Source Jsonpath"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "max_length": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Max Length"
        },
        "accepted_types": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Accepted Types"
        },
        "section": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Section"
        }
      },
      "required": [
        "name",
        "type"
      ],
      "title": "CatalogField",
      "type": "object"
    },
    "CatalogLatency": {
      "additionalProperties": false,
      "properties": {
        "cold_start_s": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Cold Start S"
        },
        "warm_per_unit": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Warm Per Unit"
        }
      },
      "title": "CatalogLatency",
      "type": "object"
    },
    "CatalogLifecycle": {
      "additionalProperties": false,
      "description": "Per-service orchestration metadata.\n\nPresence means \"asset_engine can start/stop this service from the UI\".\nAbsence (default) means \"managed externally \u2014 UI surfaces no controls.\"\nSee docs/contracts/orchestration.contract.md.\n\n  - stack:           directory name under /opt/docker/compose/ on the\n                     inference host (compose path derived).\n  - vram_gb:         VRAM the model needs at typical operating params.\n                     Used by the memory gate before docker compose up.\n  - gpu_device_id:   0 or 1 to pin to a specific card, None if the\n                     service uses both GPUs / picks dynamically. None\n                     means the gate must clear on each device.",
      "properties": {
        "stack": {
          "minLength": 1,
          "title": "Stack",
          "type": "string"
        },
        "vram_gb": {
          "exclusiveMinimum": 0,
          "title": "Vram Gb",
          "type": "number"
        },
        "gpu_device_id": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Gpu Device Id"
        }
      },
      "required": [
        "stack",
        "vram_gb"
      ],
      "title": "CatalogLifecycle",
      "type": "object"
    },
    "CatalogModel": {
      "additionalProperties": false,
      "properties": {
        "id": {
          "title": "Id",
          "type": "string"
        },
        "revision": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Revision"
        },
        "image": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Image"
        }
      },
      "required": [
        "id"
      ],
      "title": "CatalogModel",
      "type": "object"
    },
    "CatalogReproducibility": {
      "additionalProperties": false,
      "properties": {
        "seedable": {
          "title": "Seedable",
          "type": "boolean"
        },
        "deterministic": {
          "title": "Deterministic",
          "type": "boolean"
        },
        "notes": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Notes"
        },
        "seed_field": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Seed Field"
        }
      },
      "required": [
        "seedable",
        "deterministic"
      ],
      "title": "CatalogReproducibility",
      "type": "object"
    },
    "CatalogResponse": {
      "additionalProperties": false,
      "description": "How to interpret the inference response.\n\nThe `type` is the *renderer dispatch* \u2014 what kind of asset the user\nultimately sees (audio player, text block, etc). The other fields\ndescribe how to *extract* that asset from the wire shape:\n\n  - Raw-bytes wire (e.g. /v1/audio/speech returns raw audio):\n        type: audio\n        mime: audio/wav             (or mime_from_field for dynamic)\n\n  - JSON-envelope wire with base64-encoded asset (e.g. captioned\n    speech returns {audio: <b64>, audio_format: ..., timestamps: ...}):\n        type: audio\n        audio_field: audio          # JSON key with the base64 bytes\n        audio_format_field: audio_format    # JSON key with the MIME\n        timestamps_field: timestamps         # optional structured aside\n\n  - JSON-envelope wire with text payload (e.g. ASR transcript):\n        type: text\n        output_field: text          # JSON key with the text body\n        timestamps_field: segments   # optional, for ASR-with-timestamps\n\nRules:\n  - When audio_field is set, the renderer expects a JSON envelope and\n    will base64-decode that key. The wire MIME is application/json\n    regardless of `mime`; `mime_from_field` is incompatible.\n  - timestamps_field is independent of type \u2014 any service that\n    emits structured timestamps alongside its primary output can\n    declare it; the renderer extends accordingly.",
      "properties": {
        "type": {
          "enum": [
            "audio",
            "image",
            "video",
            "text",
            "json",
            "file"
          ],
          "title": "Type",
          "type": "string"
        },
        "mime": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Mime"
        },
        "mime_from_field": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Mime From Field"
        },
        "output_field": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Output Field"
        },
        "audio_field": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Audio Field"
        },
        "audio_format_field": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Audio Format Field"
        },
        "timestamps_field": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Timestamps Field"
        }
      },
      "required": [
        "type"
      ],
      "title": "CatalogResponse",
      "type": "object"
    },
    "CatalogSectionGroup": {
      "additionalProperties": false,
      "description": "A named group of fields, for progressive disclosure in form rendering.\n\nServices with many fields (ace-step has 27) declare section_groups and\ntag each field with a `section: <id>`. Consumers render fields grouped\nunder tabs / accordions / etc. Fields without a section go into an\nimplicit 'main' group rendered first.",
      "properties": {
        "id": {
          "title": "Id",
          "type": "string"
        },
        "label": {
          "title": "Label",
          "type": "string"
        },
        "hint": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Hint"
        }
      },
      "required": [
        "id",
        "label"
      ],
      "title": "CatalogSectionGroup",
      "type": "object"
    },
    "CatalogService": {
      "additionalProperties": false,
      "properties": {
        "id": {
          "title": "Id",
          "type": "string"
        },
        "name": {
          "title": "Name",
          "type": "string"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "category": {
          "enum": [
            "tts",
            "asr",
            "sfx",
            "music",
            "image",
            "multimodal"
          ],
          "title": "Category",
          "type": "string"
        },
        "version": {
          "title": "Version",
          "type": "integer"
        },
        "status": {
          "default": "ready",
          "enum": [
            "ready",
            "catalog-deferred",
            "experimental",
            "down"
          ],
          "title": "Status",
          "type": "string"
        },
        "host": {
          "title": "Host",
          "type": "string"
        },
        "endpoint": {
          "title": "Endpoint",
          "type": "string"
        },
        "method": {
          "default": "POST",
          "title": "Method",
          "type": "string"
        },
        "content_type": {
          "default": "application/json",
          "title": "Content Type",
          "type": "string"
        },
        "streamable": {
          "default": false,
          "title": "Streamable",
          "type": "boolean"
        },
        "model": {
          "$ref": "#/$defs/CatalogModel"
        },
        "fields": {
          "items": {
            "$ref": "#/$defs/CatalogField"
          },
          "title": "Fields",
          "type": "array"
        },
        "section_groups": {
          "items": {
            "$ref": "#/$defs/CatalogSectionGroup"
          },
          "title": "Section Groups",
          "type": "array"
        },
        "response": {
          "$ref": "#/$defs/CatalogResponse"
        },
        "reproducibility": {
          "$ref": "#/$defs/CatalogReproducibility"
        },
        "estimated_latency": {
          "anyOf": [
            {
              "$ref": "#/$defs/CatalogLatency"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "lifecycle": {
          "anyOf": [
            {
              "$ref": "#/$defs/CatalogLifecycle"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "license": {
          "title": "License",
          "type": "string"
        },
        "license_warning": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "License Warning"
        },
        "notes": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Notes"
        }
      },
      "required": [
        "id",
        "name",
        "category",
        "version",
        "host",
        "endpoint",
        "model",
        "response",
        "reproducibility",
        "license"
      ],
      "title": "CatalogService",
      "type": "object"
    },
    "FieldOption": {
      "additionalProperties": false,
      "description": "A select option. May be just the value (when label = value) or {value, label}.",
      "properties": {
        "value": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "integer"
            },
            {
              "type": "number"
            },
            {
              "type": "boolean"
            }
          ],
          "title": "Value"
        },
        "label": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Label"
        }
      },
      "required": [
        "value"
      ],
      "title": "FieldOption",
      "type": "object"
    }
  },
  "additionalProperties": false,
  "description": "Schema for the canonical inference-services catalog. The Python Pydantic model in asset_engine/catalog.py is the source of truth; this JSON Schema is a derived view for non-Python consumers.",
  "properties": {
    "catalog_version": {
      "default": 1,
      "title": "Catalog Version",
      "type": "integer"
    },
    "generated_at": {
      "anyOf": [
        {
          "format": "date-time",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Generated At"
    },
    "services": {
      "items": {
        "$ref": "#/$defs/CatalogService"
      },
      "title": "Services",
      "type": "array"
    },
    "reproducibility_audit": {
      "items": {
        "$ref": "#/$defs/CatalogAuditEntry"
      },
      "title": "Reproducibility Audit",
      "type": "array"
    }
  },
  "required": [
    "services"
  ],
  "title": "Asset Engine \u2014 services.yaml catalog",
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://eshpfi.local/schemas/services.schema.json"
}
