Repository navigation
feat(agent): stream chat responses as typed SSE events - #379
Merged
Merged
Conversation
inspect_mesh diagnoses a mesh without modifying it: watertight, manifold, winding, holes, degenerate and self-intersecting faces, parts, bounds, area, volume, UVs/normals, and a printable verdict. suggest_fixes derives registry op calls (repair, decimate) from that report, and lists the problems no op can fix yet as notes. Topology is checked on a position-merged copy, so UV seams do not read as holes. Self-intersections go through pymeshlab; when they are not checked, printable is null rather than a claim. Normals are read from the file itself, since trimesh computes them on demand. MeshOpResult.file_path is now optional so analysis ops return only their report. Both ops are exposed to the agent and the MCP server. Closes #296
feat(mesh-ops): read-only inspect_mesh and suggest_fixes ops (T-A2)
…point Four registry ops derive their 4x4 matrix from the mesh itself: recenter (centroid to origin), drop_to_ground (lowest point to y = 0), auto_orient (smallest rotation that turns the thinnest PCA axis vertical; meshes without a clear flat side are left alone) and normalize_scale (size in m/cm/mm along the longest side or one axis). apply_transforms composes requested steps in a fixed order (orient, scale, recenter, ground) on one load and writes a single file, so grounding is never undone by a later step. POST /optimize/arrange exposes it, validating each step's params through the registry, and the raw /transform endpoint now shares the same bake helper. The agent and MCP server get an arrange_mesh tool that takes every step at once and reports the new mesh path for chaining. The world-space geometry helpers move to mesh_ops/geometry.py, shared with inspect_mesh, and the registry exposes resolve_params. Closes #297
feat(mesh-ops): semantic transforms and one-call arrange (T-A3)
repair_mesh diagnoses the mesh, runs only the steps the diagnostic calls for (degenerate faces, non-manifold edges, hole filling without a size limit, face re-orientation), then re-checks, for up to three passes or until a pass makes no progress. A mesh left inside-out is flipped at the end. Each pass is judged on position-merged geometry, exactly as inspect_mesh sees it, so UV seams are not mistaken for holes and a reported success holds once the file is re-inspected. A sound mesh is left alone and no file is written. With fill_holes off, only face-preserving fixes run, since removing faces would open holes. The result reports the before/after topology, the remaining issues, and whether textures were dropped (the output is geometry only). inspect_mesh now flags inside-out meshes, and suggest_fixes proposes repair_mesh, which also makes inconsistent winding fixable. The legacy repair op is unchanged for the mesh-repair workflow node. The generic /optimize/op route now writes its output next to the input under a unique name, like the dedicated edit routes. The agent and MCP server get a repair_mesh tool. Closes #298
The shipped venv installs only api/requirements.txt, which never pulls scipy: trimesh treats it as optional. inspect_mesh, suggest_fixes and repair_mesh need it for connected parts, hole loops and vertex merging, so they failed outside a dev environment, where torch brings it in. repair_mesh re-oriented faces with trimesh.repair.fix_winding, which needs networkx, also undeclared; it now uses pymeshlab, and skips the step for a pass while the mesh is still non-manifold. A guard test runs every mesh-op family with networkx unimportable, including the re-orientation path, and checks scipy stays declared.
feat(mesh-ops): diagnostic-driven repair_mesh composite op (T-A4)
agent_chat now returns a StreamingResponse emitting token, thinking, tool_start, tool_done and done events. ChatPanel consumes the stream so text appears progressively and tool calls show an in-progress state. Closes #300
This was referenced Oct 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #300 (T-B1).
Summary
agent_chatreturns aStreamingResponse(SSE) emitting typed events:token,thinking,tool_start,tool_done,done. Falls back gracefully when a provider ignores"stream": true.src/shared/utils/agentStream.tsparses the event stream;ChatPanel.tsxrenders text and thinking progressively and shows tool calls as in progress until they complete.doneevent after any already-streamed text.Tests
api/tests/test_agent_streaming.py(14 tests) andagentStream.test.ts(5 tests, wired intotest:node).npm run test: all green (Python 289 OK, Node 210 pass). ESLint clean on changed files.Manual check
list_models,inspect_mesh+repair_mesh)