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,562 @@
1
+ / Agent Authentication Management Page
2
+ .container
3
+ .section
4
+ .level
5
+ .level-left
6
+ .level-item
7
+ div
8
+ h1.title.is-3 Authentication for Agent: #{@agent_auth_data[:name]}
9
+ p.subtitle.is-5.mt-1 #{@agent_auth_data[:description]}
10
+ .level-right
11
+ .level-item
12
+ a.button.is-light href="/agents/#{@agent_auth_data[:name]}"
13
+ span.icon
14
+ i.fas.fa-arrow-left
15
+ span Back to Agent
16
+
17
+ / Authentication Status Card
18
+ .card.mb-5
19
+ .card-header
20
+ .card-header-title
21
+ span.icon.mr-2
22
+ i.fas.fa-shield-alt
23
+ | Authentication Status
24
+ .card-content
25
+ - status = @agent_auth_data[:auth_status]
26
+ .notification class="is-#{status[:status] == :success ? 'success' : status[:status] == :warning ? 'warning' : 'danger'}"
27
+ .level
28
+ .level-left
29
+ .level-item
30
+ span.icon
31
+ i.fas class="fa-#{status[:status] == :success ? 'check-circle' : status[:status] == :warning ? 'exclamation-triangle' : 'times-circle'}"
32
+ strong #{status[:message]}
33
+ .level-right
34
+ .level-item
35
+ button.button.is-small.is-outlined id="refresh-status" hx-get="/agents/#{@agent_auth_data[:name]}/auth/status" hx-target="#status-details" hx-swap="innerHTML"
36
+ span.icon
37
+ i.fas.fa-sync-alt
38
+ span Refresh
39
+
40
+ #status-details
41
+ - if status[:details]
42
+ .content.is-small.mt-3
43
+ - if status[:status] == :error && status[:details][:issues]
44
+ strong Issues Found:
45
+ ul
46
+ - status[:details][:issues].each do |issue|
47
+ li #{issue}
48
+ - else
49
+ .columns.is-mobile
50
+ .column
51
+ .has-text-centered
52
+ .heading Scheme Assignments
53
+ .title.is-4 #{status[:details][:scheme_assignments] || 0}
54
+ .column
55
+ .has-text-centered
56
+ .heading Credential Assignments
57
+ .title.is-4 #{status[:details][:credential_assignments] || 0}
58
+ .column
59
+ .has-text-centered
60
+ .heading URL Mappings
61
+ .title.is-4 #{status[:details][:url_mappings] || 0}
62
+ - if status[:details][:global_mappings]
63
+ .column
64
+ .has-text-centered
65
+ .heading Global Mappings
66
+ .title.is-4 #{status[:details][:global_mappings]}
67
+
68
+ .columns
69
+ / Left Column - Authentication Assignments
70
+ .column.is-half
71
+ / Scheme Assignments Card
72
+ .card.mb-5
73
+ .card-header
74
+ .card-header-title
75
+ span.icon.mr-2
76
+ i.fas.fa-cogs
77
+ | Scheme Assignments
78
+ .card-header-icon
79
+ button.button.is-small.is-primary id="add-scheme-btn"
80
+ span.icon
81
+ i.fas.fa-plus
82
+ span Add Scheme
83
+ .card-content
84
+ #scheme-assignments
85
+ - if @agent_auth_data[:scheme_assignments].empty?
86
+ .has-text-grey-light.has-text-centered.py-4
87
+ span.icon.is-large
88
+ i.fas.fa-inbox.fa-2x
89
+ p.mt-2 No scheme assignments configured
90
+ p.is-size-7 Agent will use global authentication settings
91
+ - else
92
+ .table-container
93
+ table.table.is-fullwidth.is-striped
94
+ thead
95
+ tr
96
+ th Service
97
+ th Scheme
98
+ th Actions
99
+ tbody
100
+ - @agent_auth_data[:scheme_assignments].each do |service, scheme_name|
101
+ tr
102
+ td
103
+ span.tag.is-info #{service}
104
+ td
105
+ span.tag.is-primary #{scheme_name}
106
+ td
107
+ button.button.is-small.is-danger.is-outlined onclick="removeAssignment('scheme', '#{service}')"
108
+ span.icon
109
+ i.fas.fa-trash
110
+ span Remove
111
+
112
+ / Credential Assignments Card
113
+ .card.mb-5
114
+ .card-header
115
+ .card-header-title
116
+ span.icon.mr-2
117
+ i.fas.fa-key
118
+ | Credential Assignments
119
+ .card-header-icon
120
+ button.button.is-small.is-primary id="add-credential-btn"
121
+ span.icon
122
+ i.fas.fa-plus
123
+ span Add Credential
124
+ .card-content
125
+ #credential-assignments
126
+ - if @agent_auth_data[:credential_assignments].empty?
127
+ .has-text-grey-light.has-text-centered.py-4
128
+ span.icon.is-large
129
+ i.fas.fa-inbox.fa-2x
130
+ p.mt-2 No credential assignments configured
131
+ p.is-size-7 Agent will use global authentication settings
132
+ - else
133
+ .table-container
134
+ table.table.is-fullwidth.is-striped
135
+ thead
136
+ tr
137
+ th Service
138
+ th Credential
139
+ th Actions
140
+ tbody
141
+ - @agent_auth_data[:credential_assignments].each do |service, credential_name|
142
+ tr
143
+ td
144
+ span.tag.is-info #{service}
145
+ td
146
+ span.tag.is-warning #{credential_name}
147
+ td
148
+ button.button.is-small.is-danger.is-outlined onclick="removeAssignment('credential', '#{service}')"
149
+ span.icon
150
+ i.fas.fa-trash
151
+ span Remove
152
+
153
+ / Right Column - URL Mappings and Testing
154
+ .column.is-half
155
+ / URL Mappings Card
156
+ .card.mb-5
157
+ .card-header
158
+ .card-header-title
159
+ span.icon.mr-2
160
+ i.fas.fa-link
161
+ | URL Mappings
162
+ .card-header-icon
163
+ button.button.is-small.is-primary id="add-mapping-btn"
164
+ span.icon
165
+ i.fas.fa-plus
166
+ span Add Mapping
167
+ .card-content
168
+ #url-mappings
169
+ - if @agent_auth_data[:url_mappings].empty?
170
+ .has-text-grey-light.has-text-centered.py-4
171
+ span.icon.is-large
172
+ i.fas.fa-inbox.fa-2x
173
+ p.mt-2 No URL mappings configured
174
+ p.is-size-7 Agent will use global URL mappings
175
+ - else
176
+ - @agent_auth_data[:url_mappings].each_with_index do |mapping, index|
177
+ .box.is-small.mb-3
178
+ .level.is-mobile
179
+ .level-left
180
+ .level-item
181
+ .content.is-small
182
+ strong #{mapping['pattern'] || mapping[:pattern]}
183
+ br
184
+ span.tag.is-small.is-primary #{mapping['scheme_name'] || mapping[:scheme_name]}
185
+ span.tag.is-small.is-warning.ml-1 #{mapping['credential_name'] || mapping[:credential_name]}
186
+ .level-right
187
+ .level-item
188
+ button.button.is-small.is-danger.is-outlined onclick="removeUrlMapping(#{index})"
189
+ span.icon
190
+ i.fas.fa-trash
191
+
192
+ / Testing Card
193
+ .card
194
+ .card-header
195
+ .card-header-title
196
+ span.icon.mr-2
197
+ i.fas.fa-vial
198
+ | Authentication Testing
199
+ .card-content
200
+ .field
201
+ label.label Test URL (Optional)
202
+ .control.has-icons-left
203
+ input.input#test-url type="text" placeholder="https://api.example.com/endpoint"
204
+ span.icon.is-small.is-left
205
+ i.fas.fa-link
206
+ p.help Enter a URL to test authentication resolution for this agent
207
+
208
+ .field
209
+ .control
210
+ button.button.is-primary.is-fullwidth id="test-auth-btn"
211
+ span.icon
212
+ i.fas.fa-play
213
+ span Test Authentication
214
+
215
+ #test-results.mt-4 style="display: none;"
216
+
217
+ / Modals
218
+ / Add Scheme Assignment Modal
219
+ .modal#add-scheme-modal
220
+ .modal-background
221
+ .modal-card
222
+ header.modal-card-head
223
+ p.modal-card-title Add Scheme Assignment
224
+ button.delete aria-label="close" onclick="closeModal('add-scheme-modal')"
225
+ section.modal-card-body
226
+ .field
227
+ label.label Service Name
228
+ .control
229
+ input.input#scheme-service type="text" placeholder="e.g., github, slack, openai"
230
+ p.help The service or domain this scheme applies to
231
+
232
+ .field
233
+ label.label Authentication Scheme
234
+ .control
235
+ .select.is-fullwidth
236
+ select#scheme-select
237
+ option value="" Select a scheme...
238
+ - @agent_auth_data[:available_schemes].each do |scheme|
239
+ option value="#{scheme[:name]}" #{scheme[:name]} (#{scheme[:type]})
240
+ footer.modal-card-foot
241
+ button.button.is-primary onclick="addSchemeAssignment()" Add Assignment
242
+ button.button onclick="closeModal('add-scheme-modal')" Cancel
243
+
244
+ / Add Credential Assignment Modal
245
+ .modal#add-credential-modal
246
+ .modal-background
247
+ .modal-card
248
+ header.modal-card-head
249
+ p.modal-card-title Add Credential Assignment
250
+ button.delete aria-label="close" onclick="closeModal('add-credential-modal')"
251
+ section.modal-card-body
252
+ .field
253
+ label.label Service Name
254
+ .control
255
+ input.input#credential-service type="text" placeholder="e.g., github, slack, openai"
256
+ p.help The service or domain this credential applies to
257
+
258
+ .field
259
+ label.label Authentication Credential
260
+ .control
261
+ .select.is-fullwidth
262
+ select#credential-select
263
+ option value="" Select a credential...
264
+ - @agent_auth_data[:available_credentials].each do |credential|
265
+ option value="#{credential[:name]}" #{credential[:name]} (#{credential[:type]})
266
+ footer.modal-card-foot
267
+ button.button.is-primary onclick="addCredentialAssignment()" Add Assignment
268
+ button.button onclick="closeModal('add-credential-modal')" Cancel
269
+
270
+ / Add URL Mapping Modal
271
+ .modal#add-mapping-modal
272
+ .modal-background
273
+ .modal-card
274
+ header.modal-card-head
275
+ p.modal-card-title Add URL Mapping
276
+ button.delete aria-label="close" onclick="closeModal('add-mapping-modal')"
277
+ section.modal-card-body
278
+ .field
279
+ label.label URL Pattern
280
+ .control
281
+ input.input#mapping-pattern type="text" placeholder="https://api.github.com/*"
282
+ p.help Use * for wildcards or enter exact URLs
283
+
284
+ .field
285
+ label.label Pattern Type
286
+ .control
287
+ .select.is-fullwidth
288
+ select#pattern-type
289
+ option value="wildcard" selected Wildcard
290
+ option value="exact" Exact Match
291
+ option value="regex" Regular Expression
292
+
293
+ .field
294
+ label.label Authentication Scheme
295
+ .control
296
+ .select.is-fullwidth
297
+ select#mapping-scheme
298
+ option value="" Select a scheme...
299
+ - @agent_auth_data[:available_schemes].each do |scheme|
300
+ option value="#{scheme[:name]}" #{scheme[:name]} (#{scheme[:type]})
301
+
302
+ .field
303
+ label.label Authentication Credential
304
+ .control
305
+ .select.is-fullwidth
306
+ select#mapping-credential
307
+ option value="" Select a credential...
308
+ - @agent_auth_data[:available_credentials].each do |credential|
309
+ option value="#{credential[:name]}" #{credential[:name]} (#{credential[:type]})
310
+
311
+ .field
312
+ label.label Priority
313
+ .control
314
+ input.input#mapping-priority type="number" value="1" min="1" max="100"
315
+ p.help Higher numbers = higher priority (1-100)
316
+ footer.modal-card-foot
317
+ button.button.is-primary onclick="addUrlMapping()" Add Mapping
318
+ button.button onclick="closeModal('add-mapping-modal')" Cancel
319
+
320
+ javascript:
321
+ const agentName = '#{@agent_auth_data[:name]}';
322
+
323
+ // Modal management
324
+ function openModal(modalId) {
325
+ document.getElementById(modalId).classList.add('is-active');
326
+ }
327
+
328
+ function closeModal(modalId) {
329
+ document.getElementById(modalId).classList.remove('is-active');
330
+ // Clear form fields
331
+ const modal = document.getElementById(modalId);
332
+ const inputs = modal.querySelectorAll('input, select');
333
+ inputs.forEach(input => {
334
+ if (input.type === 'number') {
335
+ input.value = input.defaultValue || '1';
336
+ } else {
337
+ input.value = '';
338
+ }
339
+ });
340
+ }
341
+
342
+ // Event listeners for modal buttons
343
+ document.getElementById('add-scheme-btn').addEventListener('click', () => openModal('add-scheme-modal'));
344
+ document.getElementById('add-credential-btn').addEventListener('click', () => openModal('add-credential-modal'));
345
+ document.getElementById('add-mapping-btn').addEventListener('click', () => openModal('add-mapping-modal'));
346
+
347
+ // Add scheme assignment
348
+ function addSchemeAssignment() {
349
+ const service = document.getElementById('scheme-service').value.trim();
350
+ const schemeName = document.getElementById('scheme-select').value;
351
+
352
+ if (!service || !schemeName) {
353
+ alert('Please fill in all fields');
354
+ return;
355
+ }
356
+
357
+ fetch(`/agents/${agentName}/auth/assign`, {
358
+ method: 'POST',
359
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
360
+ body: new URLSearchParams({
361
+ assignment_type: 'scheme',
362
+ service: service,
363
+ auth_name: schemeName
364
+ })
365
+ })
366
+ .then(response => response.json())
367
+ .then(data => {
368
+ if (data.success) {
369
+ closeModal('add-scheme-modal');
370
+ location.reload(); // Refresh to show updated assignments
371
+ } else {
372
+ alert('Error: ' + (data.error || 'Failed to add scheme assignment'));
373
+ }
374
+ })
375
+ .catch(error => {
376
+ console.error('Error:', error);
377
+ alert('Error adding scheme assignment');
378
+ });
379
+ }
380
+
381
+ // Add credential assignment
382
+ function addCredentialAssignment() {
383
+ const service = document.getElementById('credential-service').value.trim();
384
+ const credentialName = document.getElementById('credential-select').value;
385
+
386
+ if (!service || !credentialName) {
387
+ alert('Please fill in all fields');
388
+ return;
389
+ }
390
+
391
+ fetch(`/agents/${agentName}/auth/assign`, {
392
+ method: 'POST',
393
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
394
+ body: new URLSearchParams({
395
+ assignment_type: 'credential',
396
+ service: service,
397
+ auth_name: credentialName
398
+ })
399
+ })
400
+ .then(response => response.json())
401
+ .then(data => {
402
+ if (data.success) {
403
+ closeModal('add-credential-modal');
404
+ location.reload(); // Refresh to show updated assignments
405
+ } else {
406
+ alert('Error: ' + (data.error || 'Failed to add credential assignment'));
407
+ }
408
+ })
409
+ .catch(error => {
410
+ console.error('Error:', error);
411
+ alert('Error adding credential assignment');
412
+ });
413
+ }
414
+
415
+ // Remove assignment
416
+ function removeAssignment(type, service) {
417
+ if (!confirm(`Remove ${type} assignment for service '${service}'?`)) {
418
+ return;
419
+ }
420
+
421
+ fetch(`/agents/${agentName}/auth/remove`, {
422
+ method: 'DELETE',
423
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
424
+ body: new URLSearchParams({
425
+ assignment_type: type,
426
+ service: service
427
+ })
428
+ })
429
+ .then(response => response.json())
430
+ .then(data => {
431
+ if (data.success) {
432
+ location.reload(); // Refresh to show updated assignments
433
+ } else {
434
+ alert('Error: ' + (data.error || 'Failed to remove assignment'));
435
+ }
436
+ })
437
+ .catch(error => {
438
+ console.error('Error:', error);
439
+ alert('Error removing assignment');
440
+ });
441
+ }
442
+
443
+ // Add URL mapping
444
+ function addUrlMapping() {
445
+ const pattern = document.getElementById('mapping-pattern').value.trim();
446
+ const patternType = document.getElementById('pattern-type').value;
447
+ const schemeName = document.getElementById('mapping-scheme').value;
448
+ const credentialName = document.getElementById('mapping-credential').value;
449
+ const priority = document.getElementById('mapping-priority').value;
450
+
451
+ if (!pattern || !schemeName || !credentialName) {
452
+ alert('Please fill in all required fields');
453
+ return;
454
+ }
455
+
456
+ fetch(`/agents/${agentName}/auth/url-mapping`, {
457
+ method: 'POST',
458
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
459
+ body: new URLSearchParams({
460
+ pattern: pattern,
461
+ pattern_type: patternType,
462
+ scheme_name: schemeName,
463
+ credential_name: credentialName,
464
+ priority: priority
465
+ })
466
+ })
467
+ .then(response => response.json())
468
+ .then(data => {
469
+ if (data.success) {
470
+ closeModal('add-mapping-modal');
471
+ location.reload(); // Refresh to show updated mappings
472
+ } else {
473
+ alert('Error: ' + (data.error || 'Failed to add URL mapping'));
474
+ }
475
+ })
476
+ .catch(error => {
477
+ console.error('Error:', error);
478
+ alert('Error adding URL mapping');
479
+ });
480
+ }
481
+
482
+ // Remove URL mapping
483
+ function removeUrlMapping(mappingId) {
484
+ if (!confirm('Remove this URL mapping?')) {
485
+ return;
486
+ }
487
+
488
+ fetch(`/agents/${agentName}/auth/url-mapping/${mappingId}`, {
489
+ method: 'DELETE'
490
+ })
491
+ .then(response => response.json())
492
+ .then(data => {
493
+ if (data.success) {
494
+ location.reload(); // Refresh to show updated mappings
495
+ } else {
496
+ alert('Error: ' + (data.error || 'Failed to remove URL mapping'));
497
+ }
498
+ })
499
+ .catch(error => {
500
+ console.error('Error:', error);
501
+ alert('Error removing URL mapping');
502
+ });
503
+ }
504
+
505
+ // Test authentication
506
+ document.getElementById('test-auth-btn').addEventListener('click', function() {
507
+ const testUrl = document.getElementById('test-url').value.trim();
508
+ const resultsDiv = document.getElementById('test-results');
509
+
510
+ // Show loading state
511
+ this.classList.add('is-loading');
512
+ resultsDiv.style.display = 'block';
513
+ resultsDiv.innerHTML = '<div class="notification is-info">Running authentication tests...</div>';
514
+
515
+ const params = new URLSearchParams();
516
+ if (testUrl) {
517
+ params.append('test_url', testUrl);
518
+ }
519
+
520
+ Legate.apiRequest(`/agents/${agentName}/auth/test`, {
521
+ method: 'POST',
522
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
523
+ body: params
524
+ })
525
+ .then(data => {
526
+ this.classList.remove('is-loading');
527
+
528
+ if (data.success !== undefined) {
529
+ let html = `<div class="notification is-${data.success ? 'success' : 'danger'}">`;
530
+ html += `<strong>Test Results for Agent: ${escapeHtml(data.agent_name)}</strong><br>`;
531
+ html += `Overall Status: ${data.success ? 'PASSED' : 'FAILED'}<br>`;
532
+ html += `Agent-specific Authentication: ${data.has_agent_auth ? 'Yes' : 'No (using global defaults)'}`;
533
+ html += '</div>';
534
+
535
+ if (data.tests && data.tests.length > 0) {
536
+ html += '<div class="content"><strong>Test Details:</strong><ul>';
537
+ data.tests.forEach(test => {
538
+ const statusClass = test.status === 'passed' ? 'has-text-success' :
539
+ test.status === 'warning' ? 'has-text-warning' : 'has-text-danger';
540
+ html += `<li class="${statusClass}"><strong>${escapeHtml(test.name)}:</strong> ${escapeHtml(test.message)}</li>`;
541
+ });
542
+ html += '</ul></div>';
543
+ }
544
+
545
+ resultsDiv.innerHTML = html;
546
+ } else {
547
+ Legate.renderError(resultsDiv, data.error);
548
+ }
549
+ })
550
+ .catch(error => {
551
+ this.classList.remove('is-loading');
552
+ console.error('Error:', error);
553
+ resultsDiv.innerHTML = '<div class="notification is-danger">Error running authentication tests</div>';
554
+ });
555
+ });
556
+
557
+ // Close modals when clicking background
558
+ document.querySelectorAll('.modal-background').forEach(bg => {
559
+ bg.addEventListener('click', function() {
560
+ this.closest('.modal').classList.remove('is-active');
561
+ });
562
+ });