unreal-engine-mcp-server 0.4.6 → 0.5.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 (438) hide show
  1. package/.env.example +26 -0
  2. package/.env.production +38 -7
  3. package/.eslintrc.json +0 -54
  4. package/.eslintrc.override.json +8 -0
  5. package/.github/ISSUE_TEMPLATE/bug_report.yml +94 -0
  6. package/.github/ISSUE_TEMPLATE/config.yml +8 -0
  7. package/.github/ISSUE_TEMPLATE/feature_request.yml +56 -0
  8. package/.github/copilot-instructions.md +478 -45
  9. package/.github/dependabot.yml +19 -0
  10. package/.github/labeler.yml +24 -0
  11. package/.github/labels.yml +70 -0
  12. package/.github/pull_request_template.md +42 -0
  13. package/.github/release-drafter.yml +148 -0
  14. package/.github/workflows/auto-merge.yml +38 -0
  15. package/.github/workflows/ci.yml +38 -0
  16. package/.github/workflows/dependency-review.yml +17 -0
  17. package/.github/workflows/gemini-issue-triage.yml +172 -0
  18. package/.github/workflows/greetings.yml +23 -0
  19. package/.github/workflows/labeler.yml +16 -0
  20. package/.github/workflows/links.yml +80 -0
  21. package/.github/workflows/pr-size-labeler.yml +137 -0
  22. package/.github/workflows/publish-mcp.yml +12 -7
  23. package/.github/workflows/release-drafter.yml +23 -0
  24. package/.github/workflows/release.yml +112 -0
  25. package/.github/workflows/semantic-pull-request.yml +35 -0
  26. package/.github/workflows/smoke-test.yml +36 -0
  27. package/.github/workflows/stale.yml +28 -0
  28. package/CHANGELOG.md +269 -22
  29. package/CONTRIBUTING.md +140 -0
  30. package/README.md +166 -72
  31. package/claude_desktop_config_example.json +7 -6
  32. package/dist/automation/bridge.d.ts +50 -0
  33. package/dist/automation/bridge.js +452 -0
  34. package/dist/automation/connection-manager.d.ts +23 -0
  35. package/dist/automation/connection-manager.js +107 -0
  36. package/dist/automation/handshake.d.ts +11 -0
  37. package/dist/automation/handshake.js +89 -0
  38. package/dist/automation/index.d.ts +3 -0
  39. package/dist/automation/index.js +3 -0
  40. package/dist/automation/message-handler.d.ts +12 -0
  41. package/dist/automation/message-handler.js +149 -0
  42. package/dist/automation/request-tracker.d.ts +25 -0
  43. package/dist/automation/request-tracker.js +98 -0
  44. package/dist/automation/types.d.ts +130 -0
  45. package/dist/automation/types.js +2 -0
  46. package/dist/cli.js +32 -5
  47. package/dist/config.d.ts +27 -0
  48. package/dist/config.js +60 -0
  49. package/dist/constants.d.ts +12 -0
  50. package/dist/constants.js +12 -0
  51. package/dist/graphql/resolvers.d.ts +268 -0
  52. package/dist/graphql/resolvers.js +743 -0
  53. package/dist/graphql/schema.d.ts +5 -0
  54. package/dist/graphql/schema.js +437 -0
  55. package/dist/graphql/server.d.ts +26 -0
  56. package/dist/graphql/server.js +115 -0
  57. package/dist/graphql/types.d.ts +7 -0
  58. package/dist/graphql/types.js +2 -0
  59. package/dist/handlers/resource-handlers.d.ts +20 -0
  60. package/dist/handlers/resource-handlers.js +180 -0
  61. package/dist/index.d.ts +31 -18
  62. package/dist/index.js +119 -604
  63. package/dist/prompts/index.js +4 -4
  64. package/dist/resources/actors.d.ts +17 -12
  65. package/dist/resources/actors.js +56 -76
  66. package/dist/resources/assets.d.ts +6 -14
  67. package/dist/resources/assets.js +115 -147
  68. package/dist/resources/levels.d.ts +13 -13
  69. package/dist/resources/levels.js +25 -34
  70. package/dist/server/resource-registry.d.ts +20 -0
  71. package/dist/server/resource-registry.js +37 -0
  72. package/dist/server/tool-registry.d.ts +23 -0
  73. package/dist/server/tool-registry.js +322 -0
  74. package/dist/server-setup.d.ts +21 -0
  75. package/dist/server-setup.js +111 -0
  76. package/dist/services/health-monitor.d.ts +34 -0
  77. package/dist/services/health-monitor.js +105 -0
  78. package/dist/services/metrics-server.d.ts +11 -0
  79. package/dist/services/metrics-server.js +105 -0
  80. package/dist/tools/actors.d.ts +147 -9
  81. package/dist/tools/actors.js +350 -311
  82. package/dist/tools/animation.d.ts +135 -4
  83. package/dist/tools/animation.js +510 -411
  84. package/dist/tools/assets.d.ts +117 -19
  85. package/dist/tools/assets.js +259 -284
  86. package/dist/tools/audio.d.ts +102 -42
  87. package/dist/tools/audio.js +272 -685
  88. package/dist/tools/base-tool.d.ts +17 -0
  89. package/dist/tools/base-tool.js +46 -0
  90. package/dist/tools/behavior-tree.d.ts +94 -0
  91. package/dist/tools/behavior-tree.js +39 -0
  92. package/dist/tools/blueprint/helpers.d.ts +29 -0
  93. package/dist/tools/blueprint/helpers.js +182 -0
  94. package/dist/tools/blueprint.d.ts +228 -118
  95. package/dist/tools/blueprint.js +685 -832
  96. package/dist/tools/consolidated-tool-definitions.d.ts +5475 -1627
  97. package/dist/tools/consolidated-tool-definitions.js +829 -482
  98. package/dist/tools/consolidated-tool-handlers.d.ts +2 -1
  99. package/dist/tools/consolidated-tool-handlers.js +211 -1009
  100. package/dist/tools/debug.d.ts +143 -85
  101. package/dist/tools/debug.js +234 -180
  102. package/dist/tools/dynamic-handler-registry.d.ts +11 -0
  103. package/dist/tools/dynamic-handler-registry.js +101 -0
  104. package/dist/tools/editor.d.ts +139 -18
  105. package/dist/tools/editor.js +239 -244
  106. package/dist/tools/engine.d.ts +10 -4
  107. package/dist/tools/engine.js +13 -5
  108. package/dist/tools/environment.d.ts +36 -0
  109. package/dist/tools/environment.js +267 -0
  110. package/dist/tools/foliage.d.ts +105 -14
  111. package/dist/tools/foliage.js +219 -331
  112. package/dist/tools/handlers/actor-handlers.d.ts +3 -0
  113. package/dist/tools/handlers/actor-handlers.js +232 -0
  114. package/dist/tools/handlers/animation-handlers.d.ts +3 -0
  115. package/dist/tools/handlers/animation-handlers.js +185 -0
  116. package/dist/tools/handlers/argument-helper.d.ts +16 -0
  117. package/dist/tools/handlers/argument-helper.js +80 -0
  118. package/dist/tools/handlers/asset-handlers.d.ts +3 -0
  119. package/dist/tools/handlers/asset-handlers.js +496 -0
  120. package/dist/tools/handlers/audio-handlers.d.ts +3 -0
  121. package/dist/tools/handlers/audio-handlers.js +166 -0
  122. package/dist/tools/handlers/blueprint-handlers.d.ts +4 -0
  123. package/dist/tools/handlers/blueprint-handlers.js +358 -0
  124. package/dist/tools/handlers/common-handlers.d.ts +14 -0
  125. package/dist/tools/handlers/common-handlers.js +56 -0
  126. package/dist/tools/handlers/editor-handlers.d.ts +3 -0
  127. package/dist/tools/handlers/editor-handlers.js +119 -0
  128. package/dist/tools/handlers/effect-handlers.d.ts +3 -0
  129. package/dist/tools/handlers/effect-handlers.js +171 -0
  130. package/dist/tools/handlers/environment-handlers.d.ts +3 -0
  131. package/dist/tools/handlers/environment-handlers.js +170 -0
  132. package/dist/tools/handlers/graph-handlers.d.ts +3 -0
  133. package/dist/tools/handlers/graph-handlers.js +90 -0
  134. package/dist/tools/handlers/input-handlers.d.ts +3 -0
  135. package/dist/tools/handlers/input-handlers.js +21 -0
  136. package/dist/tools/handlers/inspect-handlers.d.ts +3 -0
  137. package/dist/tools/handlers/inspect-handlers.js +383 -0
  138. package/dist/tools/handlers/level-handlers.d.ts +3 -0
  139. package/dist/tools/handlers/level-handlers.js +237 -0
  140. package/dist/tools/handlers/lighting-handlers.d.ts +3 -0
  141. package/dist/tools/handlers/lighting-handlers.js +144 -0
  142. package/dist/tools/handlers/performance-handlers.d.ts +3 -0
  143. package/dist/tools/handlers/performance-handlers.js +130 -0
  144. package/dist/tools/handlers/pipeline-handlers.d.ts +3 -0
  145. package/dist/tools/handlers/pipeline-handlers.js +110 -0
  146. package/dist/tools/handlers/sequence-handlers.d.ts +3 -0
  147. package/dist/tools/handlers/sequence-handlers.js +376 -0
  148. package/dist/tools/handlers/system-handlers.d.ts +4 -0
  149. package/dist/tools/handlers/system-handlers.js +506 -0
  150. package/dist/tools/input.d.ts +19 -0
  151. package/dist/tools/input.js +89 -0
  152. package/dist/tools/introspection.d.ts +103 -40
  153. package/dist/tools/introspection.js +425 -568
  154. package/dist/tools/landscape.d.ts +97 -36
  155. package/dist/tools/landscape.js +280 -409
  156. package/dist/tools/level.d.ts +130 -10
  157. package/dist/tools/level.js +639 -675
  158. package/dist/tools/lighting.d.ts +77 -38
  159. package/dist/tools/lighting.js +441 -943
  160. package/dist/tools/logs.d.ts +45 -0
  161. package/dist/tools/logs.js +210 -0
  162. package/dist/tools/materials.d.ts +91 -24
  163. package/dist/tools/materials.js +190 -118
  164. package/dist/tools/niagara.d.ts +149 -39
  165. package/dist/tools/niagara.js +232 -182
  166. package/dist/tools/performance.d.ts +27 -12
  167. package/dist/tools/performance.js +204 -122
  168. package/dist/tools/physics.d.ts +32 -77
  169. package/dist/tools/physics.js +171 -582
  170. package/dist/tools/property-dictionary.d.ts +13 -0
  171. package/dist/tools/property-dictionary.js +82 -0
  172. package/dist/tools/sequence.d.ts +73 -48
  173. package/dist/tools/sequence.js +196 -748
  174. package/dist/tools/tool-definition-utils.d.ts +59 -0
  175. package/dist/tools/tool-definition-utils.js +35 -0
  176. package/dist/tools/ui.d.ts +66 -34
  177. package/dist/tools/ui.js +134 -214
  178. package/dist/types/env.d.ts +0 -3
  179. package/dist/types/env.js +0 -7
  180. package/dist/types/tool-interfaces.d.ts +898 -0
  181. package/dist/types/tool-interfaces.js +2 -0
  182. package/dist/types/tool-types.d.ts +195 -11
  183. package/dist/types/tool-types.js +0 -4
  184. package/dist/unreal-bridge.d.ts +24 -131
  185. package/dist/unreal-bridge.js +364 -1506
  186. package/dist/utils/command-validator.d.ts +9 -0
  187. package/dist/utils/command-validator.js +67 -0
  188. package/dist/utils/elicitation.d.ts +1 -1
  189. package/dist/utils/elicitation.js +12 -15
  190. package/dist/utils/error-handler.d.ts +2 -51
  191. package/dist/utils/error-handler.js +11 -87
  192. package/dist/utils/ini-reader.d.ts +3 -0
  193. package/dist/utils/ini-reader.js +69 -0
  194. package/dist/utils/logger.js +9 -6
  195. package/dist/utils/normalize.d.ts +3 -0
  196. package/dist/utils/normalize.js +56 -0
  197. package/dist/utils/response-factory.d.ts +7 -0
  198. package/dist/utils/response-factory.js +33 -0
  199. package/dist/utils/response-validator.d.ts +3 -24
  200. package/dist/utils/response-validator.js +130 -81
  201. package/dist/utils/result-helpers.d.ts +4 -5
  202. package/dist/utils/result-helpers.js +15 -16
  203. package/dist/utils/safe-json.js +5 -11
  204. package/dist/utils/unreal-command-queue.d.ts +24 -0
  205. package/dist/utils/unreal-command-queue.js +120 -0
  206. package/dist/utils/validation.d.ts +0 -40
  207. package/dist/utils/validation.js +1 -78
  208. package/dist/wasm/index.d.ts +70 -0
  209. package/dist/wasm/index.js +535 -0
  210. package/docs/GraphQL-API.md +888 -0
  211. package/docs/Migration-Guide-v0.5.0.md +692 -0
  212. package/docs/Roadmap.md +53 -0
  213. package/docs/WebAssembly-Integration.md +628 -0
  214. package/docs/editor-plugin-extension.md +370 -0
  215. package/docs/handler-mapping.md +242 -0
  216. package/docs/native-automation-progress.md +128 -0
  217. package/docs/testing-guide.md +423 -0
  218. package/mcp-config-example.json +6 -6
  219. package/package.json +60 -27
  220. package/plugins/McpAutomationBridge/Config/FilterPlugin.ini +8 -0
  221. package/plugins/McpAutomationBridge/McpAutomationBridge.uplugin +64 -0
  222. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/McpAutomationBridge.Build.cs +189 -0
  223. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.cpp +22 -0
  224. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.h +30 -0
  225. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeHelpers.h +1983 -0
  226. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeModule.cpp +72 -0
  227. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSettings.cpp +46 -0
  228. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSubsystem.cpp +581 -0
  229. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AnimationHandlers.cpp +2394 -0
  230. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetQueryHandlers.cpp +300 -0
  231. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetWorkflowHandlers.cpp +2807 -0
  232. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AudioHandlers.cpp +1087 -0
  233. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BehaviorTreeHandlers.cpp +488 -0
  234. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.cpp +643 -0
  235. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.h +31 -0
  236. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintGraphHandlers.cpp +1184 -0
  237. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers.cpp +5652 -0
  238. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers_List.cpp +152 -0
  239. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ControlHandlers.cpp +2614 -0
  240. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_DebugHandlers.cpp +42 -0
  241. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EditorFunctionHandlers.cpp +1237 -0
  242. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EffectHandlers.cpp +1701 -0
  243. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EnvironmentHandlers.cpp +2145 -0
  244. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_FoliageHandlers.cpp +954 -0
  245. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InputHandlers.cpp +209 -0
  246. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InsightsHandlers.cpp +41 -0
  247. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LandscapeHandlers.cpp +1164 -0
  248. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LevelHandlers.cpp +762 -0
  249. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LightingHandlers.cpp +634 -0
  250. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LogHandlers.cpp +136 -0
  251. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_MaterialGraphHandlers.cpp +494 -0
  252. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraGraphHandlers.cpp +278 -0
  253. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraHandlers.cpp +625 -0
  254. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PerformanceHandlers.cpp +401 -0
  255. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PipelineHandlers.cpp +67 -0
  256. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ProcessRequest.cpp +735 -0
  257. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PropertyHandlers.cpp +2634 -0
  258. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_RenderHandlers.cpp +189 -0
  259. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.cpp +917 -0
  260. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.h +39 -0
  261. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequenceHandlers.cpp +2670 -0
  262. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequencerHandlers.cpp +519 -0
  263. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_TestHandlers.cpp +38 -0
  264. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_UiHandlers.cpp +668 -0
  265. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_WorldPartitionHandlers.cpp +346 -0
  266. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.cpp +1330 -0
  267. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.h +149 -0
  268. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpConnectionManager.cpp +783 -0
  269. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSettings.h +115 -0
  270. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSubsystem.h +796 -0
  271. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpConnectionManager.h +117 -0
  272. package/scripts/check-unreal-connection.mjs +19 -0
  273. package/scripts/clean-tmp.js +23 -0
  274. package/scripts/patch-wasm.js +26 -0
  275. package/scripts/run-all-tests.mjs +131 -0
  276. package/scripts/smoke-test.ts +94 -0
  277. package/scripts/sync-mcp-plugin.js +143 -0
  278. package/scripts/test-no-plugin-alternates.mjs +113 -0
  279. package/scripts/validate-server.js +46 -0
  280. package/scripts/verify-automation-bridge.js +200 -0
  281. package/server.json +57 -21
  282. package/src/automation/bridge.ts +558 -0
  283. package/src/automation/connection-manager.ts +130 -0
  284. package/src/automation/handshake.ts +99 -0
  285. package/src/automation/index.ts +2 -0
  286. package/src/automation/message-handler.ts +167 -0
  287. package/src/automation/request-tracker.ts +123 -0
  288. package/src/automation/types.ts +107 -0
  289. package/src/cli.ts +33 -6
  290. package/src/config.ts +73 -0
  291. package/src/constants.ts +12 -0
  292. package/src/graphql/resolvers.ts +1010 -0
  293. package/src/graphql/schema.ts +452 -0
  294. package/src/graphql/server.ts +154 -0
  295. package/src/graphql/types.ts +7 -0
  296. package/src/handlers/resource-handlers.ts +186 -0
  297. package/src/index.ts +152 -649
  298. package/src/prompts/index.ts +4 -4
  299. package/src/resources/actors.ts +58 -76
  300. package/src/resources/assets.ts +147 -134
  301. package/src/resources/levels.ts +28 -33
  302. package/src/server/resource-registry.ts +47 -0
  303. package/src/server/tool-registry.ts +354 -0
  304. package/src/server-setup.ts +148 -0
  305. package/src/services/health-monitor.ts +132 -0
  306. package/src/services/metrics-server.ts +142 -0
  307. package/src/tools/actors.ts +417 -322
  308. package/src/tools/animation.ts +671 -461
  309. package/src/tools/assets.ts +353 -289
  310. package/src/tools/audio.ts +323 -766
  311. package/src/tools/base-tool.ts +52 -0
  312. package/src/tools/behavior-tree.ts +45 -0
  313. package/src/tools/blueprint/helpers.ts +189 -0
  314. package/src/tools/blueprint.ts +787 -965
  315. package/src/tools/consolidated-tool-definitions.ts +993 -500
  316. package/src/tools/consolidated-tool-handlers.ts +272 -1122
  317. package/src/tools/debug.ts +292 -187
  318. package/src/tools/dynamic-handler-registry.ts +151 -0
  319. package/src/tools/editor.ts +309 -246
  320. package/src/tools/engine.ts +14 -3
  321. package/src/tools/environment.ts +287 -0
  322. package/src/tools/foliage.ts +314 -379
  323. package/src/tools/handlers/actor-handlers.ts +271 -0
  324. package/src/tools/handlers/animation-handlers.ts +237 -0
  325. package/src/tools/handlers/argument-helper.ts +142 -0
  326. package/src/tools/handlers/asset-handlers.ts +532 -0
  327. package/src/tools/handlers/audio-handlers.ts +194 -0
  328. package/src/tools/handlers/blueprint-handlers.ts +380 -0
  329. package/src/tools/handlers/common-handlers.ts +87 -0
  330. package/src/tools/handlers/editor-handlers.ts +123 -0
  331. package/src/tools/handlers/effect-handlers.ts +220 -0
  332. package/src/tools/handlers/environment-handlers.ts +183 -0
  333. package/src/tools/handlers/graph-handlers.ts +116 -0
  334. package/src/tools/handlers/input-handlers.ts +28 -0
  335. package/src/tools/handlers/inspect-handlers.ts +450 -0
  336. package/src/tools/handlers/level-handlers.ts +252 -0
  337. package/src/tools/handlers/lighting-handlers.ts +147 -0
  338. package/src/tools/handlers/performance-handlers.ts +132 -0
  339. package/src/tools/handlers/pipeline-handlers.ts +127 -0
  340. package/src/tools/handlers/sequence-handlers.ts +415 -0
  341. package/src/tools/handlers/system-handlers.ts +564 -0
  342. package/src/tools/input.ts +101 -0
  343. package/src/tools/introspection.ts +493 -584
  344. package/src/tools/landscape.ts +394 -489
  345. package/src/tools/level.ts +752 -694
  346. package/src/tools/lighting.ts +583 -984
  347. package/src/tools/logs.ts +219 -0
  348. package/src/tools/materials.ts +231 -121
  349. package/src/tools/niagara.ts +293 -168
  350. package/src/tools/performance.ts +320 -168
  351. package/src/tools/physics.ts +268 -613
  352. package/src/tools/property-dictionary.ts +98 -0
  353. package/src/tools/sequence.ts +255 -815
  354. package/src/tools/tool-definition-utils.ts +35 -0
  355. package/src/tools/ui.ts +207 -283
  356. package/src/types/env.ts +0 -10
  357. package/src/types/tool-interfaces.ts +250 -0
  358. package/src/types/tool-types.ts +250 -13
  359. package/src/unreal-bridge.ts +460 -1550
  360. package/src/utils/command-validator.ts +75 -0
  361. package/src/utils/elicitation.ts +10 -7
  362. package/src/utils/error-handler.ts +14 -90
  363. package/src/utils/ini-reader.ts +86 -0
  364. package/src/utils/logger.ts +8 -3
  365. package/src/utils/normalize.ts +60 -0
  366. package/src/utils/response-factory.ts +39 -0
  367. package/src/utils/response-validator.ts +176 -56
  368. package/src/utils/result-helpers.ts +21 -19
  369. package/src/utils/safe-json.ts +14 -11
  370. package/src/utils/unreal-command-queue.ts +152 -0
  371. package/src/utils/validation.ts +4 -1
  372. package/src/wasm/index.ts +838 -0
  373. package/test-server.mjs +100 -0
  374. package/tests/run-unreal-tool-tests.mjs +242 -14
  375. package/tests/test-animation.mjs +44 -0
  376. package/tests/test-asset-advanced.mjs +82 -0
  377. package/tests/test-asset-errors.mjs +35 -0
  378. package/tests/test-audio.mjs +219 -0
  379. package/tests/test-automation-timeouts.mjs +98 -0
  380. package/tests/test-behavior-tree.mjs +261 -0
  381. package/tests/test-blueprint-events.mjs +35 -0
  382. package/tests/test-blueprint-graph.mjs +79 -0
  383. package/tests/test-blueprint.mjs +577 -0
  384. package/tests/test-client-mode.mjs +86 -0
  385. package/tests/test-console-command.mjs +56 -0
  386. package/tests/test-control-actor.mjs +425 -0
  387. package/tests/test-control-editor.mjs +80 -0
  388. package/tests/test-extra-tools.mjs +38 -0
  389. package/tests/test-graphql.mjs +322 -0
  390. package/tests/test-inspect.mjs +72 -0
  391. package/tests/test-landscape.mjs +60 -0
  392. package/tests/test-manage-asset.mjs +438 -0
  393. package/tests/test-manage-level.mjs +70 -0
  394. package/tests/test-materials.mjs +356 -0
  395. package/tests/test-niagara.mjs +185 -0
  396. package/tests/test-no-inline-python.mjs +122 -0
  397. package/tests/test-plugin-handshake.mjs +82 -0
  398. package/tests/test-render.mjs +33 -0
  399. package/tests/test-runner.mjs +933 -0
  400. package/tests/test-search-assets.mjs +66 -0
  401. package/tests/test-sequence.mjs +68 -0
  402. package/tests/test-system.mjs +57 -0
  403. package/tests/test-wasm.mjs +193 -0
  404. package/tests/test-world-partition.mjs +215 -0
  405. package/tsconfig.json +3 -3
  406. package/wasm/Cargo.lock +363 -0
  407. package/wasm/Cargo.toml +42 -0
  408. package/wasm/LICENSE +21 -0
  409. package/wasm/README.md +253 -0
  410. package/wasm/src/dependency_resolver.rs +377 -0
  411. package/wasm/src/lib.rs +153 -0
  412. package/wasm/src/property_parser.rs +271 -0
  413. package/wasm/src/transform_math.rs +396 -0
  414. package/wasm/tests/integration.rs +109 -0
  415. package/.github/workflows/smithery-build.yml +0 -29
  416. package/dist/tools/build_environment_advanced.d.ts +0 -65
  417. package/dist/tools/build_environment_advanced.js +0 -633
  418. package/dist/tools/rc.d.ts +0 -110
  419. package/dist/tools/rc.js +0 -437
  420. package/dist/tools/visual.d.ts +0 -40
  421. package/dist/tools/visual.js +0 -282
  422. package/dist/utils/http.d.ts +0 -6
  423. package/dist/utils/http.js +0 -151
  424. package/dist/utils/python-output.d.ts +0 -18
  425. package/dist/utils/python-output.js +0 -290
  426. package/dist/utils/python.d.ts +0 -2
  427. package/dist/utils/python.js +0 -4
  428. package/dist/utils/stdio-redirect.d.ts +0 -2
  429. package/dist/utils/stdio-redirect.js +0 -20
  430. package/docs/unreal-tool-test-cases.md +0 -572
  431. package/smithery.yaml +0 -29
  432. package/src/tools/build_environment_advanced.ts +0 -732
  433. package/src/tools/rc.ts +0 -515
  434. package/src/tools/visual.ts +0 -281
  435. package/src/utils/http.ts +0 -187
  436. package/src/utils/python-output.ts +0 -351
  437. package/src/utils/python.ts +0 -3
  438. package/src/utils/stdio-redirect.ts +0 -18
@@ -0,0 +1,148 @@
1
+ name: Release Drafter
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ update_release_draft:
14
+ permissions:
15
+ contents: write
16
+ pull-requests: write
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - name: Checkout
20
+ uses: actions/checkout@v4
21
+ with:
22
+ fetch-depth: 0
23
+
24
+ - name: Run Release Drafter
25
+ id: release_drafter
26
+ uses: release-drafter/release-drafter@v6
27
+ with:
28
+ config-name: release-drafter.yml
29
+ env:
30
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31
+
32
+ - name: Get commits not in PRs
33
+ id: orphan_commits
34
+ uses: actions/github-script@v7
35
+ with:
36
+ github-token: ${{ secrets.GITHUB_TOKEN }}
37
+ script: |
38
+ const { execSync } = require('child_process');
39
+
40
+ // Get the last release tag
41
+ let lastTag;
42
+ try {
43
+ const { data: releases } = await github.rest.repos.listReleases({
44
+ owner: context.repo.owner,
45
+ repo: context.repo.repo,
46
+ per_page: 1
47
+ });
48
+ lastTag = releases[0]?.tag_name;
49
+ } catch (e) {
50
+ lastTag = null;
51
+ }
52
+
53
+ // Get all commits since last release
54
+ const range = lastTag ? `${lastTag}..HEAD` : 'HEAD~50..HEAD';
55
+ let commits;
56
+ try {
57
+ commits = execSync(`git log ${range} --pretty=format:"%H|%s|%an" --no-merges`, { encoding: 'utf-8' })
58
+ .split('\n')
59
+ .filter(Boolean)
60
+ .map(line => {
61
+ const [sha, message, author] = line.split('|');
62
+ return { sha, message, author };
63
+ });
64
+ } catch (e) {
65
+ commits = [];
66
+ }
67
+
68
+ if (commits.length === 0) {
69
+ core.setOutput('orphan_commits', '');
70
+ return;
71
+ }
72
+
73
+ // Get all PRs merged since last release to filter out PR commits
74
+ const { data: prs } = await github.rest.pulls.list({
75
+ owner: context.repo.owner,
76
+ repo: context.repo.repo,
77
+ state: 'closed',
78
+ sort: 'updated',
79
+ direction: 'desc',
80
+ per_page: 100
81
+ });
82
+
83
+ // Get commit SHAs that are part of PRs
84
+ const prCommitShas = new Set();
85
+ for (const pr of prs.filter(p => p.merged_at)) {
86
+ try {
87
+ const { data: prCommits } = await github.rest.pulls.listCommits({
88
+ owner: context.repo.owner,
89
+ repo: context.repo.repo,
90
+ pull_number: pr.number
91
+ });
92
+ prCommits.forEach(c => prCommitShas.add(c.sha));
93
+ } catch (e) {
94
+ // Skip if error
95
+ }
96
+ }
97
+
98
+ // Filter to only orphan commits (not in any PR)
99
+ const orphanCommits = commits.filter(c => !prCommitShas.has(c.sha));
100
+
101
+ if (orphanCommits.length === 0) {
102
+ core.setOutput('orphan_commits', '');
103
+ return;
104
+ }
105
+
106
+ // Format orphan commits
107
+ const formatted = orphanCommits
108
+ .map(c => `- ${c.message} (${c.sha.substring(0, 7)}) @${c.author}`)
109
+ .join('\n');
110
+
111
+ core.setOutput('orphan_commits', formatted);
112
+ core.info(`Found ${orphanCommits.length} commits not in PRs`);
113
+
114
+ - name: Update release body with commits
115
+ if: steps.orphan_commits.outputs.orphan_commits != ''
116
+ uses: actions/github-script@v7
117
+ with:
118
+ github-token: ${{ secrets.GITHUB_TOKEN }}
119
+ script: |
120
+ const releaseId = '${{ steps.release_drafter.outputs.id }}';
121
+ const orphanCommits = `${{ steps.orphan_commits.outputs.orphan_commits }}`;
122
+
123
+ if (!releaseId || !orphanCommits) return;
124
+
125
+ // Get current release body
126
+ const { data: release } = await github.rest.repos.getRelease({
127
+ owner: context.repo.owner,
128
+ repo: context.repo.repo,
129
+ release_id: parseInt(releaseId)
130
+ });
131
+
132
+ // Check if commits section already exists
133
+ if (release.body && release.body.includes('## Direct Commits')) {
134
+ core.info('Commits section already exists, skipping');
135
+ return;
136
+ }
137
+
138
+ // Append commits section
139
+ const newBody = `${release.body || ''}\n\n## Direct Commits\n\n${orphanCommits}`;
140
+
141
+ await github.rest.repos.updateRelease({
142
+ owner: context.repo.owner,
143
+ repo: context.repo.repo,
144
+ release_id: parseInt(releaseId),
145
+ body: newBody
146
+ });
147
+
148
+ core.info('Added orphan commits to release draft');
@@ -0,0 +1,38 @@
1
+ name: Auto-merge Dependabot PRs
2
+
3
+ on: pull_request
4
+
5
+ permissions:
6
+ contents: write
7
+ pull-requests: write
8
+
9
+ jobs:
10
+ dependabot:
11
+ runs-on: ubuntu-latest
12
+ if: github.actor == 'dependabot[bot]'
13
+ steps:
14
+ - name: Dependabot metadata
15
+ id: metadata
16
+ uses: dependabot/fetch-metadata@v2
17
+ with:
18
+ github-token: "${{ secrets.GITHUB_TOKEN }}"
19
+
20
+ - name: Approve patch and minor npm updates
21
+ if: |
22
+ steps.metadata.outputs.package-ecosystem == 'npm' &&
23
+ (steps.metadata.outputs.update-type == 'version-update:semver-patch' ||
24
+ steps.metadata.outputs.update-type == 'version-update:semver-minor')
25
+ run: gh pr review --approve "$PR_URL"
26
+ env:
27
+ PR_URL: ${{ github.event.pull_request.html_url }}
28
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29
+
30
+ - name: Enable auto-merge for npm Dependabot PRs
31
+ if: |
32
+ steps.metadata.outputs.package-ecosystem == 'npm' &&
33
+ (steps.metadata.outputs.update-type == 'version-update:semver-patch' ||
34
+ steps.metadata.outputs.update-type == 'version-update:semver-minor')
35
+ run: gh pr merge --auto --squash "$PR_URL"
36
+ env:
37
+ PR_URL: ${{ github.event.pull_request.html_url }}
38
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,38 @@
1
+ name: CI
2
+ permissions:
3
+ contents: read
4
+
5
+ on:
6
+ push:
7
+ branches: [ main ]
8
+ pull_request:
9
+ branches: [ main ]
10
+
11
+ concurrency:
12
+ group: ${{ github.workflow }}-${{ github.ref }}
13
+ cancel-in-progress: true
14
+
15
+ jobs:
16
+ lint:
17
+ name: Lint (TS)
18
+
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - name: Checkout
22
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
23
+
24
+ - name: Setup Node.js
25
+ uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
26
+ with:
27
+ node-version: '18'
28
+
29
+
30
+ - name: Install dependencies
31
+ run: npm ci
32
+
33
+ - name: Run ESLint (TypeScript/JavaScript)
34
+ run: |
35
+ echo "Running ESLint (fail on warnings)"
36
+ npx eslint . --ext .ts --max-warnings=0
37
+
38
+
@@ -0,0 +1,17 @@
1
+ name: 'Dependency Review'
2
+ on: [pull_request]
3
+
4
+ permissions:
5
+ contents: read
6
+
7
+ jobs:
8
+ dependency-review:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - name: 'Checkout Repository'
12
+ uses: actions/checkout@v6 # v4
13
+ - name: 'Dependency Review'
14
+ uses: actions/dependency-review-action@v4 # v4
15
+ with:
16
+ fail-on-severity: high
17
+ deny-licenses: GPL-3.0, AGPL-1.0, AGPL-3.0
@@ -0,0 +1,172 @@
1
+ name: '🏷️ Gemini Issue Triage'
2
+
3
+ on:
4
+ issues:
5
+ types:
6
+ - 'opened'
7
+ - 'reopened'
8
+ workflow_dispatch:
9
+ inputs:
10
+ issue_number:
11
+ description: 'Issue number to triage'
12
+ required: true
13
+ type: 'number'
14
+
15
+ concurrency:
16
+ group: '${{ github.workflow }}-${{ github.event.issue.number || github.event.inputs.issue_number }}'
17
+ cancel-in-progress: true
18
+
19
+ permissions:
20
+ contents: 'read'
21
+ issues: 'write'
22
+
23
+ jobs:
24
+ triage-issue:
25
+ if: |-
26
+ github.event_name == 'workflow_dispatch' ||
27
+ (
28
+ github.event_name == 'issues' &&
29
+ contains(github.event.issue.labels.*.name, 'needs-triage')
30
+ )
31
+ timeout-minutes: 5
32
+ runs-on: 'ubuntu-latest'
33
+ steps:
34
+ - name: 'Get issue data for manual trigger'
35
+ id: 'get_issue_data'
36
+ if: github.event_name == 'workflow_dispatch'
37
+ uses: 'actions/github-script@v8'
38
+ with:
39
+ github-token: '${{ secrets.GITHUB_TOKEN }}'
40
+ script: |
41
+ const { data: issue } = await github.rest.issues.get({
42
+ owner: context.repo.owner,
43
+ repo: context.repo.repo,
44
+ issue_number: ${{ github.event.inputs.issue_number }},
45
+ });
46
+ core.setOutput('title', issue.title);
47
+ core.setOutput('body', issue.body);
48
+ core.setOutput('labels', issue.labels.map(label => label.name).join(','));
49
+ return issue;
50
+
51
+ - name: 'Checkout'
52
+ uses: 'actions/checkout@v6'
53
+
54
+ - name: 'Get Repository Labels'
55
+ id: 'get_labels'
56
+ uses: 'actions/github-script@v8'
57
+ with:
58
+ github-token: '${{ secrets.GITHUB_TOKEN }}'
59
+ script: |
60
+ const { data: labels } = await github.rest.issues.listLabelsForRepo({
61
+ owner: context.repo.owner,
62
+ repo: context.repo.repo,
63
+ });
64
+ // Filter to area labels
65
+ const areaLabels = labels.map(l => l.name).filter(n =>
66
+ n.startsWith('area/') || n.startsWith('tool/') || n.startsWith('type/')
67
+ );
68
+ core.setOutput('available_labels', areaLabels.join(','));
69
+ core.info(`Found ${areaLabels.length} area labels: ${areaLabels.join(', ')}`);
70
+
71
+ - name: Analyze Issue with Gemini
72
+ id: gemini_analysis
73
+ uses: google-github-actions/run-gemini-cli@v0 # v0
74
+ env:
75
+ GITHUB_TOKEN: '' # No auth token for untrusted input analysis
76
+ ISSUE_TITLE: '${{ github.event_name == ''workflow_dispatch'' && steps.get_issue_data.outputs.title || github.event.issue.title }}'
77
+ ISSUE_BODY: '${{ github.event_name == ''workflow_dispatch'' && steps.get_issue_data.outputs.body || github.event.issue.body }}'
78
+ AVAILABLE_LABELS: '${{ steps.get_labels.outputs.available_labels }}'
79
+ with:
80
+ # Use Gemini API key only (free tier) - no Vertex AI
81
+ gemini_api_key: '${{ secrets.GEMINI_API_KEY }}'
82
+ settings: |
83
+ {
84
+ "maxSessionTurns": 10
85
+ }
86
+ prompt: |
87
+ ## Role
88
+ You are an issue triage assistant for Unreal Engine MCP Server.
89
+
90
+ ## Task
91
+ Analyze this GitHub issue and select the most appropriate label.
92
+
93
+ Issue Title: ${{ env.ISSUE_TITLE }}
94
+ Issue Body: ${{ env.ISSUE_BODY }}
95
+
96
+ Available Labels: ${{ env.AVAILABLE_LABELS }}
97
+
98
+ ## Area Definitions
99
+ - area/plugin: Issues with the C++ McpAutomationBridge plugin
100
+ - area/server: Issues with the Node.js MCP server
101
+ - area/tools: Issues with specific tool implementations
102
+ - area/testing: Issues with tests or test infrastructure
103
+ - area/docs: Documentation issues
104
+ - type/bug: Bug reports
105
+ - type/enhancement: Feature requests
106
+ - type/question: Questions or support requests
107
+
108
+ ## Output
109
+ Select exactly ONE label. Output only valid JSON:
110
+ {"label": "area/server"}
111
+
112
+ - name: 'Apply Label'
113
+ if: steps.gemini_analysis.outputs.summary != ''
114
+ uses: 'actions/github-script@v8'
115
+ env:
116
+ ISSUE_NUMBER: '${{ github.event.issue.number || github.event.inputs.issue_number }}'
117
+ GEMINI_OUTPUT: '${{ steps.gemini_analysis.outputs.summary }}'
118
+ AVAILABLE_LABELS: '${{ steps.get_labels.outputs.available_labels }}'
119
+ with:
120
+ github-token: '${{ secrets.GITHUB_TOKEN }}'
121
+ script: |
122
+ const fs = require('fs');
123
+ const summary = process.env.GEMINI_OUTPUT;
124
+
125
+ // Parse Gemini output for labels
126
+ let parsed = {};
127
+ try {
128
+ // Try to find JSON block
129
+ const match = summary.match(/```json\n([\s\S]*?)\n```/);
130
+ if (match) {
131
+ parsed = JSON.parse(match[1]);
132
+ } else {
133
+ parsed = JSON.parse(summary);
134
+ }
135
+ } catch (e) {
136
+ core.warning('Failed to parse Gemini output as JSON');
137
+ return;
138
+ }
139
+
140
+ const label = parsed.label;
141
+ if (!label) {
142
+ core.warning('No label returned from Gemini');
143
+ return;
144
+ }
145
+
146
+ const availableLabels = (process.env.AVAILABLE_LABELS || '').split(',');
147
+ if (!availableLabels.includes(label)) {
148
+ core.warning(`Label '${label}' not in available labels; skipping`);
149
+ return;
150
+ }
151
+
152
+ const issueNumber = parseInt(process.env.ISSUE_NUMBER);
153
+
154
+ await github.rest.issues.addLabels({
155
+ owner: context.repo.owner,
156
+ repo: context.repo.repo,
157
+ issue_number: issueNumber,
158
+ labels: [label]
159
+ });
160
+ core.info(`Added label '${label}' to issue #${issueNumber}`);
161
+
162
+ // Remove needs-triage label
163
+ try {
164
+ await github.rest.issues.removeLabel({
165
+ owner: context.repo.owner,
166
+ repo: context.repo.repo,
167
+ issue_number: issueNumber,
168
+ name: 'needs-triage'
169
+ });
170
+ } catch (e) {
171
+ if (e.status !== 404) throw e;
172
+ }
@@ -0,0 +1,23 @@
1
+ name: Greetings
2
+
3
+ on: [pull_request_target, issues]
4
+
5
+ permissions:
6
+ issues: write
7
+ pull-requests: write
8
+
9
+ jobs:
10
+ greeting:
11
+ runs-on: ubuntu-latest
12
+ # Skip for bots and repository owner
13
+ if: >-
14
+ github.actor != 'dependabot[bot]' &&
15
+ github.actor != 'renovate[bot]' &&
16
+ github.actor != 'github-actions[bot]' &&
17
+ github.actor != github.repository_owner
18
+ steps:
19
+ - uses: actions/first-interaction@v3
20
+ with:
21
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
22
+ issue-message: '👋 Thanks for opening this issue! We appreciate your feedback and report. A maintainer will check this out soon.'
23
+ pr-message: '👋 Thanks for your first Pull Request! We love contributions. Please ensure you have signed off your commits and followed the contribution guidelines.'
@@ -0,0 +1,16 @@
1
+ name: "Pull Request Labeler"
2
+ on:
3
+ - pull_request_target
4
+
5
+ permissions:
6
+ contents: read
7
+ pull-requests: write
8
+
9
+ jobs:
10
+ triage:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/labeler@v6
14
+ with:
15
+ repo-token: "${{ secrets.GITHUB_TOKEN }}"
16
+ sync-labels: true
@@ -0,0 +1,80 @@
1
+ name: '🔗 Check Broken Links'
2
+
3
+ on:
4
+ push:
5
+ branches: ['main']
6
+ paths:
7
+ - '**.md'
8
+ - 'docs/**'
9
+ pull_request:
10
+ branches: ['main']
11
+ paths:
12
+ - '**.md'
13
+ - 'docs/**'
14
+ schedule:
15
+ - cron: '0 0 * * 0'
16
+ workflow_dispatch:
17
+
18
+ concurrency:
19
+ group: ${{ github.workflow }}-${{ github.ref }}
20
+ cancel-in-progress: true
21
+
22
+ permissions:
23
+ contents: 'read'
24
+ issues: 'write'
25
+
26
+ jobs:
27
+ check-links:
28
+ runs-on: 'ubuntu-latest'
29
+ steps:
30
+ - name: 'Checkout'
31
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
32
+
33
+ - name: 'Check for broken links'
34
+ uses: lycheeverse/lychee-action@a8c4c7cb88f0c7386610c35eb25108e448569cb0 # v2.7.0
35
+ with:
36
+ args: >-
37
+ --verbose
38
+ --no-progress
39
+ --exclude '^https://github.com/.*/issues/new'
40
+ --exclude '^https://github.com/.*/compare/'
41
+ --exclude 'localhost'
42
+ --exclude '127.0.0.1'
43
+ --exclude 'file://'
44
+ --exclude 'npmjs.com'
45
+ --exclude 'unrealengine.com'
46
+ --exclude 'rustwasm.github.io'
47
+ --exclude 'github.com/modelcontextprotocol/sdk'
48
+
49
+ '**/*.md'
50
+ 'docs/**'
51
+ fail: true
52
+
53
+ - name: 'Create issue on failure'
54
+ if: failure() && github.event_name == 'schedule'
55
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
56
+ with:
57
+ github-token: '${{ secrets.GITHUB_TOKEN }}'
58
+ script: |
59
+ const title = '🔗 Broken links detected in documentation';
60
+ const body = `The weekly link check found broken links in the documentation.
61
+
62
+ Please review the [workflow run](${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}) for details.`;
63
+
64
+ const { data: issues } = await github.rest.issues.listForRepo({
65
+ owner: context.repo.owner,
66
+ repo: context.repo.repo,
67
+ state: 'open',
68
+ labels: 'area/docs'
69
+ });
70
+
71
+ const existingIssue = issues.find(i => i.title === title);
72
+ if (!existingIssue) {
73
+ await github.rest.issues.create({
74
+ owner: context.repo.owner,
75
+ repo: context.repo.repo,
76
+ title: title,
77
+ body: body,
78
+ labels: ['area/docs', 'type/bug']
79
+ });
80
+ }
@@ -0,0 +1,137 @@
1
+ name: '📏 Gemini PR Size Labeler'
2
+
3
+ on:
4
+ pull_request_target:
5
+ types: ['opened', 'reopened', 'synchronize']
6
+
7
+ permissions:
8
+ pull-requests: 'write'
9
+ contents: 'read'
10
+
11
+ concurrency:
12
+ group: '${{ github.workflow }}-${{ github.event.pull_request.number }}'
13
+ cancel-in-progress: true
14
+
15
+ jobs:
16
+ label-pr:
17
+ timeout-minutes: 5
18
+ runs-on: 'ubuntu-latest'
19
+ steps:
20
+ - name: 'Get PR diff stats'
21
+ id: 'diff_stats'
22
+ uses: 'actions/github-script@v8'
23
+ with:
24
+ github-token: '${{ secrets.GITHUB_TOKEN }}'
25
+ script: |
26
+ const { data: pr } = await github.rest.pulls.get({
27
+ owner: context.repo.owner,
28
+ repo: context.repo.repo,
29
+ pull_number: context.payload.pull_request.number
30
+ });
31
+
32
+ const additions = pr.additions || 0;
33
+ const deletions = pr.deletions || 0;
34
+ const totalChanges = additions + deletions;
35
+ const filesChanged = pr.changed_files || 0;
36
+
37
+ core.setOutput('total_changes', totalChanges);
38
+ core.setOutput('files_changed', filesChanged);
39
+ core.setOutput('additions', additions);
40
+ core.setOutput('deletions', deletions);
41
+
42
+ core.info(`PR #${pr.number}: +${additions} -${deletions} (${totalChanges} total) in ${filesChanged} files`);
43
+
44
+ - name: 'Determine size label'
45
+ id: 'size_label'
46
+ run: |
47
+ TOTAL=${{ steps.diff_stats.outputs.total_changes }}
48
+
49
+ if [ $TOTAL -lt 10 ]; then
50
+ echo "size_label=size/xs" >> $GITHUB_OUTPUT
51
+ elif [ $TOTAL -lt 50 ]; then
52
+ echo "size_label=size/s" >> $GITHUB_OUTPUT
53
+ elif [ $TOTAL -lt 200 ]; then
54
+ echo "size_label=size/m" >> $GITHUB_OUTPUT
55
+ elif [ $TOTAL -lt 1000 ]; then
56
+ echo "size_label=size/l" >> $GITHUB_OUTPUT
57
+ else
58
+ echo "size_label=size/xl" >> $GITHUB_OUTPUT
59
+ fi
60
+
61
+ - name: 'Apply size label'
62
+ uses: 'actions/github-script@v8'
63
+ env:
64
+ SIZE_LABEL: '${{ steps.size_label.outputs.size_label }}'
65
+ with:
66
+ github-token: '${{ secrets.GITHUB_TOKEN }}'
67
+ script: |
68
+ const prNumber = context.payload.pull_request.number;
69
+ const newLabel = process.env.SIZE_LABEL;
70
+
71
+ // Get current labels
72
+ const { data: currentLabels } = await github.rest.issues.listLabelsOnIssue({
73
+ owner: context.repo.owner,
74
+ repo: context.repo.repo,
75
+ issue_number: prNumber
76
+ });
77
+
78
+ // Remove old size labels
79
+ const sizeLabels = ['size/xs', 'size/s', 'size/m', 'size/l', 'size/xl'];
80
+ for (const label of currentLabels) {
81
+ if (sizeLabels.includes(label.name) && label.name !== newLabel) {
82
+ await github.rest.issues.removeLabel({
83
+ owner: context.repo.owner,
84
+ repo: context.repo.repo,
85
+ issue_number: prNumber,
86
+ name: label.name
87
+ });
88
+ core.info(`Removed old label: ${label.name}`);
89
+ }
90
+ }
91
+
92
+ // Add new size label
93
+ await github.rest.issues.addLabels({
94
+ owner: context.repo.owner,
95
+ repo: context.repo.repo,
96
+ issue_number: prNumber,
97
+ labels: [newLabel]
98
+ });
99
+ core.info(`Applied label: ${newLabel}`);
100
+
101
+ - name: 'Comment on large PRs'
102
+ if: steps.size_label.outputs.size_label == 'size/xl'
103
+ uses: 'actions/github-script@v8'
104
+ with:
105
+ github-token: '${{ secrets.GITHUB_TOKEN }}'
106
+ script: |
107
+ const prNumber = context.payload.pull_request.number;
108
+
109
+ // Check if we already commented
110
+ const { data: comments } = await github.rest.issues.listComments({
111
+ owner: context.repo.owner,
112
+ repo: context.repo.repo,
113
+ issue_number: prNumber
114
+ });
115
+
116
+ const botComment = comments.find(c =>
117
+ c.user && c.user.login && c.user.login.includes('[bot]') &&
118
+ c.body.includes('This pull request is quite large')
119
+ );
120
+
121
+ if (!botComment) {
122
+ await github.rest.issues.createComment({
123
+ owner: context.repo.owner,
124
+ repo: context.repo.repo,
125
+ issue_number: prNumber,
126
+ body: `## 📏 Large PR Detected
127
+
128
+ This pull request is quite large (1000+ lines changed), which can make reviewing challenging.
129
+
130
+ **Suggestions:**
131
+ - Consider breaking this into smaller, focused PRs
132
+ - Separate refactoring from new features
133
+ - Split bug fixes from feature additions
134
+
135
+ This helps reviewers provide better feedback and speeds up the merge process. Thank you! 🙏`
136
+ });
137
+ }