legate 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (317) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +345 -0
  4. data/bin/legate +13 -0
  5. data/examples/00_quickstart.rb +51 -0
  6. data/examples/01_simple_agent.rb +105 -0
  7. data/examples/02_multi_tool_agent.rb +140 -0
  8. data/examples/03_custom_tool.rb +93 -0
  9. data/examples/04_agent_instructions.rb +84 -0
  10. data/examples/05_state_and_sessions.rb +91 -0
  11. data/examples/06_callbacks.rb +186 -0
  12. data/examples/07_async_jobs.rb +112 -0
  13. data/examples/08_loop_agent.rb +197 -0
  14. data/examples/09_sequential_workflow.rb +40 -0
  15. data/examples/10_parallel_workflow.rb +34 -0
  16. data/examples/11_agent_delegation.rb +24 -0
  17. data/examples/12_http_client_tool.rb +156 -0
  18. data/examples/13_authentication.rb +220 -0
  19. data/examples/14_mcp_client.rb +154 -0
  20. data/examples/15_mcp_server.rb +79 -0
  21. data/examples/16_webhooks.rb +91 -0
  22. data/examples/README_sequential_agents.md +164 -0
  23. data/examples/advanced/auth/cookie_auth_tool.rb +146 -0
  24. data/examples/advanced/auth/custom_auth_flows_example.rb +626 -0
  25. data/examples/advanced/auth/excon_middleware.rb +317 -0
  26. data/examples/advanced/auth/excon_middleware_auth.rb +399 -0
  27. data/examples/advanced/auth/fiber_auth_example.rb +281 -0
  28. data/examples/advanced/auth/fiber_oidc_example.rb +403 -0
  29. data/examples/advanced/auth/httpbin_bearer_tool.rb +159 -0
  30. data/examples/advanced/auth/oauth2_auth.rb +419 -0
  31. data/examples/advanced/auth/oidc_auth.rb +514 -0
  32. data/examples/advanced/auth/openweather_api.rb +251 -0
  33. data/examples/advanced/auth/openweather_tool.rb +153 -0
  34. data/examples/advanced/auth/query_param_middleware_test.rb +138 -0
  35. data/examples/advanced/auth/service_account.rb +135 -0
  36. data/examples/advanced/auth/test_with_httpbin.rb +202 -0
  37. data/examples/advanced/auth/token_lifecycle_example.rb +428 -0
  38. data/examples/advanced/callback_monitoring.rb +679 -0
  39. data/examples/advanced/mas/fixed_delegation_example.rb +191 -0
  40. data/examples/advanced/mas/loop_workflow.rb +28 -0
  41. data/examples/advanced/mas/mock_planner.rb +77 -0
  42. data/examples/advanced/mas/proper_delegation_example.rb +276 -0
  43. data/examples/advanced/mcp/legate_mcp_server_resource_example.rb +182 -0
  44. data/examples/advanced/mcp/mcp_resource_server_example.rb +309 -0
  45. data/examples/advanced/mcp/mcp_server_async.rb +76 -0
  46. data/examples/advanced/mcp/mcp_server_async_tools.rb +122 -0
  47. data/examples/advanced/mcp/mcp_server_legate_agent.rb +95 -0
  48. data/examples/advanced/mcp/mcp_server_rack.rb +89 -0
  49. data/examples/advanced/random_calculator.rb +104 -0
  50. data/examples/advanced/sleep_agent.rb +153 -0
  51. data/examples/advanced/webhooks/webhook_e2e_runner.rb +110 -0
  52. data/examples/advanced/webhooks/webhook_receiver_agent.rb +58 -0
  53. data/examples/advanced/workflows/task_refinement_loop_agent.rb +278 -0
  54. data/examples/advanced/workflows/travel_planner_auto_sequential.rb +444 -0
  55. data/examples/advanced/workflows/travel_planner_parallel.rb +656 -0
  56. data/examples/advanced/workflows/travel_planner_sequential.rb +512 -0
  57. data/examples/tools/oauth2_example.rb +136 -0
  58. data/examples/tools/sleepy_tool.rb +42 -0
  59. data/lib/legate/activity_log.rb +71 -0
  60. data/lib/legate/agent.rb +959 -0
  61. data/lib/legate/agent_code_generator.rb +185 -0
  62. data/lib/legate/agent_definition.rb +812 -0
  63. data/lib/legate/agentic/decision.rb +49 -0
  64. data/lib/legate/agentic/loop.rb +134 -0
  65. data/lib/legate/agentic.rb +5 -0
  66. data/lib/legate/agents/loop_agent.rb +248 -0
  67. data/lib/legate/agents/parallel_agent.rb +163 -0
  68. data/lib/legate/agents/sequential_agent.rb +190 -0
  69. data/lib/legate/agents.rb +14 -0
  70. data/lib/legate/auth/config.rb +148 -0
  71. data/lib/legate/auth/coordinator.rb +218 -0
  72. data/lib/legate/auth/coordinators/oauth2_coordinator.rb +99 -0
  73. data/lib/legate/auth/coordinators/oidc_coordinator.rb +68 -0
  74. data/lib/legate/auth/coordinators/service_account_coordinator.rb +122 -0
  75. data/lib/legate/auth/credential.rb +157 -0
  76. data/lib/legate/auth/encryption.rb +108 -0
  77. data/lib/legate/auth/error.rb +94 -0
  78. data/lib/legate/auth/exchanged_credential.rb +180 -0
  79. data/lib/legate/auth/excon_middleware.rb +285 -0
  80. data/lib/legate/auth/http_client_utils.rb +364 -0
  81. data/lib/legate/auth/manager.rb +531 -0
  82. data/lib/legate/auth/manager_store.rb +394 -0
  83. data/lib/legate/auth/middleware_factory.rb +290 -0
  84. data/lib/legate/auth/runner.rb +279 -0
  85. data/lib/legate/auth/scheme.rb +125 -0
  86. data/lib/legate/auth/schemes/api_key.rb +212 -0
  87. data/lib/legate/auth/schemes/google_service_account.rb +108 -0
  88. data/lib/legate/auth/schemes/http_bearer.rb +98 -0
  89. data/lib/legate/auth/schemes/oauth2.rb +396 -0
  90. data/lib/legate/auth/schemes/openid_connect.rb +346 -0
  91. data/lib/legate/auth/schemes/service_account.rb +388 -0
  92. data/lib/legate/auth/schemes.rb +40 -0
  93. data/lib/legate/auth/token_manager.rb +362 -0
  94. data/lib/legate/auth/token_store.rb +86 -0
  95. data/lib/legate/auth/tool_context_extension.rb +97 -0
  96. data/lib/legate/auth/tool_integration.rb +188 -0
  97. data/lib/legate/auth/url_guard.rb +81 -0
  98. data/lib/legate/auth.rb +453 -0
  99. data/lib/legate/callbacks/callback_context.rb +71 -0
  100. data/lib/legate/cli/agent_commands.rb +950 -0
  101. data/lib/legate/cli/auth_commands.rb +520 -0
  102. data/lib/legate/cli/base_command.rb +24 -0
  103. data/lib/legate/cli/deployment_commands.rb +934 -0
  104. data/lib/legate/cli/output_helper.rb +108 -0
  105. data/lib/legate/cli/session_commands.rb +138 -0
  106. data/lib/legate/cli/skaffold_commands.rb +223 -0
  107. data/lib/legate/cli/tool_commands.rb +261 -0
  108. data/lib/legate/cli/web_commands.rb +182 -0
  109. data/lib/legate/cli.rb +40 -0
  110. data/lib/legate/configuration/webhooks.rb +113 -0
  111. data/lib/legate/configuration.rb +39 -0
  112. data/lib/legate/definition_store.rb +23 -0
  113. data/lib/legate/errors.rb +118 -0
  114. data/lib/legate/event.rb +161 -0
  115. data/lib/legate/gemini_ai_beta_patch.rb +39 -0
  116. data/lib/legate/generators/agent_generator.rb +412 -0
  117. data/lib/legate/generators/code_validator.rb +48 -0
  118. data/lib/legate/generators/legate/install_generator.rb +35 -0
  119. data/lib/legate/generators/legate/templates/create_legate_tables.rb.tt +36 -0
  120. data/lib/legate/generators/legate/templates/initializer.rb +18 -0
  121. data/lib/legate/generators/runtime_tool_loader.rb +76 -0
  122. data/lib/legate/generators/tool_generator.rb +408 -0
  123. data/lib/legate/generators.rb +11 -0
  124. data/lib/legate/global_definition_registry.rb +506 -0
  125. data/lib/legate/global_tool_manager.rb +135 -0
  126. data/lib/legate/llm/adapter.rb +69 -0
  127. data/lib/legate/llm/gemini.rb +172 -0
  128. data/lib/legate/llm/ollama.rb +80 -0
  129. data/lib/legate/llm.rb +34 -0
  130. data/lib/legate/mcp/client.rb +320 -0
  131. data/lib/legate/mcp/connection/sse.rb +292 -0
  132. data/lib/legate/mcp/connection/stdio.rb +273 -0
  133. data/lib/legate/mcp/connection_manager.rb +103 -0
  134. data/lib/legate/mcp/server/legate_agent_adapter.rb +170 -0
  135. data/lib/legate/mcp/server/legate_direct_agent_adapter.rb +140 -0
  136. data/lib/legate/mcp/server/legate_tool_adapter.rb +119 -0
  137. data/lib/legate/mcp/tool_wrapper.rb +138 -0
  138. data/lib/legate/mcp/util/schema_converter.rb +134 -0
  139. data/lib/legate/mcp.rb +23 -0
  140. data/lib/legate/plan_executor.rb +375 -0
  141. data/lib/legate/planner.rb +839 -0
  142. data/lib/legate/rails/railtie.rb +43 -0
  143. data/lib/legate/rails.rb +9 -0
  144. data/lib/legate/redaction.rb +32 -0
  145. data/lib/legate/session.rb +299 -0
  146. data/lib/legate/session_service/active_record.rb +300 -0
  147. data/lib/legate/session_service/base.rb +68 -0
  148. data/lib/legate/session_service/event_broadcast.rb +74 -0
  149. data/lib/legate/session_service/in_memory.rb +188 -0
  150. data/lib/legate/tool/metadata_dsl.rb +122 -0
  151. data/lib/legate/tool.rb +276 -0
  152. data/lib/legate/tool_code_generator.rb +103 -0
  153. data/lib/legate/tool_context.rb +350 -0
  154. data/lib/legate/tool_loader.rb +39 -0
  155. data/lib/legate/tool_registry.rb +73 -0
  156. data/lib/legate/tool_result.rb +61 -0
  157. data/lib/legate/tools/agent_tool.rb +187 -0
  158. data/lib/legate/tools/base/http_client.rb +319 -0
  159. data/lib/legate/tools/base/safe_url.rb +56 -0
  160. data/lib/legate/tools/base_async_job_tool.rb +91 -0
  161. data/lib/legate/tools/calculator.rb +89 -0
  162. data/lib/legate/tools/cat_facts.rb +81 -0
  163. data/lib/legate/tools/check_job_status_tool.rb +48 -0
  164. data/lib/legate/tools/current_time_tool.rb +64 -0
  165. data/lib/legate/tools/echo.rb +43 -0
  166. data/lib/legate/tools/http_request_tool.rb +105 -0
  167. data/lib/legate/tools/random_number_tool.rb +64 -0
  168. data/lib/legate/tools/read_webpage_tool.rb +92 -0
  169. data/lib/legate/tools/sleepy_tool.rb +74 -0
  170. data/lib/legate/tools/webhook_tool.rb +146 -0
  171. data/lib/legate/version.rb +5 -0
  172. data/lib/legate/web/app.rb +984 -0
  173. data/lib/legate/web/public/css/main.css +4980 -0
  174. data/lib/legate/web/public/images/favicon-256.png +0 -0
  175. data/lib/legate/web/public/images/favicon-32.png +0 -0
  176. data/lib/legate/web/public/images/legate-logo-dark.png +0 -0
  177. data/lib/legate/web/public/images/legate-logo-light.png +0 -0
  178. data/lib/legate/web/public/js/legate.js +616 -0
  179. data/lib/legate/web/public/styles/main.scss +4402 -0
  180. data/lib/legate/web/routes/agent_authentication_routes.rb +530 -0
  181. data/lib/legate/web/routes/agent_definition_routes.rb +803 -0
  182. data/lib/legate/web/routes/agent_generator_routes.rb +80 -0
  183. data/lib/legate/web/routes/agent_interaction_routes.rb +734 -0
  184. data/lib/legate/web/routes/agent_runtime_routes.rb +323 -0
  185. data/lib/legate/web/routes/api_routes.rb +56 -0
  186. data/lib/legate/web/routes/authentication_routes.rb +1541 -0
  187. data/lib/legate/web/routes/core_routes.rb +111 -0
  188. data/lib/legate/web/routes/documentation_routes.rb +220 -0
  189. data/lib/legate/web/routes/tool_generator_routes.rb +81 -0
  190. data/lib/legate/web/routes/tools_ui_routes.rb +207 -0
  191. data/lib/legate/web/sass_compiler.rb +73 -0
  192. data/lib/legate/web/views/_active_session_info.slim +25 -0
  193. data/lib/legate/web/views/_activity_list.slim +55 -0
  194. data/lib/legate/web/views/_agent_card.slim +56 -0
  195. data/lib/legate/web/views/_agent_generator_modal.slim +382 -0
  196. data/lib/legate/web/views/_agent_status_controls.slim +71 -0
  197. data/lib/legate/web/views/_agent_tool_table.slim +74 -0
  198. data/lib/legate/web/views/_chat_message.slim +95 -0
  199. data/lib/legate/web/views/_display_agent_configuration.slim +26 -0
  200. data/lib/legate/web/views/_display_agent_description.slim +11 -0
  201. data/lib/legate/web/views/_display_agent_fallback.slim +15 -0
  202. data/lib/legate/web/views/_display_agent_hierarchy.slim +93 -0
  203. data/lib/legate/web/views/_display_agent_instruction.slim +17 -0
  204. data/lib/legate/web/views/_display_agent_mcp.slim +13 -0
  205. data/lib/legate/web/views/_display_agent_model.slim +17 -0
  206. data/lib/legate/web/views/_display_agent_name.slim +42 -0
  207. data/lib/legate/web/views/_display_agent_output_key.slim +26 -0
  208. data/lib/legate/web/views/_display_agent_type.slim +65 -0
  209. data/lib/legate/web/views/_edit_agent_configuration.slim +74 -0
  210. data/lib/legate/web/views/_edit_agent_description.slim +16 -0
  211. data/lib/legate/web/views/_edit_agent_fallback.slim +25 -0
  212. data/lib/legate/web/views/_edit_agent_hierarchy.slim +98 -0
  213. data/lib/legate/web/views/_edit_agent_instruction.slim +49 -0
  214. data/lib/legate/web/views/_edit_agent_mcp.slim +33 -0
  215. data/lib/legate/web/views/_edit_agent_model.slim +23 -0
  216. data/lib/legate/web/views/_edit_agent_output_key.slim +36 -0
  217. data/lib/legate/web/views/_edit_agent_tools.slim +40 -0
  218. data/lib/legate/web/views/_edit_agent_type.slim +67 -0
  219. data/lib/legate/web/views/_session_error.slim +4 -0
  220. data/lib/legate/web/views/_skeleton.slim +69 -0
  221. data/lib/legate/web/views/_tool_card.slim +9 -0
  222. data/lib/legate/web/views/_tool_generator_modal.slim +311 -0
  223. data/lib/legate/web/views/agent.slim +436 -0
  224. data/lib/legate/web/views/agent_auth.slim +562 -0
  225. data/lib/legate/web/views/agents.slim +369 -0
  226. data/lib/legate/web/views/auth.slim +112 -0
  227. data/lib/legate/web/views/auth_credential_detail.slim +327 -0
  228. data/lib/legate/web/views/auth_credentials.slim +261 -0
  229. data/lib/legate/web/views/auth_debug.slim +94 -0
  230. data/lib/legate/web/views/auth_mapping_detail.slim +151 -0
  231. data/lib/legate/web/views/auth_mapping_new.slim +123 -0
  232. data/lib/legate/web/views/auth_mappings.slim +120 -0
  233. data/lib/legate/web/views/auth_scheme_detail.slim +274 -0
  234. data/lib/legate/web/views/auth_schemes.slim +259 -0
  235. data/lib/legate/web/views/auth_test.slim +418 -0
  236. data/lib/legate/web/views/chat.slim +192 -0
  237. data/lib/legate/web/views/docs_index.slim +105 -0
  238. data/lib/legate/web/views/docs_show.slim +105 -0
  239. data/lib/legate/web/views/error_404.slim +5 -0
  240. data/lib/legate/web/views/index.slim +148 -0
  241. data/lib/legate/web/views/layout.slim +144 -0
  242. data/lib/legate/web/views/tool_detail.slim +87 -0
  243. data/lib/legate/web/views/tools.slim +50 -0
  244. data/lib/legate/web/webhook_listener.rb +367 -0
  245. data/lib/legate/web.rb +9 -0
  246. data/lib/legate.rb +220 -0
  247. data/public/docs/advanced/callbacks.md +828 -0
  248. data/public/docs/advanced/mcp_schema_conversion.md +59 -0
  249. data/public/docs/authentication/api_reference/config.md +210 -0
  250. data/public/docs/authentication/api_reference/credential.md +246 -0
  251. data/public/docs/authentication/api_reference/encryption.md +218 -0
  252. data/public/docs/authentication/api_reference/exchanged_credential.md +271 -0
  253. data/public/docs/authentication/api_reference/excon_middleware.md +175 -0
  254. data/public/docs/authentication/api_reference/index.md +30 -0
  255. data/public/docs/authentication/api_reference/scheme.md +250 -0
  256. data/public/docs/authentication/api_reference/schemes/api_key.md +175 -0
  257. data/public/docs/authentication/api_reference/schemes/google_service_account.md +221 -0
  258. data/public/docs/authentication/api_reference/schemes/http_bearer.md +169 -0
  259. data/public/docs/authentication/api_reference/schemes/oauth2.md +343 -0
  260. data/public/docs/authentication/api_reference/schemes/oidc.md +73 -0
  261. data/public/docs/authentication/api_reference/schemes/openid_connect.md +311 -0
  262. data/public/docs/authentication/api_reference/schemes/service_account.md +287 -0
  263. data/public/docs/authentication/api_reference/token_manager.md +221 -0
  264. data/public/docs/authentication/api_reference/token_store.md +146 -0
  265. data/public/docs/authentication/api_reference/tool_context_extension.md +166 -0
  266. data/public/docs/authentication/guides/api_key.md +190 -0
  267. data/public/docs/authentication/guides/bearer.md +172 -0
  268. data/public/docs/authentication/guides/configuration.md +255 -0
  269. data/public/docs/authentication/guides/custom_flow.md +523 -0
  270. data/public/docs/authentication/guides/index.md +24 -0
  271. data/public/docs/authentication/guides/migration.md +435 -0
  272. data/public/docs/authentication/guides/oauth2.md +252 -0
  273. data/public/docs/authentication/guides/oidc.md +241 -0
  274. data/public/docs/authentication/guides/overview.md +155 -0
  275. data/public/docs/authentication/guides/secure_storage.md +301 -0
  276. data/public/docs/authentication/guides/service_account.md +228 -0
  277. data/public/docs/authentication/guides/token_lifecycle.md +295 -0
  278. data/public/docs/authentication/guides/web_ui_integration.md +504 -0
  279. data/public/docs/authentication/index.md +58 -0
  280. data/public/docs/authentication/troubleshooting/credential_storage.md +550 -0
  281. data/public/docs/authentication/troubleshooting/environment_variables.md +540 -0
  282. data/public/docs/authentication/troubleshooting/index.md +11 -0
  283. data/public/docs/authentication/troubleshooting/oauth2_issues.md +220 -0
  284. data/public/docs/authentication/troubleshooting/oidc_issues.md +412 -0
  285. data/public/docs/authentication/troubleshooting/token_refresh.md +338 -0
  286. data/public/docs/cli/legate_cli_usage.md +363 -0
  287. data/public/docs/core_concepts/legate_agent_lifecycle.md +124 -0
  288. data/public/docs/core_concepts/legate_architecture_overview.md +110 -0
  289. data/public/docs/core_concepts/legate_configuration.md +116 -0
  290. data/public/docs/core_concepts/legate_definition_store.md +102 -0
  291. data/public/docs/core_concepts/legate_planner.md +94 -0
  292. data/public/docs/core_concepts/legate_session_service.md +104 -0
  293. data/public/docs/error_handling/legate_error_handling.md +122 -0
  294. data/public/docs/examples.md +199 -0
  295. data/public/docs/getting_started.md +111 -0
  296. data/public/docs/guides/agentic_agents.md +137 -0
  297. data/public/docs/guides/ai_code_generators.md +437 -0
  298. data/public/docs/guides/auto_loading.md +326 -0
  299. data/public/docs/guides/configuring_agent_webhooks.md +219 -0
  300. data/public/docs/guides/http_client_usage.md +264 -0
  301. data/public/docs/guides/llm_providers.md +137 -0
  302. data/public/docs/guides/mcp_client_integration.md +232 -0
  303. data/public/docs/guides/mcp_server_exposure.md +206 -0
  304. data/public/docs/guides/rails_integration.md +128 -0
  305. data/public/docs/guides/sending_outbound_webhooks.md +227 -0
  306. data/public/docs/guides/streaming.md +112 -0
  307. data/public/docs/guides/webhooks.md +288 -0
  308. data/public/docs/introduction.md +51 -0
  309. data/public/docs/multi_agent_systems/advanced_features.md +57 -0
  310. data/public/docs/multi_agent_systems/agent_delegation.md +190 -0
  311. data/public/docs/multi_agent_systems/agent_hierarchy.md +49 -0
  312. data/public/docs/multi_agent_systems/state_management.md +47 -0
  313. data/public/docs/multi_agent_systems/workflow_agents.md +72 -0
  314. data/public/docs/tools/legate_built_in_tools.md +332 -0
  315. data/public/docs/tools/legate_tools_and_registry.md +263 -0
  316. data/public/docs/web_ui/legate_web_ui.md +137 -0
  317. metadata +823 -0
@@ -0,0 +1,311 @@
1
+ / File: lib/legate/web/views/_tool_generator_modal.slim
2
+ / AI-powered tool generator modal
3
+
4
+ - runtime_load_enabled = Legate.config.allow_runtime_tool_load
5
+
6
+ #tool-generator-modal.modal
7
+ .modal-background onclick="closeToolGeneratorModal()"
8
+ .modal-card style="width: 90%; max-width: 1200px; max-height: 90vh;"
9
+ header.modal-card-head
10
+ p.modal-card-title
11
+ span.icon.mr-2
12
+ i.fas.fa-wand-magic-sparkles
13
+ | Generate Tool with AI
14
+ button.delete aria-label="close" onclick="closeToolGeneratorModal()"
15
+
16
+ section.modal-card-body style="display: flex; flex-direction: column; gap: 1.5rem;"
17
+ / Input Section
18
+ #tool-generator-input-section
19
+ .field
20
+ label.label
21
+ span.icon.is-small.mr-1
22
+ i.fas.fa-comment-dots
23
+ | Describe Your Tool
24
+ .control
25
+ textarea#tool-generator-description.textarea(
26
+ rows="5"
27
+ placeholder="Describe the tool you want to create. Examples: 'A tool that converts temperatures', 'A tool that fetches weather from OpenWeather API', 'A background job that processes CSV files'"
28
+ )
29
+ p.help
30
+ | Describe what you want your tool to do. The AI will automatically choose the best tool type:
31
+ br
32
+ strong Simple
33
+ | (calculations, transformations),
34
+ strong HTTP
35
+ | (API calls), or
36
+ strong Async
37
+ | (background jobs).
38
+
39
+ .field
40
+ .control
41
+ button#tool-generator-btn.button.is-primary.is-medium(onclick="generateToolCode()")
42
+ span.icon
43
+ i.fas.fa-wand-magic-sparkles
44
+ span Generate Code
45
+ span#tool-generator-loading.ml-3 style="display: none;"
46
+ span.icon.has-text-info
47
+ i.fas.fa-spinner.fa-spin
48
+ span.has-text-grey Generating...
49
+
50
+ / Error Display
51
+ #tool-generator-error.notification.is-danger.is-light style="display: none;"
52
+ button.delete onclick="this.parentElement.style.display='none'"
53
+ span#tool-generator-error-message
54
+
55
+ / Output Section (hidden until generation)
56
+ #tool-generator-output-section style="display: none;"
57
+ .level.mb-3
58
+ .level-left
59
+ .level-item
60
+ p.subtitle.is-5
61
+ span.icon.is-small.mr-1
62
+ i.fas.fa-code
63
+ | Generated Code
64
+ .level-item
65
+ span#tool-generator-name-tag.tag.is-info.is-light
66
+ .level-item
67
+ span#tool-generator-type-tag.tag.is-light
68
+ .level-right
69
+ .level-item
70
+ .buttons
71
+ button.button.is-small.is-light(onclick="regenerateToolCode()" title="Generate again with same description")
72
+ span.icon.is-small
73
+ i.fas.fa-sync
74
+ span Regenerate
75
+ button.button.is-small.is-success.is-light(onclick="copyToolCode()" title="Copy to clipboard")
76
+ span.icon.is-small
77
+ i.fas.fa-copy
78
+ span Copy
79
+ button.button.is-small.is-link.is-light(onclick="downloadToolCode()" title="Download as .rb file")
80
+ span.icon.is-small
81
+ i.fas.fa-download
82
+ span Download
83
+
84
+ .code-preview-container style="max-height: 360px; overflow: auto; border-radius: 6px;"
85
+ pre
86
+ code#tool-generator-code.language-ruby
87
+
88
+ / Install (live) — gated by config (on outside production)
89
+ - if runtime_load_enabled
90
+ .tool-install-box.mt-3
91
+ label.checkbox.tool-install-confirm
92
+ input#tool-install-confirm type="checkbox"
93
+ span
94
+ strong Run this code on the server
95
+ | and save it to your tools/ directory. Only install tools you've reviewed.
96
+ .is-flex.is-align-items-center.mt-2(style="gap: 0.75rem;")
97
+ button#tool-install-btn.button.is-primary(onclick="installTool()")
98
+ span.icon
99
+ i.fas.fa-circle-plus
100
+ span Add Tool to Legion
101
+ span#tool-install-result
102
+ - else
103
+ p.help.tool-install-disabled.mt-3
104
+ span.icon.is-small
105
+ i.fas.fa-circle-info
106
+ | Live install is disabled in this environment. Download the tool, place it in tools/, and restart to activate it.
107
+
108
+ / Copy success toast
109
+ #tool-generator-copy-toast.notification.is-success.is-light style="display: none; position: absolute; bottom: 1rem; right: 1rem; padding: 0.75rem 1rem;"
110
+ span.icon.is-small.mr-1
111
+ i.fas.fa-check
112
+ | Copied to clipboard!
113
+
114
+ footer.modal-card-foot style="justify-content: flex-end;"
115
+ button.button onclick="closeToolGeneratorModal()" Close
116
+
117
+ javascript:
118
+ // Tool Generator Modal Functions
119
+ let generatedToolCode = '';
120
+ let suggestedToolName = 'generated_tool';
121
+ let detectedToolType = 'simple';
122
+
123
+ function openToolGeneratorModal() {
124
+ document.getElementById('tool-generator-modal').classList.add('is-active');
125
+ document.getElementById('tool-generator-description').focus();
126
+ }
127
+
128
+ function closeToolGeneratorModal() {
129
+ document.getElementById('tool-generator-modal').classList.remove('is-active');
130
+ // Reset state
131
+ document.getElementById('tool-generator-error').style.display = 'none';
132
+ }
133
+
134
+ async function generateToolCode() {
135
+ const description = document.getElementById('tool-generator-description').value.trim();
136
+
137
+ if (!description) {
138
+ showToolGeneratorError('Please enter a description of the tool you want to create.');
139
+ return;
140
+ }
141
+
142
+ // Show loading state
143
+ const btn = document.getElementById('tool-generator-btn');
144
+ const loading = document.getElementById('tool-generator-loading');
145
+ btn.disabled = true;
146
+ loading.style.display = 'inline';
147
+ document.getElementById('tool-generator-error').style.display = 'none';
148
+ document.getElementById('tool-generator-output-section').style.display = 'none';
149
+
150
+ try {
151
+ const tokenEl = document.querySelector('meta[name="csrf-token"]');
152
+ const response = await fetch('/tools/generate', {
153
+ method: 'POST',
154
+ headers: {
155
+ 'Content-Type': 'application/json',
156
+ 'X-CSRF-Token': tokenEl ? tokenEl.content : ''
157
+ },
158
+ body: JSON.stringify({ description: description })
159
+ });
160
+
161
+ const data = await response.json();
162
+
163
+ if (!response.ok) {
164
+ throw new Error(data.error || 'Generation failed');
165
+ }
166
+
167
+ // Store the generated code
168
+ generatedToolCode = data.code;
169
+ suggestedToolName = data.suggested_name || 'generated_tool';
170
+ detectedToolType = data.tool_type || 'simple';
171
+
172
+ // Display the code
173
+ const codeElement = document.getElementById('tool-generator-code');
174
+
175
+ // Reset highlight.js state before setting new content
176
+ codeElement.classList.remove('hljs');
177
+ delete codeElement.dataset.highlighted;
178
+ codeElement.textContent = data.code;
179
+
180
+ // Apply syntax highlighting
181
+ if (typeof hljs !== 'undefined') {
182
+ hljs.highlightElement(codeElement);
183
+ }
184
+
185
+ // Update name tag
186
+ document.getElementById('tool-generator-name-tag').textContent = suggestedToolName;
187
+
188
+ // Update type tag with appropriate styling
189
+ const typeTag = document.getElementById('tool-generator-type-tag');
190
+ typeTag.textContent = detectedToolType.charAt(0).toUpperCase() + detectedToolType.slice(1) + ' Tool';
191
+ typeTag.className = 'tag is-light';
192
+ if (detectedToolType === 'http') {
193
+ typeTag.classList.add('is-link');
194
+ } else if (detectedToolType === 'async') {
195
+ typeTag.classList.add('is-warning');
196
+ } else {
197
+ typeTag.classList.add('is-success');
198
+ }
199
+
200
+ // Show output section
201
+ document.getElementById('tool-generator-output-section').style.display = 'block';
202
+
203
+ // Reset the install affordance for the freshly generated code
204
+ const confirmEl = document.getElementById('tool-install-confirm');
205
+ if (confirmEl) confirmEl.checked = false;
206
+ const installBtn = document.getElementById('tool-install-btn');
207
+ if (installBtn) installBtn.disabled = false;
208
+ const installResult = document.getElementById('tool-install-result');
209
+ if (installResult) installResult.innerHTML = '';
210
+
211
+ } catch (error) {
212
+ showToolGeneratorError(error.message);
213
+ } finally {
214
+ btn.disabled = false;
215
+ loading.style.display = 'none';
216
+ }
217
+ }
218
+
219
+ function regenerateToolCode() {
220
+ generateToolCode();
221
+ }
222
+
223
+ function showToolGeneratorError(message) {
224
+ const errorEl = document.getElementById('tool-generator-error');
225
+ document.getElementById('tool-generator-error-message').textContent = message;
226
+ errorEl.style.display = 'block';
227
+ }
228
+
229
+ async function copyToolCode() {
230
+ try {
231
+ await navigator.clipboard.writeText(generatedToolCode);
232
+
233
+ // Show toast
234
+ const toast = document.getElementById('tool-generator-copy-toast');
235
+ toast.style.display = 'block';
236
+ setTimeout(() => {
237
+ toast.style.display = 'none';
238
+ }, 2000);
239
+ } catch (err) {
240
+ showToolGeneratorError('Failed to copy to clipboard');
241
+ }
242
+ }
243
+
244
+ function downloadToolCode() {
245
+ const blob = new Blob([generatedToolCode], { type: 'text/plain' });
246
+ const url = URL.createObjectURL(blob);
247
+ const a = document.createElement('a');
248
+ a.href = url;
249
+ a.download = `${suggestedToolName}.rb`;
250
+ document.body.appendChild(a);
251
+ a.click();
252
+ document.body.removeChild(a);
253
+ URL.revokeObjectURL(url);
254
+ }
255
+
256
+ async function installTool() {
257
+ const confirmEl = document.getElementById('tool-install-confirm');
258
+ if (!confirmEl || !confirmEl.checked) {
259
+ showToolGeneratorError('Please tick the confirmation box — this runs the generated code on the server.');
260
+ return;
261
+ }
262
+ const btn = document.getElementById('tool-install-btn');
263
+ btn.classList.add('is-loading');
264
+ try {
265
+ const tokenEl = document.querySelector('meta[name="csrf-token"]');
266
+ const response = await fetch('/tools/install', {
267
+ method: 'POST',
268
+ headers: {
269
+ 'Content-Type': 'application/json',
270
+ 'X-CSRF-Token': tokenEl ? tokenEl.content : ''
271
+ },
272
+ body: JSON.stringify({
273
+ code: generatedToolCode,
274
+ suggested_name: suggestedToolName,
275
+ confirm: true
276
+ })
277
+ });
278
+ const data = await response.json();
279
+ if (!response.ok) throw new Error(data.error || 'Install failed');
280
+
281
+ // If we got here from the agent builder's "Build →", return to it with the
282
+ // newly-installed tool added + checked (it didn't exist when the form rendered).
283
+ if (window.legateReturnToAgentBuilder && typeof returnToAgentBuilderWithTool === 'function') {
284
+ const original = window.legateReturnToAgentBuilder;
285
+ window.legateReturnToAgentBuilder = null;
286
+ closeToolGeneratorModal();
287
+ returnToAgentBuilderWithTool(data.tool_name, original);
288
+ return;
289
+ }
290
+
291
+ const result = document.getElementById('tool-install-result');
292
+ result.innerHTML = '<span class="has-text-success"><span class="icon is-small"><i class="fas fa-check-circle"></i></span> Installed <strong>' + data.tool_name + '</strong> — usable by agents now.</span>';
293
+ btn.disabled = true;
294
+ confirmEl.disabled = true;
295
+ } catch (error) {
296
+ showToolGeneratorError(error.message);
297
+ } finally {
298
+ btn.classList.remove('is-loading');
299
+ }
300
+ }
301
+
302
+ // Close modal on Escape key
303
+ document.addEventListener('keydown', function(e) {
304
+ if (e.key === 'Escape') {
305
+ const modal = document.getElementById('tool-generator-modal');
306
+ if (modal && modal.classList.contains('is-active')) {
307
+ closeToolGeneratorModal();
308
+ }
309
+ }
310
+ });
311
+