codewave-openclaw-installer 2.1.10 → 2.1.12

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 (211) hide show
  1. package/bin/check.mjs +0 -0
  2. package/bin/install.mjs +0 -0
  3. package/package.json +2 -1
  4. package/skills/ppt-master/.env.example +35 -0
  5. package/skills/ppt-master/README.md +90 -0
  6. package/skills/ppt-master/SKILL.md +390 -17
  7. package/skills/ppt-master/audit_report_model_perf.md +213 -0
  8. package/skills/ppt-master/audit_report_portability.md +90 -0
  9. package/skills/ppt-master/audit_report_robustness.md +192 -0
  10. package/skills/ppt-master/audit_report_workflow.md +233 -0
  11. package/skills/ppt-master/fix_report_bid.md +51 -0
  12. package/skills/ppt-master/fix_report_scripts.md +41 -0
  13. package/skills/ppt-master/references/bid-content-example-netease.md +815 -0
  14. package/skills/ppt-master/references/bid-content-template.md +390 -0
  15. package/skills/ppt-master/references/bid-example-netease.md +339 -0
  16. package/skills/ppt-master/references/bid-presentation.md +384 -0
  17. package/skills/ppt-master/references/bid-svgs/03_toc.svg +38 -0
  18. package/skills/ppt-master/references/bid-svgs/04_chapter_company.svg +7 -0
  19. package/skills/ppt-master/references/bid-svgs/05_company_overview.svg +28 -0
  20. package/skills/ppt-master/references/bid-svgs/06_vision_business.svg +45 -0
  21. package/skills/ppt-master/references/bid-svgs/07_product_system.svg +52 -0
  22. package/skills/ppt-master/references/bid-svgs/08_codewave_timeline.svg +29 -0
  23. package/skills/ppt-master/references/bid-svgs/09_certifications.svg +33 -0
  24. package/skills/ppt-master/references/bid-svgs/10_client_logos.svg +25 -0
  25. package/skills/ppt-master/references/bid-svgs/11_brand_mission.svg +14 -0
  26. package/skills/ppt-master/references/bid-svgs/12_chapter_demand.svg +7 -0
  27. package/skills/ppt-master/references/bid-svgs/16_chapter_advantages.svg +7 -0
  28. package/skills/ppt-master/references/bid-svgs/18_platform_arch.svg +24 -0
  29. package/skills/ppt-master/references/bid-svgs/19_function_matrix.svg +35 -0
  30. package/skills/ppt-master/references/bid-svgs/20_dev_arch.svg +29 -0
  31. package/skills/ppt-master/references/bid-svgs/21_source_code.svg +25 -0
  32. package/skills/ppt-master/references/bid-svgs/22_ai_dev.svg +27 -0
  33. package/skills/ppt-master/references/bid-svgs/23_asset_market.svg +33 -0
  34. package/skills/ppt-master/references/bid-svgs/24_multi_org.svg +28 -0
  35. package/skills/ppt-master/references/bid-svgs/25_i18n.svg +22 -0
  36. package/skills/ppt-master/references/bid-svgs/26_multi_tenant.svg +25 -0
  37. package/skills/ppt-master/references/bid-svgs/27_integration.svg +27 -0
  38. package/skills/ppt-master/references/bid-svgs/28_permission.svg +31 -0
  39. package/skills/ppt-master/references/bid-svgs/29_security.svg +25 -0
  40. package/skills/ppt-master/references/bid-svgs/30_ai_capabilities.svg +21 -0
  41. package/skills/ppt-master/references/bid-svgs/31_product_combo.svg +25 -0
  42. package/skills/ppt-master/references/bid-svgs/32_digital_transform.svg +28 -0
  43. package/skills/ppt-master/references/bid-svgs/33_chapter_cases.svg +7 -0
  44. package/skills/ppt-master/references/bid-svgs/34_cummins_case.svg +23 -0
  45. package/skills/ppt-master/references/bid-svgs/35_cpq_cost.svg +22 -0
  46. package/skills/ppt-master/references/bid-svgs/36_tech_platform.svg +18 -0
  47. package/skills/ppt-master/references/bid-svgs/37_platform_value.svg +24 -0
  48. package/skills/ppt-master/references/bid-svgs/38_operation_plan.svg +25 -0
  49. package/skills/ppt-master/references/bid-svgs/39_zpmc_case.svg +21 -0
  50. package/skills/ppt-master/references/bid-svgs/40_zpmc_apps.svg +23 -0
  51. package/skills/ppt-master/references/bid-svgs/41_chapter_service.svg +7 -0
  52. package/skills/ppt-master/references/bid-svgs/42_tech_support.svg +24 -0
  53. package/skills/ppt-master/references/bid-svgs/43_knowledge_transfer.svg +25 -0
  54. package/skills/ppt-master/references/bid-svgs/44_operation_promotion.svg +20 -0
  55. package/skills/ppt-master/references/bid-svgs/45_custom_dev_guide.svg +24 -0
  56. package/skills/ppt-master/references/bid-svgs/46_sla_guarantee.svg +18 -0
  57. package/skills/ppt-master/references/bid-svgs/47_strategic_cooperation.svg +25 -0
  58. package/skills/ppt-master/references/bid-svgs/48_ecosystem.svg +24 -0
  59. package/skills/ppt-master/references/bid-svgs/49_chapter_delivery.svg +23 -0
  60. package/skills/ppt-master/references/bid-svgs/53_pm_intro.svg +24 -0
  61. package/skills/ppt-master/references/bid-svgs/54_after_sales.svg +27 -0
  62. package/skills/ppt-master/references/bid-svgs/55_ending.svg +8 -0
  63. package/skills/ppt-master/references/company_intro.md +93 -0
  64. package/skills/ppt-master/references/company_intro_images/slide1_img00.png +0 -0
  65. package/skills/ppt-master/references/company_intro_images/slide1_img01.png +0 -0
  66. package/skills/ppt-master/references/company_intro_images/slide1_img02.png +0 -0
  67. package/skills/ppt-master/references/company_intro_images/slide1_img03.png +0 -0
  68. package/skills/ppt-master/references/company_intro_images/slide1_img04.png +0 -0
  69. package/skills/ppt-master/references/company_intro_images/slide1_img05.png +0 -0
  70. package/skills/ppt-master/references/company_intro_images/slide1_img06.png +0 -0
  71. package/skills/ppt-master/references/company_intro_images/slide1_img07.png +0 -0
  72. package/skills/ppt-master/references/company_intro_images/slide1_img08.png +0 -0
  73. package/skills/ppt-master/references/company_intro_images/slide1_img09.png +0 -0
  74. package/skills/ppt-master/references/company_intro_images/slide1_img10.png +0 -0
  75. package/skills/ppt-master/references/company_intro_images/slide1_img11.png +0 -0
  76. package/skills/ppt-master/references/company_intro_images/slide1_img12.png +0 -0
  77. package/skills/ppt-master/references/company_intro_images/slide1_img13.png +0 -0
  78. package/skills/ppt-master/references/company_intro_images/slide1_img14.png +0 -0
  79. package/skills/ppt-master/references/company_intro_images/slide1_img15.png +0 -0
  80. package/skills/ppt-master/references/company_intro_images/slide1_img16.png +0 -0
  81. package/skills/ppt-master/references/company_intro_images/slide1_img17.png +0 -0
  82. package/skills/ppt-master/references/company_intro_images/slide1_img18.png +0 -0
  83. package/skills/ppt-master/references/company_intro_images/slide1_img19.png +0 -0
  84. package/skills/ppt-master/references/company_intro_images/slide1_img20.png +0 -0
  85. package/skills/ppt-master/references/company_intro_images/slide1_img21.png +0 -0
  86. package/skills/ppt-master/references/company_intro_images/slide1_img22.png +0 -0
  87. package/skills/ppt-master/references/company_intro_images/slide1_img23.png +0 -0
  88. package/skills/ppt-master/references/company_intro_images/slide1_img24.png +0 -0
  89. package/skills/ppt-master/references/company_intro_images/slide1_img25.png +0 -0
  90. package/skills/ppt-master/references/company_intro_images/slide1_img26.png +0 -0
  91. package/skills/ppt-master/references/company_intro_images/slide1_img27.png +0 -0
  92. package/skills/ppt-master/references/company_intro_images/slide1_img28.png +0 -0
  93. package/skills/ppt-master/references/company_intro_images/slide1_img29.png +0 -0
  94. package/skills/ppt-master/references/company_intro_images/slide2_img30.png +0 -0
  95. package/skills/ppt-master/references/company_intro_images/slide2_img31.jpg +0 -0
  96. package/skills/ppt-master/references/company_intro_images/slide3_img32.png +0 -0
  97. package/skills/ppt-master/references/company_intro_images/slide3_img33.png +0 -0
  98. package/skills/ppt-master/references/drawio-integration.md +144 -0
  99. package/skills/ppt-master/references/executor-base.md +3 -4
  100. package/skills/ppt-master/references/image-generator.md +93 -6
  101. package/skills/ppt-master/references/strategist.md +8 -5
  102. package/skills/ppt-master/requirements.txt +19 -0
  103. package/skills/ppt-master/resources/backgrounds/chapter_bg.png +0 -0
  104. package/skills/ppt-master/resources/backgrounds/company_bg.png +0 -0
  105. package/skills/ppt-master/resources/backgrounds/cover_bg.png +0 -0
  106. package/skills/ppt-master/resources/backgrounds/index.json +40 -0
  107. package/skills/ppt-master/resources/backgrounds/tech_bg.png +0 -0
  108. package/skills/ppt-master/scripts/README.md +1 -1
  109. package/skills/ppt-master/scripts/__pycache__/config.cpython-314.pyc +0 -0
  110. package/skills/ppt-master/scripts/__pycache__/error_helper.cpython-314.pyc +0 -0
  111. package/skills/ppt-master/scripts/__pycache__/pptx_animations.cpython-314.pyc +0 -0
  112. package/skills/ppt-master/scripts/__pycache__/project_utils.cpython-314.pyc +0 -0
  113. package/skills/ppt-master/scripts/arch_diagram.py +370 -0
  114. package/skills/ppt-master/scripts/bid_init.py +79 -0
  115. package/skills/ppt-master/scripts/drawio_gen.py +366 -0
  116. package/skills/ppt-master/scripts/drawio_to_svg.py +458 -0
  117. package/skills/ppt-master/scripts/finalize_svg.py +14 -0
  118. package/skills/ppt-master/scripts/image_backends/__pycache__/__init__.cpython-314.pyc +0 -0
  119. package/skills/ppt-master/scripts/image_backends/__pycache__/backend_aigw_gemini.cpython-314.pyc +0 -0
  120. package/skills/ppt-master/scripts/image_backends/__pycache__/backend_common.cpython-314.pyc +0 -0
  121. package/skills/ppt-master/scripts/svg_finalize/__pycache__/__init__.cpython-314.pyc +0 -0
  122. package/skills/ppt-master/scripts/svg_finalize/__pycache__/crop_images.cpython-314.pyc +0 -0
  123. package/skills/ppt-master/scripts/svg_finalize/__pycache__/embed_icons.cpython-314.pyc +0 -0
  124. package/skills/ppt-master/scripts/svg_finalize/__pycache__/embed_images.cpython-314.pyc +0 -0
  125. package/skills/ppt-master/scripts/svg_finalize/__pycache__/fix_image_aspect.cpython-314.pyc +0 -0
  126. package/skills/ppt-master/scripts/svg_finalize/__pycache__/flatten_tspan.cpython-314.pyc +0 -0
  127. package/skills/ppt-master/scripts/svg_finalize/__pycache__/svg_rect_to_path.cpython-314.pyc +0 -0
  128. package/skills/ppt-master/scripts/svg_page_gen.py +871 -0
  129. package/skills/ppt-master/scripts/svg_quality_checker.py +169 -8
  130. package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/__init__.cpython-314.pyc +0 -0
  131. package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/drawingml_context.cpython-314.pyc +0 -0
  132. package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/drawingml_converter.cpython-314.pyc +0 -0
  133. package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/drawingml_elements.cpython-314.pyc +0 -0
  134. package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/drawingml_paths.cpython-314.pyc +0 -0
  135. package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/drawingml_styles.cpython-314.pyc +0 -0
  136. package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/drawingml_utils.cpython-314.pyc +0 -0
  137. package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/pptx_builder.cpython-314.pyc +0 -0
  138. package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/pptx_cli.cpython-314.pyc +0 -0
  139. package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/pptx_dimensions.cpython-314.pyc +0 -0
  140. package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/pptx_discovery.cpython-314.pyc +0 -0
  141. package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/pptx_media.cpython-314.pyc +0 -0
  142. package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/pptx_notes.cpython-314.pyc +0 -0
  143. package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/pptx_slide_xml.cpython-314.pyc +0 -0
  144. package/skills/ppt-master/scripts/svg_to_pptx/pptx_builder.py +7 -1
  145. package/skills/ppt-master/scripts/svg_to_pptx/pptx_cli.py +14 -0
  146. package/skills/ppt-master/projects/.gitkeep +0 -0
  147. /package/skills/ppt-master/templates/layouts/{/351/207/215/345/272/206/345/244/247/345/255/246/01_cover.svg" → Technology Blue Business/01_cover.svg} +0 -0
  148. /package/skills/ppt-master/templates/layouts/{/351/207/215/345/272/206/345/244/247/345/255/246/02_chapter.svg" → Technology Blue Business/02_chapter.svg} +0 -0
  149. /package/skills/ppt-master/templates/layouts/{/351/207/215/345/272/206/345/244/247/345/255/246/02_toc.svg" → Technology Blue Business/02_toc.svg} +0 -0
  150. /package/skills/ppt-master/templates/layouts/{/351/207/215/345/272/206/345/244/247/345/255/246/03_content.svg" → Technology Blue Business/03_content.svg} +0 -0
  151. /package/skills/ppt-master/templates/layouts/{/351/207/215/345/272/206/345/244/247/345/255/246/04_ending.svg" → Technology Blue Business/04_ending.svg} +0 -0
  152. /package/skills/ppt-master/templates/layouts/{/351/207/215/345/272/206/345/244/247/345/255/246/design_spec.md" → Technology Blue Business/design_spec.md} +0 -0
  153. /package/skills/ppt-master/templates/layouts/{/351/207/215/345/272/206/345/244/247/345/255/246//351/207/215/345/272/206/345/244/247/345/255/246logo.png" → Technology Blue Business//316/230c/314/247i/314/200/317/203/342/225/221a/314/212/317/203n/314/203/302/272/317/203/302/241/302/252logo.png"} +0 -0
  154. /package/skills/ppt-master/templates/layouts/{/351/207/215/345/272/206/345/244/247/345/255/246//351/207/215/345/272/206/345/244/247/345/255/246logo2.png" → Technology Blue Business//316/230c/314/247i/314/200/317/203/342/225/221a/314/212/317/203n/314/203/302/272/317/203/302/241/302/252logo2.png"} +0 -0
  155. /package/skills/ppt-master/templates/layouts//{346/213/233/345/225/206/351/223/266/350/241/214 → 302/265i/314/210/302/242/317/203o/314/200a/314/212/316/230o/314/202/342/225/242/316/246i/314/201i/314/202}/01_cover.svg" +0 -0
  156. /package/skills/ppt-master/templates/layouts//{346/213/233/345/225/206/351/223/266/350/241/214 → 302/265i/314/210/302/242/317/203o/314/200a/314/212/316/230o/314/202/342/225/242/316/246i/314/201i/314/202}/02_chapter.svg" +0 -0
  157. /package/skills/ppt-master/templates/layouts//{346/213/233/345/225/206/351/223/266/350/241/214 → 302/265i/314/210/302/242/317/203o/314/200a/314/212/316/230o/314/202/342/225/242/316/246i/314/201i/314/202}/02_toc.svg" +0 -0
  158. /package/skills/ppt-master/templates/layouts//{346/213/233/345/225/206/351/223/266/350/241/214 → 302/265i/314/210/302/242/317/203o/314/200a/314/212/316/230o/314/202/342/225/242/316/246i/314/201i/314/202}/03_content.svg" +0 -0
  159. /package/skills/ppt-master/templates/layouts//{346/213/233/345/225/206/351/223/266/350/241/214 → 302/265i/314/210/302/242/317/203o/314/200a/314/212/316/230o/314/202/342/225/242/316/246i/314/201i/314/202}/04_ending.svg" +0 -0
  160. /package/skills/ppt-master/templates/layouts//{346/213/233/345/225/206/351/223/266/350/241/214 → 302/265i/314/210/302/242/317/203o/314/200a/314/212/316/230o/314/202/342/225/242/316/246i/314/201i/314/202}/design_spec.md" +0 -0
  161. /package/skills/ppt-master/templates/layouts//{346/213/233/345/225/206/351/223/266/350/241/214//346/213/233/345/225/206/351/223/266/350/241/214/345/205/254/345/217/270/351/207/221/350/236/215.png" → 302/265i/314/210/302/242/317/203o/314/200a/314/212/316/230o/314/202/342/225/242/316/246i/314/201i/314/202//302/265i/314/210/302/242/317/203o/314/200a/314/212/316/230o/314/202/342/225/242/316/246i/314/201i/314/202/317/203a/314/200/302/274/317/203A/314/212/342/225/225/316/230c/314/247/303/246/316/246/342/202/247i/314/200.png"} +0 -0
  162. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/345/225/206/345/212/241 → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203o/314/200a/314/212/317/203e/314/200i/314/201}/01_cover.svg" +0 -0
  163. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/345/225/206/345/212/241 → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203o/314/200a/314/212/317/203e/314/200i/314/201}/02_chapter.svg" +0 -0
  164. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/345/225/206/345/212/241 → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203o/314/200a/314/212/317/203e/314/200i/314/201}/02_toc.svg" +0 -0
  165. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/345/225/206/345/212/241 → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203o/314/200a/314/212/317/203e/314/200i/314/201}/03_content.svg" +0 -0
  166. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/345/225/206/345/212/241 → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203o/314/200a/314/212/317/203e/314/200i/314/201}/04_ending.svg" +0 -0
  167. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/345/225/206/345/212/241 → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203o/314/200a/314/212/317/203e/314/200i/314/201}/design_spec.md" +0 -0
  168. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/345/225/206/345/212/241//345/217/263/344/270/212/350/247/222 logo.png" → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203o/314/200a/314/212/317/203e/314/200i/314/201//317/203A/314/212/342/224/202/316/243/342/225/225e/314/200/316/246/302/272/303/206 logo.png"} +0 -0
  169. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/345/225/206/345/212/241//345/244/247/345/236/213 logo.png" → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203o/314/200a/314/212/317/203e/314/200i/314/201//317/203n/314/203/302/272/317/203/342/202/247i/314/210 logo.png"} +0 -0
  170. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/345/270/270/350/247/204 → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210}/01_cover.svg" +0 -0
  171. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/345/270/270/350/247/204 → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210}/02_chapter.svg" +0 -0
  172. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/345/270/270/350/247/204 → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210}/02_toc.svg" +0 -0
  173. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/345/270/270/350/247/204 → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210}/03_content.svg" +0 -0
  174. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/345/270/270/350/247/204 → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210}/04_ending.svg" +0 -0
  175. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/345/270/270/350/247/204 → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210}/design_spec.md" +0 -0
  176. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/345/270/270/350/247/204//345/217/263/344/270/212/350/247/222 logo.png" → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210//317/203A/314/212/342/224/202/316/243/342/225/225e/314/200/316/246/302/272/303/206 logo.png"} +0 -0
  177. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/345/270/270/350/247/204//345/244/247/345/236/213 logo.png" → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210//317/203n/314/203/302/272/317/203/342/202/247i/314/210 logo.png"} +0 -0
  178. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/347/216/260/344/273/243 → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201}/01_cover.svg" +0 -0
  179. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/347/216/260/344/273/243 → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201}/02_chapter.svg" +0 -0
  180. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/347/216/260/344/273/243 → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201}/02_toc.svg" +0 -0
  181. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/347/216/260/344/273/243 → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201}/03_content.svg" +0 -0
  182. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/347/216/260/344/273/243 → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201}/04_ending.svg" +0 -0
  183. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/347/216/260/344/273/243 → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201}/design_spec.md" +0 -0
  184. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/347/216/260/344/273/243//345/217/263/344/270/212/350/247/222 logo.png" → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201//317/203A/314/212/342/224/202/316/243/342/225/225e/314/200/316/246/302/272/303/206 logo.png"} +0 -0
  185. /package/skills/ppt-master/templates/layouts//{344/270/255/346/261/275/347/240/224_/347/216/260/344/273/243//345/244/247/345/236/213 logo.png" → 316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201//317/203n/314/203/302/272/317/203/342/202/247i/314/210 logo.png"} +0 -0
  186. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204 → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210}/01_cover.svg" +0 -0
  187. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204 → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210}/02_chapter.svg" +0 -0
  188. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204 → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210}/02_toc.svg" +0 -0
  189. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204 → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210}/03_content.svg" +0 -0
  190. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204 → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210}/04_ending.svg" +0 -0
  191. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204 → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210}/design_spec.md" +0 -0
  192. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204//346/260/264/347/224/265/344/270/211/345/261/200logo.png" → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210//302/265/342/226/221/342/224/244/317/204o/314/210/342/225/241/316/243/342/225/225e/314/210/317/203/342/226/222C/314/247logo.png"} +0 -0
  193. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204//344/270/255/345/233/275/346/260/264/345/212/241logo.png" → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210//316/243/342/225/225/302/241/317/203/302/242/342/225/234/302/265/342/226/221/342/224/244/317/203e/314/200i/314/201logo.png"} +0 -0
  194. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204//345/215/216/344/270/234/351/231/242logo.png" → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210//317/203i/314/200A/314/210/316/243/342/225/225/302/243/316/230O/314/210o/314/201logo.png"} +0 -0
  195. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204//347/224/265/345/273/272logo.png" → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210//317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221logo.png"} +0 -0
  196. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243 → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201}/01_cover.svg" +0 -0
  197. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243 → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201}/02_chapter.svg" +0 -0
  198. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243 → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201}/02_toc.svg" +0 -0
  199. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243 → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201}/03_content.svg" +0 -0
  200. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243 → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201}/04_ending.svg" +0 -0
  201. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243 → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201}/design_spec.md" +0 -0
  202. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243//346/260/264/347/224/265/344/270/211/345/261/200logo.png" → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201//302/265/342/226/221/342/224/244/317/204o/314/210/342/225/241/316/243/342/225/225e/314/210/317/203/342/226/222C/314/247logo.png"} +0 -0
  203. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243//344/270/255/345/233/275/346/260/264/345/212/241logo.png" → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201//316/243/342/225/225/302/241/317/203/302/242/342/225/234/302/265/342/226/221/342/224/244/317/203e/314/200i/314/201logo.png"} +0 -0
  204. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243//345/215/216/344/270/234/351/231/242logo.png" → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201//317/203i/314/200A/314/210/316/243/342/225/225/302/243/316/230O/314/210o/314/201logo.png"} +0 -0
  205. /package/skills/ppt-master/templates/layouts//{344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243//347/224/265/345/273/272logo.png" → 316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201//317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221logo.png"} +0 -0
  206. /package/skills/ppt-master/templates/layouts//{347/247/221/346/212/200/350/223/235/345/225/206/345/212/241 → 317/204/302/272/303/246/302/265e/314/200C/314/247/316/246o/314/202/302/245/317/203o/314/200a/314/212/317/203e/314/200i/314/201}/01_cover.svg" +0 -0
  207. /package/skills/ppt-master/templates/layouts//{347/247/221/346/212/200/350/223/235/345/225/206/345/212/241 → 317/204/302/272/303/246/302/265e/314/200C/314/247/316/246o/314/202/302/245/317/203o/314/200a/314/212/317/203e/314/200i/314/201}/02_chapter.svg" +0 -0
  208. /package/skills/ppt-master/templates/layouts//{347/247/221/346/212/200/350/223/235/345/225/206/345/212/241 → 317/204/302/272/303/246/302/265e/314/200C/314/247/316/246o/314/202/302/245/317/203o/314/200a/314/212/317/203e/314/200i/314/201}/02_toc.svg" +0 -0
  209. /package/skills/ppt-master/templates/layouts//{347/247/221/346/212/200/350/223/235/345/225/206/345/212/241 → 317/204/302/272/303/246/302/265e/314/200C/314/247/316/246o/314/202/302/245/317/203o/314/200a/314/212/317/203e/314/200i/314/201}/03_content.svg" +0 -0
  210. /package/skills/ppt-master/templates/layouts//{347/247/221/346/212/200/350/223/235/345/225/206/345/212/241 → 317/204/302/272/303/246/302/265e/314/200C/314/247/316/246o/314/202/302/245/317/203o/314/200a/314/212/317/203e/314/200i/314/201}/04_ending.svg" +0 -0
  211. /package/skills/ppt-master/templates/layouts//{347/247/221/346/212/200/350/223/235/345/225/206/345/212/241 → 317/204/302/272/303/246/302/265e/314/200C/314/247/316/246o/314/202/302/245/317/203o/314/200a/314/212/317/203e/314/200i/314/201}/design_spec.md" +0 -0
@@ -0,0 +1,366 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ drawio_gen.py - Generate draw.io XML diagrams from JSON definitions.
4
+
5
+ Produces .drawio files with automatic layout for architecture diagrams,
6
+ flowcharts, sequence diagrams, etc.
7
+
8
+ Usage:
9
+ python drawio_gen.py <json_file> -o <output.drawio>
10
+ python drawio_gen.py --from-stdin -o <output.drawio>
11
+ echo '{"nodes":[...], "edges":[...]}' | python drawio_gen.py --from-stdin -o out.drawio
12
+
13
+ JSON Schema:
14
+ {
15
+ "title": "System Architecture", // optional
16
+ "diagram_type": "architecture", // architecture|flowchart|sequence|network
17
+ "direction": "TB", // TB|LR|BT|RL (layout direction)
18
+ "nodes": [
19
+ {
20
+ "id": "client",
21
+ "label": "Client App",
22
+ "group": "frontend", // optional, for grouping
23
+ "shape": "rounded", // rounded|cylinder|cloud|hexagon|diamond|ellipse|rect|process|document|parallelogram
24
+ "color": "#dae8fc", // fill color
25
+ "stroke": "#6c8ebf", // stroke color
26
+ "icon": "mxgraph.aws3.lambda", // optional mxGraph stencil
27
+ "width": 140, // optional, default 120
28
+ "height": 60 // optional, default 60
29
+ }
30
+ ],
31
+ "edges": [
32
+ {
33
+ "source": "client",
34
+ "target": "server",
35
+ "label": "HTTPS", // optional
36
+ "style": "dashed", // solid|dashed|dotted
37
+ "arrow": "open", // open|block|classic|diamond|none
38
+ "color": "#666666" // optional
39
+ }
40
+ ],
41
+ "groups": [ // optional, for visual grouping
42
+ {
43
+ "id": "frontend",
44
+ "label": "Frontend Layer",
45
+ "color": "#f5f5f5",
46
+ "stroke": "#999999"
47
+ }
48
+ ]
49
+ }
50
+ """
51
+
52
+ import json
53
+ import sys
54
+ import argparse
55
+ import hashlib
56
+ import math
57
+ from xml.etree.ElementTree import Element, SubElement, tostring
58
+ from xml.dom.minidom import parseString
59
+
60
+ # Shape style mappings
61
+ SHAPE_STYLES = {
62
+ "rounded": "rounded=1;whiteSpace=wrap;html=1;arcSize=12;",
63
+ "rect": "whiteSpace=wrap;html=1;",
64
+ "cylinder": "shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;",
65
+ "cloud": "ellipse;shape=cloud;whiteSpace=wrap;html=1;",
66
+ "hexagon": "shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;fixedSize=1;size=20;",
67
+ "diamond": "rhombus;whiteSpace=wrap;html=1;",
68
+ "ellipse": "ellipse;whiteSpace=wrap;html=1;",
69
+ "process": "shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;size=0.1;",
70
+ "document": "shape=document;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=0.25;",
71
+ "parallelogram": "shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;size=20;",
72
+ "database": "shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;",
73
+ "server": "shape=mxgraph.cisco.servers.standard_server;whiteSpace=wrap;html=1;",
74
+ "queue": "shape=mxgraph.lean_mapping.fifo_sequence_lane;whiteSpace=wrap;html=1;",
75
+ "component": "shape=component;align=left;spacingLeft=36;whiteSpace=wrap;html=1;",
76
+ }
77
+
78
+ ARROW_STYLES = {
79
+ "open": "endArrow=open;endFill=0;",
80
+ "block": "endArrow=block;endFill=1;",
81
+ "classic": "endArrow=classic;endFill=1;",
82
+ "diamond": "endArrow=diamond;endFill=0;",
83
+ "none": "endArrow=none;",
84
+ }
85
+
86
+ LINE_STYLES = {
87
+ "solid": "",
88
+ "dashed": "dashed=1;dashPattern=8 8;",
89
+ "dotted": "dashed=1;dashPattern=2 2;",
90
+ }
91
+
92
+ DEFAULT_COLORS = [
93
+ ("#dae8fc", "#6c8ebf"), # blue
94
+ ("#d5e8d4", "#82b366"), # green
95
+ ("#f8cecc", "#b85450"), # red
96
+ ("#fff2cc", "#d6b656"), # yellow
97
+ ("#e1d5e7", "#9673a6"), # purple
98
+ ("#d0cee2", "#56517e"), # indigo
99
+ ("#f5f5f5", "#666666"), # gray
100
+ ("#ffe6cc", "#d79b00"), # orange
101
+ ]
102
+
103
+
104
+ def uid(text: str) -> str:
105
+ return hashlib.md5(text.encode()).hexdigest()[:16]
106
+
107
+
108
+ def auto_layout(nodes: list, edges: list, groups: dict, direction: str = "TB") -> dict:
109
+ """Group-aware layered auto-layout. Returns {node_id: (x, y)}.
110
+
111
+ Strategy:
112
+ 1. Determine group ordering by inter-group edge flow (topological sort on groups)
113
+ 2. Within each group, arrange nodes in a compact horizontal row
114
+ 3. Groups are stacked vertically, centered on the canvas
115
+ 4. Ungrouped nodes placed in their topological layer
116
+ """
117
+ node_map = {n["id"]: n for n in nodes}
118
+ canvas_w = 1280 # target canvas width
119
+
120
+ # Separate grouped and ungrouped nodes
121
+ group_members = {} # group_id -> [node_ids]
122
+ ungrouped = []
123
+ for n in nodes:
124
+ gid = n.get("group")
125
+ if gid and gid in groups:
126
+ group_members.setdefault(gid, []).append(n["id"])
127
+ else:
128
+ ungrouped.append(n["id"])
129
+
130
+ # Determine group order by inter-group edge flow
131
+ group_ids = list(groups.keys())
132
+ group_in_deg = {gid: 0 for gid in group_ids}
133
+ group_adj = {gid: set() for gid in group_ids}
134
+ for e in edges:
135
+ sg = node_map.get(e["source"], {}).get("group")
136
+ tg = node_map.get(e["target"], {}).get("group")
137
+ if sg and tg and sg != tg and sg in groups and tg in groups:
138
+ if tg not in group_adj[sg]:
139
+ group_adj[sg].add(tg)
140
+ group_in_deg[tg] += 1
141
+
142
+ # Topological sort groups
143
+ group_order = []
144
+ remaining_g = set(group_ids)
145
+ while remaining_g:
146
+ roots = [g for g in remaining_g if group_in_deg.get(g, 0) == 0]
147
+ if not roots:
148
+ roots = [min(remaining_g)]
149
+ # Sort roots by original list order for determinism
150
+ roots.sort(key=lambda g: group_ids.index(g) if g in group_ids else 999)
151
+ group_order.extend(roots)
152
+ for r in roots:
153
+ remaining_g.discard(r)
154
+ for t in group_adj.get(r, set()):
155
+ group_in_deg[t] = max(0, group_in_deg[t] - 1)
156
+
157
+ # Layout parameters
158
+ h_gap = 30 # horizontal gap between nodes in a group
159
+ v_gap = 100 # vertical gap between group rows
160
+ margin_x = 60 # left margin
161
+ margin_y = 40 # top margin
162
+
163
+ positions = {}
164
+ current_y = margin_y
165
+
166
+ for gid in group_order:
167
+ members = group_members.get(gid, [])
168
+ if not members:
169
+ continue
170
+
171
+ # Calculate total row width
172
+ total_w = sum(node_map[nid].get("width", 120) for nid in members) + h_gap * (len(members) - 1)
173
+ # Center the row on canvas
174
+ start_x = max(margin_x, (canvas_w - total_w) / 2)
175
+
176
+ x = start_x
177
+ max_h = 0
178
+ for nid in members:
179
+ n = node_map[nid]
180
+ w = n.get("width", 120)
181
+ h = n.get("height", 60)
182
+ positions[nid] = (x, current_y)
183
+ x += w + h_gap
184
+ max_h = max(max_h, h)
185
+
186
+ current_y += max_h + v_gap
187
+
188
+ # Place ungrouped nodes
189
+ if ungrouped:
190
+ # Simple topological layer for ungrouped
191
+ adj = {n["id"]: [] for n in nodes}
192
+ in_deg = {n["id"]: 0 for n in nodes}
193
+ for e in edges:
194
+ s, t = e["source"], e["target"]
195
+ if s in adj:
196
+ adj[s].append(t)
197
+ if t in in_deg:
198
+ in_deg[t] = in_deg.get(t, 0) + 1
199
+
200
+ for nid in ungrouped:
201
+ if nid not in positions:
202
+ total_w = node_map[nid].get("width", 120)
203
+ start_x = (canvas_w - total_w) / 2
204
+ positions[nid] = (start_x, current_y)
205
+ current_y += node_map[nid].get("height", 60) + v_gap
206
+
207
+ return positions
208
+
209
+
210
+ def build_node_style(node: dict, color_idx: int = 0) -> str:
211
+ shape = node.get("shape", "rounded")
212
+ base = SHAPE_STYLES.get(shape, SHAPE_STYLES["rounded"])
213
+
214
+ fill = node.get("color", DEFAULT_COLORS[color_idx % len(DEFAULT_COLORS)][0])
215
+ stroke = node.get("stroke", DEFAULT_COLORS[color_idx % len(DEFAULT_COLORS)][1])
216
+
217
+ style = f"{base}fillColor={fill};strokeColor={stroke};fontFamily=Helvetica;fontSize=12;"
218
+
219
+ if node.get("icon"):
220
+ style = f"shape={node['icon']};{style}"
221
+
222
+ return style
223
+
224
+
225
+ def build_edge_style(edge: dict) -> str:
226
+ arrow = ARROW_STYLES.get(edge.get("arrow", "classic"), ARROW_STYLES["classic"])
227
+ line = LINE_STYLES.get(edge.get("style", "solid"), "")
228
+ color = edge.get("color", "#666666")
229
+ return f"html=1;rounded=1;{arrow}{line}strokeColor={color};fontFamily=Helvetica;fontSize=11;"
230
+
231
+
232
+ def generate_drawio(spec: dict) -> str:
233
+ """Generate a .drawio XML string from a diagram specification."""
234
+ nodes = spec.get("nodes", [])
235
+ edges = spec.get("edges", [])
236
+ groups_list = spec.get("groups", [])
237
+ direction = spec.get("direction", "TB")
238
+ title = spec.get("title", "Diagram")
239
+
240
+ groups = {g["id"]: g for g in groups_list}
241
+
242
+ # Auto layout
243
+ positions = auto_layout(nodes, edges, groups, direction)
244
+
245
+ # Build XML
246
+ root = Element("mxfile", type="device", compressed="false")
247
+ diagram = SubElement(root, "diagram", id="diagram-1", name=title)
248
+ model = SubElement(diagram, "mxGraphModel", dx="1360", dy="864",
249
+ grid="1", gridSize="10", guides="1", tooltips="1",
250
+ connect="1", arrows="1", fold="1", page="1",
251
+ pageScale="1", pageWidth="1280", pageHeight="720",
252
+ math="0", shadow="0")
253
+ mxroot = SubElement(model, "root")
254
+ SubElement(mxroot, "mxCell", id="0")
255
+ SubElement(mxroot, "mxCell", id="1", parent="0")
256
+
257
+ # Group containers
258
+ group_nodes = {}
259
+ for g in groups_list:
260
+ gid = f"group_{g['id']}"
261
+ cell = SubElement(mxroot, "mxCell",
262
+ id=gid, value=g.get("label", ""),
263
+ style=f"rounded=1;whiteSpace=wrap;html=1;fillColor={g.get('color', '#f5f5f5')};strokeColor={g.get('stroke', '#999999')};dashed=1;dashPattern=4 4;verticalAlign=top;fontStyle=1;fontSize=13;fontFamily=Helvetica;container=1;collapsible=0;",
264
+ vertex="1", parent="1")
265
+ # Calculate group bounds from member nodes
266
+ member_ids = [n["id"] for n in nodes if n.get("group") == g["id"]]
267
+ if member_ids:
268
+ xs = [positions[mid][0] for mid in member_ids if mid in positions]
269
+ ys = [positions[mid][1] for mid in member_ids if mid in positions]
270
+ if xs and ys:
271
+ padding = 30
272
+ gx = min(xs) - padding
273
+ gy = min(ys) - padding - 20 # extra for label
274
+ gw = max(xs) - min(xs) + 180 + 2 * padding
275
+ gh = max(ys) - min(ys) + 80 + 2 * padding + 20
276
+ SubElement(cell, "mxGeometry", x=str(int(gx)), y=str(int(gy)),
277
+ width=str(int(gw)), height=str(int(gh)),
278
+ attrib={"as": "geometry"})
279
+ group_nodes[g["id"]] = gid
280
+
281
+ # Nodes
282
+ node_color_map = {}
283
+ for idx, n in enumerate(nodes):
284
+ nid = n["id"]
285
+ x, y = positions.get(nid, (100, 100))
286
+ w = n.get("width", 120)
287
+ h = n.get("height", 60)
288
+
289
+ # Assign color index by group or sequential
290
+ group_id = n.get("group")
291
+ if group_id:
292
+ if group_id not in node_color_map:
293
+ node_color_map[group_id] = len(node_color_map)
294
+ cidx = node_color_map[group_id]
295
+ else:
296
+ cidx = idx
297
+
298
+ style = build_node_style(n, cidx)
299
+ parent = group_nodes.get(group_id, "1")
300
+
301
+ cell = SubElement(mxroot, "mxCell",
302
+ id=nid, value=n.get("label", nid),
303
+ style=style, vertex="1", parent=parent)
304
+
305
+ # If inside a group, use relative coordinates
306
+ if group_id in group_nodes:
307
+ gid = group_nodes[group_id]
308
+ # Find group bounds to compute relative position
309
+ member_ids = [nd["id"] for nd in nodes if nd.get("group") == group_id]
310
+ gxs = [positions[mid][0] for mid in member_ids if mid in positions]
311
+ gys = [positions[mid][1] for mid in member_ids if mid in positions]
312
+ if gxs and gys:
313
+ rel_x = x - min(gxs) + 30
314
+ rel_y = y - min(gys) + 50
315
+ SubElement(cell, "mxGeometry", x=str(int(rel_x)), y=str(int(rel_y)),
316
+ width=str(w), height=str(h),
317
+ attrib={"as": "geometry"})
318
+ else:
319
+ SubElement(cell, "mxGeometry", x=str(int(x)), y=str(int(y)),
320
+ width=str(w), height=str(h),
321
+ attrib={"as": "geometry"})
322
+ else:
323
+ SubElement(cell, "mxGeometry", x=str(int(x)), y=str(int(y)),
324
+ width=str(w), height=str(h),
325
+ attrib={"as": "geometry"})
326
+
327
+ # Edges
328
+ for e in edges:
329
+ eid = uid(f"{e['source']}-{e['target']}-{e.get('label','')}")
330
+ style = build_edge_style(e)
331
+ cell = SubElement(mxroot, "mxCell",
332
+ id=eid, value=e.get("label", ""),
333
+ style=style, edge="1", parent="1",
334
+ source=e["source"], target=e["target"])
335
+ SubElement(cell, "mxGeometry", relative="1",
336
+ attrib={"as": "geometry"})
337
+
338
+ # Pretty print
339
+ xml_str = tostring(root, encoding="unicode")
340
+ return parseString(xml_str).toprettyxml(indent=" ", encoding=None)
341
+
342
+
343
+ def main():
344
+ parser = argparse.ArgumentParser(description="Generate draw.io diagrams from JSON")
345
+ parser.add_argument("input", nargs="?", help="JSON input file")
346
+ parser.add_argument("--from-stdin", action="store_true", help="Read JSON from stdin")
347
+ parser.add_argument("-o", "--output", required=True, help="Output .drawio file")
348
+ args = parser.parse_args()
349
+
350
+ if args.from_stdin:
351
+ spec = json.load(sys.stdin)
352
+ elif args.input:
353
+ with open(args.input, "r", encoding="utf-8") as f:
354
+ spec = json.load(f)
355
+ else:
356
+ parser.error("Provide an input file or --from-stdin")
357
+
358
+ xml = generate_drawio(spec)
359
+ with open(args.output, "w", encoding="utf-8") as f:
360
+ f.write(xml)
361
+ print(f"✅ Generated: {args.output}")
362
+ print(f" Nodes: {len(spec.get('nodes', []))}, Edges: {len(spec.get('edges', []))}")
363
+
364
+
365
+ if __name__ == "__main__":
366
+ main()