openapi: 3.1.0 info: title: Texture Agent Service description: "# Texture Agent Service\n\nFastAPI service for AI-driven texture generation\ \ on materialized USD assets. Wraps the [Texture Agent](../texture_agent/) pipeline\ \ behind a REST API with session management, async progress streaming via Server-Sent\ \ Events (SSE), and Docker-ready deployment.\n\n## Default backends (product-default\ \ change)\n\nThe service ships with an NVIDIA-first default stack:\n\n| Role |\ \ Default | Env var | Model |\n|---|---|---|---|\n| Image generation | `nim` |\ \ `TA_IMAGE_GEN_BACKEND` | `black-forest-labs/flux_2-klein-4b` (build.nvidia.com)\ \ |\n| Auto-prompt LLM | `nim` | `TA_LLM_BACKEND` | `google/gemma-4-31b-it`\ \ (build.nvidia.com) |\n\nBoth honor `NVIDIA_API_KEY`. One key unlocks the whole\ \ default path.\n\n> **PBR coherence trade-off \u2014 read before deploying.**\n\ >\n> The cloud `nim` image-gen endpoint does not accept reference images, so\n\ > the normal- and roughness-map passes (which otherwise condition on the\n> generated\ \ albedo) run text-only on the default path. The pipeline still\n> produces a\ \ full PBR set, but the normal/roughness maps are less coherent\n> with the albedo\ \ than on a conditioning-capable backend. The pipeline\n> logs one warning per\ \ run to the service stdout (visible via\n> `docker logs texture-agent-service`)\ \ so operators can tell at a glance\n> whether a given run went through the text-only\ \ path.\n>\n> To keep full PBR coherence:\n> - run `docker compose --profile image-gen`\ \ (local FLUX.2 NIM sidecar \u2014\n> same model, but exposes `images.edit`\ \ and supports conditioning), **or**\n> - set `TA_IMAGE_GEN_BACKEND=gemini` or\ \ `TA_IMAGE_GEN_BACKEND=openai`\n> (both support img2img, but leave the NVIDIA-only\ \ stack).\n>\n> See the [root README](../../README.md) system requirements and\n> [`../texture_agent/examples/`](../texture_agent/examples/)\ \ for the runnable\n> simple image-gen example.\n\n## Quick Start (Docker)\n\n\ Requires **Docker Compose v2.24+** (for `env_file: required: false` support).\n\ \n```bash\n# From the repo root -- set your image-gen provider key\n# (NIM or\ \ Gemini). The compose file reads .env at the repo root\n# via env_file.\necho\ \ 'NVIDIA_API_KEY=your_key' > .env\n\n# Build and run. `--env-file .env` is required\ \ so that any `${VAR}`\n# overrides in compose (e.g. `TA_IMAGE_GEN_BACKEND=gemini`)\ \ read from\n# the repo-root `.env`. Without it, Compose's variable substitution\n\ # looks for `.env` next to the compose file\n# (`apps/texture_agent_service/.env`)\ \ and silently falls back to the\n# built-in defaults.\ndocker compose --env-file\ \ .env \\\n -f apps/texture_agent_service/docker-compose.yml up --build\n\n#\ \ Service available at http://localhost:8001\n```\n\nBy default the texture service\ \ does not start GPU sidecars; texture generation\nruns against the configured\ \ image-gen backend and cold start is fast.\n\n### Texture Variation API Backend\n\ \nThe public 0.5 source release ships the service backend contract and the\nStep1X-compatible\ \ adapter, but does not ship a managed Step1X runtime,\ndownloader/setup package,\ \ model checkpoints, or runtime cache layout. To use a\nTexture Variation API-compatible\ \ backend, deploy that backend separately after\nyour own security and legal review,\ \ then configure Texture Agent to call it:\n\n```bash\nTA_TEXTURE_BACKEND=service\ \ \\\nTA_TEXTURE_ENDPOINT=http://texture-variation-backend:8000 \\\nTA_BACKEND_ENGINE=step1x\ \ \\\ndocker compose --env-file .env \\\n -f apps/texture_agent_service/docker-compose.yml\ \ \\\n up --build\n```\n\nUse the optional `docker-compose.step1x.yml` overlay\ \ only when you have already\nmounted a complete external runtime for `texture-gen-step1x`:\n\ \n```bash\nTEXTURE_STEP1X_HOST_RUNTIME=/path/to/reviewed/texture-editing-runtime\ \ \\\ndocker compose --env-file .env \\\n -f apps/texture_agent_service/docker-compose.yml\ \ \\\n -f apps/texture_agent_service/docker-compose.step1x.yml \\\n up --build\n\ ```\n\nThat overlay starts the API adapter and OVRTX sidecar, routes\n`TA_TEXTURE_ENDPOINT=http://texture-gen-step1x:8000`,\ \ and requires the runtime\nto be supplied through `TEXTURE_STEP1X_HOST_RUNTIME`.\ \ It does not download or\ninstall Step1X, Material Anything, Swin2SR, Kaolin,\ \ nvdiffrast, or model\ncheckpoints.\n\n## Quick Start (Local Dev)\n\n```bash\n\ # From repo root\nsource .venv/bin/activate\n\n# Install\nuv pip install -e \"\ .[dev]\"\nuv pip install -e apps/texture_agent -e apps/texture_agent_service\n\ \n# Configure\ncp .env_example .env\n# Edit .env to set NVIDIA_API_KEY or GOOGLE_API_KEY\n\ \n# Run\ntexture-agent-service\n# or: uvicorn service.main:app --host 0.0.0.0\ \ --port 8001\n```\n\n## API\n\n- **Interactive docs:** http://localhost:8001/docs\ \ (Swagger UI) once the service is running.\n- **Full reference:** [`docs/api.md`](docs/api.md).\n\ - **Brev deployment planning:** [`docs/brev.md`](docs/brev.md).\n- **OpenAPI spec:**\ \ [`openapi.yaml`](openapi.yaml).\n\nThe pipeline endpoints (`POST /pipeline/upload-usd`,\ \ `POST /pipeline`, `GET /pipeline/{id}/status`, etc.) accept a materialized USD\ \ file (typically the output of the Material Agent) and a per-material texture\ \ prompt map, then run the texture discovery / generation / apply pipeline. Stream\ \ real-time progress over SSE at `GET /pipeline/{id}/events`. Download textured\ \ output USDZ, textures, and the run manifest via `/artifacts/{id}/output`, `/artifacts/{id}/textures`,\ \ and `/artifacts/{id}/manifest`.\n\nFor release validation, the service path should\ \ agree with the CLI path on the\nprimary ladder fixture: four discovered materials,\ \ one generated texture set\nwhen only `Aluminum_Matte` is provided in `material_textures_json`\ \ with\n`auto_prompt_enabled=false`, matching output USD counts, and the same\ \ UV/report\ndiagnostics. Omitting `auto_prompt_enabled` preserves the service's\ \ legacy\nauto-prompting behavior. The repeatable fake-backend smoke test is\n\ `apps/texture_agent_service/tests/unit/test_issue31_validation_smoke.py`;\nreal\ \ NIM/Gemini service runs should be recorded as manual evidence, not as the\n\ only gate.\n\n### Session Cleanup\n\nLong-lived deployments should delete sessions\ \ after downloading required artifacts so session storage does not grow indefinitely:\n\ \n```bash\ncurl -X DELETE http://localhost:8001/sessions/$SESSION_ID\n```\n\n\ `DELETE /sessions/{session_id}` returns `204 No Content` when the session, stored\ \ artifacts, and in-memory progress state are removed. It returns JSON `404 Not\ \ Found` when the session does not exist, and JSON `409 Conflict` when a live\ \ pipeline job is still active or a worker lock shows artifact writes are still\ \ in progress; cancel the pipeline and wait for the worker to stop before deleting\ \ it. If a service restart leaves a persisted `cancelling` status with no live\ \ worker lock, deletion is allowed so stale artifacts can be cleaned up.\n\n###\ \ Artifact Response Types\n\nThe `/artifacts/{session_id}/...` routes use per-kind\ \ response media types:\n\n| Endpoint | Success media type | Payload |\n|----------|--------------------|---------|\n\ | `GET /artifacts/{session_id}/materials` | `application/json` | Discovered material\ \ metadata |\n| `GET /artifacts/{session_id}/manifest` | `application/json` |\ \ Schema-versioned artifact manifest |\n| `GET /artifacts/{session_id}/textures`\ \ | `application/zip` | ZIP containing generated textures under `textures/` |\n\ | `GET /artifacts/{session_id}/textures/{filename}` | `image/png` | Single texture\ \ image |\n| `GET /artifacts/{session_id}/output` | `model/vnd.usdz+zip` | Self-contained\ \ textured USDZ |\n| `GET /artifacts/{session_id}/renders` | `application/zip`\ \ | ZIP containing final rendered images under `renders/` |\n| `GET /artifacts/{session_id}/renders/{filename}`\ \ | `image/png` | Single render image |\n| `GET /artifacts/{session_id}/preview/{filename}`\ \ | `image/png` | Single material preview image |\n\nError responses, including\ \ missing artifacts, are JSON.\n\n## Python Client\n\n```python\nfrom client.client\ \ import TextureAgentClient\n\nclient = TextureAgentClient(\"http://localhost:8001\"\ )\n\n# Upload and run\nsession_id, status = client.run_and_monitor(\n usd_path=\"\ scene.usd\",\n material_textures={\n \"Steel_Carbon\": {\n \ \ \"prompt\": \"rusted steel\",\n \"opacity\": 0.85,\n },\n\ \ },\n auto_prompt_enabled=False, # strict material_textures scope\n)\n\ \n# Download artifacts\nclient.download_output(session_id, \"output.usdz\")\n\ client.download_textures(session_id, \"./textures/\")\n\n# Delete the session\ \ after required artifacts are downloaded\nclient.delete_session(session_id)\n\ ```\n\nThe bundled CLI exits with status `0` only after the final pipeline status\ \ is\n`completed`. Scripted callers that intentionally stop client polling early\n\ should keep the printed session ID and poll `GET /pipeline/{id}/status` before\n\ deciding whether a nonzero client exit is a hard failure.\n\nProjection backend\ \ runs use the same client helper with the `service` texture\nbackend and an endpoint.\ \ Global conditioning is merged with material-specific\nconditioning before each\ \ Issue #116 texture variation request:\n\n```python\nsession_id, status = client.run_and_monitor(\n\ \ usd_path=\"ladder.usd\",\n material_textures={\n \"Aluminum_Matte\"\ : {\n \"prompt\": \"matte aluminum\",\n \"reference_image_uris\"\ : [\"file:///refs/aluminum.png\"],\n },\n },\n auto_prompt_enabled=False,\n\ \ texture_backend=\"service\",\n texture_endpoint=\"http://localhost:8011\"\ ,\n backend_engine=\"fake_projection\",\n backend_custom_parameters={\"\ variant\": \"success_full_pbr\"},\n reference_image_uris=[\"file:///refs/ladder.png\"\ ],\n reference_image_path=\"reference.png\",\n multiview_image_uris=[\"\ file:///refs/view0.png\"],\n seed=11631,\n strength=0.8,\n strict_scope=True,\n\ )\n```\n\nFor AOI, CAD, PCB, or SimReady-style assets where traces, vias, pads,\ \ labels,\nholes, seams, components, or markings already exist as modeled geometry,\ \ pass\n`detail_policy=\"surface_only\"` globally or set `detail_policy` inside\ \ a material\nor per-prim entry in `material_textures`. This adds conservative\ \ prompt\nconditioning for simple image generation and passes policy metadata\ \ to\nprojection backends.\n\nFor the command-line client wrapper, pass `--disable-auto-prompt`\ \ to send\n`auto_prompt_enabled=false` and keep the run scoped to `material_textures`.\n\ Use `--detail-policy surface_only` for the global conservative/AOI policy.\n\n\ ## Configuration\n\nService configuration is loaded from environment variables\ \ at startup. Key\nsettings are below. Docker Compose packages may set topology-specific\ \ overrides\nsuch as external Texture Variation API or OVRTX sidecar endpoints.\n\ \n| Variable | Default | Description |\n|----------|---------|-------------|\n\ | `NVIDIA_API_KEY` | - | API key for NIM image generation |\n| `GOOGLE_API_KEY`\ \ | - | API key for Gemini image generation |\n| `TA_TEXTURE_BACKEND` | `simple_image_gen`\ \ | Texture gen backend |\n| `TA_TEXTURE_ENDPOINT` | - | Default Texture Variation\ \ API endpoint when `TA_TEXTURE_BACKEND=service` |\n| `TA_BACKEND_ENGINE` | -\ \ | Default Texture Variation API engine/model hint, e.g. `step1x` |\n| `TA_IMAGE_GEN_BACKEND`\ \ | `nim` | Image gen backend (`nim`, `gemini`, `openai`) |\n| `TA_IMAGE_GEN_BASE_URL`\ \ | - | Override image-gen base URL; used by the multi-gpu overlay to route to\ \ the local FLUX sidecar |\n| `TA_IMAGE_GEN_API_KEY` | - | Endpoint-specific image-gen\ \ key; the local NIM overlay sets `not-used` in Compose |\n| `TA_TEXTURE_SIZE`\ \ | `1024` | Texture resolution |\n| `TA_TEXTURE_WORKERS` | `4` | Parallel gen\ \ workers |\n| `TA_TEXTURE_JOB_TIMEOUT_SEC` | `3600` | Per-material service backend\ \ wait timeout; raise for slow Step1X GPU jobs |\n| `TA_AUTO_PROMPT_MAX_GENERATED_MATERIALS`\ \ | `64` | Maximum missing materials auto-prompt may select before requiring explicit\ \ scope; `0` disables the guard |\n| `TA_TEXTURE_PLAN_DEFAULT_CAP` | `32` | Generic/simple-image-gen\ \ planning default from `texture-agent-plan.v1` |\n| `TA_TEXTURE_PLAN_UV_AWARE_DEFAULT_CAP`\ \ | `16` | UV-aware/service and Step1X planning default from `texture-agent-plan.v1`\ \ |\n| `TA_TEXTURE_PLAN_HARD_CAP` | `64` | Immutable planning maximum; plans above\ \ it require consolidation or narrower scope before backend work |\n| `TA_MAX_TEXTURE_UNITS`\ \ | `64` | Compatibility executor guard from issue #463; keep aligned with the\ \ planning hard cap. It is not the normal selection default |\n| `TA_BLEND_OPACITY`\ \ | `0.85` | Default blend opacity |\n| `TA_UV_POLICY` | `generate_missing` |\ \ UV prep policy for service-created pipelines (`generate_missing`, `force_projection`,\ \ etc.) |\n| `TA_UV_SCOPE` | `stage` | UV preparation scope; use `target_prims`\ \ only with explicit prim targets |\n| `TA_UV_BACKEND` | `python` | UV prep backend\ \ |\n| `TA_UV_PROJECTION` | `box` | Projection mode used when UVs are generated\ \ |\n| `TA_UV_OVERWRITE_EXISTING` | `false` | Whether generated UVs overwrite\ \ existing UV primvars |\n| `TA_UV_REBAKE_SOURCE_ALBEDO` | `false` | Rebake source\ \ albedo when scoped projection UVs are generated |\n| `TA_UV_REBAKE_SIZE` | -\ \ | Optional source texture rebake resolution |\n| `TA_UV_NORMALIZE_OUT_OF_RANGE`\ \ | `false` | Whether out-of-range UVs are normalized during UV prep |\n| `TA_RENDER_ENABLED`\ \ | `false` | Enable final render step for service-created pipelines |\n| `RENDER_ENDPOINT`\ \ | - | Remote renderer endpoint used by final render tasks |\n| `TEXTURE_STEP1X_HOST_RUNTIME`\ \ | - | Host runtime directory for the optional external Step1X-compatible adapter\ \ overlay |\n| `TEXTURE_GEN_SIMPLE_ENV_FILE` | `/dev/null` | Optional extra env\ \ file for the simple sidecar, useful when provider keys live outside this checkout\ \ |\n| `TEXTURE_STEP1X_GPU_DEVICE` | `0` | GPU device ID for the Step1X sidecar\ \ |\n| `OVRTX_GPU_DEVICE` | `1` | GPU device ID for the OVRTX sidecar; set both\ \ GPU vars to `0` on one-GPU hosts |\n| `TEXTURE_STEP1X_PYTHON` | - | Advanced\ \ override for custom mounted runtimes |\n| `TEXTURE_STEP1X_LD_LIBRARY_PATH` |\ \ reference `.venv_gen` torch/CUDA libs | Advanced override when a custom mounted\ \ runtime stores CUDA libraries outside the reference layout |\n| `TEXTURE_STEP1X_HEALTHCHECK_RUNTIME_IMPORTS`\ \ | readiness healthcheck `true` | Enables cached torch/CuPy/NVRTC runtime preflight\ \ when `healthcheck.py` checks `/health` |\n| `TEXTURE_STEP1X_HEALTHCHECK_TIMEOUT`\ \ | `180s` | Docker healthcheck timeout; relevant to cold runtime imports only\ \ for readiness healthchecks |\n| `TA_RENDER_PREVIEWS_ENABLED` | `false` | Enable\ \ material preview render step |\n| `TA_RENDER_IMAGE_WIDTH` / `TA_RENDER_IMAGE_HEIGHT`\ \ | `1024` / `1024` | Final render dimensions |\n| `TA_RENDER_PREVIEW_IMAGE_WIDTH`\ \ / `TA_RENDER_PREVIEW_IMAGE_HEIGHT` | `512` / `512` | Material preview render\ \ dimensions |\n| `TA_SESSION_STORAGE_PATH` | `/var/texture-agent/sessions` |\ \ Session storage |\n| `TA_SESSION_TTL_HOURS` | `24` | Session expiry |\n| `TA_STORAGE_KIND`\ \ | `local` | Session store backend (`local` or `s3`) |\n| `TA_STORAGE_S3_BUCKET`\ \ | `WU_S3_BUCKET` | S3 bucket for shared sessions |\n| `TA_STORAGE_S3_PREFIX`\ \ | - | Prefix for shared session objects |\n| `TA_STORAGE_S3_REGION` | `WU_S3_REGION`\ \ | S3 region |\n| `TA_STORAGE_S3_PROFILE` | `WU_S3_PROFILE` | Optional AWS profile\ \ for local/dev runs |\n| `TA_STORAGE_S3_ENDPOINT_URL` | - | Optional S3-compatible\ \ endpoint URL |\n| `TA_STORAGE_S3_PRESIGN` | `true` | Return presigned artifact\ \ URLs when possible |\n| `TA_STORAGE_S3_MAX_POOL_CONNECTIONS` | `64` | S3 client\ \ connection pool size |\n| `TA_MAX_ACTIVE_SESSIONS` | `4` | Max concurrent pipelines,\ \ read when the registry starts. Invalid or negative values fall back to `4`; `0` permits\ \ no active executions. |\n| `TA_CANCEL_DRAIN_TIMEOUT_SECONDS` | `30.0` | Seconds a cancelled request\ \ waits for a synchronous worker thread to stop before marking the session failed\ \ with a stalled-worker deletion guard |\n| `TA_MAX_UPLOAD_SIZE_MB` | `500` |\ \ Max USD upload size |\n\nFor multi-instance deployments, use `TA_STORAGE_KIND=s3`\ \ and configure the S3\nbucket, prefix, region, and credentials before increasing\ \ replicas. Local\nstorage is single-instance only because each pod sees only\ \ its own session\ndirectory. The Helm chart exposes the same settings under `sessionStorage.*`;\n\ keep `replicaCount: 1` unless `sessionStorage.kind` is `s3`. If both explicit\n\ S3 credentials and `TA_STORAGE_S3_PROFILE` are configured, the explicit\ncredentials\ \ take precedence; if the named profile is unavailable, the service\nfalls back\ \ to the default boto3 credential chain.\n\n## Project Structure\n\n```\ntexture_agent_service/\n\ \u251C\u2500\u2500 client/ # Python client (client.py)\n\u251C\ \u2500\u2500 docs/ # Documentation (api.md REST reference)\n\ \u251C\u2500\u2500 service/ # FastAPI app, routers, runtime,\ \ storage\n\u251C\u2500\u2500 tests/ # Test suite\n\u251C\ \u2500\u2500 docker-compose.yml # Docker Compose\n\u251C\u2500\u2500\ \ Dockerfile # Service image\n\u251C\u2500\u2500 openapi.yaml\ \ # API specification\n\u2514\u2500\u2500 pyproject.toml \ \ # Install metadata\n```\n" version: 0.5.2 paths: /pipeline/upload-usd: post: tags: - pipeline summary: Upload Usd Immediate description: 'Upload a USD file and create a session for later pipeline execution. Provide exactly one of these two input modes: 1. **File upload**: Provide ``usd_file`` (multipart). 2. **S3 reference**: Provide ``s3_uri`` -- the service downloads server-side. Client S3 access is fail-closed: the exact bucket name must be listed in ``TA_S3_ALLOWED_BUCKETS``, and an empty allowlist rejects every client S3 URI before session-manager or S3 I/O. Use the returned session_id with ``POST /pipeline`` to start processing.' operationId: upload_usd_immediate_pipeline_upload_usd_post requestBody: content: multipart/form-data: schema: $ref: '#/components/schemas/Body_upload_usd_immediate_pipeline_upload_usd_post' responses: '201': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/SessionCreated' '400': description: Missing, conflicting, or invalid input source, including an unsupported USD extension. content: application/json: schema: $ref: '#/components/schemas/ErrorDetail' '403': description: Client S3 URI rejected by the configured bucket allowlist, or S3 access denied. content: application/json: schema: $ref: '#/components/schemas/ErrorDetail' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /pipeline: post: tags: - pipeline summary: Create Pipeline description: 'Create and execute a texture generation pipeline. Provide at least one of these three input modes: 1. **Existing session**: Provide ``session_id`` (from ``/upload-usd``). 2. **S3 reference**: Provide ``s3_uri``, downloads from S3 server-side. 3. **File upload**: Provide ``usd_file``, creates new session. When multiple sources are supplied, selection follows the legacy precedence ``session_id`` > ``s3_uri`` > ``usd_file`` and lower-priority fields are ignored. A selected S3 source is admitted only when its exact bucket name is listed in ``TA_S3_ALLOWED_BUCKETS``; an empty allowlist rejects every client S3 input before session-manager or S3 I/O. Optionally provide ``material_textures_json`` to specify per-material texture prompts, blend opacity, and per-prim overrides.' operationId: create_pipeline_pipeline_post requestBody: content: multipart/form-data: schema: $ref: '#/components/schemas/Body_create_pipeline_pipeline_post' responses: '202': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/SessionCreated' '400': description: Missing, conflicting, or invalid input source, including an unsupported USD extension. content: application/json: schema: $ref: '#/components/schemas/ErrorDetail' '403': description: Client S3 URI rejected by the configured bucket allowlist, or S3 access denied. content: application/json: schema: $ref: '#/components/schemas/ErrorDetail' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /pipeline/{session_id}/plan: get: tags: - pipeline summary: Get Pipeline Plan description: Return the validated immutable texture plan when planning is complete. operationId: get_pipeline_plan_pipeline__session_id__plan_get parameters: - name: session_id in: path required: true schema: type: string title: Session Id responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/TexturePlan' '404': content: application/json: schema: {} description: Not Found '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /pipeline/{session_id}/status: get: tags: - pipeline summary: Get Pipeline Status description: 'Get pipeline execution status with detailed progress. Uses the same merged disk+bus view as ``/sessions/{sid}`` so the two endpoints agree on every observable field for the same session, even when the executor''s outer exception handler persists a terminal disk status without emitting a corresponding bus event.' operationId: get_pipeline_status_pipeline__session_id__status_get parameters: - name: session_id in: path required: true schema: type: string title: Session Id responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/PipelineStatus' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /pipeline/{session_id}/results: get: tags: - pipeline summary: Get Pipeline Results description: 'Get pipeline execution results (only available when completed). Reads from the same merged disk+bus view as ``/sessions/{sid}`` and ``/pipeline/{sid}/status``: when the bus has reached a terminal status but ``_persist_status`` hasn''t yet awaited its disk write, a disk-only read here would briefly return 202 ("still running") while the other two endpoints already report "completed".' operationId: get_pipeline_results_pipeline__session_id__results_get parameters: - name: session_id in: path required: true schema: type: string title: Session Id responses: '200': description: Successful Response content: application/json: schema: anyOf: - $ref: '#/components/schemas/PipelineResults' - $ref: '#/components/schemas/PipelineError' title: Response Get Pipeline Results Pipeline Session Id Results Get '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /pipeline/{session_id}/cancel: post: tags: - pipeline summary: Cancel Pipeline description: Cancel a running pipeline. operationId: cancel_pipeline_pipeline__session_id__cancel_post parameters: - name: session_id in: path required: true schema: type: string title: Session Id responses: '200': description: Successful Response content: application/json: schema: {} '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /pipeline/{session_id}/events: get: tags: - pipeline summary: Stream Progress Events description: "Stream real-time progress events via Server-Sent Events (SSE).\n\ \nExample client (JavaScript):\n const eventSource = new EventSource(`/pipeline/${sessionId}/events`);\n\ \ eventSource.addEventListener('progress', (e) => {\n const data\ \ = JSON.parse(e.data);\n console.log(`Step: ${data.step}, Progress:\ \ ${data.percent}%`);\n });" operationId: stream_progress_events_pipeline__session_id__events_get parameters: - name: session_id in: path required: true schema: type: string title: Session Id responses: '200': description: Successful Response content: application/json: schema: {} '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /pipeline/{session_id}/regenerate: post: tags: - pipeline summary: Regenerate Pipeline description: 'Regenerate specific pipeline steps from cached data. Useful for re-running texture generation with different prompts/opacity without re-discovering materials.' operationId: regenerate_pipeline_pipeline__session_id__regenerate_post parameters: - name: session_id in: path required: true schema: type: string title: Session Id requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RegenerateRequest' responses: '202': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/SessionCreated' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /pipeline/{session_id}/event-log: get: tags: - pipeline summary: Get Event Log description: Get the persisted event log for a session with sanitized diagnostics. operationId: get_event_log_pipeline__session_id__event_log_get parameters: - name: session_id in: path required: true schema: type: string title: Session Id responses: '200': description: Successful Response content: application/json: schema: type: object additionalProperties: true title: Response Get Event Log Pipeline Session Id Event Log Get '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /artifacts/{session_id}/materials: get: tags: - artifacts summary: Download Materials description: Download discovered materials JSON file. operationId: download_materials_artifacts__session_id__materials_get parameters: - name: session_id in: path required: true schema: type: string title: Session Id responses: '200': description: Successful Response content: application/json: schema: {} '404': content: application/json: schema: {} description: Not Found '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /artifacts/{session_id}/manifest: get: tags: - artifacts summary: Download Manifest description: Download the run artifact manifest JSON file. operationId: download_manifest_artifacts__session_id__manifest_get parameters: - name: session_id in: path required: true schema: type: string title: Session Id responses: '200': description: Successful Response content: application/json: schema: {} '404': content: application/json: schema: {} description: Not Found '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /artifacts/{session_id}/textures: get: tags: - artifacts summary: Download Textures Zip description: Download all blended textures as a ZIP archive. operationId: download_textures_zip_artifacts__session_id__textures_get parameters: - name: session_id in: path required: true schema: type: string title: Session Id responses: '200': description: Successful Response content: application/zip: schema: type: string format: binary '404': content: application/json: schema: {} description: Not Found '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /artifacts/{session_id}/textures/{filename}: get: tags: - artifacts summary: Download Single Texture description: Download a single texture file. operationId: download_single_texture_artifacts__session_id__textures__filename__get parameters: - name: session_id in: path required: true schema: type: string title: Session Id - name: filename in: path required: true schema: type: string title: Filename responses: '200': description: Successful Response content: image/png: schema: type: string format: binary '400': content: application/json: schema: {} description: Bad Request '404': content: application/json: schema: {} description: Not Found '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /artifacts/{session_id}/output: get: tags: - artifacts summary: Download Output description: "Download the textured output as a self-contained USDZ archive.\n\ \nThe USDZ bundles the USD file with all texture images into a single\ndownload\ \ \u2014 no separate texture download needed." operationId: download_output_artifacts__session_id__output_get parameters: - name: session_id in: path required: true schema: type: string title: Session Id responses: '200': description: Successful Response content: model/vnd.usdz+zip: schema: type: string format: binary '404': content: application/json: schema: {} description: Not Found '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /artifacts/{session_id}/renders: get: tags: - artifacts summary: Download Renders Zip description: Download all rendered images as a ZIP archive. operationId: download_renders_zip_artifacts__session_id__renders_get parameters: - name: session_id in: path required: true schema: type: string title: Session Id responses: '200': description: Successful Response content: application/zip: schema: type: string format: binary '404': content: application/json: schema: {} description: Not Found '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /artifacts/{session_id}/renders/{filename}: get: tags: - artifacts summary: Download Single Render description: Download a single rendered image. operationId: download_single_render_artifacts__session_id__renders__filename__get parameters: - name: session_id in: path required: true schema: type: string title: Session Id - name: filename in: path required: true schema: type: string title: Filename responses: '200': description: Successful Response content: image/png: schema: type: string format: binary '400': content: application/json: schema: {} description: Bad Request '404': content: application/json: schema: {} description: Not Found '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /artifacts/{session_id}/preview/{filename}: get: tags: - artifacts summary: Download Preview description: Download a preview/thumbnail image. operationId: download_preview_artifacts__session_id__preview__filename__get parameters: - name: session_id in: path required: true schema: type: string title: Session Id - name: filename in: path required: true schema: type: string title: Filename responses: '200': description: Successful Response content: image/png: schema: type: string format: binary '400': content: application/json: schema: {} description: Bad Request '404': content: application/json: schema: {} description: Not Found '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /sessions: get: tags: - sessions summary: List Sessions description: List all sessions with sanitized metadata. operationId: list_sessions_sessions_get responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/SessionListResponse' /sessions/{session_id}: get: tags: - sessions summary: Get Session description: Get detailed session information with sanitized error fields. operationId: get_session_sessions__session_id__get parameters: - name: session_id in: path required: true schema: type: string title: Session Id responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/SessionDetail' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' delete: tags: - sessions summary: Delete Session description: Delete a session and all its artifacts. operationId: delete_session_sessions__session_id__delete parameters: - name: session_id in: path required: true schema: type: string title: Session Id responses: '204': description: Successful Response '404': content: application/json: schema: {} description: Not Found '409': content: application/json: schema: {} description: Conflict '500': content: application/json: schema: {} description: Internal Server Error '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /health: get: summary: Health Check description: Health check endpoint. operationId: health_check_health_get responses: '200': description: Successful Response content: application/json: schema: {} /api: get: summary: Root Api Info description: Root endpoint with service info. operationId: root_api_info_api_get responses: '200': description: Successful Response content: application/json: schema: {} /: get: summary: Root description: Root endpoint redirects to API info. operationId: root__get responses: '200': description: Successful Response content: application/json: schema: {} components: schemas: ErrorDetail: properties: detail: type: string title: Detail description: Human-readable error detail type: object required: - detail title: ErrorDetail description: Standard FastAPI error payload returned by input failures. Body_create_pipeline_pipeline_post: properties: usd_file: anyOf: - type: string contentMediaType: application/octet-stream - type: 'null' title: Usd File description: Lowest-priority USD source. Used only when session_id and s3_uri are both omitted. reference_image_file: anyOf: - type: string contentMediaType: application/octet-stream - type: 'null' title: Reference Image File description: Optional global reference image upload for projection backend conditioning. Added to reference_image_uris. session_id: type: string title: Session Id description: 'Highest-priority source: an existing session ID from /upload-usd. When provided, s3_uri and usd_file are ignored.' s3_uri: type: string title: S3 Uri description: Second-priority source, used when session_id is omitted. Its exact bucket name must be listed in TA_S3_ALLOWED_BUCKETS; an empty allowlist rejects all selected client S3 inputs before session-manager or S3 I/O. When selected, usd_file is ignored. material_textures_json: type: string title: Material Textures Json description: 'Per-material texture config JSON. Shape: {"Material": {"prompt": "rusted steel", "opacity": 0.85, "per_prim": {"/World/Prim": {"prompt": "scratches", "opacity": 0.65}}}}. Material prompt is required and non-empty, opacity is optional and bounded to 0.0-1.0, unknown fields are rejected, and any per_prim entry runs the request in per-prim texture mode.' default: '' user_prompt: type: string title: User Prompt description: Aesthetic direction for auto-prompt generation (e.g. 'old and weathered'). Used to auto-generate prompts for materials not covered by material_textures_json. default: '' auto_prompt_enabled: anyOf: - type: boolean - type: 'null' title: Auto Prompt Enabled description: Whether to auto-generate prompts for discovered materials missing from material_textures_json. Defaults to true for legacy service behavior; set false for strict material_textures_json scope. texture_backend: anyOf: - type: string - type: 'null' title: Texture Backend description: Texture backend override, for example 'service'. texture_endpoint: anyOf: - type: string - type: 'null' title: Texture Endpoint description: Texture variation backend endpoint for texture_backend='service'. backend_engine: anyOf: - type: string - type: 'null' title: Backend Engine description: Projection backend engine/model route hint. backend_custom_parameters_json: type: string title: Backend Custom Parameters Json description: Backend custom parameters JSON object. default: '' detail_policy: anyOf: - $ref: '#/components/schemas/TextureDetailPolicy-Input' - type: 'null' description: Texture detail policy. Use 'surface_only' for AOI/CAD assets where traces, labels, holes, seams, or other semantic details already exist as geometry and textures should stay limited to subtle material surface variation. reference_image_uris_json: type: string title: Reference Image Uris Json description: Global reference image URI JSON list. default: '' turntable_video_uri: anyOf: - type: string - type: 'null' title: Turntable Video Uri description: Global turntable video URI for projection backend conditioning. multiview_image_uris_json: type: string title: Multiview Image Uris Json description: Global multi-view image URI JSON list. default: '' seed: anyOf: - type: integer - type: 'null' title: Seed description: Texture backend seed override. strength: anyOf: - type: number maximum: 1.0 minimum: 0.0 - type: 'null' title: Strength description: Texture edit strength override. strict_scope: anyOf: - type: boolean - type: 'null' title: Strict Scope description: Whether projection backend requests must preserve selected scope. uv_policy: anyOf: - type: string - type: 'null' title: Uv Policy description: UV preparation policy override, for example 'force_projection' for UV-aware texture backends. uv_scope: anyOf: - type: string - type: 'null' title: Uv Scope description: UV projection scope override, for example 'target_prims'. uv_backend: anyOf: - type: string - type: 'null' title: Uv Backend description: UV preparation backend override. uv_projection: anyOf: - type: string - type: 'null' title: Uv Projection description: UV projection mode override, for example 'box'. uv_overwrite_existing: anyOf: - type: boolean - type: 'null' title: Uv Overwrite Existing description: Whether UV preparation may overwrite existing UV coordinates. uv_rebake_source_albedo: anyOf: - type: boolean - type: 'null' title: Uv Rebake Source Albedo description: Whether scoped UV projection should rebake source albedo, normal, and ORM maps into the generated UV layout. uv_rebake_size: anyOf: - type: integer exclusiveMinimum: 0.0 - type: 'null' title: Uv Rebake Size description: Optional scoped source texture rebake resolution. uv_normalize_out_of_range: anyOf: - type: boolean - type: 'null' title: Uv Normalize Out Of Range description: Whether UV preparation should normalize out-of-range UVs. render_timeout_sec: anyOf: - type: integer exclusiveMinimum: 0.0 - type: 'null' title: Render Timeout Sec description: Optional final render request timeout in seconds. Texture generation and USD packaging can still complete when the renderer is unavailable or slow. plan_only: type: boolean title: Plan Only description: Discover and persist texture_plan.json without invoking prompt, image-generation, application, or render backends. default: false discovery_mode: $ref: '#/components/schemas/TextureDiscoveryMode' description: 'Planning scope: effective_bound, explicit, or all_authored.' default: effective_bound unit_mode: anyOf: - $ref: '#/components/schemas/TextureUnitMode' - type: 'null' description: 'Planning unit mode: per_material, per_group, or per_prim.' explicit_material_paths_json: type: string title: Explicit Material Paths Json description: JSON list of absolute material paths for explicit discovery. default: '' explicit_prim_paths_json: type: string title: Explicit Prim Paths Json description: JSON list of absolute prim/subset paths for explicit discovery. default: '' operator_override_cap: anyOf: - type: integer minimum: 1.0 - type: 'null' title: Operator Override Cap description: Intentional generation-unit cap override. Values above the backend default and no greater than 64 are recorded in the plan. type: object title: Body_create_pipeline_pipeline_post Body_upload_usd_immediate_pipeline_upload_usd_post: properties: usd_file: anyOf: - type: string contentMediaType: application/octet-stream - type: 'null' title: Usd File description: USD file to upload. Provide exactly one of usd_file or s3_uri. s3_uri: type: string title: S3 Uri description: S3 URI to a USD file. Its exact bucket name must be listed in TA_S3_ALLOWED_BUCKETS; an empty allowlist rejects all client S3 inputs. Provide exactly one of usd_file or s3_uri. type: object title: Body_upload_usd_immediate_pipeline_upload_usd_post CompletedStepInfo: properties: name: type: string title: Name description: Step internal name display_name: type: string title: Display Name description: Human-readable step name started_at: type: string title: Started At description: ISO timestamp when step started completed_at: type: string title: Completed At description: ISO timestamp when step completed duration_seconds: type: integer title: Duration Seconds description: Step duration in seconds stats: additionalProperties: true type: object title: Stats description: Step-specific statistics type: object required: - name - display_name - started_at - completed_at - duration_seconds title: CompletedStepInfo description: Information about a completed step. CurrentStepInfo: properties: name: type: string title: Name description: Step internal name display_name: type: string title: Display Name description: Human-readable step name started_at: type: string title: Started At description: ISO timestamp when step started progress: $ref: '#/components/schemas/StepProgress' elapsed_seconds: type: integer title: Elapsed Seconds description: Seconds since step started type: object required: - name - display_name - started_at - progress - elapsed_seconds title: CurrentStepInfo description: Information about the currently executing step. HTTPValidationError: properties: detail: items: $ref: '#/components/schemas/ValidationError' type: array title: Detail type: object title: HTTPValidationError MaterialTextureOverride: properties: prompt: type: string minLength: 1 title: Prompt opacity: anyOf: - type: number maximum: 1.0 minimum: 0.0 - type: 'null' title: Opacity detail_policy: anyOf: - $ref: '#/components/schemas/TextureDetailPolicy-Input' - type: 'null' material_path: anyOf: - type: string - type: 'null' title: Material Path prim_path: anyOf: - type: string - type: 'null' title: Prim Path prim_paths: anyOf: - items: type: string type: array - type: 'null' title: Prim Paths reference_image_uris: anyOf: - items: type: string type: array - type: 'null' title: Reference Image Uris turntable_video_uri: anyOf: - type: string - type: 'null' title: Turntable Video Uri multiview_image_uris: anyOf: - items: type: string type: array - type: 'null' title: Multiview Image Uris per_prim: anyOf: - additionalProperties: $ref: '#/components/schemas/PrimTextureOverride' type: object - type: 'null' title: Per Prim additionalProperties: false type: object required: - prompt title: MaterialTextureOverride description: Per-material texture prompt/opacity override accepted by the API. OverallProgress: properties: current_step: type: integer title: Current Step description: Current step number (1-indexed) total_steps: type: integer title: Total Steps description: Total number of steps percent: type: integer title: Percent description: Overall percentage complete (0-100) estimated_remaining_seconds: anyOf: - type: integer - type: 'null' title: Estimated Remaining Seconds description: Estimated seconds until completion type: object required: - current_step - total_steps - percent title: OverallProgress description: Overall pipeline progress. PipelineError: properties: session_id: type: string title: Session Id status: type: string title: Status default: failed error_message: type: string title: Error Message description: Error description failed_step: type: string title: Failed Step description: Step that failed completed_steps: items: type: string type: array title: Completed Steps description: Steps completed before failure partial_results: anyOf: - additionalProperties: true type: object - type: 'null' title: Partial Results description: Partial results if available failed_step_stats: anyOf: - additionalProperties: true type: object - type: 'null' title: Failed Step Stats description: Stats from the failed step at the moment it raised, including any structured per-unit errors (e.g. ``errors`` and ``textures_failed`` for texture-generation/blend steps). Lets REST consumers without an SSE subscription diagnose threshold-gated failures without grepping container logs. type: object required: - session_id - error_message - failed_step title: PipelineError description: Pipeline error response. PipelineResults: properties: session_id: type: string title: Session Id status: type: string title: Status stats: additionalProperties: true type: object title: Stats description: Execution statistics examples: - materials_found: 12 output_usd_count: 1 renders_count: 2 textures_generated: 12 download_urls: additionalProperties: type: string type: object title: Download Urls description: URLs to download artifacts examples: - manifest: /artifacts/abc123/manifest materials: /artifacts/abc123/materials output: /artifacts/abc123/output renders: /artifacts/abc123/renders textures: /artifacts/abc123/textures duration_seconds: type: integer title: Duration Seconds description: Total pipeline duration in seconds completed_at: type: string title: Completed At description: ISO timestamp when completed type: object required: - session_id - status - duration_seconds - completed_at title: PipelineResults description: Pipeline execution results. PipelineStatus: properties: session_id: type: string title: Session Id status: type: string title: Status description: 'Current status: pending, running, completed, failed, cancelled, cancelling' current_step: anyOf: - $ref: '#/components/schemas/CurrentStepInfo' - type: 'null' completed_steps: items: $ref: '#/components/schemas/CompletedStepInfo' type: array title: Completed Steps overall_progress: $ref: '#/components/schemas/OverallProgress' preview_images: items: type: string type: array title: Preview Images description: URLs to preview images can_cancel: type: boolean title: Can Cancel description: Whether pipeline can be cancelled elapsed_seconds: type: integer title: Elapsed Seconds description: Total elapsed time in seconds created_at: type: string title: Created At description: ISO timestamp when session created updated_at: type: string title: Updated At description: ISO timestamp of last update error: anyOf: - type: string - type: 'null' title: Error description: Sanitized top-level error message (failed runs) failed_step: anyOf: - type: string - type: 'null' title: Failed Step description: Step that failed (only set when status=failed) failed_step_stats: anyOf: - additionalProperties: true type: object - type: 'null' title: Failed Step Stats description: Structured failed-step stats including any per-unit ``errors`` and ``textures_failed`` count. Mirrors the SSE FAILED event extra so polling clients see the same diagnostic detail. texture_plan: anyOf: - $ref: '#/components/schemas/TexturePlanStatus' - type: 'null' description: Bounded plan summary once planning has completed, including the decision, audited counts, and exact effective/hard caps. type: object required: - session_id - status - overall_progress - can_cancel - elapsed_seconds - created_at - updated_at title: PipelineStatus description: Pipeline execution status with progress. PrimTextureOverride: properties: prompt: anyOf: - type: string minLength: 1 - type: 'null' title: Prompt opacity: anyOf: - type: number maximum: 1.0 minimum: 0.0 - type: 'null' title: Opacity detail_policy: anyOf: - $ref: '#/components/schemas/TextureDetailPolicy-Input' - type: 'null' additionalProperties: false type: object title: PrimTextureOverride description: Per-prim prompt/opacity override nested under a material override. RegenerateRequest: properties: steps: items: $ref: '#/components/schemas/TexturePipelineStep' type: array minItems: 1 title: Steps description: Steps to re-run from cache (at least one) material_textures: anyOf: - additionalProperties: $ref: '#/components/schemas/MaterialTextureOverride' type: object - type: 'null' title: Material Textures description: Override per-material prompt/opacity for regeneration texture_unit_ids: anyOf: - items: type: string type: array - type: 'null' title: Texture Unit Ids description: Exact approved texture-plan unit IDs to regenerate. Omit to regenerate every approved unit when generate_textures is selected. type: object required: - steps title: RegenerateRequest description: Request to regenerate specific steps from cache. SessionConfigSummary: properties: project_name: anyOf: - type: string - type: 'null' title: Project Name original_filename: anyOf: - type: string - type: 'null' title: Original Filename description: Filename the client uploaded (None for S3 inputs) input_extension: anyOf: - type: string - type: 'null' title: Input Extension description: USD extension, e.g. '.usd' or '.usdz' has_usd_upload: anyOf: - type: boolean - type: 'null' title: Has Usd Upload s3_uri: anyOf: - type: string - type: 'null' title: S3 Uri description: S3 URI when input was sourced from S3 (client-supplied) material_textures: anyOf: - additionalProperties: true type: object - type: 'null' title: Material Textures type: object title: SessionConfigSummary description: 'Sanitized subset of pipeline config echoed back on /sessions. Excludes absolute filesystem paths (the input USD lives at a server- internal location implied by the session id; surfacing it would leak the container''s storage layout).' SessionCreated: properties: session_id: type: string title: Session Id status: type: string title: Status default: pending message: type: string title: Message default: Pipeline queued for execution estimated_duration_minutes: anyOf: - type: integer - type: 'null' title: Estimated Duration Minutes description: Estimated completion time plan_url: anyOf: - type: string - type: 'null' title: Plan Url description: Stable texture-plan endpoint for this session; returns 404 until planning has produced texture_plan.json. type: object required: - session_id title: SessionCreated description: Response when session is created. SessionDetail: properties: session_id: type: string title: Session Id status: type: string title: Status created_at: anyOf: - type: string - type: 'null' title: Created At updated_at: anyOf: - type: string - type: 'null' title: Updated At elapsed_seconds: type: integer title: Elapsed Seconds default: 0 ttl_expires_at: anyOf: - type: string - type: 'null' title: Ttl Expires At config: $ref: '#/components/schemas/SessionConfigSummary' current_step: anyOf: - $ref: '#/components/schemas/CurrentStepInfo' - type: 'null' completed_steps: items: $ref: '#/components/schemas/CompletedStepInfo' type: array title: Completed Steps overall_progress: anyOf: - $ref: '#/components/schemas/OverallProgress' - type: 'null' preview_images: items: type: string type: array title: Preview Images can_cancel: type: boolean title: Can Cancel default: false error: anyOf: - type: string - type: 'null' title: Error description: Sanitized top-level error message (failed runs) failed_step: anyOf: - type: string - type: 'null' title: Failed Step failed_step_stats: anyOf: - additionalProperties: true type: object - type: 'null' title: Failed Step Stats partial_results: anyOf: - additionalProperties: true type: object - type: 'null' title: Partial Results results: anyOf: - additionalProperties: true type: object - type: 'null' title: Results description: Final stats (completed runs) duration_seconds: anyOf: - type: integer - type: 'null' title: Duration Seconds completed_at: anyOf: - type: string - type: 'null' title: Completed At type: object required: - session_id - status title: SessionDetail description: 'Detail payload for ``GET /sessions/{session_id}``. Whitelists fields that are safe for public surface. Free-form strings in ``error`` and ``failed_step_stats`` are sanitized to redact NVCF function URLs and absolute session paths.' SessionListResponse: properties: sessions: items: $ref: '#/components/schemas/SessionSummary' type: array title: Sessions total: type: integer title: Total default: 0 type: object title: SessionListResponse description: Response payload for ``GET /sessions``. SessionSummary: properties: session_id: type: string title: Session Id status: type: string title: Status created_at: anyOf: - type: string - type: 'null' title: Created At updated_at: anyOf: - type: string - type: 'null' title: Updated At elapsed_seconds: type: integer title: Elapsed Seconds default: 0 config: $ref: '#/components/schemas/SessionConfigSummary' type: object required: - session_id - status title: SessionSummary description: One row in the ``GET /sessions`` listing. StepProgress: properties: current: type: integer title: Current description: Current progress count total: type: integer title: Total description: Total items to process percent: type: integer title: Percent description: Percentage complete (0-100) message: type: string title: Message description: Human-readable progress message type: object required: - current - total - percent - message title: StepProgress description: Progress information for a single step. TextureDetailPolicy-Input: type: string enum: - default - surface_only title: TextureDetailPolicy description: Texture detail policy values accepted by the service API. TextureDetailPolicy-Output: type: string enum: - default - surface_only title: TextureDetailPolicy description: Semantic-detail policy recorded in a plan. TextureDiscoveryMode: type: string enum: - effective_bound - explicit - all_authored title: TextureDiscoveryMode description: How candidate materials are discovered for a plan. TexturePipelineStep: type: string enum: - prepare_uvs - discover_materials - plan_textures - generate_prompts - render_previews - generate_textures - blend_textures - apply_textures - render title: TexturePipelineStep description: Available pipeline steps. TexturePlan: properties: schema_version: type: string const: texture-agent-plan.v1 title: Schema Version default: texture-agent-plan.v1 generated_at: type: string format: date-time title: Generated At request: $ref: '#/components/schemas/TexturePlanRequest' limits: $ref: '#/components/schemas/TexturePlanLimits' execution: $ref: '#/components/schemas/TexturePlanExecution' counts: $ref: '#/components/schemas/TexturePlanCounts' selected_units: items: $ref: '#/components/schemas/TexturePlanUnit' type: array title: Selected Units default: [] skipped_items: items: $ref: '#/components/schemas/TexturePlanSkippedItem' type: array title: Skipped Items default: [] decision: $ref: '#/components/schemas/TexturePlanDecision' additionalProperties: false type: object required: - request - limits - execution - counts - decision title: TexturePlan description: Immutable plan artifact shared across all Texture Agent surfaces. TexturePlanCounts: properties: authored_material_count: type: integer minimum: 0.0 title: Authored Material Count renderable_prim_count: type: integer minimum: 0.0 title: Renderable Prim Count renderable_subset_count: type: integer minimum: 0.0 title: Renderable Subset Count effective_bound_material_count: type: integer minimum: 0.0 title: Effective Bound Material Count selected_material_count: type: integer minimum: 0.0 title: Selected Material Count selected_unit_count: type: integer minimum: 0.0 title: Selected Unit Count skipped_item_count: type: integer minimum: 0.0 title: Skipped Item Count planned_generation_job_count: type: integer minimum: 0.0 title: Planned Generation Job Count additionalProperties: false type: object required: - authored_material_count - renderable_prim_count - renderable_subset_count - effective_bound_material_count - selected_material_count - selected_unit_count - skipped_item_count - planned_generation_job_count title: TexturePlanCounts description: Auditable discovery, selection, and backend-job counts. TexturePlanDecision: properties: state: $ref: '#/components/schemas/TexturePlanDecisionState' execution_allowed: type: boolean title: Execution Allowed consolidation_required: type: boolean title: Consolidation Required default: false explicit_narrowing_required: type: boolean title: Explicit Narrowing Required default: false reasons: items: type: string type: array title: Reasons default: [] recommended_actions: items: type: string type: array title: Recommended Actions default: [] additionalProperties: false type: object required: - state - execution_allowed title: TexturePlanDecision description: Whether the immutable plan is approved for bounded execution. TexturePlanDecisionState: type: string enum: - ready - requires_operator_override - requires_narrowing - requires_consolidation - unsupported title: TexturePlanDecisionState description: Planner decision before any LLM or image-generation work starts. TexturePlanExecution: properties: backend: type: string minLength: 1 title: Backend texture_size: type: integer maximum: 16384.0 minimum: 1.0 title: Texture Size max_concurrency: type: integer maximum: 64.0 minimum: 1.0 title: Max Concurrency unit_timeout_seconds: type: integer maximum: 86400.0 minimum: 1.0 title: Unit Timeout Seconds additionalProperties: false type: object required: - backend - texture_size - max_concurrency - unit_timeout_seconds title: TexturePlanExecution description: Bounded execution settings frozen into the plan. TexturePlanLimits: properties: global_default_cap: type: integer const: 32 title: Global Default Cap default: 32 backend_default_cap: type: integer maximum: 32.0 minimum: 1.0 title: Backend Default Cap operator_override_cap: anyOf: - type: integer maximum: 64.0 minimum: 1.0 - type: 'null' title: Operator Override Cap effective_cap: type: integer maximum: 64.0 minimum: 1.0 title: Effective Cap hard_cap: type: integer const: 64 title: Hard Cap default: 64 additionalProperties: false type: object required: - backend_default_cap - effective_cap title: TexturePlanLimits description: Default, backend, override, and hard limits recorded in a plan. TexturePlanRequest: properties: schema_version: type: string const: texture-agent-plan-request.v1 title: Schema Version default: texture-agent-plan-request.v1 source: $ref: '#/components/schemas/TexturePlanSource' discovery_mode: $ref: '#/components/schemas/TextureDiscoveryMode' default: effective_bound unit_mode: $ref: '#/components/schemas/TextureUnitMode' default: per_material explicit_material_paths: items: type: string type: array title: Explicit Material Paths default: [] explicit_prim_paths: items: type: string type: array title: Explicit Prim Paths default: [] detail_policy: $ref: '#/components/schemas/TextureDetailPolicy-Output' default: default texture_size: type: integer maximum: 16384.0 minimum: 1.0 title: Texture Size default: 1024 backend: type: string minLength: 1 title: Backend default: simple_image_gen backend_default_cap: type: integer maximum: 32.0 minimum: 1.0 title: Backend Default Cap default: 32 operator_override_cap: anyOf: - type: integer maximum: 64.0 minimum: 1.0 - type: 'null' title: Operator Override Cap max_concurrency: type: integer maximum: 64.0 minimum: 1.0 title: Max Concurrency default: 4 unit_timeout_seconds: type: integer maximum: 86400.0 minimum: 1.0 title: Unit Timeout Seconds default: 600 additionalProperties: false type: object required: - source title: TexturePlanRequest description: Normalized deterministic request consumed by a texture planner. TexturePlanSkippedItem: properties: item_kind: $ref: '#/components/schemas/TextureSelectionKind' canonical_id: type: string minLength: 1 title: Canonical Id display_name: anyOf: - type: string - type: 'null' title: Display Name reason_code: type: string minLength: 1 title: Reason Code reason: type: string minLength: 1 title: Reason additionalProperties: false type: object required: - item_kind - canonical_id - reason_code - reason title: TexturePlanSkippedItem description: One candidate omitted from selection, with a machine-readable reason. TexturePlanSource: properties: source_asset: type: string minLength: 1 title: Source Asset upstream_assignment_artifact: anyOf: - type: string - type: 'null' title: Upstream Assignment Artifact source_asset_sha256: anyOf: - type: string pattern: ^[0-9a-f]{64}$ - type: 'null' title: Source Asset Sha256 description: Optional lowercase SHA-256 for durable source identity. additionalProperties: false type: object required: - source_asset title: TexturePlanSource description: Input asset and optional upstream Material Agent assignment artifact. TexturePlanStatus: properties: schema_version: type: string title: Schema Version decision_state: type: string title: Decision State execution_allowed: type: boolean title: Execution Allowed counts: additionalProperties: type: integer type: object title: Counts limits: additionalProperties: anyOf: - type: integer - type: 'null' type: object title: Limits plan_url: type: string title: Plan Url type: object required: - schema_version - decision_state - execution_allowed - counts - limits - plan_url title: TexturePlanStatus description: Compact immutable-plan summary embedded in polling responses. TexturePlanUnit: properties: unit_id: type: string pattern: ^tu_[0-9a-f]{20}$ title: Unit Id unit_mode: $ref: '#/components/schemas/TextureUnitMode' material_prim_paths: items: type: string type: array minItems: 1 title: Material Prim Paths member_prim_paths: items: type: string type: array title: Member Prim Paths default: [] member_subset_paths: items: type: string type: array title: Member Subset Paths default: [] group_key: anyOf: - type: string - type: 'null' title: Group Key display_name: type: string minLength: 1 title: Display Name selection_reason_code: type: string minLength: 1 title: Selection Reason Code selection_reason: type: string minLength: 1 title: Selection Reason detail_policy: $ref: '#/components/schemas/TextureDetailPolicy-Output' additionalProperties: false type: object required: - unit_id - unit_mode - material_prim_paths - display_name - selection_reason_code - selection_reason - detail_policy title: TexturePlanUnit description: One selected material, appearance group, or scoped-prim texture job. TextureSelectionKind: type: string enum: - material - group - prim - subset title: TextureSelectionKind description: Kinds of candidates that may be selected or skipped. TextureUnitMode: type: string enum: - per_material - per_group - per_prim title: TextureUnitMode description: How selected scene members are reduced to generation units. ValidationError: properties: loc: items: anyOf: - type: string - type: integer type: array title: Location msg: type: string title: Message type: type: string title: Error Type input: title: Input ctx: type: object title: Context type: object required: - loc - msg - type title: ValidationError