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,151 @@
1
+ / File: lib/legate/web/views/auth_mapping_detail.slim
2
+ .content.mb-6
3
+ nav.breadcrumb(aria-label="breadcrumbs")
4
+ ul
5
+ li
6
+ a(href="/auth") Authentication
7
+ li
8
+ a(href="/auth/mappings") URL Mappings
9
+ li.is-active
10
+ a(href="/auth/mappings/#{@mapping[:id]}" aria-current="page") Mapping #{@mapping[:id]}
11
+
12
+ h1.title.is-2 Edit URL Mapping
13
+ p.subtitle.is-4 Update the mapping from URL pattern to authentication
14
+
15
+ form#edit-mapping-form
16
+ .columns
17
+ .column.is-half
18
+ - @mapping_fields.each do |field|
19
+ .field
20
+ label.label = field[:label]
21
+ .control
22
+ - if field[:type] == 'select'
23
+ .select.is-fullwidth
24
+ select(name="#{field[:name]}" required=field[:required])
25
+ - if field[:name] == 'scheme_name'
26
+ - @schemes.each do |name, scheme|
27
+ option(value="#{name}" selected=(@mapping[:scheme_name] == name)) = name
28
+ - elsif field[:name] == 'credential_name'
29
+ - @credentials.each do |name, cred|
30
+ option(value="#{name}" selected=(@mapping[:credential_name] == name)) = name
31
+ - else
32
+ - field[:options].each do |option|
33
+ option(value="#{option}" selected=(@mapping[:pattern_type] == option || field[:default] == option)) = option
34
+ - elsif field[:type] == 'checkbox'
35
+ label.checkbox
36
+ input(type="checkbox" name="#{field[:name]}" checked=(@mapping[:active] != false))
37
+ = " #{field[:label]}"
38
+ - else
39
+ input.input(type=field[:type] name=field[:name] value=@mapping[field[:name].to_sym] placeholder=field[:placeholder] required=field[:required])
40
+ .column.is-half
41
+ .box
42
+ h3.title.is-5 Pattern Tester
43
+ .field
44
+ label.label Test URL
45
+ .control
46
+ input.input(type="text" id="test-url-input" placeholder="Enter a URL to test against the pattern")
47
+ .field
48
+ .control
49
+ button.button.is-info#test-pattern-btn(type="button")
50
+ span.icon
51
+ i.fas.fa-vial
52
+ span Test Pattern
53
+ .notification.is-hidden#pattern-test-result
54
+
55
+ .field.mt-5
56
+ .control
57
+ button.button.is-primary(type="submit") Update Mapping
58
+ a.button(href="/auth/mappings") Cancel
59
+ button.button.is-danger#delete-mapping-btn(type="button") Delete Mapping
60
+
61
+ javascript:
62
+ document.addEventListener('DOMContentLoaded', function() {
63
+ const form = document.getElementById('edit-mapping-form');
64
+ const testBtn = document.getElementById('test-pattern-btn');
65
+ const testUrlInput = document.getElementById('test-url-input');
66
+ const patternInput = form.querySelector('input[name="pattern"]');
67
+ const patternTypeSelect = form.querySelector('select[name="pattern_type"]');
68
+ const resultBox = document.getElementById('pattern-test-result');
69
+ const deleteBtn = document.getElementById('delete-mapping-btn');
70
+
71
+ testBtn.addEventListener('click', function() {
72
+ const pattern = patternInput.value;
73
+ const patternType = patternTypeSelect.value;
74
+ const url = testUrlInput.value;
75
+ resultBox.classList.add('is-hidden');
76
+ fetch('/auth/mappings/test', {
77
+ method: 'POST',
78
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
79
+ body: `pattern=${encodeURIComponent(pattern)}&pattern_type=${encodeURIComponent(patternType)}&url=${encodeURIComponent(url)}`
80
+ })
81
+ .then(response => response.json())
82
+ .then(data => {
83
+ resultBox.classList.remove('is-hidden');
84
+ if (data.success) {
85
+ resultBox.className = 'notification is-success';
86
+ resultBox.textContent = data.matched ? 'Pattern matches the URL!' : 'Pattern does NOT match the URL.';
87
+ } else {
88
+ resultBox.className = 'notification is-danger';
89
+ resultBox.textContent = data.error || 'Pattern test failed.';
90
+ }
91
+ })
92
+ .catch(error => {
93
+ resultBox.className = 'notification is-danger';
94
+ resultBox.textContent = 'Network error: ' + error.message;
95
+ resultBox.classList.remove('is-hidden');
96
+ });
97
+ });
98
+
99
+ form.addEventListener('submit', function(e) {
100
+ e.preventDefault();
101
+ const formData = new FormData(form);
102
+ fetch(`/auth/mappings/#{@mapping[:id]}`, {
103
+ method: 'PUT',
104
+ body: formData
105
+ })
106
+ .then(response => response.json())
107
+ .then(data => {
108
+ if (data.success) {
109
+ if (typeof showToast === 'function') {
110
+ showToast(data.message, 'is-success');
111
+ }
112
+ window.location.reload();
113
+ } else {
114
+ if (typeof showToast === 'function') {
115
+ showToast(data.error || 'Failed to update mapping', 'is-danger');
116
+ }
117
+ }
118
+ })
119
+ .catch(error => {
120
+ if (typeof showToast === 'function') {
121
+ showToast('Network error occurred', 'is-danger');
122
+ }
123
+ });
124
+ });
125
+
126
+ deleteBtn.addEventListener('click', function() {
127
+ if (confirm('Are you sure you want to delete this mapping?')) {
128
+ fetch(`/auth/mappings/#{@mapping[:id]}`, {
129
+ method: 'DELETE'
130
+ })
131
+ .then(response => response.json())
132
+ .then(data => {
133
+ if (data.success) {
134
+ if (typeof showToast === 'function') {
135
+ showToast(data.message, 'is-success');
136
+ }
137
+ window.location.href = '/auth/mappings';
138
+ } else {
139
+ if (typeof showToast === 'function') {
140
+ showToast(data.error || 'Failed to delete mapping', 'is-danger');
141
+ }
142
+ }
143
+ })
144
+ .catch(error => {
145
+ if (typeof showToast === 'function') {
146
+ showToast('Network error occurred', 'is-danger');
147
+ }
148
+ });
149
+ }
150
+ });
151
+ });
@@ -0,0 +1,123 @@
1
+ / File: lib/legate/web/views/auth_mapping_new.slim
2
+ .content.mb-6
3
+ nav.breadcrumb(aria-label="breadcrumbs")
4
+ ul
5
+ li
6
+ a(href="/auth") Authentication
7
+ li
8
+ a(href="/auth/mappings") URL Mappings
9
+ li.is-active
10
+ a(href="/auth/mappings/new" aria-current="page") New Mapping
11
+
12
+ h1.title.is-2 Add New URL Mapping
13
+ p.subtitle.is-4 Configure a new mapping from URL pattern to authentication
14
+
15
+ form#add-mapping-form
16
+ .columns
17
+ .column.is-half
18
+ - @mapping_fields.each do |field|
19
+ .field
20
+ label.label = field[:label]
21
+ .control
22
+ - if field[:type] == 'select'
23
+ .select.is-fullwidth
24
+ select(name="#{field[:name]}" required=field[:required])
25
+ - if field[:name] == 'scheme_name'
26
+ - @schemes.each do |name, scheme|
27
+ option(value="#{name}") = name
28
+ - elsif field[:name] == 'credential_name'
29
+ - @credentials.each do |name, cred|
30
+ option(value="#{name}") = name
31
+ - else
32
+ - field[:options].each do |option|
33
+ option(value="#{option}" selected=(field[:default] == option)) = option
34
+ - elsif field[:type] == 'checkbox'
35
+ label.checkbox
36
+ input(type="checkbox" name="#{field[:name]}" checked=field[:default])
37
+ = " #{field[:label]}"
38
+ - else
39
+ input.input(type=field[:type] name=field[:name] placeholder=field[:placeholder] required=field[:required])
40
+ .column.is-half
41
+ .box
42
+ h3.title.is-5 Pattern Tester
43
+ .field
44
+ label.label Test URL
45
+ .control
46
+ input.input(type="text" id="test-url-input" placeholder="Enter a URL to test against the pattern")
47
+ .field
48
+ .control
49
+ button.button.is-info#test-pattern-btn(type="button")
50
+ span.icon
51
+ i.fas.fa-vial
52
+ span Test Pattern
53
+ .notification.is-hidden#pattern-test-result
54
+
55
+ .field.mt-5
56
+ .control
57
+ button.button.is-primary(type="submit") Create Mapping
58
+ a.button(href="/auth/mappings") Cancel
59
+
60
+ javascript:
61
+ document.addEventListener('DOMContentLoaded', function() {
62
+ const form = document.getElementById('add-mapping-form');
63
+ const testBtn = document.getElementById('test-pattern-btn');
64
+ const testUrlInput = document.getElementById('test-url-input');
65
+ const patternInput = form.querySelector('input[name="pattern"]');
66
+ const patternTypeSelect = form.querySelector('select[name="pattern_type"]');
67
+ const resultBox = document.getElementById('pattern-test-result');
68
+
69
+ testBtn.addEventListener('click', function() {
70
+ const pattern = patternInput.value;
71
+ const patternType = patternTypeSelect.value;
72
+ const url = testUrlInput.value;
73
+ resultBox.classList.add('is-hidden');
74
+ fetch('/auth/mappings/test', {
75
+ method: 'POST',
76
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
77
+ body: `pattern=${encodeURIComponent(pattern)}&pattern_type=${encodeURIComponent(patternType)}&url=${encodeURIComponent(url)}`
78
+ })
79
+ .then(response => response.json())
80
+ .then(data => {
81
+ resultBox.classList.remove('is-hidden');
82
+ if (data.success) {
83
+ resultBox.className = 'notification is-success';
84
+ resultBox.textContent = data.matched ? 'Pattern matches the URL!' : 'Pattern does NOT match the URL.';
85
+ } else {
86
+ resultBox.className = 'notification is-danger';
87
+ resultBox.textContent = data.error || 'Pattern test failed.';
88
+ }
89
+ })
90
+ .catch(error => {
91
+ resultBox.className = 'notification is-danger';
92
+ resultBox.textContent = 'Network error: ' + error.message;
93
+ resultBox.classList.remove('is-hidden');
94
+ });
95
+ });
96
+
97
+ form.addEventListener('submit', function(e) {
98
+ e.preventDefault();
99
+ const formData = new FormData(form);
100
+ fetch('/auth/mappings', {
101
+ method: 'POST',
102
+ body: formData
103
+ })
104
+ .then(response => response.json())
105
+ .then(data => {
106
+ if (data.success) {
107
+ if (typeof showToast === 'function') {
108
+ showToast(data.message, 'is-success');
109
+ }
110
+ window.location.href = `/auth/mappings/${data.id}`;
111
+ } else {
112
+ if (typeof showToast === 'function') {
113
+ showToast(data.error || 'Failed to create mapping', 'is-danger');
114
+ }
115
+ }
116
+ })
117
+ .catch(error => {
118
+ if (typeof showToast === 'function') {
119
+ showToast('Network error occurred', 'is-danger');
120
+ }
121
+ });
122
+ });
123
+ });
@@ -0,0 +1,120 @@
1
+ / File: lib/legate/web/views/auth_mappings.slim
2
+ .content.mb-6
3
+ nav.breadcrumb(aria-label="breadcrumbs")
4
+ ul
5
+ li
6
+ a(href="/auth") Authentication
7
+ li.is-active
8
+ a(href="/auth/mappings" aria-current="page") URL Mappings
9
+
10
+ h1.title.is-2 URL Mappings
11
+ p.subtitle.is-4 Configure which authentication to use for specific URLs
12
+
13
+ .buttons.mb-4
14
+ a.button.is-primary#add-mapping-btn(href="/auth/mappings/new")
15
+ span.icon
16
+ i.fas.fa-plus
17
+ span Add New Mapping
18
+
19
+ - if @mappings && @mappings.any?
20
+ .table-container
21
+ table.table.is-fullwidth.is-striped.is-hoverable
22
+ thead
23
+ tr
24
+ th URL Pattern
25
+ th Type
26
+ th Scheme
27
+ th Credential
28
+ th Priority
29
+ th Status
30
+ th Actions
31
+ tbody
32
+ - @mappings.each do |mapping|
33
+ tr
34
+ td
35
+ code = mapping[:pattern]
36
+ td
37
+ span.tag class=("is-warning" if mapping[:pattern_type] == 'regex')
38
+ = mapping[:pattern_type] == 'regex' ? 'Regex' : 'String'
39
+ td
40
+ span.tag.is-primary.is-light = mapping[:scheme_name]
41
+ td
42
+ span.tag.is-info.is-light = mapping[:credential_name]
43
+ td
44
+ = mapping[:priority] || 1
45
+ td
46
+ span.tag class=(mapping[:active] == false ? 'is-danger' : 'is-success')
47
+ = mapping[:active] == false ? 'Inactive' : 'Active'
48
+ td
49
+ .buttons.are-small
50
+ a.button.is-info.is-light(href="/auth/mappings/#{mapping[:id]}")
51
+ span.icon.is-small
52
+ i.fas.fa-edit
53
+ span Edit
54
+ button.button.is-danger.is-light.delete-mapping-btn(data-id="#{mapping[:id]}")
55
+ span.icon.is-small
56
+ i.fas.fa-trash
57
+ span Delete
58
+
59
+ - else
60
+ .columns.is-centered
61
+ .column.is-half
62
+ .notification.is-info
63
+ h3.title.is-4 No URL Mappings Configured
64
+ p No URL mappings are currently configured.
65
+ p URL mappings tell agents which authentication to use for specific services automatically.
66
+
67
+ .content.mt-6
68
+ h2.title.is-4 How URL Mappings Work
69
+ .columns
70
+ .column.is-half
71
+ .content
72
+ h3.title.is-5
73
+ span.icon.has-text-primary
74
+ i.fas.fa-sitemap
75
+ span Pattern Matching
76
+ p When an agent makes a request to an external service, the system checks URL patterns to find the right authentication.
77
+ p Patterns can be simple strings (like "api.github.com") or complex regular expressions.
78
+
79
+ .column.is-half
80
+ .content
81
+ h3.title.is-5
82
+ span.icon.has-text-info
83
+ i.fas.fa-cogs
84
+ span Automatic Application
85
+ p Once a URL matches a pattern, the corresponding scheme and credential are automatically applied.
86
+ p This means agents don't need to worry about authentication details - it's handled automatically.
87
+
88
+ /! JS for delete action
89
+ javascript:
90
+ document.addEventListener('DOMContentLoaded', function() {
91
+ document.querySelectorAll('.delete-mapping-btn').forEach(function(btn) {
92
+ btn.addEventListener('click', function(e) {
93
+ e.preventDefault();
94
+ const id = btn.getAttribute('data-id');
95
+ if (confirm('Are you sure you want to delete this mapping?')) {
96
+ fetch(`/auth/mappings/${id}`, {
97
+ method: 'DELETE'
98
+ })
99
+ .then(response => response.json())
100
+ .then(data => {
101
+ if (data.success) {
102
+ if (typeof showToast === 'function') {
103
+ showToast(data.message, 'is-success');
104
+ }
105
+ window.location.reload();
106
+ } else {
107
+ if (typeof showToast === 'function') {
108
+ showToast(data.error || 'Failed to delete mapping', 'is-danger');
109
+ }
110
+ }
111
+ })
112
+ .catch(error => {
113
+ if (typeof showToast === 'function') {
114
+ showToast('Network error occurred', 'is-danger');
115
+ }
116
+ });
117
+ }
118
+ });
119
+ });
120
+ });
@@ -0,0 +1,274 @@
1
+ / File: lib/legate/web/views/auth_scheme_detail.slim
2
+ .content.mb-6
3
+ nav.breadcrumb(aria-label="breadcrumbs")
4
+ ul
5
+ li
6
+ a(href="/auth") Authentication
7
+ li
8
+ a(href="/auth/schemes") Schemes
9
+ li.is-active
10
+ a(href="/auth/schemes/#{@scheme[:name]}" aria-current="page") = @scheme[:name]
11
+
12
+ .level
13
+ .level-left
14
+ .level-item
15
+ div
16
+ h1.title.is-2 = @scheme[:name]
17
+ p.subtitle.is-4 = @scheme[:description]
18
+ .level-right
19
+ .level-item
20
+ .buttons
21
+ - if @scheme[:config_fields].any?
22
+ button.button.is-warning#edit-scheme-btn
23
+ span.icon
24
+ i.fas.fa-edit
25
+ span Configure
26
+ button.button.is-danger.is-outlined#delete-scheme-btn
27
+ span.icon
28
+ i.fas.fa-trash
29
+ span Delete
30
+
31
+ .columns
32
+ .column.is-half
33
+ .card
34
+ .card-header
35
+ p.card-header-title Scheme Information
36
+ .card-content
37
+ .content
38
+ table.table.is-narrow.is-fullwidth
39
+ tbody
40
+ tr
41
+ td <strong>Name:</strong>
42
+ td
43
+ code = @scheme[:name]
44
+ tr
45
+ td <strong>Type:</strong>
46
+ td
47
+ span.tag.is-info.is-light = @scheme[:scheme_type]
48
+ tr
49
+ td <strong>Class:</strong>
50
+ td
51
+ code = @scheme[:class_name]
52
+ tr
53
+ td <strong>Compatible Credential Types:</strong>
54
+ td
55
+ .tags
56
+ - @scheme[:compatible_credential_types].each do |type|
57
+ span.tag.is-success.is-light = type
58
+
59
+ - if @scheme[:config_fields].any?
60
+ .card.mt-4
61
+ .card-header
62
+ p.card-header-title Current Configuration
63
+ .card-content
64
+ .content
65
+ - if @scheme[:current_config].any?
66
+ table.table.is-narrow.is-fullwidth
67
+ tbody
68
+ - @scheme[:current_config].each do |key, value|
69
+ tr
70
+ td <strong>#{key.to_s.gsub('_', ' ').split.map(&:capitalize).join(' ')}:</strong>
71
+ td
72
+ - if key.include?('url')
73
+ a(href="#{value}" target="_blank") = value
74
+ - elsif key == 'use_pkce'
75
+ span.tag class=("is-success" if value) = value ? 'Enabled' : 'Disabled'
76
+ - else
77
+ code = value
78
+ - else
79
+ p.has-text-grey No configuration set
80
+
81
+ .column.is-half
82
+ .card
83
+ .card-header
84
+ p.card-header-title Usage Information
85
+ .card-content
86
+ .content
87
+ .columns.is-mobile.is-gapless.has-text-centered
88
+ .column
89
+ p.heading Compatible Credentials
90
+ p.title.is-4 = @scheme[:compatible_credentials].size
91
+ .column
92
+ p.heading URL Mappings
93
+ p.title.is-4 = @scheme[:url_mappings].size
94
+
95
+ - if @scheme[:compatible_credentials].any?
96
+ .card.mt-4
97
+ .card-header
98
+ p.card-header-title Compatible Credentials
99
+ .card-content
100
+ .content
101
+ - @scheme[:compatible_credentials].each do |credential|
102
+ .media
103
+ .media-left
104
+ span.icon.has-text-info
105
+ i.fas.fa-id-card
106
+ .media-content
107
+ p.title.is-6 = credential[:name]
108
+ p.subtitle.is-7 = credential[:description]
109
+ p.is-size-7.has-text-grey = credential[:masked_info]
110
+
111
+ - if @scheme[:url_mappings].any?
112
+ .card.mt-4
113
+ .card-header
114
+ p.card-header-title URL Mappings
115
+ .card-content
116
+ .content
117
+ .table-container
118
+ table.table.is-fullwidth.is-striped
119
+ thead
120
+ tr
121
+ th Pattern
122
+ th Type
123
+ th Credential
124
+ tbody
125
+ - @scheme[:url_mappings].each do |mapping|
126
+ tr
127
+ td
128
+ code = mapping[:pattern]
129
+ td
130
+ span.tag class=("is-warning" if mapping[:pattern_type] == 'regex')
131
+ = mapping[:pattern_type] == 'regex' ? 'Regex' : 'String'
132
+ td
133
+ span.tag.is-info.is-light = mapping[:credential_name]
134
+
135
+ - if @scheme[:config_fields].any?
136
+ /! Edit Scheme Configuration Modal
137
+ #edit-scheme-modal.modal
138
+ .modal-background
139
+ .modal-card
140
+ header.modal-card-head
141
+ p.modal-card-title Configure #{@scheme[:name]}
142
+ button.delete(aria-label="close")
143
+ section.modal-card-body
144
+ form#edit-scheme-form
145
+ - @scheme[:config_fields].each do |field|
146
+ .field
147
+ label.label = field[:label]
148
+ .control
149
+ - if field[:type] == 'checkbox'
150
+ label.checkbox
151
+ input(type="checkbox" name="#{field[:name]}" checked=(@scheme[:current_config][field[:name]] == true))
152
+ = " #{field[:label]}"
153
+ - else
154
+ input.input(type="#{field[:type]}" name="#{field[:name]}" value="#{@scheme[:current_config][field[:name]]}" placeholder="#{field[:placeholder] || ''}" required=field[:required])
155
+
156
+ footer.modal-card-foot
157
+ button.button.is-primary(type="submit" form="edit-scheme-form") Update Configuration
158
+ button.button Cancel
159
+
160
+ /! Delete Confirmation Modal
161
+ #delete-scheme-modal.modal
162
+ .modal-background
163
+ .modal-card
164
+ header.modal-card-head
165
+ p.modal-card-title Delete Scheme
166
+ button.delete(aria-label="close")
167
+ section.modal-card-body
168
+ .content
169
+ p Are you sure you want to delete the scheme <strong>#{@scheme[:name]}</strong>?
170
+ - if @scheme[:url_mappings].any?
171
+ .notification.is-warning
172
+ p <strong>Warning:</strong> This scheme is used by #{@scheme[:url_mappings].size} URL mapping(s). You must remove these mappings first.
173
+ - else
174
+ p This action cannot be undone.
175
+
176
+ footer.modal-card-foot
177
+ button.button.is-danger#confirm-delete-btn Delete Scheme
178
+ button.button Cancel
179
+
180
+ javascript:
181
+ document.addEventListener('DOMContentLoaded', function() {
182
+ const editSchemeBtn = document.getElementById('edit-scheme-btn');
183
+ const editSchemeModal = document.getElementById('edit-scheme-modal');
184
+ const editSchemeForm = document.getElementById('edit-scheme-form');
185
+ const deleteSchemeBtn = document.getElementById('delete-scheme-btn');
186
+ const deleteSchemeModal = document.getElementById('delete-scheme-modal');
187
+ const confirmDeleteBtn = document.getElementById('confirm-delete-btn');
188
+
189
+ // Show edit modal
190
+ if (editSchemeBtn) {
191
+ editSchemeBtn.addEventListener('click', function() {
192
+ editSchemeModal.classList.add('is-active');
193
+ });
194
+ }
195
+
196
+ // Show delete modal
197
+ deleteSchemeBtn.addEventListener('click', function() {
198
+ deleteSchemeModal.classList.add('is-active');
199
+ });
200
+
201
+ // Hide modals
202
+ function hideModals() {
203
+ if (editSchemeModal) editSchemeModal.classList.remove('is-active');
204
+ deleteSchemeModal.classList.remove('is-active');
205
+ }
206
+
207
+ document.querySelectorAll('.modal-background, .delete, .button:not(.is-primary):not(.is-danger)').forEach(function(element) {
208
+ element.addEventListener('click', hideModals);
209
+ });
210
+
211
+ // Handle edit form submission
212
+ if (editSchemeForm) {
213
+ editSchemeForm.addEventListener('submit', function(e) {
214
+ e.preventDefault();
215
+
216
+ const formData = new FormData(this);
217
+
218
+ fetch(`/auth/schemes/#{@scheme[:name]}`, {
219
+ method: 'PUT',
220
+ body: formData
221
+ })
222
+ .then(response => response.json())
223
+ .then(data => {
224
+ if (data.success) {
225
+ hideModals();
226
+ if (typeof showToast === 'function') {
227
+ showToast(data.message, 'is-success');
228
+ }
229
+ // Reload the page to show updated configuration
230
+ window.location.reload();
231
+ } else {
232
+ if (typeof showToast === 'function') {
233
+ showToast(data.error || 'Failed to update scheme', 'is-danger');
234
+ }
235
+ }
236
+ })
237
+ .catch(error => {
238
+ console.error('Error:', error);
239
+ if (typeof showToast === 'function') {
240
+ showToast('Network error occurred', 'is-danger');
241
+ }
242
+ });
243
+ });
244
+ }
245
+
246
+ // Handle delete confirmation
247
+ confirmDeleteBtn.addEventListener('click', function() {
248
+ fetch(`/auth/schemes/#{@scheme[:name]}`, {
249
+ method: 'DELETE'
250
+ })
251
+ .then(response => response.json())
252
+ .then(data => {
253
+ if (data.success) {
254
+ if (typeof showToast === 'function') {
255
+ showToast(data.message, 'is-success');
256
+ }
257
+ // Redirect to schemes list
258
+ window.location.href = '/auth/schemes';
259
+ } else {
260
+ hideModals();
261
+ if (typeof showToast === 'function') {
262
+ showToast(data.error || 'Failed to delete scheme', 'is-danger');
263
+ }
264
+ }
265
+ })
266
+ .catch(error => {
267
+ console.error('Error:', error);
268
+ hideModals();
269
+ if (typeof showToast === 'function') {
270
+ showToast('Network error occurred', 'is-danger');
271
+ }
272
+ });
273
+ });
274
+ });