@hybridlabor-api/bdb-hardware-pcb 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/README.md +116 -0
  2. package/config/mcp/antigravity.json +22 -0
  3. package/config/mcp/claude.json +22 -0
  4. package/config/mcp/codex.toml +25 -0
  5. package/docs/adr/ADR-001-KICAD-OPENSCAD-MCP-STRATEGY.md +334 -0
  6. package/docs/review_documentation.md +121 -0
  7. package/installer.js +358 -0
  8. package/mcp_servers/kicad-mcp-server/.env.example +22 -0
  9. package/mcp_servers/kicad-mcp-server/.github/workflows/ci.yml +36 -0
  10. package/mcp_servers/kicad-mcp-server/CLAUDE.md +487 -0
  11. package/mcp_servers/kicad-mcp-server/README.md +316 -0
  12. package/mcp_servers/kicad-mcp-server/docs/DEVICE_TREE.md +416 -0
  13. package/mcp_servers/kicad-mcp-server/docs/INSTALLATION.md +332 -0
  14. package/mcp_servers/kicad-mcp-server/docs/PIN_ANALYSIS.md +332 -0
  15. package/mcp_servers/kicad-mcp-server/docs/README.md +240 -0
  16. package/mcp_servers/kicad-mcp-server/docs/TESTING.md +613 -0
  17. package/mcp_servers/kicad-mcp-server/docs/VALIDATION.md +268 -0
  18. package/mcp_servers/kicad-mcp-server/pyproject.toml +96 -0
  19. package/mcp_servers/kicad-mcp-server/requirements-dev.txt +16 -0
  20. package/mcp_servers/kicad-mcp-server/requirements-test.txt +24 -0
  21. package/mcp_servers/kicad-mcp-server/requirements.txt +13 -0
  22. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/__init__.py +3 -0
  23. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/__main__.py +17 -0
  24. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/config.py +46 -0
  25. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/models/__init__.py +1 -0
  26. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/models/types.py +87 -0
  27. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/__init__.py +1 -0
  28. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/netlist_parser.py +234 -0
  29. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/pcb_parser.py +375 -0
  30. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/pcb_parser_kicad.py +327 -0
  31. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/schematic_parser.py +902 -0
  32. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/server.py +71 -0
  33. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/__init__.py +1 -0
  34. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/arduino/connectivity_test.cpp.j2 +189 -0
  35. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/device_tree/atmega.dts.j2 +77 -0
  36. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/device_tree/esp32.dts.j2 +77 -0
  37. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/device_tree/nrf52.dts.j2 +77 -0
  38. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/device_tree/stm32f4.dts.j2 +89 -0
  39. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/esp_idf/test_suite.c.j2 +340 -0
  40. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/pytest/test_connectivity.py.j2 +147 -0
  41. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/st_hal/hal_test.c.j2 +313 -0
  42. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/pytest_gpio_test.py.j2 +99 -0
  43. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/pytest_i2c_test.py.j2 +117 -0
  44. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/pytest_pinmux_test.py.j2 +43 -0
  45. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/pytest_spi_test.py.j2 +94 -0
  46. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/unity_gpio_test.c.j2 +113 -0
  47. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/unity_i2c_test.c.j2 +101 -0
  48. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/unity_spi_test.c.j2 +94 -0
  49. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/unittest/test_schematic.py.j2 +172 -0
  50. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/__init__.py +36 -0
  51. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/device_tree.py +1187 -0
  52. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/hierarchical_analysis.py +211 -0
  53. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/netlist.py +320 -0
  54. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/parts_registry.py +142 -0
  55. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/pcb.py +955 -0
  56. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/pcb_layout.py +308 -0
  57. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/pin_analysis.py +765 -0
  58. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/project.py +196 -0
  59. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/schematic.py +319 -0
  60. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/schematic_editor.py +674 -0
  61. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/schematic_search.py +158 -0
  62. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/validation.py +866 -0
  63. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/visualization.py +225 -0
  64. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/__init__.py +1 -0
  65. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/file_handlers.py +65 -0
  66. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/kicad_cli.py +103 -0
  67. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/kicad_version.py +103 -0
  68. package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/parts_registry.py +197 -0
  69. package/mcp_servers/kicad-mcp-server/tests/__init__.py +1 -0
  70. package/mcp_servers/kicad-mcp-server/tests/examples/ESP32S3_TEST.md +219 -0
  71. package/mcp_servers/kicad-mcp-server/tests/fixtures/README.md +65 -0
  72. package/mcp_servers/kicad-mcp-server/tests/fixtures/__init__.py +1 -0
  73. package/mcp_servers/kicad-mcp-server/tests/fixtures/example_pcb.kicad_pcb +177 -0
  74. package/mcp_servers/kicad-mcp-server/tests/fixtures/example_schematic.kicad_sch +145 -0
  75. package/mcp_servers/kicad-mcp-server/tests/fixtures/hier/child.kicad_sch +24 -0
  76. package/mcp_servers/kicad-mcp-server/tests/fixtures/hier/root.kicad_sch +38 -0
  77. package/mcp_servers/kicad-mcp-server/tests/test_tools/__init__.py +1 -0
  78. package/mcp_servers/kicad-mcp-server/tests/test_tools/test_hierarchical_labels.py +195 -0
  79. package/mcp_servers/kicad-mcp-server/tests/test_tools/test_kicad_cli.py +116 -0
  80. package/mcp_servers/kicad-mcp-server/tests/test_tools/test_netlist_cache_path.py +29 -0
  81. package/mcp_servers/kicad-mcp-server/tests/test_tools/test_schematic.py +189 -0
  82. package/mcp_servers/kicad-mcp-server/tests/test_tools/test_schematic_hierarchy.py +69 -0
  83. package/mcp_servers/kicad-mcp-server/tests/test_tools/test_visualization.py +136 -0
  84. package/mcp_servers/kicad-mcp-server/uv.lock +2873 -0
  85. package/mcp_servers/openscad-mcp-server/.dockerignore +9 -0
  86. package/mcp_servers/openscad-mcp-server/.github/workflows/test.yml +40 -0
  87. package/mcp_servers/openscad-mcp-server/Dockerfile +29 -0
  88. package/mcp_servers/openscad-mcp-server/LICENSE +21 -0
  89. package/mcp_servers/openscad-mcp-server/README.md +154 -0
  90. package/mcp_servers/openscad-mcp-server/docs/audit.md +56 -0
  91. package/mcp_servers/openscad-mcp-server/docs/docker.md +66 -0
  92. package/mcp_servers/openscad-mcp-server/docs/issue-followup.md +19 -0
  93. package/mcp_servers/openscad-mcp-server/docs/jetson.md +17 -0
  94. package/mcp_servers/openscad-mcp-server/glama.json +4 -0
  95. package/mcp_servers/openscad-mcp-server/legacy/README.md +15 -0
  96. package/mcp_servers/openscad-mcp-server/legacy/README.original.md +294 -0
  97. package/mcp_servers/openscad-mcp-server/legacy/implementation_plan.md +100 -0
  98. package/mcp_servers/openscad-mcp-server/legacy/old/download_sam2_checkpoint.py +115 -0
  99. package/mcp_servers/openscad-mcp-server/legacy/old/src/ai/sam_segmentation.py +209 -0
  100. package/mcp_servers/openscad-mcp-server/legacy/old/src/models/threestudio_generator.py +231 -0
  101. package/mcp_servers/openscad-mcp-server/legacy/old/src/workflow/image_to_model_pipeline.py +260 -0
  102. package/mcp_servers/openscad-mcp-server/legacy/old/test_sam2_segmentation.py +96 -0
  103. package/mcp_servers/openscad-mcp-server/legacy/requirements.txt +57 -0
  104. package/mcp_servers/openscad-mcp-server/legacy/rtfmd/README.md +39 -0
  105. package/mcp_servers/openscad-mcp-server/legacy/rtfmd/decisions/ai-driven-code-generation.md +122 -0
  106. package/mcp_servers/openscad-mcp-server/legacy/rtfmd/decisions/export-formats.md +76 -0
  107. package/mcp_servers/openscad-mcp-server/legacy/rtfmd/files/src/ai/ai_service.py.md +51 -0
  108. package/mcp_servers/openscad-mcp-server/legacy/rtfmd/files/src/main.py.md +63 -0
  109. package/mcp_servers/openscad-mcp-server/legacy/rtfmd/files/src/models/code_generator.py.md +63 -0
  110. package/mcp_servers/openscad-mcp-server/legacy/rtfmd/files/src/nlp/parameter_extractor.py.md +63 -0
  111. package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/ai/natural-language-processing.md +78 -0
  112. package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/nlp/parameter-extraction.md +173 -0
  113. package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/openscad/export-formats.md +91 -0
  114. package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/openscad/openscad-basics.md +66 -0
  115. package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/openscad/primitive-testing.md +79 -0
  116. package/mcp_servers/openscad-mcp-server/legacy/src/__init__.py +0 -0
  117. package/mcp_servers/openscad-mcp-server/legacy/src/ai/ai_service.py +257 -0
  118. package/mcp_servers/openscad-mcp-server/legacy/src/ai/gemini_api.py +161 -0
  119. package/mcp_servers/openscad-mcp-server/legacy/src/ai/venice_api.py +203 -0
  120. package/mcp_servers/openscad-mcp-server/legacy/src/config.py +121 -0
  121. package/mcp_servers/openscad-mcp-server/legacy/src/main.py +1456 -0
  122. package/mcp_servers/openscad-mcp-server/legacy/src/main.py.new +404 -0
  123. package/mcp_servers/openscad-mcp-server/legacy/src/main_remote.py +401 -0
  124. package/mcp_servers/openscad-mcp-server/legacy/src/models/__init__.py +0 -0
  125. package/mcp_servers/openscad-mcp-server/legacy/src/models/code_generator.py +321 -0
  126. package/mcp_servers/openscad-mcp-server/legacy/src/models/cuda_mvs.py +209 -0
  127. package/mcp_servers/openscad-mcp-server/legacy/src/models/scad_templates/basic_shapes.scad +144 -0
  128. package/mcp_servers/openscad-mcp-server/legacy/src/nlp/__init__.py +0 -0
  129. package/mcp_servers/openscad-mcp-server/legacy/src/nlp/parameter_extractor.py +388 -0
  130. package/mcp_servers/openscad-mcp-server/legacy/src/openscad_wrapper/__init__.py +0 -0
  131. package/mcp_servers/openscad-mcp-server/legacy/src/openscad_wrapper/wrapper.py +418 -0
  132. package/mcp_servers/openscad-mcp-server/legacy/src/printer_discovery/__init__.py +1 -0
  133. package/mcp_servers/openscad-mcp-server/legacy/src/printer_discovery/printer_discovery.py +471 -0
  134. package/mcp_servers/openscad-mcp-server/legacy/src/remote/connection_manager.py +537 -0
  135. package/mcp_servers/openscad-mcp-server/legacy/src/remote/cuda_mvs_client.py +435 -0
  136. package/mcp_servers/openscad-mcp-server/legacy/src/remote/cuda_mvs_server.py +787 -0
  137. package/mcp_servers/openscad-mcp-server/legacy/src/remote/error_handling.py +415 -0
  138. package/mcp_servers/openscad-mcp-server/legacy/src/testing/__init__.py +0 -0
  139. package/mcp_servers/openscad-mcp-server/legacy/src/testing/primitive_tester.py +203 -0
  140. package/mcp_servers/openscad-mcp-server/legacy/src/testing/test_primitives.py +98 -0
  141. package/mcp_servers/openscad-mcp-server/legacy/src/utils/__init__.py +1 -0
  142. package/mcp_servers/openscad-mcp-server/legacy/src/utils/cad_exporter.py +241 -0
  143. package/mcp_servers/openscad-mcp-server/legacy/src/utils/format_validator.py +206 -0
  144. package/mcp_servers/openscad-mcp-server/legacy/src/utils/stl_exporter.py +140 -0
  145. package/mcp_servers/openscad-mcp-server/legacy/src/utils/stl_repair.py +91 -0
  146. package/mcp_servers/openscad-mcp-server/legacy/src/utils/stl_validator.py +123 -0
  147. package/mcp_servers/openscad-mcp-server/legacy/src/visualization/__init__.py +0 -0
  148. package/mcp_servers/openscad-mcp-server/legacy/src/visualization/headless_renderer.py +52 -0
  149. package/mcp_servers/openscad-mcp-server/legacy/src/visualization/renderer.py +177 -0
  150. package/mcp_servers/openscad-mcp-server/legacy/src/visualization/web_interface.py +639 -0
  151. package/mcp_servers/openscad-mcp-server/legacy/src/workflow/image_approval.py +148 -0
  152. package/mcp_servers/openscad-mcp-server/legacy/src/workflow/multi_view_to_model_pipeline.py +338 -0
  153. package/mcp_servers/openscad-mcp-server/legacy/test_complete_workflow.py +374 -0
  154. package/mcp_servers/openscad-mcp-server/legacy/test_cuda_mvs.py +191 -0
  155. package/mcp_servers/openscad-mcp-server/legacy/test_gemini_api.py +168 -0
  156. package/mcp_servers/openscad-mcp-server/legacy/test_image_approval.py +192 -0
  157. package/mcp_servers/openscad-mcp-server/legacy/test_image_approval_workflow.py +251 -0
  158. package/mcp_servers/openscad-mcp-server/legacy/test_image_to_model_pipeline.py +145 -0
  159. package/mcp_servers/openscad-mcp-server/legacy/test_model_selection.py +41 -0
  160. package/mcp_servers/openscad-mcp-server/legacy/test_multi_view_pipeline.py +290 -0
  161. package/mcp_servers/openscad-mcp-server/legacy/test_primitives.sh +13 -0
  162. package/mcp_servers/openscad-mcp-server/legacy/test_rabbit_direct.py +71 -0
  163. package/mcp_servers/openscad-mcp-server/legacy/test_remote_cuda_mvs.py +283 -0
  164. package/mcp_servers/openscad-mcp-server/legacy/test_venice_example.py +69 -0
  165. package/mcp_servers/openscad-mcp-server/pyproject.toml +33 -0
  166. package/mcp_servers/openscad-mcp-server/requirements.txt +2 -0
  167. package/mcp_servers/openscad-mcp-server/scad/simple_cube.scad +2 -0
  168. package/mcp_servers/openscad-mcp-server/scripts/test_docker.py +220 -0
  169. package/mcp_servers/openscad-mcp-server/src/openscad_mcp/__init__.py +3 -0
  170. package/mcp_servers/openscad-mcp-server/src/openscad_mcp/__main__.py +3 -0
  171. package/mcp_servers/openscad-mcp-server/src/openscad_mcp/engine.py +94 -0
  172. package/mcp_servers/openscad-mcp-server/src/openscad_mcp/geometry.py +242 -0
  173. package/mcp_servers/openscad-mcp-server/src/openscad_mcp/server.py +245 -0
  174. package/mcp_servers/openscad-mcp-server/src/openscad_mcp/service.py +190 -0
  175. package/mcp_servers/openscad-mcp-server/tests/conftest.py +17 -0
  176. package/mcp_servers/openscad-mcp-server/tests/test_engine.py +37 -0
  177. package/mcp_servers/openscad-mcp-server/tests/test_geometry.py +106 -0
  178. package/mcp_servers/openscad-mcp-server/tests/test_integration.py +172 -0
  179. package/mcp_servers/openscad-mcp-server/tests/test_transports.py +314 -0
  180. package/mcp_servers/openscad-mcp-server/uv.lock +1123 -0
  181. package/package.json +44 -0
  182. package/scripts/install_mcps.sh +86 -0
  183. package/scripts/openscad_wrapper.sh +62 -0
  184. package/scripts/run_kicad_mcp.sh +25 -0
  185. package/scripts/run_openscad_mcp.sh +41 -0
  186. package/scripts/test_mcp_connection.py +626 -0
  187. package/scripts/test_mcp_connection.sh +168 -0
  188. package/skills/code-first-hardware-design/SKILL.md +260 -0
  189. package/skills/pcb-constraint-definition/SKILL.md +236 -0
  190. package/skills/pcb-layout-routing-automation/SKILL.md +153 -0
  191. package/skills/pcb-validation-dfm-signoff/SKILL.md +194 -0
  192. package/skills/schematic-datasheet-analysis/SKILL.md +202 -0
@@ -0,0 +1,404 @@
1
+ import os
2
+ import logging
3
+ import uuid
4
+ import json
5
+ from typing import Dict, Any, List, Optional, Tuple
6
+ from fastapi import FastAPI, Request, Response, HTTPException
7
+ from fastapi.responses import JSONResponse, FileResponse
8
+ from fastapi.middleware.cors import CORSMiddleware
9
+ from fastapi.staticfiles import StaticFiles
10
+ from fastapi.templating import Jinja2Templates
11
+ import uvicorn
12
+ from mcp import MCPServer, MCPTool, MCPToolCall, MCPToolCallResult
13
+
14
+ # Import configuration
15
+ from src.config import *
16
+
17
+ # Import components
18
+ from src.nlp.parameter_extractor import ParameterExtractor
19
+ from src.models.code_generator import CodeGenerator
20
+ from src.openscad_wrapper.wrapper import OpenSCADWrapper
21
+ from src.utils.cad_exporter import CADExporter
22
+ from src.visualization.headless_renderer import HeadlessRenderer
23
+ from src.printer_discovery.printer_discovery import PrinterDiscovery, PrinterInterface
24
+
25
+ # Import AI components
26
+ from src.ai.venice_api import VeniceImageGenerator
27
+ from src.ai.gemini_api import GeminiImageGenerator
28
+ from src.models.cuda_mvs import CUDAMultiViewStereo
29
+ from src.workflow.image_approval import ImageApprovalTool
30
+ from src.workflow.multi_view_to_model_pipeline import MultiViewToModelPipeline
31
+
32
+ # Configure logging
33
+ logging.basicConfig(
34
+ level=logging.INFO,
35
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
36
+ )
37
+ logger = logging.getLogger(__name__)
38
+
39
+ # Create FastAPI app
40
+ app = FastAPI(title="OpenSCAD MCP Server")
41
+
42
+ # Add CORS middleware
43
+ app.add_middleware(
44
+ CORSMiddleware,
45
+ allow_origins=["*"],
46
+ allow_credentials=True,
47
+ allow_methods=["*"],
48
+ allow_headers=["*"],
49
+ )
50
+
51
+ # Create directories
52
+ os.makedirs("scad", exist_ok=True)
53
+ os.makedirs("output", exist_ok=True)
54
+ os.makedirs("output/models", exist_ok=True)
55
+ os.makedirs("output/preview", exist_ok=True)
56
+ os.makedirs("output/images", exist_ok=True)
57
+ os.makedirs("output/multi_view", exist_ok=True)
58
+ os.makedirs("output/approved_images", exist_ok=True)
59
+ os.makedirs("templates", exist_ok=True)
60
+ os.makedirs("static", exist_ok=True)
61
+
62
+ # Initialize components
63
+ parameter_extractor = ParameterExtractor()
64
+ code_generator = CodeGenerator("scad", "output")
65
+ openscad_wrapper = OpenSCADWrapper("scad", "output")
66
+ cad_exporter = CADExporter()
67
+ headless_renderer = HeadlessRenderer()
68
+ printer_discovery = PrinterDiscovery()
69
+
70
+ # Initialize AI components
71
+ venice_generator = None
72
+ gemini_generator = None
73
+ cuda_mvs = None
74
+ approval_tool = None
75
+ multi_view_pipeline = None
76
+
77
+ # Initialize Venice.ai generator if API key is available
78
+ if VENICE_API_KEY:
79
+ venice_generator = VeniceImageGenerator(VENICE_API_KEY, IMAGES_DIR)
80
+ logger.info("Venice.ai image generator initialized")
81
+ else:
82
+ logger.info("Venice.ai API key not provided, skipping initialization")
83
+
84
+ # Initialize Google Gemini generator if API key is available
85
+ if GEMINI_API_KEY:
86
+ gemini_generator = GeminiImageGenerator(GEMINI_API_KEY, IMAGES_DIR)
87
+ logger.info("Google Gemini image generator initialized")
88
+ else:
89
+ logger.warning("Google Gemini API key not provided, multi-view workflow will not be available")
90
+
91
+ # Initialize CUDA MVS if path is available
92
+ if os.path.exists(CUDA_MVS_PATH):
93
+ cuda_mvs = CUDAMultiViewStereo(CUDA_MVS_PATH, MODELS_DIR)
94
+ logger.info("CUDA Multi-View Stereo initialized")
95
+ else:
96
+ logger.warning(f"CUDA MVS not found at {CUDA_MVS_PATH}, 3D reconstruction will not be available")
97
+
98
+ # Initialize image approval tool
99
+ approval_tool = ImageApprovalTool(APPROVED_IMAGES_DIR)
100
+ logger.info("Image approval tool initialized")
101
+
102
+ # Initialize multi-view pipeline if required components are available
103
+ if gemini_generator and cuda_mvs:
104
+ multi_view_pipeline = MultiViewToModelPipeline(
105
+ gemini_generator=gemini_generator,
106
+ venice_generator=venice_generator,
107
+ cuda_mvs=cuda_mvs,
108
+ openscad_wrapper=openscad_wrapper,
109
+ approval_tool=approval_tool,
110
+ output_dir=OUTPUT_DIR
111
+ )
112
+ logger.info("Multi-view to model pipeline initialized")
113
+ else:
114
+ logger.warning("Multi-view to model pipeline not initialized due to missing components")
115
+
116
+ # Store models in memory
117
+ models = {}
118
+ printers = {}
119
+
120
+ # Create MCP server
121
+ mcp_server = MCPServer()
122
+
123
+ # Mount static files
124
+ app.mount("/static", StaticFiles(directory="static"), name="static")
125
+
126
+ # Create Jinja2 templates
127
+ templates = Jinja2Templates(directory="templates")
128
+
129
+ # Create model preview template
130
+ with open("templates/preview.html", "w") as f:
131
+ f.write("""
132
+ <!DOCTYPE html>
133
+ <html lang="en">
134
+ <head>
135
+ <meta charset="UTF-8">
136
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
137
+ <title>OpenSCAD Model Preview</title>
138
+ <style>
139
+ body {
140
+ font-family: Arial, sans-serif;
141
+ margin: 0;
142
+ padding: 0;
143
+ background-color: #f5f5f5;
144
+ }
145
+ .container {
146
+ max-width: 1200px;
147
+ margin: 0 auto;
148
+ padding: 20px;
149
+ }
150
+ h1 {
151
+ color: #333;
152
+ margin-bottom: 20px;
153
+ }
154
+ .preview-container {
155
+ display: flex;
156
+ flex-wrap: wrap;
157
+ gap: 20px;
158
+ margin-top: 20px;
159
+ }
160
+ .preview-image {
161
+ border: 1px solid #ddd;
162
+ border-radius: 5px;
163
+ padding: 10px;
164
+ background-color: white;
165
+ }
166
+ .preview-image img {
167
+ max-width: 100%;
168
+ height: auto;
169
+ }
170
+ .preview-image h3 {
171
+ margin-top: 10px;
172
+ margin-bottom: 5px;
173
+ color: #555;
174
+ }
175
+ .parameters {
176
+ margin-top: 20px;
177
+ background-color: #f9f9f9;
178
+ padding: 15px;
179
+ border-radius: 5px;
180
+ border: 1px solid #eee;
181
+ }
182
+ .parameters h2 {
183
+ margin-top: 0;
184
+ color: #333;
185
+ }
186
+ .parameters table {
187
+ width: 100%;
188
+ border-collapse: collapse;
189
+ }
190
+ .parameters table th, .parameters table td {
191
+ padding: 8px;
192
+ text-align: left;
193
+ border-bottom: 1px solid #ddd;
194
+ }
195
+ .parameters table th {
196
+ background-color: #f2f2f2;
197
+ }
198
+ .actions {
199
+ margin-top: 20px;
200
+ display: flex;
201
+ gap: 10px;
202
+ }
203
+ .actions button {
204
+ padding: 10px 15px;
205
+ background-color: #4CAF50;
206
+ color: white;
207
+ border: none;
208
+ border-radius: 4px;
209
+ cursor: pointer;
210
+ }
211
+ .actions button:hover {
212
+ background-color: #45a049;
213
+ }
214
+ </style>
215
+ </head>
216
+ <body>
217
+ <div class="container">
218
+ <h1>OpenSCAD Model Preview: {{ model_id }}</h1>
219
+
220
+ <div class="parameters">
221
+ <h2>Parameters</h2>
222
+ <table>
223
+ <tr>
224
+ <th>Parameter</th>
225
+ <th>Value</th>
226
+ </tr>
227
+ {% for key, value in parameters.items() %}
228
+ <tr>
229
+ <td>{{ key }}</td>
230
+ <td>{{ value }}</td>
231
+ </tr>
232
+ {% endfor %}
233
+ </table>
234
+ </div>
235
+
236
+ <div class="preview-container">
237
+ {% for view, image_path in previews.items() %}
238
+ <div class="preview-image">
239
+ <h3>{{ view|title }} View</h3>
240
+ <img src="{{ image_path }}" alt="{{ view }} view">
241
+ </div>
242
+ {% endfor %}
243
+ </div>
244
+
245
+ <div class="actions">
246
+ <button onclick="window.location.href='/download/{{ model_id }}'">Download Model</button>
247
+ </div>
248
+ </div>
249
+ </body>
250
+ </html>
251
+ """)
252
+
253
+ # Create multi-view approval template
254
+ with open("templates/multi_view_approval.html", "w") as f:
255
+ f.write("""
256
+ <!DOCTYPE html>
257
+ <html lang="en">
258
+ <head>
259
+ <meta charset="UTF-8">
260
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
261
+ <title>Multi-View Image Approval</title>
262
+ <style>
263
+ body {
264
+ font-family: Arial, sans-serif;
265
+ margin: 0;
266
+ padding: 0;
267
+ background-color: #f5f5f5;
268
+ }
269
+ .container {
270
+ max-width: 1200px;
271
+ margin: 0 auto;
272
+ padding: 20px;
273
+ }
274
+ h1 {
275
+ color: #333;
276
+ margin-bottom: 20px;
277
+ }
278
+ .images-container {
279
+ display: flex;
280
+ flex-wrap: wrap;
281
+ gap: 20px;
282
+ margin-top: 20px;
283
+ }
284
+ .image-card {
285
+ border: 1px solid #ddd;
286
+ border-radius: 5px;
287
+ padding: 10px;
288
+ background-color: white;
289
+ width: calc(50% - 20px);
290
+ box-sizing: border-box;
291
+ }
292
+ .image-card img {
293
+ max-width: 100%;
294
+ height: auto;
295
+ }
296
+ .image-card h3 {
297
+ margin-top: 10px;
298
+ margin-bottom: 5px;
299
+ color: #555;
300
+ }
301
+ .image-card .metadata {
302
+ font-size: 0.9em;
303
+ color: #777;
304
+ margin-bottom: 10px;
305
+ }
306
+ .image-card .actions {
307
+ display: flex;
308
+ gap: 10px;
309
+ margin-top: 10px;
310
+ }
311
+ .image-card .actions button {
312
+ padding: 8px 12px;
313
+ border: none;
314
+ border-radius: 4px;
315
+ cursor: pointer;
316
+ }
317
+ .approve-btn {
318
+ background-color: #4CAF50;
319
+ color: white;
320
+ }
321
+ .approve-btn:hover {
322
+ background-color: #45a049;
323
+ }
324
+ .deny-btn {
325
+ background-color: #f44336;
326
+ color: white;
327
+ }
328
+ .deny-btn:hover {
329
+ background-color: #d32f2f;
330
+ }
331
+ .submit-container {
332
+ margin-top: 20px;
333
+ text-align: center;
334
+ }
335
+ .submit-container button {
336
+ padding: 10px 20px;
337
+ background-color: #2196F3;
338
+ color: white;
339
+ border: none;
340
+ border-radius: 4px;
341
+ cursor: pointer;
342
+ font-size: 1.1em;
343
+ }
344
+ .submit-container button:hover {
345
+ background-color: #0b7dda;
346
+ }
347
+ </style>
348
+ <script>
349
+ function toggleApproval(id, approved) {
350
+ const card = document.getElementById(`card-${id}`);
351
+ const approveBtn = document.getElementById(`approve-${id}`);
352
+ const denyBtn = document.getElementById(`deny-${id}`);
353
+
354
+ if (approved) {
355
+ card.style.borderColor = '#4CAF50';
356
+ approveBtn.disabled = true;
357
+ denyBtn.disabled = false;
358
+ } else {
359
+ card.style.borderColor = '#f44336';
360
+ approveBtn.disabled = false;
361
+ denyBtn.disabled = true;
362
+ }
363
+
364
+ document.getElementById(`approval-${id}`).value = approved;
365
+ }
366
+
367
+ function submitApprovals() {
368
+ document.getElementById('approval-form').submit();
369
+ }
370
+ </script>
371
+ </head>
372
+ <body>
373
+ <div class="container">
374
+ <h1>Multi-View Image Approval</h1>
375
+ <p>Please approve or deny each image for 3D reconstruction.</p>
376
+
377
+ <form id="approval-form" action="/approve_images" method="post">
378
+ <input type="hidden" name="pipeline_id" value="{{ pipeline_id }}">
379
+
380
+ <div class="images-container">
381
+ {% for image in images %}
382
+ <div id="card-{{ image.approval_id }}" class="image-card">
383
+ <h3>{{ image.metadata.view_direction }}</h3>
384
+ <div class="metadata">
385
+ <p>{{ image.metadata.prompt }}</p>
386
+ </div>
387
+ <img src="{{ image.image_url }}" alt="{{ image.metadata.view_direction }}">
388
+ <input type="hidden" id="approval-{{ image.approval_id }}" name="approvals[{{ image.approval_id }}]" value="false">
389
+ <div class="actions">
390
+ <button id="approve-{{ image.approval_id }}" type="button" class="approve-btn" onclick="toggleApproval('{{ image.approval_id }}', true)">Approve</button>
391
+ <button id="deny-{{ image.approval_id }}" type="button" class="deny-btn" onclick="toggleApproval('{{ image.approval_id }}', false)">Deny</button>
392
+ </div>
393
+ </div>
394
+ {% endfor %}
395
+ </div>
396
+
397
+ <div class="submit-container">
398
+ <button type="button" onclick="submitApprovals()">Submit Approvals</button>
399
+ </div>
400
+ </form>
401
+ </div>
402
+ </body>
403
+ </html>
404
+ """)