-
Scaffolded the Azure GPU deployment direction for neural models:
- Added
docs/plans/2026-04-08-azure-container-apps-neural-deployment.md - Captured the current preferred migration path:
- Azure Container Apps with serverless GPUs
- Azure Container Registry
- GitHub Actions CI/CD
- Explicitly documented that AKS is not the first migration target
- Added
-
Documented the key portability constraint between RunPod and Azure:
- Added
deploy/azure/README.md - Confirmed from the existing code that the current images under
deploy/runpod/**are RunPod worker containers whose entrypoint ends inrunpod.serverless.start(...) - That means they are not direct Azure Container Apps images and should not be treated as drop-in deploy targets for ACR + ACA
- Added
-
Defined the intended Azure service split:
hunyuan-api- future Azure HTTP service for:
POST /generatePOST /texturizeGET /health
- aligns with the existing
HUNYUAN_API_URLclient contract
- future Azure HTTP service for:
hunyuan-part-api- future Azure HTTP service for:
POST /segmentGET /health
- aligns with the existing
HUNYUAN_PART_URLcontract
- future Azure HTTP service for:
-
Added Azure CI/CD examples without enabling broken workflows prematurely:
- Added
deploy/azure/github-actions/azure-neural-container-apps.yml.example - The example workflow documents the desired GitHub Actions path:
- GitHub OIDC login to Azure
- build/push to ACR
- update existing Azure Container App revisions
- Kept it as an example rather than an active workflow because the Azure-ready HTTP Dockerfiles do not exist yet
- Added
-
Added GitHub/Azure configuration docs for the future deployment path:
- Added
deploy/azure/github-actions/vars-and-secrets.example.md - Documented the expected GitHub secrets:
AZURE_CLIENT_IDAZURE_TENANT_IDAZURE_SUBSCRIPTION_ID
- Documented the expected GitHub variables:
AZURE_RESOURCE_GROUPAZURE_ACR_NAMEAZURE_CONTAINER_APP_HUNYUAN_APIAZURE_CONTAINER_APP_HUNYUAN_PART
- Added
-
Created explicit placeholders for the future Azure HTTP images:
- Added:
deploy/azure/hunyuan-api/README.mddeploy/azure/hunyuan-part-api/README.md
- This gives the repo a concrete home for the future Azure container implementations instead of leaving the migration path implicit
- Added:
- The current state is infrastructure scaffolding only.
- No runtime provider switch to Azure was made yet.
- The next actual implementation step, once ACR and the Container Apps path are ready, is to build the Azure-ready HTTP service images for:
hunyuan-apihunyuan-part-api
- Only after that should an active GitHub Actions deployment workflow be moved into
.github/workflows.
-
Applied the verified CodeRabbit review fixes for PR #28:
- Treated CodeRabbit comments as hypotheses and only patched the ones that were defensible against the current code and runtime behavior
- Skipped broader or ambiguous suggestions that would have required feature-scope changes rather than review-driven corrections
-
Hardened neural output path handling and output URLs:
- Updated
lib/neural/output-files.ts - Neural output paths are now canonicalized with
realpathSyncbefore use - Added a regular-file check to prevent directories or symlink escapes from being treated as valid outputs
buildNeuralOutputUrl()no longer exposes absolute local filesystem paths to the client; it now emits a relative path scoped undertmp/neural-output
- Updated
-
Tightened the authenticated neural output streaming route:
- Updated
app/api/ai/neural-output/route.ts - The route now rejects any resolved neural output that is not a
.glb - This keeps the viewer transport surface aligned with the current Studio neural viewer contract
- Updated
-
Fixed the generic Studio neural run route for non-geometry completions:
- Updated
app/api/ai/neural-run/route.ts - The route now validates mesh-based tool runs using the normalized mesh input
/api/ai/neural-output?...mesh inputs are resolved back to safe local paths before provider execution- Completion handling now accepts successful providers whose result path lives in:
modelPathriggedModelPathretopologyPath
- This avoids incorrectly rejecting valid
unirigormeshanything-v2completions
- Updated
-
Hardened RunPod provider selection:
- Updated
lib/neural/registry.ts hunyuan-paintandhunyuan-partnow only route toRunPodClientwhen both:RUNPOD_API_KEYis present- the corresponding endpoint env var is configured
- This prevents the registry from selecting RunPod and then failing later with a missing-endpoint runtime exception
- Updated
-
Fixed the sample viewer route and sandbox fetch behavior:
- Updated
app/api/generate/3d/samples/route.ts - Missing sample files now return
404instead of surfacing as a route error - Updated
components/generation/GenerationPanel.tsx - The viewer sample bootstrap no longer refetches repeatedly because of the selected-sample state loop
- Updated
-
Improved viewer safety and accessibility polish:
- Updated
components/generation/ModelViewer.tsx - Added
vbscript:to the blocked protocol list - Replaced the hardcoded
model-viewer-descriptionID with a per-instanceuseId()value so multiple viewers do not share duplicate IDs - Improved download naming so
/api/ai/neural-output?...viewer URLs save as stable.glbfilenames instead of query-string fragments - Updated
lib/types/model-viewer.d.tsso the custom-element JSX augmentation hangs offreactrather thanreact/jsx-runtime
- Updated
-
Fixed sidebar/shelf accessibility and Studio launch-state issues:
- Updated
components/projects/generated-assets-shelf.tsx - The generated-assets shelf now unmounts fully when closed, so hidden buttons are no longer left mounted and tabbable
- Updated
components/projects/studio-sidebar.tsx - Added explicit
aria-labelandaria-expandedstate to the icon-only Generated Assets toggle - Updated
components/projects/studio-workspace.tsx - Deduplicated repeated
externalToolLaunchhandling by launch token - Removed duplicated
tool.inputs.find(...)work when resolving the active image input
- Updated
npx tsc --noEmit✅npm run lint✅
- Intentionally did not apply every CodeRabbit suggestion. The skipped ones were either:
- lower-value performance nits
- ambiguous version-contract suggestions
- or broader behavior changes that should be handled as separate product work rather than folded into a review-fix pass
- The remaining lint output is only the existing
baseline-browser-mappingage notice, not an ESLint failure.
-
Fixed the Studio neural handoff path for mesh-based tools:
- Investigated the first successful TRELLIS → Hunyuan Paint handoff in Studio
- Found that all neural reruns were still being sent through the generic geometry-oriented
/api/ai/neural-runrequest shape - This caused Hunyuan Paint to fail before generation because the request schema did not accept
hunyuan-paintor carry the requiredmeshUrl
-
Expanded the shared Studio neural route to support mesh-based neural tools:
- Updated
app/api/ai/neural-run/route.ts - The route now accepts:
hunyuan-shapetrellishunyuan-paintyvo3dhunyuan-partunirigmeshanything-v2
- Added request fields for:
meshUrltextureResolutiontargetFaces
- Added provider-specific validation and generation-mode resolution instead of the old shape-only assumptions
- Updated
-
Fixed carried mesh normalization for server-side neural clients:
- The Studio handoff was storing the geometry result as the authenticated viewer URL (
/api/ai/neural-output?...) - Added route-side normalization so mesh-based providers resolve that viewer URL back to the safe local GLB path before calling the client
- This keeps the same generated geometry reusable across shape → paint / retopo / rigging flows without exposing the raw local path in the browser state
- The Studio handoff was storing the geometry result as the authenticated viewer URL (
-
Improved Studio mesh input UX:
- Replaced the plain text
A model from your current project session is attached to this toolplaceholder with a richer attached-model card incomponents/projects/studio-workspace.tsx - The card now shows:
- attached model state
- resolved filename label
- explanatory copy about using the current project model
- Added the same mesh-card rendering to:
- first-run tool detail forms
- rerun overlay fields
- running neural overlay summaries
- Replaced the plain text
-
Improved viewer continuity for mesh-based neural tools:
- When a neural tool starts with an attached
meshUrl, the right-hand viewer now keeps that mesh visible during the run instead of dropping to an empty white canvas - This makes shape → paint feel like a true continuation of the same asset instead of a reset between tools
- When a neural tool starts with an attached
-
Cleaned up Studio viewer header collisions:
- Moved the neural viewer time/status badges into the left overlay chip row with the viewer label
- This avoids the collision between Studio viewer metadata and the top-right
Fit / Reset / Fullscreen / Downloadcontrols insideModelViewer
npx tsc --noEmit✅npm run lint✅
- This resolves the immediate TRELLIS → Hunyuan Paint Studio handoff bug.
- There is still no full user-facing mesh picker yet; current mesh attachment is driven by the workflow continuation path. The new mesh card is a better temporary UX, but a real project asset selector is still a later step.
-
Fixed the TRELLIS runtime routing bug:
- Investigated the Studio failure
TRELLIS 2 generation failed: Cannot find module '@gradio/client' - Root cause was provider selection in
lib/neural/registry.ts:.envcurrently usesNEURAL_PROVIDER=runpod- that setting prevented TRELLIS from taking the intended fal path
- the registry then fell through to the self-hosted TRELLIS Gradio client, which requires
@gradio/client
- Investigated the Studio failure
-
Hardened provider routing to match the actual backend mix:
- Updated
lib/neural/registry.ts trellisnow prefers fal wheneverFAL_KEYis available, unless the user explicitly forcesNEURAL_PROVIDER=self-hostedhunyuan-paint,hunyuan-part,unirig,momask, andmeshanything-v2still use RunPod when availablehunyuan-shapedeliberately stays on the current self-hosted path by default for now, so the existing Studio prompt flow is not broken before the full provider/input audit lands
- Updated
-
Added the missing Gradio dependency for self-hosted fallbacks:
- Installed
@gradio/client@2.1.0 - This keeps the self-hosted TRELLIS / Hunyuan Part fallback clients from failing immediately on module resolution if they are selected intentionally later
- Installed
-
Verified the current official provider contracts before changing the runtime:
- fal
fal-ai/hunyuan3d-v21is image-based (input_image_url) with optional controls likeoctree_resolutionandtextured_mesh - fal
fal-ai/trellis-2is image-to-3D - Current repo/UI state now aligns correctly for TRELLIS specifically
- Hunyuan Shape still needs a follow-up audit because the self-hosted client path in this repo accepts prompt/image, while fal's Hunyuan 2.1 endpoint is image-based
- fal
npx tsc --noEmit✅npm run lint✅- Verified resolved clients under current
.env:trellis -> FalClienthunyuan-shape -> HunyuanShapeClienthunyuan-paint -> RunPodClient
- This fix is intentionally narrow so TRELLIS works now without accidentally breaking the current Hunyuan Studio flow.
- A separate neural provider/input audit is still warranted to align every tool card, route schema, and backend contract exactly with the live provider capabilities.
-
Added a separate migration-sequence note for the future asset system:
- Added
docs/local-asset-production-stages.md - This stays separate from both
docs/future-plans.mdand the broader production draft
- Added
-
Defined the staged path from current local-disk behavior to a more production-capable asset system:
- Stage 0: current dev baseline
- Stage 1: managed local defaults
- Stage 2: previews and human browsing
- Stage 3: cloud catalog with local files still primary
- Stage 4: managed download and local cache
- Stage 5: multi-source managed + BYO model
- Stage 6: optional product-layer UX additions
-
Linked the stages note from the existing production draft:
- Updated
docs/local-asset-production-draft.md
- Updated
- This is intentionally a pragmatic migration path, not a fixed product roadmap.
- The current recommendation in the doc is to start with Stage 1 when production work begins.
-
Saved a separate draft architecture note for future managed asset delivery:
- Added
docs/local-asset-production-draft.md - This document is explicitly marked as a draft and intentionally kept separate from
docs/future-plans.md
- Added
-
Captured the current preferred long-term direction without locking the product into a final implementation:
- cloud catalog for metadata and search
- object storage / CDN for binary assets and previews
- managed local cache on the user machine for Blender imports
- optional BYO asset library override for private user assets
-
Clarified an important production constraint:
- Blender still needs real local files at import time
- the agent can choose assets, but the Blender addon still imports them from disk
- so a cloud database alone is not enough without a local cache or download step
-
Stored the same direction in Graphiti memory:
- Saved under group
modelforgeasModelForge long-term managed asset delivery draft
- Saved under group
- This is intentionally a working architecture note, not a committed final production design.
- Other upcoming product features may still change the final shape of the managed asset system.
-
Confirmed the local asset library is already runtime-gated in the addon:
- When
blendermcp_use_local_assetsis off, the Blender MCP server does not expose:search_local_assetsimport_local_asset
- So the user-facing checkbox already controls whether the agent can use the curated local asset library at all
- When
-
Renamed the addon UI wording from generic local-library language to product language:
Local Asset Library→ViperMesh Assets- Updated both addon copies:
desktop/assets/vipermesh-addon.pypublic/downloads/vipermesh-addon.py
- Updated the enabled/disabled status messages to use the same wording
-
Strengthened the live Blender agent policy for hybrid asset use:
- Updated
lib/orchestration/prompts/blender-agent-system.md - The prompt now tells the agent to:
- use local curated assets selectively for commodity props with recognizable silhouettes
- keep room shells, layout, architecture, cameras, lighting, and bespoke hero forms procedural/direct
- search/import a single strong asset candidate rather than replacing whole scenes with premade assets
- expect some local assets to need transform correction because cross-asset scale may not match perfectly
- Updated
-
Strengthened supporting local-asset guidance and tool descriptions:
- Updated
data/tool-guides/local-asset-guide.md - Updated local asset tool descriptions in
lib/ai/agents.ts
- Updated
python -m py_compile desktop/assets/vipermesh-addon.py public/downloads/vipermesh-addon.py✅npx tsc --noEmit✅npm run lint✅
-
Promoted the current BlenderKit intake batch into the final local asset library:
- External asset root:
C:\Users\krist\Documents\ViperMeshAssets
- Promoted curated
.blendassets into finalprops\...folders for:- footwear
- plants
- baskets
- lamps
- books
- External asset root:
-
Added reproducible promotion tooling and metadata:
- Added
scripts/maintenance/promote-local-asset-batch.ts - Added
data/local-assets/initial-blenderkit-batch.json - This promotion plan now captures the curated target paths, category/tags/style metadata, quality scores, and exact
.blendcollection names for import
- Added
-
Extracted exact import collection names from the staged
.blendfiles using Blender 5.0:- The catalog now points at real
import_spec.asset_namesinstead of empty placeholders - Examples:
Army ShoesOlive Branches in Ceramic VaseWhite Ceramic Table LampStack of magazines Blue Grey
- The catalog now points at real
-
Built the live external catalog:
C:\Users\krist\Documents\ViperMeshAssets\catalog\assets.json- Current catalog count:
29curated assets - The normal
assets:catalogrebuild now preserves this metadata and still skips rawincoming\...assets
npm run assets:promote -- --root "C:\Users\krist\Documents\ViperMeshAssets"✅npm run assets:catalog -- --root "C:\Users\krist\Documents\ViperMeshAssets"✅npx tsc --noEmit✅npm run lint✅
- Preview images have not been generated yet;
preview_pathis still empty for this batch. - A few basket and book subtype placements remain provisional semantic matches, but the assets are fully usable as curated local imports now.
-
Copied the current BlenderKit download batch into the ViperMesh intake tree:
- Source cache root:
C:\Users\krist\blenderkit_data\models
- Destination staging root:
C:\Users\krist\Documents\ViperMeshAssets\incoming\blenderkit
- Source cache root:
-
Imported the first full raw intake set across the current priority categories:
- footwear
- plants
- baskets
- lamps
- books
-
Normalized the raw intake filenames to stable ViperMesh staging names:
- examples:
blenderkit_ankle_boots_suede_brown_a.blendblenderkit_olive_branch_vase_a.blendblenderkit_lamp_brass_desk_a.blendblenderkit_books_stack_blue_gray_a.blend
- examples:
-
Kept the BlenderKit cache intact:
- Files were copied into the ViperMesh intake tree rather than removed from the BlenderKit cache
- This batch includes more than the original strict 20-target minimum because a few categories now have multiple candidate variants staged for later curation.
- Some category placements are intentionally provisional at the raw intake stage, especially for:
- basket subtypes
- book subtype buckets
- That is acceptable because these are still incoming assets. Final correctness will be enforced during the curated
.blendpromotion pass intoprops\....
-
Hardened the local asset catalog builder for real curation workflows:
- Updated
scripts/maintenance/build-local-asset-catalog.ts - The generator now skips raw staging folders under
incoming\... - Rebuilds now preserve manual enrichment where the curated file path stays the same:
nametagsstyledescriptionlicensesourcesource_urlpreview_pathquality_scorevalidated_blender_versiondimensions_m.blendimport settings such asappend_typeandasset_names
- Updated
-
Improved generated manifest quality:
- Derived
categoryis now more useful for curatedprops\...assets, e.g.footwearinstead of the deepest folder slug - Rebuilds now filter noisy one-character auto-tags
- Derived
-
Updated docs to match the live local library workflow:
docs/local-asset-library.mddocs/first-20-local-assets.md- Clarified that
incoming\...is staging only and that the catalog should point at curated assets only
npx tsc --noEmit✅npm run lint✅- Fixture rebuild test confirmed:
- raw
incoming\...assets are skipped - curated metadata survives rebuilds
- exact
.blendimport names are preserved
- raw
-
Moved the first real BlenderKit source asset out of the BlenderKit cache and into the ViperMesh intake library:
- Source cache path:
C:\Users\krist\blenderkit_data\models\army-shoes_0a407d12-e06d-42a5-9b94-d4777b5384a5\army-shoes_2K_412e4cfe-3568-4d4c-a8ce-246a3be7a75f.blend
- New intake path:
C:\Users\krist\Documents\ViperMeshAssets\incoming\blenderkit\footwear\ankle-boots-dark\blenderkit_ankle_boots_dark_a.blend
- Source cache path:
-
Naming choice:
- Renamed the file away from the BlenderKit UUID-style cache name to a stable intake filename:
blenderkit_ankle_boots_dark_a.blend
- Renamed the file away from the BlenderKit UUID-style cache name to a stable intake filename:
- This is still a raw intake asset, not the final curated library asset yet.
- The later curated target remains:
C:\Users\krist\Documents\ViperMeshAssets\props\footwear\ankle-boots\ankle_boots_dark_a.blend
-
Aligned the seed scaffold with the actual raw intake source:
- Updated
scripts/maintenance/init-local-asset-library.ts - Added
incoming/blenderkitto the generated library structure
- Updated
-
Aligned the first 20 intake document with the real working paths:
- Updated
docs/first-20-local-assets.md - Switched the raw staging examples from old
a23dpaths to the currentblenderkitpaths under:C:\\Users\\krist\\Documents\\ViperMeshAssets\\incoming\\blenderkit\\...
- Updated
-
Created the real BlenderKit raw intake folders on disk for the current shortlist:
- footwear
- plants
- baskets
- lamps
- books
- including the specific target folders for the full 20-asset shortlist
-
Validation:
npx tsc --noEmitpassesnpm run lintpasses
- This was a path-alignment checkpoint only. No changes to the live agent/runtime behavior.
- The working raw intake root for the current curation pass is:
C:\\Users\\krist\\Documents\\ViperMeshAssets\\incoming\\blenderkit
-
Extended the local asset sourcing strategy doc:
- Updated
docs/local-asset-library.mdwith:- BlenderKit guidance
- Adobe Substance 3D Assets guidance
- a clearer source matrix for what is safe as:
- manual artist-side use
- manual curation input
- agent-accessible internal library source
- Updated
-
Captured the current position on BlenderKit:
- Attractive for its large Blender-native library and subscription pricing
- Not yet something to architect the ViperMesh agent runtime around because:
- no clearly documented stable third-party API was surfaced in the public docs review
- BlenderKit's current public user terms require caution for use in developing other products/services or competing services
-
Captured the current position on Adobe Substance 3D Assets:
- Best fit is materials / PBRs rather than models
- Strong manual look-dev value
- Public terms still need caution for an agent-accessible internal library because of AI/ML restrictions in the published Product Specific Terms
- The practical recommendation remains:
- Poly Haven for open/on-demand assets
- private/user-owned/internal-safe assets for the first agent library seed
- BlenderKit and Adobe as manual curation sources first, not automatic agent-library defaults
-
Defined the first concrete 20-asset intake shortlist:
- Added
docs/first-20-local-assets.md - The doc specifies for each target asset:
- target prop
- recommended source class
- raw download staging folder
- curated final library path
- final preferred format
- Added
-
Extended the seed scaffold for raw download staging:
- Updated
scripts/maintenance/init-local-asset-library.tsto create:incoming/a23dincoming/polyhavenincoming/privateincoming/marketplace
- Updated
-
Re-verified the A23D fit for ViperMesh:
- Updated
docs/local-asset-library.mdwith the key restriction:- A23D's public Fair Usage Policy dated 2026-01-06 says downloading assets solely to build private libraries is prohibited
- the same public policy also says downloading assets for creating, testing, benchmarking, improving, or operating AI/generative systems is prohibited
- Also noted from A23D's public Licenses page dated 2026-01-06:
- only Business Commercial allows storage on company servers/internal asset libraries
- Enterprise is the path for custom AI/ML permissions
- Updated
-
Validation:
npx tsc --noEmitpassesnpm run lintpassesnpm run assets:init -- --root tmp/local-assets-seed-2succeeds with the new staging folders
- Because of the current published A23D restrictions, a one-month bulk download plan just to seed the ViperMesh agent's private local asset library is not a safe assumption under their standard public terms.
- The practical recommendation remains:
- keep Poly Haven mostly on-demand
- use private/user-owned/internal-safe assets for the first local catalog population
- use A23D for the local agent library only after written confirmation or a license that explicitly covers the AI/internal-library workflow
-
Added a seed local-library scaffold script:
- Added
scripts/maintenance/init-local-asset-library.ts - Added npm script
assets:init - The script creates the first recommended folder structure for:
- footwear
- plants
- baskets
- lamps
- books
- decor
- console tables / chairs / stools
- materials
- HDRIs
- It also creates:
README.mdcatalog/taxonomy.json
- Added
-
Extended the local asset library doc with sourcing guidance:
- Updated
docs/local-asset-library.mdwith:- A23D guidance
- the Poly Haven on-demand vs local-cache distinction
- the new two-step bootstrap flow:
npm run assets:initnpm run assets:catalog
- Updated
-
Validation:
npx tsc --noEmitpassesnpm run lintpassesnpm run assets:init -- --root tmp/local-assets-seedsucceedsnpm run assets:catalog -- --root tmp/local-assets-seed --out tmp/local-assets-seed/catalog/assets.jsonsucceeds and produces an empty starter manifest before assets are added
- A23D looks useful as a selective paid source for local ingestion, but not as something to mirror wholesale into ViperMesh. Their public legal terms explicitly restrict circumvention/scraping and treat assets as licensed, not sold.
- Poly Haven should remain mostly on-demand through the existing integration. Only frequently reused assets need local caching.
-
Added the first local curated asset-library layer to the live Studio stack:
- Added local asset MCP support to both addon copies:
desktop/assets/vipermesh-addon.pypublic/downloads/vipermesh-addon.py
- New Blender-side tools:
get_local_asset_library_statussearch_local_assetsimport_local_asset
- Added addon UI settings for:
- enabling the local asset library
- setting the catalog JSON path
- setting an optional library root path
- Added local asset MCP support to both addon copies:
-
Wired the new tools into the live agent/runtime path:
- Added LangGraph tool wrappers in
lib/ai/agents.ts - Added tool metadata in
lib/orchestration/tool-registry.ts - Updated tool selection heuristics in
lib/orchestration/tool-filter.ts - Updated the live system prompt in
lib/orchestration/prompts/blender-agent-system.md - Updated UI/tool label maps in:
components/projects/agent-activity.tsxcomponents/projects/step-session-drawer.tsx
- Updated post-run tool summaries in
app/api/ai/chat/route.ts
- Added LangGraph tool wrappers in
-
Added the first manifest/bootstrap layer for catalog population:
- Added schema/helpers in
lib/assets/local-catalog.ts - Added bootstrap script
scripts/maintenance/build-local-asset-catalog.ts - Added npm script
assets:catalog - Added example manifest
data/local-assets/catalog.example.json - Added local asset tool guide
data/tool-guides/local-asset-guide.md - Added sourcing/design doc
docs/local-asset-library.md
- Added schema/helpers in
-
Validation:
python -m py_compile desktop/assets/vipermesh-addon.py public/downloads/vipermesh-addon.pypassesnpx tsc --noEmitpassesnpm run lintpassesnpm run assets:catalog -- --root tmp/local-assets-test --out tmp/local-assets-test/catalog/assets.jsongenerated a valid starter manifest
- This is intentionally an MVP with no DB migration yet. The feature is configured through the Blender addon and live MCP tools so it can be tested immediately in Studio once the addon is reloaded.
- The bootstrap script discovers supported asset files and creates a starter manifest, but
.blendentries still need manualasset_namesrefinement for precise imports. - The intended routing order is now:
- local curated assets
- Poly Haven
- Sketchfab when explicitly enabled and license-safe
- procedural
execute_code
-
Validated the remaining uncommitted user edits:
app/auth/start-oauth/page.tsxswitches the logo from raw<img>tonext/imagedesktop/assets/vipermesh-addon.pyandpublic/downloads/vipermesh-addon.pyboth:- update
doc_urlfrom the old ModelForge repo tohttps://github.com/Ker102/ViperMesh - add explicit request timeouts to PolyHaven HTTP calls
- update
-
Verification:
npm run lintpassespython -m py_compilepasses for both addon copies- Confirmed the GitHub repository URL is live
- The two addon copies are byte-identical after the change.
- These edits appear to be valid leftover local changes from an earlier session rather than new experimental work.
-
Added generalized expert-pattern Blender scripts:
- Added
data/blender-scripts/reference_reconstruction_workflow.py - Added
data/blender-scripts/support_surface_alignment.py - These scripts encode the missing generalized patterns from the Studio image-reference analysis:
- anchor-first blockout
- camera-prominence-based refinement ordering
- local-to-world attachment-point alignment
- world-space bounding-box support placement
- raycast-assisted drop placement for irregular surfaces
- Added
-
Strengthened existing RAG guides with the same non-scene-specific rules:
- Extended
data/tool-guides/spatial-positioning-guide.mdwith:- local-to-world attachment point alignment
- world-space support-surface placement
- raycast placement for sloped/irregular supports
- Extended
data/tool-guides/scene-composition-guide.mdwith a reference-reconstruction priorities section:- blockout anchors first
- screenshot checkpoint before detail
- refine by camera prominence
- preserve recognizable silhouettes
- use focused follow-up passes instead of full-scene rebuilds
- Extended
- This checkpoint is intentionally generalized. No scene-specific recipes or hardcoded placement heuristics were added.
- The goal is to narrow the gap between coarse first-pass agent scripts and expert reconstruction strategy without overfitting the corpus to the entryway test.
-
Re-verified Blender 5.x EEVEE API against official docs:
- Confirmed from current Blender API docs that
scene.eevee.taa_render_samplesis still valid in Blender 5.x for final renders - Confirmed
scene.eevee.taa_samplesis the viewport sample property - Confirmed current AO distance lives on
view_layer.eevee.ambient_occlusion_distance - Confirmed the current render engine enum is
BLENDER_EEVEE
- Confirmed from current Blender API docs that
-
Corrected inaccurate EEVEE guidance in the RAG corpus:
- Fixed
data/tool-guides/render-guide.mdso it no longer falsely claimstaa_render_sampleswas removed - Rewrote the Blender 5.x EEVEE compatibility notes in:
data/blender-scripts/api_version_compatibility.pydata/blender-scripts/tasks/rendering/eevee_setup.pydata/blender-scripts/render_settings.pydata/blender-scripts/tasks/rendering/render_configuration.py
- Updated the affected scripts to use Blender 5.x-compatible sampling, compositor bloom guidance, and view-layer AO handling
- Fixed
-
Hardened compositor compatibility guidance:
- Replaced the hard claim that
scene.node_treeis simply “removed” with a version-safe access pattern: preferscene.compositing_node_groupin Blender 5.x and fall back toscene.node_treefor older versions
- Replaced the hard claim that
- This audit was triggered by the Studio entryway test review and a factual contradiction in the render guide
- The goal of this checkpoint is corpus correctness first; the next checkpoint will add new generalized expert-pattern scripts/guides for staged reference reconstruction and prop refinement
-
Fixed false-success tool streaming:
- Updated
lib/ai/agents.tsso tool results that return an embedded JSON error payload (for example{"error":"..."}insideToolMessage.content) are treated as failures - Both the dedup cache and the streaming middleware now use the same parsing path, so failed MCP responses no longer get cached as successful executions and no longer show green checks in the Studio activity panel
- Updated
-
Raised default Blender MCP timeout:
- Increased
lib/mcp/config.tsdefault timeout from 30s to 120s - The existing
BLENDER_MCP_TIMEOUT_MSenv override still works, but the default now better matches real Studio preview renders and other long-running Blender operations
- Increased
-
Verification:
npx tsc --noEmitpassesnpm run lintpasses
- This change was driven by the entryway Studio trace where
delete_object(Camera)andrender_imagereturned embedded MCP errors even though the local monitor showed them as completed - The goal is trustworthy telemetry first; recursion limits and agent strategy decisions should not be made from false-positive success states
-
Fixed live
execute_codeguide wiring:- Audited the tool-guide binding path in
lib/ai/agents.ts - Confirmed
TOOL_GUIDE_MAPkeeps only one guide per tool name, andexecute_codewas accidentally resolving toweight-painting-guide.md - Added a new curated guide
data/tool-guides/execute-code-guide.mdsoexecute_codenow receives general scene-building guidance instead of an unrelated specialist document
- Audited the tool-guide binding path in
-
Aligned guide triggers with the one-guide-per-tool architecture:
- Removed
execute_codefrommaterial-realism-guide.md,object-assembly-guide.md, andspatial-positioning-guide.mdtrigger lists so they continue to serve their direct tools without hijacking generic scene generation - Cleared
weight-painting-guide.mdtriggers so it no longer overrides the globalexecute_codeguide
- Removed
-
Added generalized expert-strategy guidance for reference scenes:
- New
execute-code-guide.mdteaches staged reference reconstruction:- block out scene anchors first
- verify with screenshot
- refine only the camera-visible props that still fail silhouette/proportion
- avoid monolithic “build everything at once” Python passes
- Encoded the generalized missing-link rule from the entryway test: prominent props need a minimum-part decomposition that preserves recognizable silhouette, even when the overall scene blockout is already correct
- New
-
Updated the live Blender agent system prompt:
lib/orchestration/prompts/blender-agent-system.mdnow explicitly tells the Studio Blender agent to:- stage image-reference reconstructions
- use screenshot checkpoints to decide targeted refinement
- reserve giant first-pass scripts for major layout only
- use direct tools for camera/light/render work once geometry stabilizes
-
Strengthened preview-render guidance:
data/tool-guides/render-guide.mdnow explicitly distinguishes interactive validation renders from final renders- New rule: prefer EEVEE or low-sample Cycles for iterative previews, and avoid near-final Cycles settings until composition is already approved
- This was driven by the successful 8-tool Studio entryway run: layout was decent, but prop fidelity on camera-visible details lagged because the agent over-compressed the scene into one coarse geometry pass
- The design intent is generalized guidance only — no scene-specific heuristics were added
- Blender target remains 5.x+
-
Recursion-limit failure diagnosis:
- Reviewed the failing Studio-mode session
d85b06a0 - Confirmed the agent ran for about 3 minutes after CRAG injection, then died with
GraphRecursionError: Recursion limit of 50 reached - Confirmed the current persisted monitoring did not preserve the in-flight tool-call sequence for this failure mode, so the logs could not prove whether the agent was making real progress or looping wastefully
- Reviewed the failing Studio-mode session
-
Partial tool-trace persistence added for direct agent runs:
- Enriched
agent:tool_callevents withtoolCallId,args, duplicate markers, and failure details - Dedup middleware now emits explicit
skippedevents when an identical tool call is suppressed app/api/ai/chat/route.tsnow records streamed tool events incrementally intoexecutionLogduring the run instead of reconstructing everything only afteragent.invoke()returns- On agent crashes, partial tool history is now preserved in
planningMetadata.rawPlan,planningMetadata.executionLog, and the orchestration log record
- Enriched
-
Failure summaries improved:
- Recursion/interruption failures no longer collapse to “no tools were used” if tools actually ran before the crash
- Partial completed/failed tool calls are now surfaced from the streamed trace so the next failure can be diagnosed from stored logs
-
UI typing aligned with richer tool events:
- Added
skippedsupport to the Agent Activity event typing so duplicate-suppression events remain type-safe
- Added
- This patch does not raise the recursion limit yet
- The current conclusion is: we need one rerun with the new telemetry to determine whether the Blender agent is genuinely hitting a complexity ceiling or wasting steps on redundant action patterns
-
TypeScript baseline repair:
- Fixed live typecheck failures in
app/api/ai/chat/route.ts,app/api/ai/workflow-step/route.ts, andapp/api/projects/studio-session/route.ts - Aligned workflow event typing across
workflow-timeline.tsx,studio-layout.tsx, andstep-session-drawer.tsx - Excluded non-runtime
scripts/andtmp/paths from repo-wide typecheck noise intsconfig.json - Verified:
npx tsc --noEmitpasses
- Fixed live typecheck failures in
-
Lint/tooling modernization for Next 16:
- Replaced deprecated
next lintscript with direct ESLint invocation inpackage.json - Removed legacy
.eslintrc.jsonand added flat config viaeslint.config.mjs - Fixed error-level React/JSX lint issues in setup, generation, and project activity/session UI files
- Verified:
npm run lintpasses
- Replaced deprecated
-
Image warning cleanup:
- Converted static public asset usage to
next/imagein the auth callback and landing UI - Kept user-supplied data URL previews on raw
<img>in Studio/session surfaces via small helper wrappers with explicit rationale
- Converted static public asset usage to
-
Studio test-analysis workflow saved:
- Added
docs/studio-script-gap-analysis.mdto capture the reusable comparison process for failed agent scripts vs expert scripts - This is intended for manual Studio-mode test review, not Autopilot validation
- Added
-
New Studio-only image-context test added:
- Added Test 20 in
docs/test-prompts.mdfor an entryway console scene with round-mirror alignment, on-surface placement, and under-table spacing checks - Included both a reference-image generation prompt and the matching Studio Blender agent prompt
- Added Test 20 in
-
Studio streaming indicator cleanup:
- Removed the redundant standalone
Thinking…bubble from the Studio session drawer - Moved reasoning-state display into the
AgentActivitypanel so it appears inline between tool-call phases while the step is still running
- Removed the redundant standalone
components/generation/ModelViewer.tsxis already imported bycomponents/generation/GenerationPanel.tsx, so it is part of the checked surface even if broader viewer work is still future-facing- Remaining non-failing console notice during lint:
baseline-browser-mappingpackage age warning
- README Updates: Renamed "Gemini 2.5 Pro" → "ViperAgent 2.0", Next.js 15 → 16, "Together.ai embeddings" → "Gemini embeddings".
- PR #26 Triage — Batch 1 (Quick Wins):
- Fixed
doc_urlin both addon copies (ModelForge → ViperMesh repo) - Added
timeout=30/60to all 6requests.get()calls in both addons - Replaced
<img>with Next.jsImageinstart-oauth/page.tsx - Fixed markdown lint (MD040) in
spatial-positioning-guide.mdandtest-prompts.md - Added "attach image" instruction to Test 18
- Fixed
- PR #26 Triage — Batch 2 (Component Fixes):
- Fixed nested
<button>inside<Link>innavbar.tsx(motion.button → motion.div) - Added file input reset, 10MB validation, and FileReader error handling in
studio-workspace.tsx - Added failed tool count + display in
agent-activity.tsxcollapsed summary
- Fixed nested
- PR #26 Triage — Batch 3 (Logic Fixes):
- Fixed RAG retry: now picks most-recent substantive prompt (reverse iter) instead of longest
- Fixed stale closure: added
workflowStepsRefinstudio-layout.tsxforexecuteStep/handleRunAll - Fixed pre-existing lint: added
"skipped"toStepCommandResult.statusunion inworkflow-timeline.tsx
-
Streaming UI Fix (
project-chat.tsx,agent-activity.tsx):- Hid per-message
mcpCommands(TOOL CALLS) block during active streaming — onlyAgentActivityshows live - Fixed "Thinking…" indicator — now only appears when agent is reasoning, NOT during tool execution
AgentActivitycollapses into a closed-by-default<details>dropdown ("✓ N tools used") when agent finishes- MCP execution summary is also now a
<details>(closed by default) for past messages
- Hid per-message
-
Follow-up Quality Fix (
route.ts):- Expanded
friendlyToolMapfrom 7 to 27 entries — all common Blender tools now have human-readable labels - Grouped & deduplicated tool labels (e.g. "cleaned up the scene (3×)" instead of "delete_object, delete_object, delete_object")
- Summary prompt now references visual outcomes, not tool names
- Fallback message uses grouped labels instead of raw tool names
- System prompt updated from "ModelForge" to "ViperMesh"
- Expanded
-
Documentation Rebrand (previous sub-session) — All ~50 "ModelForge" → "ViperMesh" references updated across 13 doc files
-
New Test Prompts (
docs/test-prompts.md):- Test 17: Multi-Object Fruit Market Stall (spatial + lighting)
- Test 18: Image Reference Recreation (vision + spatial)
- Tests 14-16 marked as future-only
- Documentation Rebrand — Renamed all ~50 "ModelForge" → "ViperMesh" references across 13 doc files:
docs/future-plans.md,docs/architecture.md,docs/architecture-notes.mddocs/3d-pipeline-strategy.md,docs/3d-pipeline-integration.mddocs/HANDOFF.md,docs/research-pipeline-techniques.md,docs/test-prompts.mddocs/addon-integration-roadmap.mdSETUP.md,SECURITY.md,deploy/runpod/README.md- Zero remaining
ModelForgereferences in the entire project (code + docs + config verified)
- Code Logic Rebrand — Renamed
window.modelforge→window.vipermeshandmodelforge-addon.py→vipermesh-addon.py:- Electron bridge:
preload.js(exposeInMainWorld key),electron.d.ts(interface + Window prop) - Frontend consumers:
login-form.tsx,electron-auth-listener.tsx,setup/page.tsx - Desktop app:
main.js(env vars, deep link protocol, window title, HTML auth pages, addon paths) - Desktop metadata:
package.json(name, description, author, appId, productName, copyright) - Addon file: renamed in both
desktop/assets/andpublic/downloads/ - Addon internals: bl_info, User-Agent, sidebar panel category, class names, operator bl_idnames, UI text
- Download URLs:
docs/page.tsx,quick-start-card.tsx - Build passed (exit code 0). Zero remaining
window.modelforge,modelforge-addon, ormodelforgerefs.
- Electron bridge:
-
Expert Comparison Artifact for Test 20
- Added scene-specific expert comparison script at
scripts/expert/test20_entryway_expert.py - Kept it outside the RAG corpus intentionally to avoid contaminating general retrieval with scene-specific patterns
- Added reusable MCP helper runner at
scripts/test/run-blender-script.ts
- Added scene-specific expert comparison script at
-
Expert Scene Build Validation
- Validated the expert script with
python -m py_compile - Confirmed the scene builds cleanly in Blender 5.0 headless mode
- Saved preview outputs:
tmp/expert-test20-render.pngtmp/expert-test20.blend
- Validated the expert script with
-
Crash Diagnosis
- First attempt crashed Blender 5.0 during a boot construction path that used a more aggressive merged/remesh style
- Replaced that with a safer boot-construction approach that builds successfully
- This expert artifact is now usable as the first manual comparison baseline for Test 20
- Expert scene script exists and builds successfully
- Plant silhouette is noticeably stronger than the agent output
- Boot silhouette has been refined again using a safer blended-body construction path and darker materials
- Current expert preview is materially closer to the reference than the earlier blocky boot pass
- ViperMesh UI Rebrand — Replaced all ~80 user-facing "ModelForge" text strings with "ViperMesh" across 20 files
- NOT changed:
--forge-CSS variable prefix (user confirmed leave as-is)
- NOT changed:
-
window.modelforge→window.vipermesh✅ -
modelforge-addon.py→vipermesh-addon.py✅ -
--forge-*CSS variable prefix →--viper-*(optional cosmetic, user deferred) - GitHub repo, Vercel project, domain
-
Chat UI Fixes (
project-chat.tsx):- Cleared agent streaming state (
agentEvents,agentActive,monitoringLogs,monitoringSummary) on new sends - Old failed plan blocks now collapsed with "Previous run" label — hides stale error details
- TypeScript compilation verified clean for touched files (repo has known legacy error: missing
ExecutionResultimport inroute.ts) - Committed:
fix: clear agent state on new send + collapse old plan errors
- Cleared agent streaming state (
-
Aesthetic Quality Skill Guide (
data/tool-guides/aesthetic-quality-guide.md):- Created new guide teaching agent anti-minimalism, stylistic coherence, and multi-component assembly
- Refactored to remove scene-specific code (torch/chair Python) — replaced with generic multi-component assembly template
- Ingested into vectorstore (13 total guides)
- Committed:
feat: add aesthetic quality & stylistic coherence guide+ refactor commit
-
Test Prompts 13-16 (
docs/test-prompts.md):- Test 13: Rigify biped rigging with weight painting
- Test 14: UniRig AI auto-rigging for quadrupeds
- Test 15: Keyframe bouncing ball animation with easing
- Test 16: MoMask AI text-to-motion walking animation
- Committed:
test: add rigging/animation/skeleton test prompts (13-16)
- Test 13 failed: Agent didn't execute any tools — didn't even remove default cube. Root cause NOT YET diagnosed (terminal logs rotated). Need to reproduce and check:
- Was it run in Studio or Autopilot?
- Which tool card was selected?
- Did the agent respond with text-only or error?
- Possible: skeleton tools might not be available under the selected tool card
- Pre-existing TS error:
ExecutionResulttype not imported inroute.tsline 192 (legacy dead code)
- Live test reasoning streaming — verify
agent:reasoningevents appear inline in chat during execution - Live test friendly tool names — verify Executed Commands list shows "Running Python code" instead of
execute_code - Reproduce and debug Test 13 — check agent routing for skeleton/rigging tool card
- Run Tests 14-16 (UniRig, keyframe animation, MoMask)
Two separate modes, fully decoupled:
-
Autopilot (
workflowMode: "autopilot"— default):chat/route.ts→ strategy router classifiesprocedural|neural|hybrid- Procedural path →
createBlenderAgentV2()directly (no planner) - Agent uses LangChain v1
createAgentwith built-in ReAct loop (LangGraph) - Middleware stack: Dedup → Streaming → ViewportScreenshot → RAG/CRAG
- System prompt loaded from
lib/orchestration/prompts/blender-agent-system.md - Domain guides bound to tool descriptions from
data/tool-guides/*.md - RAG: blender-scripts searched in route.ts, tool-guides injected via agents.ts at module load
- Recursion limit: 50 (line 738 in
route.ts)
-
Studio (
workflowMode: "studio"):chat/route.ts→workflow-advisor.tsgenerates a workflow proposal (step-by-step cards)- UI shows cards; user clicks Execute/Skip/Manual Done per step
- Each step hits
workflow-step/route.tswhich creates a freshcreateBlenderAgentV2()per step - Neural steps use
lib/neural/registry→ provider clients (fal.ai, RunPod, YVO3D)
Dead code (preserved for reference/revert):
planner.ts— old planner prompt; NOT in the live execution pathexecutor.legacy.ts— old hand-rolled step executor (37KB)agents.legacy.ts— old agent without LangChain v1 (19KB)
Key rules:
- Tool guides must be GENERAL, never scene-specific (RAG matches wrong guides otherwise)
- 13 tool guides total; ingestion:
npx tsx scripts/ingestion/ingest-tool-guides.ts --force
See
docs/future-plans.md— the single source of truth for P0-P3 roadmap
Seedocs/architecture.md— the canonical architecture reference (current vs legacy)
- Added glassmorphism floating pill navbar with magnetic hover pills and spring CTA animations.
- Added LineShadowText component (Magic UI) to '3D Models' hero text with teal shadow.
- Managed Local Asset Defaults:
- Desktop app now bootstraps a managed local asset root automatically on startup at
Documents/ViperMeshAssets - Added default managed catalog creation at
catalog/assets.jsonand reserved cache directory atcache/ - Blender addon now auto-discovers the same managed catalog/root by default while keeping manual override fields for BYO libraries
- Desktop setup page now shows the managed library root, catalog path, cache root, and includes an "Open Managed Asset Folder" action
assets:initnow seeds the samecache/structure and writes an emptycatalog/assets.json
- Desktop app now bootstraps a managed local asset root automatically on startup at
- The reserved cache path is only a stable location for future managed downloads. The current runtime still imports local files directly.
- Manual
Catalog JSONandLibrary Rootoverrides remain intact for advanced users and BYO asset libraries.
- Gemini Tool Schema Compatibility Fix:
- Fixed a Studio startup failure where Gemini rejected the
search_local_assetstool schema becauselimitused a strict positive Zod constraint that serialized to JSON SchemaexclusiveMinimum - Replaced that tool parameter constraint with a Gemini-safe integer range using
min(1)andmax(25)
- Fixed a Studio startup failure where Gemini rejected the
- Studio Runtime Hardening for Local Assets + MCP Transport:
- Investigated Test 20 run
60874546-2f70-4a50-9f07-80fda1892f84: local asset search failed once withLocal asset catalog path is not configured, while 17 material calls failed withECONNREFUSED 127.0.0.1:9876 - Added a Blender-side local asset status probe to the live chat route and Studio workflow-step route, and now only expose
search_local_assets/import_local_assetto the agent when Blender reports the local library as enabled and ready - Extended
/api/mcp/statusto include local asset runtime status, not just raw TCP reachability - Serialized MCP command execution in the app and added small retries for transient transport errors so Gemini tool bursts do not open a storm of parallel Blender TCP connections
- This should prevent the exact failure mode where local asset tools are advertised while Blender is still on stale addon state, and reduce
ECONNREFUSEDchurn during material batches
- Investigated Test 20 run
- Addon Version Visibility:
- Bumped the Blender addon metadata version from
1.1.0to1.2.0in both distributed addon copies - Updated the Add-ons panel description to mention the Studio agent and managed asset-source support
- Added a visible
Addon v1.2.0label inside the ViperMesh sidebar so stale Blender installs are easier to identify without opening Blender preferences
- Bumped the Blender addon metadata version from
- Render Policy + Follow-up Response Hardening:
- Updated the live Blender system prompt and
render-guide.mdto enforce an active camera beforerender_image, prefer lightweight preview renders by default, and stop repeated same-run render retries after the first render failure - Added a middleware guard that blocks additional
render_imagecalls after one render failure in the same agent run - Reworked post-execution follow-up generation in
app/api/ai/chat/route.tsto use a guarded non-streaming response, reject rubric/instruction leak text likeFits the criteria. 2 sentences. No tool names, and fall back to a scene-aware user-facing message - Render-failure follow-ups now explicitly suggest a dedicated lighter retry pass in the next run instead of silently retrying renders during the same run
- Updated the live Blender system prompt and
- Generation Viewer MVP Direction Started:
- Updated the local
originremote to the renamed GitHub repository URL (Ker102/ViperMesh) so the new feature branch no longer relies on GitHub redirects - Verified the current viewer research and roadmap direction:
<model-viewer>remains the intended MVP stack for the first in-browser 3D preview milestone, while editing-heavy features like the AI texture brush stay deferred to later phases - Added
@google/model-viewerand alignedthree/@types/threeto0.182.0to match the package peer dependency cleanly with the repo's existing React 19 setup - Replaced the old
@react-three/fiber-basedcomponents/generation/ModelViewer.tsximplementation with a client-only<model-viewer>wrapper that keeps the sameurlprop contract, supports load/error states, safer URL validation, camera controls, and a reset-view action - Added app-level React 19 JSX typing for the custom
<model-viewer>element inlib/types/model-viewer.d.ts
- Updated the local
- Viewer Test Samples (No Generation Cost):
- Added
lib/generation/sample-models.tsto discover local.glbfiles from the existing dev-only sample locations undertmp/neural-outputandtmp/local-assets-test/props - Added authenticated route
app/api/generate/3d/samples/route.tsthat lists available local sample models and streams a selected.glbback to the browser - Extended
components/generation/GenerationPanel.tsxwith a "Viewer Test Models" section so the model viewer can be exercised with existing local GLBs instead of calling Replicate or fal - This keeps
/generateuseful as a viewer sandbox while the real long-term viewer integration still targets the in-project Studio workflow after neural stages succeed
- Added
- Viewer Sample Filtering Fix:
- Diagnosed the sample-model runtime failure: the sandbox route was exposing tiny placeholder
.glbfiles (13bytes and772bytes) that were not valid renderable scene assets - Updated
lib/generation/sample-models.tsto only surface usable GLBs by checking the file header forglTFmagic bytes and enforcing a minimum sample size threshold - The viewer sandbox now only lists the two valid neural-output GLBs, avoiding malformed sample files that caused
<model-viewer>to fail withthis[$preparedGLTF] is undefined
- Diagnosed the sample-model runtime failure: the sandbox route was exposing tiny placeholder
- Desktop Studio Workspace Expansion:
- Widened the project page shell from the old
container+max-w-5xllayout to a desktop-friendlymax-w-[1760px]workspace so Studio has enough room for future model viewer and richer tool panels - Kept the page responsive by using wider desktop padding and moving the lower "Connect to Blender" and "Conversation History" sections into a responsive grid rather than leaving the whole project page cramped
- Increased the Studio frame height on desktop and removed the inner
max-w-2xlcap insideStudioWorkspacedetail view so larger forms, prompts, and future model previews can breathe - Expanded Studio tool grids to allow a fourth column on very wide displays while leaving tablet/mobile breakpoints intact
- Widened the project page shell from the old
- Studio Neural Viewer Design + Plan:
- Captured the agreed Studio neural workflow in
docs/studio-neural-viewer-design.md: afterRun Now, neural tools dock left, the viewer stage stays persistent on the right, prompts become read-only during generation, and collapsing the dock leaves a slim restore handle attached near the left toolbar - Added the first implementation plan in
docs/plans/2026-03-31-studio-neural-viewer-implementation.mdso the split-view rollout can be built in controlled batches instead of ad hoc UI edits
- Studio Neural Split View — First Working Batch:
- Added authenticated neural output transport routes:
app/api/ai/neural-run/route.tsexecutes neural runs via the live provider registry, andapp/api/ai/neural-output/route.tsstreams generated local GLBs back into the browser viewer through safe authenticated URLs - Added
lib/neural/output-files.tsto validate generated output paths undertmp/neural-outputand construct viewer-safe in-app URLs for the new Studio neural viewer stage - Updated
StudioLayoutso neural runs are represented in the bottom pipeline as dedicated steps rather than being misrouted through the generic chat/blender-agent path - Updated
StudioWorkspaceso neuralRun Nowtransitions into a split workspace: docked read-only neural panel on the left, persistent viewer stage on the right, stop action during generation, collapse-to-handle behavior, and automatic viewer loading when a generated GLB is returned - Reused the existing
components/generation/ModelViewer.tsxinside Studio, so the same viewer engine now powers both the/generatesandbox and the in-project neural workspace - During validation, the local
HUNYUAN_API_URLendpoint (http://localhost:8080) did not answer quick health probes, so real Hunyuan generation still depends on that local service actually being up even though the Studio UI and route wiring are now in place
- Studio Neural Viewer Overlay Refinement:
- Removed the extra nested "Viewer" window framing inside the Studio neural workspace so the model viewer now acts as the actual workspace canvas rather than living inside a second bordered panel
- Changed the neural side panel from a layout sibling into an overlay inspector: the viewer keeps the same width whether the panel is open or collapsed, and the left panel now floats over the viewer instead of shrinking it
- Added a more visible collapsed restore handle (
Tool panel) attached near the left toolbar so the neural panel is easier to rediscover after collapse - Added a focus toggle for the neural panel, allowing it to reopen as a much wider read-only inspector with prompt/config fields and tool descriptions visible again without making the prompt editable during an active run
- Increased the desktop Studio shell height again so the workspace dominates more of the project page and leaves less unused screen space below it
- Studio Neural Canvas + Demo Preview Pass:
- Removed the remaining inner padding around the Studio neural viewer stage so the model viewer now fills the workspace canvas directly instead of reading like a smaller sub-window inside the shell
- Changed the collapsed
Tool panelrestore action to reopen the richer focus inspector by default, making the reopened neural panel feel closer to the original full-detail tool view instead of a narrow dock - Rebalanced the focus overlay width so it stays information-dense without covering nearly the entire viewer surface
- Moved the local sample GLB controls into a high-visibility "Viewer demo" section near the top of the neural inspector, including active demo labeling so the Studio viewer can be previewed without waiting for a real neural generation to complete
- Studio Neural In-Place Rerun Flow:
- Moved the collapsed
Tool panelrestore handle lower so it no longer overlaps the viewer title and model label in the top-left canvas overlay - Replaced the old
New Runbehavior that spawned a duplicate pipeline entry with an in-placeRun Againflow for neural tools - Neural runs now keep editable draft inputs after a run completes, fails, or is stopped, so the user can adjust the prompt or reference image directly inside the overlay panel and rerun the same pipeline step
- Updated the Studio timeline integration so rerunning a neural tool reuses the existing neural step ID and refreshes that step's inputs/status instead of adding a second copy of the same tool to the pipeline
- Studio Neural Pipeline Restore Fix:
- Pipeline clicks now distinguish neural steps from generic agent/chat steps: clicking a neural chip in the bottom pipeline no longer opens the generic white session drawer
- Studio now restores the neural workspace state for that pipeline step instead, including the overlay viewer context that was cached for the step ID
- Added local neural run state caching keyed by pipeline step ID inside
StudioWorkspace, so returning to the same Hunyuan/TRELLIS pipeline tab restores the last known neural viewer state instead of falling back to a blank prompt/session shell - Pipeline chip selection now also switches the active Studio category to the selected tool's category, so reopening a neural step returns the user to the correct workspace mode automatically
- Viewer Professionalization + Geometry Handoff:
- Upgraded
components/generation/ModelViewer.tsxwith a more product-grade control layer:Fit,Reset,Fullscreen, andDownloadactions now live directly in the viewer stage instead of leaving the Studio neural result as a passive preview - The viewer now explicitly reframes on model load using
<model-viewer>'s staging support before jumping the camera to goal, producing a cleaner first impression for generated models - Added the first cross-tool continuation affordance in Studio: once a neural geometry run finishes successfully with a real generated result, the neural side panel now shows a suggested
Continue to Hunyuan3D Paintbutton - That continuation carries the generated model URL into the texturing tool as a prefilled
meshUrl, and also carries forward the original reference image when available so users can move from geometry to texturing without manually reattaching inputs - Added basic
meshinput handling in the Studio tool detail form so downstream tools can visibly acknowledge that a current model is attached, even before a full project-asset picker exists - Preserved the current plan to keep
<model-viewer>as the polished review/result viewer while reserving more interactive engines for future tools like AI texture brushing that need real manual scene editing rather than display-oriented material swapping
- Studio Neural Refresh Persistence:
- Extended
WorkflowTimelineStepwith persistedneuralStateso Studio neural pipeline tabs can retain their viewer URL, viewer label/source, generation time, and rerun draft inputs across browser refreshes instead of keeping them only in React memory - Updated
StudioWorkspaceso selecting a neural pipeline step restores from either the in-memory cache or the persistedneuralStatesaved on the pipeline step, allowing generated TRELLIS/Hunyuan results to return to the model viewer after a refresh - Wired neural run state changes back into the pipeline step itself on every meaningful change, so successful generated models remain attached to their pipeline tab until the tab is removed
- Added session-scoped selected-step restore in
StudioLayoutusingsessionStorage, so refreshing the browser in the same tab reopens the same Studio pipeline step and category automatically without waiting for the user to click the chip again - Kept this intentionally session-scoped rather than global: the open-step restore survives refresh/connection hiccups in the same tab, while closing the browser tab clears that UI selection as expected
- Studio Generated Assets Shelf (Project-Scoped First Slice):
- Added a dedicated
Generated Assetsshelf panel off the Studio sidebar so persisted neural outputs from the current project can be reopened without scrolling through the pipeline or relying only on the in-view continuation button - The shelf is derived from persisted
WorkflowTimelineStep.neuralState, so it survives refreshes and only includes successful generated neural outputs with a real viewer URL - Each asset card can reopen the original pipeline step in the viewer, and geometry outputs from shape tools can be pushed directly into
Hunyuan3D Paintfrom the shelf using the saved mesh URL plus the carried reference image when available - Added an explicit generated-assets sidebar button with a count badge, while keeping this first version project-scoped and step-backed rather than introducing a separate user asset table before the UX is validated
- Added a lightweight external-tool launch path in
StudioWorkspace, so shelf-driven handoffs can open downstream tool forms with prefilledmeshUrlinputs without spawning duplicate pipeline tabs
- Generated Asset Picker Planning + Shared Setup:
- Added the next-batch implementation plan at
docs/plans/2026-03-31-generated-assets-picker-and-library.md, covering the shared picker for allmeshUrltools, richer visual attachment cards, and the later saved-user-library DB phase - Kept the DB/storage phase explicitly separate from the immediate picker work because the next UX slice can be built entirely on top of the already-persisted
studio_sessions.stepsJSON - Extracted the generated-asset domain logic into
components/projects/generated-assets.ts, creating a sharedGeneratedAssetItemmodel plusextractGeneratedAssets()so the sidebar shelf and the future inline picker do not diverge - Updated
StudioLayoutandGeneratedAssetsShelfto use that shared helper as the source of truth, which is the first low-risk setup slice before wiringAttach from Generated Assetsinto everymeshinput
- Neural Paint Failure Clarity + Attachment Preview Pass:
- Diagnosed the first
TRELLIS → Hunyuan3D Paintfailure path from the local server logs: the RunPod job stayed queued for the full five-minute polling window and never reached a worker, so the failure was a queue/warmup timeout rather than a malformed handoff payload - Updated
lib/neural/providers/runpod-client.tsto replace the generic timeout path with RunPod-specific polling, so queue-stalled jobs now return a clearer user-facing message distinguishing "never started" from "started but did not finish" - Fixed
getAssetDisplayLabel()incomponents/projects/studio-workspace.tsxso relative in-app viewer URLs like/api/ai/neural-output?path=...resolve to clean filenames instead of leaking raw encoded transport/query strings into the UI - Upgraded
MeshAttachmentCardto include a compact visual 3D preview using the shared<ModelViewer>component, replacing the previous plain-text attachment treatment formeshinputs in both the inline tool form and the neural rerun panel - Added a visible failure banner inside the neural viewer stage when a run fails or is stopped while an earlier mesh is still displayed, so long-running paint failures are visible directly on the canvas instead of only in the side-panel status copy
- Rebalanced the neural viewer's top overlay layout with reserved space for the built-in model-viewer controls and truncation-safe metadata chips, reducing the overlap between viewer actions and attached-model / status indicators
- RunPod Paint/Part Worker Crash Diagnosis + Dependency Pinning:
- Verified from the RunPod worker logs that the paint endpoint was not merely cold-starting; workers were crashing during startup with
AttributeError: module 'torch' has no attribute 'xpu', which explains the throttled queue and the UI-side "did not start within 5 minutes" message - Confirmed the current failure mode came from a version mismatch in the serverless image: the Dockerfiles pinned
torch==2.2.0while leavingdiffusers,transformers, andacceleratefloating, allowing an incompatible diffusers release to import APIs absent from that torch build - Cross-checked Tencent's official Hunyuan3D 2.1 setup guidance, which states they test with Python 3.10 and
torch==2.5.1,torchvision==0.20.1,torchaudio==2.5.1, plus pinnedtransformers==4.46.0,diffusers==0.30.0,accelerate==1.1.1, andhuggingface-hub==0.30.2 - Updated
deploy/runpod/hunyuan-paint/Dockerfileanddeploy/runpod/hunyuan-part/Dockerfileto pin those core dependency versions instead of floating them, so future RunPod builds stop drifting into startup-crash combinations - Confirmed the Hugging Face repo reference itself is valid (
tencent/Hunyuan3D-2/tencent/Hunyuan3D-2.1); the browser-side404came from checking an invalid page URL format with a colonized revision string rather than from a missing upstream model repository
- Azure GPU Setup Hardening + Split Endpoint Prep:
- While turning the Azure migration notes into a concrete setup checklist, identified an architectural mismatch in the first draft: the docs assumed a single
hunyuan-apiservice for both Shape and Paint, but the current provider metadata and Azure GPU lanes make that a poor long-term fit because Shape belongs on the lighter lane while Paint belongs on the heavier lane - Added dedicated runtime env-var support in the app clients:
lib/neural/providers/hunyuan-shape.tsnow prefersHUNYUAN_SHAPE_API_URLand falls back toHUNYUAN_API_URL, whilelib/neural/providers/hunyuan-paint.tsnow prefersHUNYUAN_PAINT_API_URLand falls back to the same legacy shared URL - Updated the Azure migration scaffolding to recommend three services instead of one combined Hunyuan service:
hunyuan-shape-api,hunyuan-paint-api, andhunyuan-part-api, while keeping the old combineddeploy/azure/hunyuan-api/README.mdonly as a compatibility note - Added
deploy/azure/setup-checklist.mdwith the exact one-time Azure setup order: region choice (Sweden Central), ACR Premium, Container Apps environment, managed identity/AcrPull wiring, app names, recommendedminReplicas/maxReplicas, GitHub Actions variables, and rollout order - Added
deploy/azure/gpu-and-quota-reference.mdwith the current ViperMesh GPU mapping and the exact quota labels/search terms to request for both Azure Container Apps (Managed Environment Consumption T4 Gpus,Managed Environment Consumption NCA100 Gpus) and AKS fallback (Standard NCASv3_T4 Family vCPUs,Standard NCADS_A100_v4 Family vCPUs) - Updated the Azure GitHub Actions example and vars/secrets template so future CI/CD is already aligned with the split-service Azure layout instead of the earlier single combined app assumption
- First Azure-Ready Hunyuan Service Implementation Slice:
- Implemented a real Azure-ready
deploy/azure/hunyuan-shape-api/Dockerfileandstart.shthat run Tencent's officialHunyuan3D-2.1FastAPIapi_server.pyon0.0.0.0:${PORT:-8080}, rather than relying on a RunPod worker entrypoint - Implemented
deploy/azure/hunyuan-paint-api/app.pyas a dedicated FastAPI wrapper for the existing ViperMesh/texturizecontract, decoding base64 mesh/image payloads, lazily loadingHunyuan3DPaintPipeline, and returning a binary GLB/OBJ file response - Added
deploy/azure/hunyuan-paint-api/Dockerfileandstart.sh, including the paint-specificcustom_rasterizerandDifferentiableRendererbuild steps from Tencent's official Hunyuan3D 2.1 setup instructions plus the Real-ESRGAN checkpoint download required by the paint stack - Updated the Azure docs to reflect the actual state of the repo: Shape and Paint now have implemented HTTP container scaffolds, while
hunyuan-part-apiremains a planned later slice and should not yet be included in the active GitHub Actions deployment workflow
- Azure CI/CD Activation + Current Environment Wiring:
- Added the real workflow at
.github/workflows/deploy-azure-neural-gpu.yml, activating build-and-push forhunyuan-shape-apiandhunyuan-paint-apiand supporting both Azure auth modes:AZURE_CREDENTIALSservice-principal JSON or the OIDC-styleAZURE_CLIENT_ID/AZURE_TENANT_ID/AZURE_SUBSCRIPTION_ID - Added
deploy/azure/create-container-apps.ps1, a PowerShell helper that targets the live Azure environment (gpumodels,managedEnvironment-gpumodels-970d,vipershreg,T4profile,a100profile) and can create or update the Shape and Paint Container Apps against the ACR images - Verified with Azure CLI that the current registry is not anonymously pullable:
vipershreghaspublicNetworkAccess=EnabledbutanonymousPullEnabled=false, so Container Apps still need registry auth unless anonymous pull is explicitly enabled later - Updated the Azure setup docs and GitHub variable template with the current concrete Azure resource names plus the extra repository variables used by the new workflow and helper script
- Azure Service Bearer Auth + OIDC Fix:
- Added backend-only bearer token support to the Azure Shape and Paint paths so the services are no longer protected only by undisclosed URLs
- Implemented
deploy/azure/hunyuan-shape-api/app.pyas an authenticated FastAPI proxy in front of Tencent's localapi_server.py, leaving/healthopen while protecting/generate - Updated
deploy/azure/hunyuan-paint-api/app.pyto enforce an optionalAPI_BEARER_TOKENon/texturize, again leaving/healthopen for readiness checks - Updated
lib/neural/providers/hunyuan-shape.tsandlib/neural/providers/hunyuan-paint.tsto sendAuthorization: Bearer ...whenHUNYUAN_SHAPE_API_TOKEN/HUNYUAN_PAINT_API_TOKENare configured on the ViperMesh backend - Updated
lib/neural/registry.tsso dedicated Azure Shape/Paint endpoints take precedence over RunPod whenHUNYUAN_SHAPE_API_URL/HUNYUAN_PAINT_API_URLare set - Extended
deploy/azure/create-container-apps.ps1so it can inject the service tokens into each Container App as secret-backedAPI_BEARER_TOKENenvironment variables - Verified and fixed the GitHub OIDC Azure app setup: the federated credential subject originally targeted
refs/heads/Main, but the repo default branch ismain, so the credential was replaced withrepo:Ker102/ViperMesh:ref:refs/heads/main - Added the missing GitHub secrets
AZURE_CLIENT_ID,AZURE_TENANT_ID, andAZURE_SUBSCRIPTION_IDfor the OIDC-based Azure deploy workflow
- Local Azure Container Smoke-Test Harness:
- Added
deploy/azure/docker-compose.local.ymlto run the Azure-targetedhunyuan-shape-apiandhunyuan-paint-apiimages locally, without having to wait for another ACR build or Azure Container Apps rollout - Added
deploy/azure/smoke-test-local.ps1, a PowerShell smoke script that can build and launch the selected local service, wait for/health, and perform cheap contract checks before a cloud deployment - The Paint smoke path now explicitly verifies that
RealESRGAN_x4plus.pthexists at/app/hunyuan3d/hy3dpaint/ckpt/RealESRGAN_x4plus.pth, which would have caught the previous Azure checkpoint-path bug before the image was pushed - The same script supports optional end-to-end local requests when a real input image or mesh path is provided, so we can choose between a fast boot/path smoke test and a heavier full request test
- Updated
deploy/azure/README.mdanddeploy/azure/setup-checklist.mdso the local Compose smoke test is now part of the expected pre-rollout path rather than tribal knowledge
- Azure Paint Config Path Regression Fix:
- Reproduced the latest Paint regression locally through the new Docker Compose smoke path instead of guessing from Azure-only failures
- Confirmed Tencent's
Hunyuan3DPaintConfigdefaultsmultiview_cfg_pathto the relative pathhy3dpaint/cfgs/hunyuan-paint-pbr.yaml, which only resolves if the process starts from the repository root - Identified that the Azure wrapper runs from
/app, so requests were failing at runtime withNo such file or directory: '/app/hy3dpaint/cfgs/hunyuan-paint-pbr.yaml'even though the config file actually exists at/app/hunyuan3d/hy3dpaint/cfgs/hunyuan-paint-pbr.yaml - Updated
deploy/azure/hunyuan-paint-api/app.pysoload_model()now overridesconfig.multiview_cfg_pathto the absolute repo-aware path before constructingHunyuan3DPaintPipeline - Tightened
deploy/azure/smoke-test-local.ps1to verify both required runtime assets for Paint: the RealESRGAN checkpoint and thehunyuan-paint-pbr.yamlconfig file, so this class of path regression is caught before the next Azure rollout - Updated
deploy/azure/README.mdto document that both runtime assets are part of the expected local Paint smoke test
- Azure Paint Health-Probe Concurrency Fix:
- Investigated a later
503 upstream connect error or disconnect/reset before headersfailure and correlated it with a~63.7srequest time plus a delayed container restart in Azure metrics, which did not match the documented Azure Container Apps ingress timeout (240s) and instead pointed to the app becoming unresponsive during inference - Confirmed the paint wrapper used
async def /texturizewhile performing long synchronous GPU/model work on the main event loop, which blocks/healthresponses during inference and lets Azure health probes mark the replica unhealthy even though the revision later recovers - Updated
deploy/azure/hunyuan-paint-api/app.pyso/texturizeis now a synchronous FastAPI handler, allowing FastAPI/Uvicorn to run the heavy work in the threadpool rather than on the event loop - Added an
INFERENCE_LOCKaround the paint pipeline call to keep model access serialized inside the single replica while still allowing/healthto respond concurrently - This change is intended to stop long Paint requests from starving the health probes and triggering ingress-level upstream resets during otherwise valid inference runs
- Azure Paint Memory Lift + Attachment Viewer Simplification:
- Investigated the next failure round where Azure restarted the Paint replica again and the Studio input model preview reported
webglcontextlost, even after the probe-starvation fix landed - Confirmed from Azure metrics that the failing Paint request still ran for about
63.4s, droveMemoryPercentageto99%, and then restarted the replica, shifting the likely root cause from ingress/probe starvation to process memory exhaustion during model load or inference - Updated
deploy/azure/hunyuan-paint-api/app.pyto preload the paint model during FastAPI startup, so the Azure revision now has to prove it can hold the model before traffic is routed to it instead of failing only on the first user request - Updated
deploy/azure/create-container-apps.ps1defaults for Paint to a larger runtime envelope (4 CPU,24Gimemory) and reducedPAINT_MAX_NUM_VIEWfrom6to4to lower runtime pressure on the A100 lane - Rolled the live Paint app to
vipershreg.azurecr.io/vipermesh/hunyuan-paint-api:memfix-20260419190251and updated the active Azure revision tovipermesh-paint-api--memfix20260419190251 - Removed the nested
ModelViewerfromMeshAttachmentCardincomponents/projects/studio-workspace.tsx, replacing it with a lightweight asset preview card so the side panel no longer competes with the main stage for another WebGL context while the source mesh is already visible in the primary viewer
- TRELLIS-to-Paint GLB Sanitization + Static Attachment Preview:
- Investigated the next immediate Paint failure and confirmed it was no longer a container restart issue: Hunyuan Paint was rejecting the attached TRELLIS GLB because the source file embedded
image/webptextures that the loader could not decode (Unknown image format. STB cannot decode image data) - Verified against the actual local TRELLIS output (
tmp/neural-output/fal-trellis-1774966329800.glb) that it contained2embedded images,2textures,1material, andEXT_texture_webp - Added
lib/neural/glb-sanitize.ts, a backend-side helper that strips images, textures, samplers, material assignments, and texture/material extension declarations from GLB inputs while preserving the geometry payload, which is the correct contract for the Paint stage - Updated
lib/neural/providers/hunyuan-paint.tsso all GLB mesh inputs are sanitized before the mesh bytes are posted to the Azure Paint service - Reworked
MeshAttachmentCardincomponents/projects/studio-workspace.tsxso it can show a static preview image when one is available (for example the carried source/reference image) without spinning up another live<model-viewer>instance inside the side panel - Added
deploy/azure/acr-build.ps1as a Windows-safe ACR build helper that avoids the Azure CLI log-stream Unicode issue by using--no-logsand polling the queued build status instead of streaming the problematic console output
npx tsc --noEmitnpm run lint(passes; only the existingbaseline-browser-mappingage notice remains)