meltygui 0.1.0__py3-none-any.whl

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 (372) hide show
  1. meltygui/__init__.py +107 -0
  2. meltygui/accounts/__init__.py +0 -0
  3. meltygui/accounts/internet_accounts.py +1355 -0
  4. meltygui/chat/__init__.py +91 -0
  5. meltygui/chat/activity.py +75 -0
  6. meltygui/chat/backends.py +36 -0
  7. meltygui/chat/chat_interface.py +732 -0
  8. meltygui/chat/chat_proxy.py +352 -0
  9. meltygui/chat/codex_proxy.py +592 -0
  10. meltygui/chat/codex_settings.py +100 -0
  11. meltygui/chat/codex_transport.py +60 -0
  12. meltygui/chat/command_parser.py +204 -0
  13. meltygui/chat/images.py +227 -0
  14. meltygui/chat/messages.py +417 -0
  15. meltygui/chat/metadata.py +139 -0
  16. meltygui/chat/writer_locks.py +64 -0
  17. meltygui/code/__init__.py +0 -0
  18. meltygui/code/basic_converters.py +533 -0
  19. meltygui/code/chain_converters.py +2111 -0
  20. meltygui/code/code_checks.py +2209 -0
  21. meltygui/code/core_syntax.py +1430 -0
  22. meltygui/code/file_converters.py +1933 -0
  23. meltygui/code/fileref.py +702 -0
  24. meltygui/code/hotswap_guard.py +144 -0
  25. meltygui/code/libcst_conversion.py +9724 -0
  26. meltygui/code/live_instrument.py +392 -0
  27. meltygui/code/live_view.py +2490 -0
  28. meltygui/code/melty_scan.py +2684 -0
  29. meltygui/code/new_codecs.py +1255 -0
  30. meltygui/code/new_converters.py +3017 -0
  31. meltygui/code/project_code.py +278 -0
  32. meltygui/code/source_context.py +63 -0
  33. meltygui/code/symbol_roster.py +1588 -0
  34. meltygui/code/syntax_check.py +34 -0
  35. meltygui/code/syntax_check_worker.py +114 -0
  36. meltygui/completion/__init__.py +0 -0
  37. meltygui/completion/fim.py +1232 -0
  38. meltygui/completion/fim_context.py +481 -0
  39. meltygui/completion/providers/__init__.py +0 -0
  40. meltygui/completion/providers/anthropic_oauth.py +446 -0
  41. meltygui/completion/providers/anthropic_requests.py +69 -0
  42. meltygui/completion/providers/claude.py +203 -0
  43. meltygui/completion/providers/claude_usage.py +499 -0
  44. meltygui/completion/providers/codex_accounts.py +180 -0
  45. meltygui/completion/providers/copilot.py +617 -0
  46. meltygui/completion/providers/oauth_popup.py +220 -0
  47. meltygui/completion/providers/ollama.py +320 -0
  48. meltygui/completion/providers/profiles.py +23 -0
  49. meltygui/core/README.md +88 -0
  50. meltygui/core/__init__.py +1 -0
  51. meltygui/core/automation/__init__.py +1 -0
  52. meltygui/core/automation/action_core.py +153 -0
  53. meltygui/core/automation/collection_action.py +45 -0
  54. meltygui/core/automation/mcp_eval.py +167 -0
  55. meltygui/core/automation/mcp_hotswap.py +107 -0
  56. meltygui/core/automation/mcp_query.py +552 -0
  57. meltygui/core/automation/mcp_server.py +657 -0
  58. meltygui/core/automation/orchestration_core.py +2636 -0
  59. meltygui/core/automation/query_core.py +124 -0
  60. meltygui/core/automation/search_core.py +26 -0
  61. meltygui/core/automation/selector_core.py +340 -0
  62. meltygui/core/automation/value_core.py +1752 -0
  63. meltygui/core/cache/__init__.py +1 -0
  64. meltygui/core/cache/cache_diagnostics.py +0 -0
  65. meltygui/core/cache/invalidation_decoration.py +153 -0
  66. meltygui/core/cache/invalidation_tracker.py +43 -0
  67. meltygui/core/cache/tile_cache.py +5968 -0
  68. meltygui/core/conversion/__init__.py +1 -0
  69. meltygui/core/conversion/bubbling.py +599 -0
  70. meltygui/core/conversion/cache_tree.py +188 -0
  71. meltygui/core/conversion/chain.py +113 -0
  72. meltygui/core/conversion/converter_register.py +145 -0
  73. meltygui/core/conversion/data_decoration.py +67 -0
  74. meltygui/core/conversion/dict_conversion.py +1815 -0
  75. meltygui/core/conversion/dict_conversion_util.py +177 -0
  76. meltygui/core/conversion/dynamic_obj.py +89 -0
  77. meltygui/core/conversion/graph_compare.py +183 -0
  78. meltygui/core/conversion/load_save_v2.py +1032 -0
  79. meltygui/core/conversion/missing_saved_class.py +39 -0
  80. meltygui/core/conversion/path_finder.py +606 -0
  81. meltygui/core/conversion/render_host.py +1083 -0
  82. meltygui/core/core_render.py +6537 -0
  83. meltygui/core/definition_hotswap.py +231 -0
  84. meltygui/core/diagnostics/__init__.py +1 -0
  85. meltygui/core/diagnostics/attribute_churn.py +38 -0
  86. meltygui/core/diagnostics/fps_counter.py +39 -0
  87. meltygui/core/diagnostics/gpu_frame_timer.py +103 -0
  88. meltygui/core/diagnostics/inspection_core.py +169 -0
  89. meltygui/core/diagnostics/monitor_core.py +105 -0
  90. meltygui/core/diagnostics/notifications.py +706 -0
  91. meltygui/core/diagnostics/perf_trace.py +281 -0
  92. meltygui/core/diagnostics/profile_decoration.py +88 -0
  93. meltygui/core/diagnostics/resize_trace.py +62 -0
  94. meltygui/core/diagnostics/screenshot_core.py +247 -0
  95. meltygui/core/diagnostics/session_status.py +98 -0
  96. meltygui/core/diagnostics/trace_core.py +445 -0
  97. meltygui/core/files/__init__.py +1 -0
  98. meltygui/core/files/file_core.py +208 -0
  99. meltygui/core/files/file_explorer_core.py +104 -0
  100. meltygui/core/files/file_tree_core.py +198 -0
  101. meltygui/core/files/file_watch_core.py +43 -0
  102. meltygui/core/files/import_graph_core.py +43 -0
  103. meltygui/core/files/metadata_core.py +51 -0
  104. meltygui/core/graphics/__init__.py +1 -0
  105. meltygui/core/graphics/cuda_context_core.py +166 -0
  106. meltygui/core/graphics/cuda_interop_core.py +136 -0
  107. meltygui/core/graphics/cuda_kernel_core.py +91 -0
  108. meltygui/core/graphics/framebuffer_recorder.py +337 -0
  109. meltygui/core/graphics/gl_state.py +658 -0
  110. meltygui/core/graphics/lut_core.py +52 -0
  111. meltygui/core/graphics/overlay_renderer.py +984 -0
  112. meltygui/core/graphics/scene_target.py +180 -0
  113. meltygui/core/graphics/screenshot.py +439 -0
  114. meltygui/core/graphics/shader_func.py +478 -0
  115. meltygui/core/graphics/tensor_core.py +45 -0
  116. meltygui/core/graphics/text_texture.py +329 -0
  117. meltygui/core/graphics/wayland_color.py +635 -0
  118. meltygui/core/input/__init__.py +1 -0
  119. meltygui/core/input/collision.py +165 -0
  120. meltygui/core/input/drag_drop_core.py +1525 -0
  121. meltygui/core/input/hypr_left_drag.py +323 -0
  122. meltygui/core/input/input_core.py +245 -0
  123. meltygui/core/input/input_handler.py +1101 -0
  124. meltygui/core/input/mouse_cursor.py +355 -0
  125. meltygui/core/input/pynput_backend.py +1054 -0
  126. meltygui/core/input/space_mouse.py +338 -0
  127. meltygui/core/input/touchpad_backend.py +393 -0
  128. meltygui/core/input/view_selection.py +177 -0
  129. meltygui/core/layout/__init__.py +1 -0
  130. meltygui/core/layout/column_core.py +2153 -0
  131. meltygui/core/layout/cursor_core.py +161 -0
  132. meltygui/core/layout/dropdown_core.py +278 -0
  133. meltygui/core/layout/edge_constraints.py +155 -0
  134. meltygui/core/layout/grid_core.py +117 -0
  135. meltygui/core/layout/header_core.py +23 -0
  136. meltygui/core/layout/header_runtime.py +67 -0
  137. meltygui/core/layout/layout_core.py +87 -0
  138. meltygui/core/layout/tile_manager_core.py +591 -0
  139. meltygui/core/melty.py +6726 -0
  140. meltygui/core/module_map.json +896 -0
  141. meltygui/core/module_names.py +19 -0
  142. meltygui/core/rendering/__init__.py +1 -0
  143. meltygui/core/rendering/core_decoration.py +431 -0
  144. meltygui/core/rendering/core_render_helpers.py +328 -0
  145. meltygui/core/rendering/func_metadata.py +398 -0
  146. meltygui/core/rendering/mode.py +818 -0
  147. meltygui/core/rendering/mode_defaults.py +41 -0
  148. meltygui/core/rendering/modes.py +136 -0
  149. meltygui/core/rendering/parameter_core.py +1665 -0
  150. meltygui/core/rendering/render_dispatch.py +1891 -0
  151. meltygui/core/rendering/render_funcs.py +273 -0
  152. meltygui/core/rendering/shaped.py +312 -0
  153. meltygui/core/rendering/window_decoration.py +25 -0
  154. meltygui/core/runtime/__init__.py +1 -0
  155. meltygui/core/runtime/app.py +735 -0
  156. meltygui/core/runtime/app_session.py +140 -0
  157. meltygui/core/runtime/background.py +564 -0
  158. meltygui/core/runtime/extensions.py +53 -0
  159. meltygui/core/runtime/gc_manager.py +1163 -0
  160. meltygui/core/runtime/lifecycle.py +21 -0
  161. meltygui/core/runtime/paths.py +27 -0
  162. meltygui/core/runtime/settings.py +14 -0
  163. meltygui/core/runtime/singleton.py +16 -0
  164. meltygui/core/runtime/thread_safe_bool.py +24 -0
  165. meltygui/core/runtime/thread_signal.py +30 -0
  166. meltygui/core/runtime/toggles.py +3115 -0
  167. meltygui/core/services/__init__.py +1 -0
  168. meltygui/core/services/account_core.py +10 -0
  169. meltygui/core/services/chat_core.py +19 -0
  170. meltygui/core/services/claude_terminal_core.py +346 -0
  171. meltygui/core/services/terminal_core.py +458 -0
  172. meltygui/core/services/terminal_runtime.py +78 -0
  173. meltygui/core/styling/__init__.py +1 -0
  174. meltygui/core/styling/color_core.py +46 -0
  175. meltygui/core/styling/fonts.py +639 -0
  176. meltygui/core/styling/global_style.py +338 -0
  177. meltygui/core/styling/style.py +198 -0
  178. meltygui/core/styling/style_core.py +522 -0
  179. meltygui/core/styling/warm_start.py +149 -0
  180. meltygui/core/windowing/__init__.py +1 -0
  181. meltygui/core/windowing/backends/PYIMGUI_LICENSE +28 -0
  182. meltygui/core/windowing/backends/__init__.py +1 -0
  183. meltygui/core/windowing/backends/imgui_renderer.py +138 -0
  184. meltygui/core/windowing/backends/native_wayland.py +850 -0
  185. meltygui/core/windowing/backends/protocols/xdg-decoration-unstable-v1.xml +156 -0
  186. meltygui/core/windowing/backends/protocols/xdg-shell.xml +1420 -0
  187. meltygui/core/windowing/backends/wayland_protocol.py +101 -0
  188. meltygui/core/windowing/dock_core.py +182 -0
  189. meltygui/core/windowing/frame_geometry.py +42 -0
  190. meltygui/core/windowing/geometry_feed.py +864 -0
  191. meltygui/core/windowing/glfw_utils.py +1343 -0
  192. meltygui/core/windowing/os_frame.py +1552 -0
  193. meltygui/core/windowing/surface.py +643 -0
  194. meltygui/core/windowing/titlebar.py +1560 -0
  195. meltygui/core/windowing/titlebar_buttons.py +281 -0
  196. meltygui/core/windowing/wayland_move.py +932 -0
  197. meltygui/core/windowing/window_api.py +62 -0
  198. meltygui/core/windowing/window_constants.py +339 -0
  199. meltygui/core/windowing/window_visibility.py +162 -0
  200. meltygui/debug/__init__.py +0 -0
  201. meltygui/debug/app_view_utils.py +9 -0
  202. meltygui/editor/__init__.py +0 -0
  203. meltygui/editor/bash_syntax.py +30 -0
  204. meltygui/editor/code_line_fast.py +152 -0
  205. meltygui/editor/diff.py +139 -0
  206. meltygui/editor/external_changes.py +159 -0
  207. meltygui/editor/file_header.py +41 -0
  208. meltygui/editor/live_usage.py +169 -0
  209. meltygui/editor/live_view_views.py +1803 -0
  210. meltygui/editor/pending_save.py +1351 -0
  211. meltygui/editor/roster_tints.py +547 -0
  212. meltygui/editor/source_preview.py +16 -0
  213. meltygui/editor/source_tools.py +10 -0
  214. meltygui/editor/source_ui.py +70 -0
  215. meltygui/editor/spell_check.py +77 -0
  216. meltygui/editor/text_editor.py +9076 -0
  217. meltygui/editor/usage_picker.py +538 -0
  218. meltygui/events/__init__.py +0 -0
  219. meltygui/events/example.py +118 -0
  220. meltygui/examples/__init__.py +0 -0
  221. meltygui/examples/columns_demo.py +33 -0
  222. meltygui/examples/columns_window_demo.py +60 -0
  223. meltygui/examples/context_menu_demo.py +24 -0
  224. meltygui/examples/context_menu_window_demo.py +49 -0
  225. meltygui/examples/gui_playground.py +127 -0
  226. meltygui/examples/live_view_playground.py +256 -0
  227. meltygui/examples/lora.py +43 -0
  228. meltygui/examples/lora_data.py +59 -0
  229. meltygui/examples/lora_policies.py +67 -0
  230. meltygui/examples/mode_demo.py +49 -0
  231. meltygui/examples/modifies_demo.py +119 -0
  232. meltygui/examples/scalar_policies.py +60 -0
  233. meltygui/examples/style_layouts.py +149 -0
  234. meltygui/examples/tile_manager_demo.py +74 -0
  235. meltygui/examples/tint_demo.py +160 -0
  236. meltygui/examples/tint_functions.py +56 -0
  237. meltygui/examples/trace_demo.py +88 -0
  238. meltygui/examples/two_windows.py +36 -0
  239. meltygui/files/__init__.py +0 -0
  240. meltygui/files/fast_file_explorer.py +439 -0
  241. meltygui/gnome_extension/lsd-window-geometry@latent-descent/extension.js +237 -0
  242. meltygui/gnome_extension/lsd-window-geometry@latent-descent/lsd-window-geometry@latent-descent.iml +9 -0
  243. meltygui/gnome_extension/lsd-window-geometry@latent-descent/metadata.json +7 -0
  244. meltygui/graphics/__init__.py +6 -0
  245. meltygui/graphics/base.py +85 -0
  246. meltygui/graphics/examples.py +507 -0
  247. meltygui/graphics/executor.py +520 -0
  248. meltygui/graphics/filter.py +667 -0
  249. meltygui/graphics/filter.pyi +856 -0
  250. meltygui/graphics/generate_stubs.py +22 -0
  251. meltygui/graphics/registry.py +203 -0
  252. meltygui/graphics/shader_compiler.py +155 -0
  253. meltygui/graphics/shaders.py +1302 -0
  254. meltygui/graphics/stub_generator.py +250 -0
  255. meltygui/graphics/texture_manager.py +170 -0
  256. meltygui/graphics/texture_min_max.py +295 -0
  257. meltygui/hdr_color.py +757 -0
  258. meltygui/image_load.py +308 -0
  259. meltygui/model/__init__.py +1 -0
  260. meltygui/model/account_model.py +142 -0
  261. meltygui/model/camera_model.py +159 -0
  262. meltygui/model/chat_model.py +86 -0
  263. meltygui/model/code_model.py +62 -0
  264. meltygui/model/code_proxy_model.py +876 -0
  265. meltygui/model/collection_model.py +41 -0
  266. meltygui/model/color_model.py +127 -0
  267. meltygui/model/cuda_tensor_model.py +36 -0
  268. meltygui/model/cuda_texture_model.py +149 -0
  269. meltygui/model/dropdown_model.py +137 -0
  270. meltygui/model/file_metadata_model.py +73 -0
  271. meltygui/model/file_model.py +289 -0
  272. meltygui/model/format_model.py +390 -0
  273. meltygui/model/graph_model.py +98 -0
  274. meltygui/model/icon_model.py +1024 -0
  275. meltygui/model/import_graph_model.py +468 -0
  276. meltygui/model/layout_model.py +15 -0
  277. meltygui/model/lut_model.py +266 -0
  278. meltygui/model/search_model.py +173 -0
  279. meltygui/model/tensor_model.py +402 -0
  280. meltygui/model/terminal_model.py +329 -0
  281. meltygui/model/texture_model.py +146 -0
  282. meltygui/model/tile_model.py +24 -0
  283. meltygui/model/trace_model.py +198 -0
  284. meltygui/model/trace_report_model.py +146 -0
  285. meltygui/models/__init__.py +0 -0
  286. meltygui/models/file_meta.py +613 -0
  287. meltygui/models/function_console.py +184 -0
  288. meltygui/models/orchestration.py +48 -0
  289. meltygui/pbr.py +1576 -0
  290. meltygui/png_unfilter.c +49 -0
  291. meltygui/resources/JetBrainsMono-Regular.ttf +0 -0
  292. meltygui/resources/THIRD_PARTY_NOTICES.md +21 -0
  293. meltygui/resources/dejavu/DejaVuSans-Bold.ttf +0 -0
  294. meltygui/resources/dejavu/DejaVuSans-ExtraLight.ttf +0 -0
  295. meltygui/resources/dejavu/DejaVuSans.ttf +0 -0
  296. meltygui/resources/dejavu/LICENSE.txt +78 -0
  297. meltygui/resources/fontawesome-LICENSE.txt +121 -0
  298. meltygui/resources/fontawesome-webfont.ttf +0 -0
  299. meltygui/resources/hdri/studio_small_09_1k.hdr +0 -0
  300. meltygui/resources/jetbrains-weights/JetBrainsMono-Bold.ttf +0 -0
  301. meltygui/resources/jetbrains-weights/JetBrainsMono-ExtraBold.ttf +0 -0
  302. meltygui/resources/jetbrains-weights/JetBrainsMono-ExtraLight.ttf +0 -0
  303. meltygui/resources/jetbrains-weights/JetBrainsMono-Light.ttf +0 -0
  304. meltygui/resources/jetbrains-weights/JetBrainsMono-Medium.ttf +0 -0
  305. meltygui/resources/jetbrains-weights/JetBrainsMono-SemiBold.ttf +0 -0
  306. meltygui/resources/jetbrains-weights/JetBrainsMono-Thin.ttf +0 -0
  307. meltygui/resources/jetbrains-weights/OFL.txt +93 -0
  308. meltygui/resources/jetbrains-weights/README.md +2 -0
  309. meltygui/state/__init__.py +0 -0
  310. meltygui/state/account_state.py +22 -0
  311. meltygui/state/animation_state.py +97 -0
  312. meltygui/state/annotation_state.py +22 -0
  313. meltygui/state/chat_state.py +36 -0
  314. meltygui/state/code_state.py +10 -0
  315. meltygui/state/core_enums.py +59 -0
  316. meltygui/state/core_markers.py +115 -0
  317. meltygui/state/core_undo.py +1075 -0
  318. meltygui/state/file_state.py +75 -0
  319. meltygui/state/graph_state.py +26 -0
  320. meltygui/state/inspection_state.py +47 -0
  321. meltygui/state/menu_state.py +10 -0
  322. meltygui/state/model_enums.py +11 -0
  323. meltygui/state/new_core_model.py +2394 -0
  324. meltygui/state/orchestration_state.py +14 -0
  325. meltygui/state/query_state.py +24 -0
  326. meltygui/state/tensor_state.py +10 -0
  327. meltygui/state/terminal_state.py +23 -0
  328. meltygui/state/trace_state.py +32 -0
  329. meltygui/state/voxel_state.py +12 -0
  330. meltygui/text_index.py +816 -0
  331. meltygui/utils/__init__.py +0 -0
  332. meltygui/utils/jump_to_code.py +344 -0
  333. meltygui/utils/pkl_inspect.py +90 -0
  334. meltygui/utils/render_utils.py +1419 -0
  335. meltygui/view/__init__.py +1 -0
  336. meltygui/view/account_view.py +524 -0
  337. meltygui/view/action_view.py +73 -0
  338. meltygui/view/chat_decoration_view.py +112 -0
  339. meltygui/view/chat_view.py +1703 -0
  340. meltygui/view/code_view.py +2677 -0
  341. meltygui/view/collection_view.py +1185 -0
  342. meltygui/view/color_view.py +824 -0
  343. meltygui/view/control_view.py +559 -0
  344. meltygui/view/decoration_view.py +439 -0
  345. meltygui/view/diagnostic_view.py +177 -0
  346. meltygui/view/dropdown_view.py +1082 -0
  347. meltygui/view/file_view.py +1599 -0
  348. meltygui/view/graph_cuda_view.py +105 -0
  349. meltygui/view/graph_view.py +882 -0
  350. meltygui/view/header_view.py +848 -0
  351. meltygui/view/input_view.py +238 -0
  352. meltygui/view/inspection_view.py +1783 -0
  353. meltygui/view/layout_view.py +596 -0
  354. meltygui/view/lut_view.py +45 -0
  355. meltygui/view/menu_view.py +212 -0
  356. meltygui/view/orchestration_view.py +658 -0
  357. meltygui/view/query_view.py +118 -0
  358. meltygui/view/search_view.py +342 -0
  359. meltygui/view/tab_view.py +258 -0
  360. meltygui/view/tensor_view.py +430 -0
  361. meltygui/view/terminal_view.py +355 -0
  362. meltygui/view/text_view.py +8031 -0
  363. meltygui/view/texture_view.py +480 -0
  364. meltygui/view/tile_view.py +38 -0
  365. meltygui/view/trace_view.py +923 -0
  366. meltygui/view/voxel_cuda_view.py +824 -0
  367. meltygui/view/voxel_view.py +1860 -0
  368. meltygui/view/window_view.py +111 -0
  369. meltygui-0.1.0.dist-info/METADATA +143 -0
  370. meltygui-0.1.0.dist-info/RECORD +372 -0
  371. meltygui-0.1.0.dist-info/WHEEL +4 -0
  372. meltygui-0.1.0.dist-info/licenses/LICENSE +202 -0
@@ -0,0 +1,153 @@
1
+ """Actions window — renders Toggles' sibling Actions class (toggles.py), the
2
+ general-purpose stash for app triggers ("New file", "New Render Function").
3
+
4
+ Also registers the "Actions" global-search category: every function on the
5
+ Actions class is a hit, and activating one pops up the ActionRunner window —
6
+ its parameters (seeded from the function signature) as editable rows plus a
7
+ Run button that calls the function."""
8
+
9
+ import inspect
10
+ import types
11
+ from pathlib import Path
12
+
13
+ import meltygui_imgui as imgui
14
+
15
+ from meltygui.core.melty import Melty
16
+ from meltygui.core.rendering.modes import Modes
17
+ from meltygui.core.diagnostics.notifications import notify
18
+ from meltygui.core.runtime.toggles import Actions
19
+ from meltygui.core.windowing.glfw_utils import request_render
20
+ from meltygui.core.core_render import render_func
21
+ from meltygui.core.rendering.core_decoration import Core
22
+ from meltygui.core.rendering.core_decoration import defaults
23
+ from meltygui.core.rendering.window_decoration import window
24
+ from meltygui.editor.source_ui import SearchHit
25
+ from meltygui.editor.source_ui import _category_tint
26
+ from meltygui.core.runtime.extensions import jump_to_symbol as _jump_to_symbol_def
27
+ from meltygui.core.rendering.render_dispatch import draw_any
28
+
29
+
30
+ def _action_funcs():
31
+ """(name, function, icon) for every public function on Actions, definition
32
+ order. Reads vars() live each call so a hotswapped/added action shows up
33
+ without any cache to invalidate. The icon is the @defaults(icon=...)
34
+ registration — keyed by whatever object @defaults decorated, which is the
35
+ staticmethod wrapper when it sits outside @staticmethod and the raw
36
+ function when inside, so both keys are tried."""
37
+ out = []
38
+ for name, member in vars(Actions).items():
39
+ if name.startswith("_"):
40
+ continue
41
+ fn = member.__func__ if isinstance(member, (staticmethod, classmethod)) else member
42
+ if not isinstance(fn, types.FunctionType):
43
+ continue
44
+ icon = None
45
+ for key in (member, fn):
46
+ icon = Melty.default_kwargs_by_type.get(key, {}).get("icon")
47
+ if icon:
48
+ break
49
+ out.append((name, fn, icon))
50
+ return out
51
+
52
+
53
+ def _sig_label(name, fn):
54
+ """`new_render_func(name='draw_other')` — the search-row label, so a hit
55
+ shows what inputs the runner will ask for."""
56
+ parts = []
57
+ for pname, p in inspect.signature(fn).parameters.items():
58
+ if p.default is not inspect.Parameter.empty:
59
+ parts.append(f"{pname}={p.default!r}")
60
+ else:
61
+ parts.append(pname)
62
+ return f"{name}({', '.join(parts)})"
63
+
64
+
65
+ def _seed_params(fn):
66
+ """Initial editable values for a function's parameters: the signature
67
+ default where there is one, a fresh instance of the annotation type
68
+ otherwise (str -> "", int -> 0, ...), else an empty string."""
69
+ params = {}
70
+ for pname, p in inspect.signature(fn).parameters.items():
71
+ if p.default is not inspect.Parameter.empty:
72
+ params[pname] = p.default
73
+ elif isinstance(p.annotation, type):
74
+ try:
75
+ params[pname] = p.annotation()
76
+ except Exception:
77
+ params[pname] = ""
78
+ else:
79
+ params[pname] = ""
80
+ return params
81
+
82
+
83
+ def activate_action(fn):
84
+ """A search hit's activation: an action with parameters opens the
85
+ ActionRunner to fill them in; a parameterless one (screenshot,
86
+ claude_terminal) just RUNS — there is nothing to ask, and a popup with
87
+ only a Run button was a dead click."""
88
+ if not inspect.signature(fn).parameters:
89
+ try:
90
+ result = fn()
91
+ except Exception as e:
92
+ notify(f"Actions.{fn.__name__} failed: {e}", tag="actions")
93
+ else:
94
+ notify(f"Actions.{fn.__name__} -> {result!r}" if result is not None
95
+ else f"Actions.{fn.__name__} ran", tag="actions")
96
+ request_render()
97
+ return
98
+ open_action_runner(fn)
99
+
100
+
101
+ def open_action_runner(fn):
102
+ """Point the ActionRunner window at `fn` and summon it next to the search
103
+ window (the same come-to-you placement window hits use)."""
104
+ ActionRunner.action = fn
105
+ ActionRunner.params = _seed_params(fn)
106
+ ActionRunner._focus_requested = True
107
+ ds = Core.melty.open_window("ActionRunner")
108
+ if ds is not None:
109
+ gs = Core.melty.find_window("GlobalSearch")
110
+ if gs is not None and gs.abs_left is not None:
111
+ Core.melty.summon_window(ds, gs.abs_left, gs.abs_top)
112
+ Core.melty.focused_ds = ds
113
+ # The action and params changed outside the window's body - a cached
114
+ # blit would keep showing the previous action.
115
+ ds.invalidate()
116
+ request_render()
117
+
118
+
119
+ def _close_action_runner():
120
+ """Close the runner and release any text focus a param field holds — the
121
+ shared exit for the title-row X, Esc (draw_main's root handler) and a
122
+ successful run."""
123
+ win = Core.melty.find_window("ActionRunner")
124
+ if win is not None:
125
+ win.closed = True
126
+ Core.melty.text_focused_ds = None
127
+ request_render()
128
+
129
+
130
+ def _run_action(input_value):
131
+ """Call the runner's action with the edited params. A successful run
132
+ closes the window; an error keeps it up (with a notification) so the
133
+ inputs can be fixed."""
134
+ fn = input_value.action
135
+ try:
136
+ result = fn(**dict(input_value.params))
137
+ except Exception as e:
138
+ notify(f"Actions.{fn.__name__} failed: {e}", tag="actions")
139
+ else:
140
+ notify(f"Actions.{fn.__name__} -> {result!r}" if result is not None
141
+ else f"Actions.{fn.__name__} ran", tag="actions")
142
+ _close_action_runner()
143
+
144
+
145
+ from meltygui.view.action_view import draw_action_runner
146
+
147
+
148
+ @window(view_func=draw_action_runner, mode=Modes.WINDOW_AUTO_FIT, always_on_top=True)
149
+ @defaults(tint=(0.92, 0.58, 0.25))
150
+ class ActionRunner:
151
+ action = None # the Actions function the window is parameterizing
152
+ params = {} # name -> value being edited, seeded from the signature
153
+ _focus_requested = False # one-shot: focus the first str param next frame
@@ -0,0 +1,45 @@
1
+ from enum import Enum
2
+
3
+
4
+ class OperationType(Enum):
5
+ COPY = 'copy'
6
+ MOVE = 'move'
7
+ ADD = 'add'
8
+ DELETE = 'delete'
9
+ NAME_CHANGE = 'name_change'
10
+
11
+
12
+ class CollectionAction:
13
+ def __init__(self,
14
+ target_unique=None,
15
+ source_unique=None,
16
+ target_tag=None,
17
+ target_key=None,
18
+ source_key=None,
19
+ source_collection=None,
20
+ target_collection=None,
21
+ operation=OperationType.MOVE):
22
+ self.target_unique = target_unique
23
+ self.target_key = target_key
24
+ self.target_tag = target_tag
25
+ self.target_collection = target_collection
26
+ self.target_draw_state = None
27
+
28
+ self.source_unique = source_unique
29
+ self.source_key = source_key
30
+ self.source_collection = source_collection
31
+ self.source_draw_state = None
32
+
33
+ self.operation = operation
34
+ self.class_move = False
35
+ self.target_class = None
36
+
37
+ def print(self):
38
+ print(f"CollectionAction: op {self.operation}\n"
39
+ f"source_key {self.source_key}\n"
40
+ f"source_unique {self.source_unique}\n"
41
+ f"target_key {self.target_key}\n"
42
+ f"target_unique {self.target_unique}\n"
43
+ f"target_tag {self.target_tag}\n"
44
+ f"source collection {type(self.source_collection).__name__}\n"
45
+ f"target collection {type(self.target_collection).__name__}")
@@ -0,0 +1,167 @@
1
+ """Evaluate Python in the live launcher process via MCP.
2
+
3
+ When a studio session is running the snippet runs on the render thread (GL
4
+ context current, safe to read/poke Melty + imgui state) via a post_frame
5
+ hand-off, mirroring screenshot.py; otherwise it runs inline on the caller's
6
+ thread (fine for pure-Python inspection of launcher/server state).
7
+
8
+ `Melty` and `server`/`model_server` are pre-bound; import anything else you
9
+ need. A trailing expression's repr is returned alongside captured stdout/stderr.
10
+
11
+ This is arbitrary in-process code execution — intended for inspecting and
12
+ poking live state while iterating.
13
+ """
14
+
15
+ import threading
16
+
17
+ _pending = []
18
+ _lock = threading.Lock()
19
+
20
+
21
+ def _build_namespace(extra=None):
22
+ ns = {"__builtins__": __builtins__}
23
+ try:
24
+ from meltygui.core.melty import Melty
25
+ ns["Melty"] = Melty
26
+ # Conveniences reachable from Melty: the studio (vis) and the root
27
+ # AppModel (vis.root). Everything here derives from Melty.
28
+ vis = getattr(Melty, "vis", None)
29
+ if vis is not None:
30
+ ns["vis"] = vis
31
+ root = getattr(vis, "root", None)
32
+ if root is not None:
33
+ ns["app"] = root
34
+ ns["root"] = root
35
+ except Exception:
36
+ pass
37
+ if extra:
38
+ ns.update(extra)
39
+ return ns
40
+
41
+
42
+ def _run_code(code, extra=None):
43
+ """Execute `code`, returning (stdout_text, result_repr_or_None, error_or_None).
44
+
45
+ Tries to evaluate it as a single expression first (to capture a value);
46
+ falls back to exec for statements.
47
+ """
48
+ import io
49
+ import contextlib
50
+ import traceback
51
+
52
+ ns = _build_namespace(extra)
53
+ buf = io.StringIO()
54
+ result = None
55
+ error = None
56
+ with contextlib.redirect_stdout(buf), contextlib.redirect_stderr(buf):
57
+ try:
58
+ try:
59
+ compiled = compile(code, "<eval_python>", "eval")
60
+ except SyntaxError:
61
+ compiled = None
62
+ if compiled is not None:
63
+ value = eval(compiled, ns)
64
+ if value is not None:
65
+ result = repr(value)
66
+ else:
67
+ exec(compile(code, "<eval_python>", "exec"), ns)
68
+ except Exception:
69
+ error = traceback.format_exc()
70
+ return buf.getvalue(), result, error
71
+
72
+
73
+ def request_eval(code, model_server, timeout=10.0):
74
+ """Run `code` and return formatted text (where it ran + stdout + result/error)."""
75
+ extra = {"server": model_server, "model_server": model_server}
76
+
77
+ studio_running = False
78
+ try:
79
+ studio_running = model_server._studio_running()
80
+ except Exception:
81
+ pass
82
+
83
+ if not studio_running:
84
+ out, result, error = _run_code(code, extra)
85
+ return _format(out, result, error, where="launcher thread (no studio)")
86
+
87
+ req = {"code": code, "extra": extra, "event": threading.Event(),
88
+ "out": "", "result": None, "error": None}
89
+ with _lock:
90
+ _pending.append(req)
91
+ try:
92
+ from meltygui.core.windowing.glfw_utils import request_render
93
+ request_render() # force a frame so the request is served soon
94
+ except Exception:
95
+ pass
96
+
97
+ if not req["event"].wait(timeout):
98
+ with _lock:
99
+ if req in _pending:
100
+ _pending.remove(req)
101
+ return f"timed out after {timeout:.0f}s waiting for the render thread"
102
+ return _format(req["out"], req["result"], req["error"], where="render thread")
103
+
104
+
105
+ def request_call(fn, model_server, timeout=10.0):
106
+ """Run the no-arg callable `fn` on the render thread (inline when no
107
+ studio is running) and return `(result, error_text)`. The typed MCP
108
+ query tools (mcp_query.py) ride this instead of eval_python's source
109
+ string: same queue, same post_frame drain, a Python value back."""
110
+ import traceback
111
+ studio_running = False
112
+ try:
113
+ studio_running = model_server._studio_running()
114
+ except Exception:
115
+ pass
116
+ if not studio_running:
117
+ try:
118
+ return fn(), None
119
+ except Exception:
120
+ return None, traceback.format_exc()
121
+
122
+ req = {"fn": fn, "event": threading.Event(), "result": None, "error": None}
123
+ with _lock:
124
+ _pending.append(req)
125
+ try:
126
+ from meltygui.core.windowing.glfw_utils import request_render
127
+ request_render()
128
+ except Exception:
129
+ pass
130
+ if not req["event"].wait(timeout):
131
+ with _lock:
132
+ if req in _pending:
133
+ _pending.remove(req)
134
+ return None, f"timed out after {timeout:.0f}s waiting for the render thread"
135
+ return req["result"], req["error"]
136
+
137
+
138
+ def process_evals():
139
+ """Run pending eval requests on the render thread. Call from post_frame."""
140
+ import traceback
141
+ with _lock:
142
+ if not _pending:
143
+ return
144
+ reqs = _pending[:]
145
+ _pending.clear()
146
+ for req in reqs:
147
+ if "fn" in req:
148
+ try:
149
+ req["result"] = req["fn"]()
150
+ except Exception:
151
+ req["error"] = traceback.format_exc()
152
+ else:
153
+ req["out"], req["result"], req["error"] = _run_code(req["code"], req["extra"])
154
+ req["event"].set()
155
+
156
+
157
+ def _format(out, result, error, where):
158
+ parts = [f"[ran on {where}]"]
159
+ if out.strip():
160
+ parts.append("stdout:\n" + out.rstrip())
161
+ if result is not None:
162
+ parts.append("result: " + result)
163
+ if error:
164
+ parts.append("error:\n" + error.rstrip())
165
+ if len(parts) == 1:
166
+ parts.append("(no output)")
167
+ return "\n".join(parts)
@@ -0,0 +1,107 @@
1
+ """Hotswap a project source file into the running process, for the MCP server.
2
+
3
+ Lets an MCP caller apply code edits to a live studio without a full restart. It
4
+ reuses the editor's hotswap machinery rather than re-implementing it:
5
+
6
+ * ``_recompile_module`` (file_converters.py) compiles the new source and patches
7
+ every function/class in the module **in place** — existing references (imported
8
+ names, live instances) keep working because their ``__code__`` is overwritten
9
+ rather than the objects being replaced.
10
+ * It registers a rollback with ``hotswap_guard``, so a swap that compiles cleanly
11
+ but throws at runtime is auto-reverted by the render loop's except hook.
12
+ * ``is_editable_source`` is the same fail-closed gate the editor uses — only paths
13
+ inside the project tree are ever compiled or written.
14
+
15
+ The launcher (which hosts the MCP server) runs the studio in-process, so the
16
+ studio's modules live in this process's ``sys.modules`` and can be patched from
17
+ the MCP server thread — the same off-render-thread path the editor's background
18
+ recompile already uses.
19
+ """
20
+
21
+ import sys
22
+ from pathlib import Path
23
+
24
+
25
+ def _resolve_module(path):
26
+ """Find the live module object loaded from `path` (resolved), or None."""
27
+ target = Path(path).resolve()
28
+ for mod in list(sys.modules.values()):
29
+ f = getattr(mod, "__file__", None)
30
+ if not f:
31
+ continue
32
+ try:
33
+ if Path(f).resolve() == target:
34
+ return mod
35
+ except (OSError, ValueError):
36
+ continue
37
+ return None
38
+
39
+
40
+ def hotswap_file(path, source=None):
41
+ """Recompile `path`'s module into the running process and return a status line.
42
+
43
+ If `source` is None, the file's current on-disk contents are reloaded. If
44
+ `source` is given, it is hotswapped first and persisted to disk only after a
45
+ clean compile, so a syntax error never leaves broken code on disk.
46
+ """
47
+ # Imported lazily: this module is loaded by the MCP server, which must not
48
+ # drag in the (imgui-heavy) editor stack unless a hotswap is actually asked for.
49
+ from meltygui.code.file_converters import _recompile_module
50
+ from meltygui.code.fileref import is_editable_source
51
+ from meltygui.code.libcst_conversion import invalidate_usage_cache
52
+
53
+ p = Path(path).resolve()
54
+ if not is_editable_source(p):
55
+ return f"refusing to hotswap source outside the project tree: {p}"
56
+ if source is None and not p.exists():
57
+ return f"no such file: {p}"
58
+
59
+ module = _resolve_module(p)
60
+ if module is None:
61
+ return (f"no live module is loaded from {p} — nothing to hotswap. "
62
+ f"(The file must already be imported in the running process.)")
63
+
64
+ provided = source is not None
65
+ if not provided:
66
+ try:
67
+ source = p.read_text(encoding="utf-8")
68
+ except Exception as e:
69
+ return f"could not read {p}: {e}"
70
+
71
+ # Swap the live module from the in-memory source first; only touch disk on
72
+ # success. _recompile_module RAISES on a syntax error (compile() in its
73
+ # try) and RETURNS the exception on an exec-time error - handle both.
74
+ try:
75
+ err = _recompile_module(module, source, str(p))
76
+ except Exception as e:
77
+ err = e
78
+ if err is not None:
79
+ return (f"hotswap FAILED for {module.__name__} ({p.name}): "
80
+ f"{type(err).__name__}: {err} — live module unchanged, disk unchanged")
81
+
82
+ if provided:
83
+ try:
84
+ p.write_text(source, encoding="utf-8")
85
+ except Exception as e:
86
+ return (f"hotswapped {module.__name__} live, but FAILED to persist to disk: {e} "
87
+ f"— change will be lost on restart")
88
+
89
+ # Refresh the line caches in BOTH paths - a from-disk reload means the file
90
+ # was just changed by an external editor, so linecache may still hold the
91
+ # pre-save content. Stale lines make getsourcelines-based span resolution
92
+ # (and thus the in-process editor's next save) splice at wrong offsets.
93
+ invalidate_usage_cache(p)
94
+ import linecache
95
+ linecache.checkcache(str(p))
96
+
97
+ # Wake the render loop so the new code runs on the next frame.
98
+ try:
99
+ from meltygui.core.windowing.glfw_utils import request_render
100
+ request_render()
101
+ except Exception:
102
+ pass
103
+
104
+ verb = "applied + saved to disk" if provided else "reloaded from disk"
105
+ return (f"hotswapped {module.__name__} ({p.name}) — {verb}. "
106
+ f"Every function/class in the file was patched in place; a runtime "
107
+ f"error will auto-revert it via the hotswap guard.")