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,221 @@
1
+ # Token Lifecycle Management
2
+
3
+ ## Overview
4
+
5
+ The `Legate::Auth::TokenManager` is responsible for managing the lifecycle of authentication tokens, including token storage, expiration handling, and automatic refresh. It serves as a critical component in the Legate authentication system, ensuring that valid tokens are always available for API requests.
6
+
7
+ ## Class Definition
8
+
9
+ ```ruby
10
+ module Legate
11
+ module Auth
12
+ class TokenManager
13
+ # Token lifecycle management implementation
14
+ end
15
+ end
16
+ end
17
+ ```
18
+
19
+ ## Key Features
20
+
21
+ - Caching of authentication tokens via the token store
22
+ - Automatic token refresh before expiration
23
+ - Token validation and expiration checking
24
+ - Support for all token-based authentication schemes
25
+ - Event callbacks for token lifecycle events
26
+ - Integration with the Legate token store
27
+
28
+ ## Constructor
29
+
30
+ ### `new`
31
+
32
+ Creates a new token manager instance.
33
+
34
+ **Parameters:**
35
+ - `token_store` (Legate::Auth::TokenStore): The token store for persisting tokens (positional argument)
36
+ - `config` (Hash, optional): Configuration options (positional argument, default: {})
37
+
38
+ **Examples:**
39
+
40
+ ```ruby
41
+ # Create a token manager with a token store
42
+ token_store = Legate::Auth::TokenStore.new(session_service)
43
+ token_manager = Legate::Auth::TokenManager.new(token_store)
44
+
45
+ # With configuration options
46
+ token_manager = Legate::Auth::TokenManager.new(token_store, { refresh_buffer: 300 })
47
+ ```
48
+
49
+ **Configuration keys** (with defaults):
50
+
51
+ | Key | Default | Description |
52
+ |-----|---------|-------------|
53
+ | `refresh_buffer` | `60` | Seconds before expiration to trigger refresh |
54
+ | `retry_max_attempts` | `3` | Maximum number of refresh retry attempts |
55
+ | `retry_delay` | `2` | Initial delay between retries (seconds) |
56
+ | `retry_backoff` | `1.5` | Backoff multiplier for subsequent retries |
57
+ | `auto_refresh` | `true` | Whether to automatically refresh tokens |
58
+ | `background_refresh` | `false` | Whether to refresh tokens in the background |
59
+
60
+ ## Instance Methods
61
+
62
+ ### `get_token`
63
+
64
+ Retrieves a valid token for the given scheme and credential, refreshing if necessary.
65
+
66
+ **Parameters:**
67
+ - `scheme` (Legate::Auth::Scheme): The authentication scheme
68
+ - `credential` (Legate::Auth::Credential): The credential to get a token for
69
+ - `force_refresh` (Boolean, optional): Force a token refresh even if the current token is valid (default: false)
70
+
71
+ **Returns:**
72
+ - Legate::Auth::ExchangedCredential: A valid token
73
+
74
+ **Examples:**
75
+
76
+ ```ruby
77
+ # Get a token (will auto-refresh if expired)
78
+ token = token_manager.get_token(scheme, credential)
79
+
80
+ # Force a fresh token
81
+ token = token_manager.get_token(scheme, credential, force_refresh: true)
82
+ ```
83
+
84
+ ### `refresh_token`
85
+
86
+ Refreshes a token using the scheme's refresh mechanism.
87
+
88
+ **Parameters:**
89
+ - `scheme` (Legate::Auth::Scheme): The authentication scheme
90
+ - `credential` (Legate::Auth::Credential): The credential associated with the token
91
+ - `token` (Legate::Auth::ExchangedCredential, optional): The token to refresh (default: nil)
92
+ - `cache_key` (String, optional): The cache key for the token (default: nil)
93
+
94
+ **Returns:**
95
+ - Legate::Auth::ExchangedCredential: The refreshed token
96
+
97
+ **Examples:**
98
+
99
+ ```ruby
100
+ # Refresh a specific token
101
+ refreshed = token_manager.refresh_token(scheme, credential, token)
102
+
103
+ # Refresh with a cache key
104
+ refreshed = token_manager.refresh_token(scheme, credential, token, 'my_cache_key')
105
+ ```
106
+
107
+ ### `invalidate_token`
108
+
109
+ Invalidates a cached token, removing it from the store.
110
+
111
+ **Parameters:**
112
+ - `cache_key` (String): The cache key of the token to invalidate
113
+
114
+ **Examples:**
115
+
116
+ ```ruby
117
+ token_manager.invalidate_token('oauth2_client123')
118
+ ```
119
+
120
+ ### `revoke_token`
121
+
122
+ Revokes a token using the scheme's revocation mechanism.
123
+
124
+ **Parameters:**
125
+ - `scheme` (Legate::Auth::Scheme): The authentication scheme
126
+ - `credential` (Legate::Auth::Credential): The credential associated with the token
127
+ - `token` (Legate::Auth::ExchangedCredential): The token to revoke
128
+
129
+ **Examples:**
130
+
131
+ ```ruby
132
+ token_manager.revoke_token(scheme, credential, token)
133
+ ```
134
+
135
+ ### `on`
136
+
137
+ Registers an event callback for token lifecycle events.
138
+
139
+ **Parameters:**
140
+ - `event` (Symbol): The event to listen for. Valid events are `:before_expiry`, `:refresh_success`, `:refresh_failure`, and `:invalidated`. Any other event raises `ArgumentError`.
141
+ - `&callback` (Block): The callback to invoke when the event occurs
142
+
143
+ Each callback receives a **single Hash** argument with keys including `:event`, `:token`, `:scheme`, `:credential` (plus event-specific extras such as `:error` for `:refresh_failure` or `:cache_key` for `:invalidated`).
144
+
145
+ **Examples:**
146
+
147
+ ```ruby
148
+ # Listen for successful token refreshes
149
+ token_manager.on(:refresh_success) do |data|
150
+ puts "Token refreshed for #{data[:scheme]&.scheme_type}"
151
+ end
152
+
153
+ # Listen for tokens approaching expiry
154
+ token_manager.on(:before_expiry) do |data|
155
+ puts "Token approaching expiration"
156
+ end
157
+
158
+ # Listen for refresh failures
159
+ token_manager.on(:refresh_failure) do |data|
160
+ puts "Refresh failed: #{data[:error]&.message}"
161
+ end
162
+ ```
163
+
164
+ ## Usage
165
+
166
+ ### Basic Usage
167
+
168
+ ```ruby
169
+ # Create a token store and manager
170
+ token_store = Legate::Auth::TokenStore.new(session_service)
171
+ token_manager = Legate::Auth::TokenManager.new(token_store)
172
+
173
+ # Get a token for an OAuth2 flow
174
+ token = token_manager.get_token(oauth2_scheme, oauth2_credential)
175
+
176
+ # Use the token
177
+ puts token[:access_token]
178
+ ```
179
+
180
+ ### With Automatic Refresh
181
+
182
+ ```ruby
183
+ # The token manager automatically refreshes expired tokens
184
+ token = token_manager.get_token(scheme, credential)
185
+
186
+ # If the token is expired and the scheme supports refresh,
187
+ # it will be automatically refreshed before being returned
188
+ ```
189
+
190
+ ## Token Structure
191
+
192
+ Tokens are stored as Legate::Auth::ExchangedCredential objects with attributes like:
193
+
194
+ ```ruby
195
+ {
196
+ access_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
197
+ refresh_token: 'rtok_abc123...',
198
+ id_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', # Optional, for OIDC
199
+ token_type: 'Bearer',
200
+ expires_in: 3600
201
+ }
202
+ ```
203
+
204
+ ## Integration with Authentication Schemes
205
+
206
+ The token manager integrates with authentication schemes to handle scheme-specific token operations:
207
+
208
+ ```ruby
209
+ # OAuth2 token management
210
+ token = token_manager.get_token(oauth2_scheme, oauth2_credential)
211
+
212
+ # Service account token management
213
+ token = token_manager.get_token(service_account_scheme, sa_credential)
214
+ ```
215
+
216
+ ## Related Classes
217
+
218
+ - [`Legate::Auth::TokenStore`](./token_store): Secure storage for tokens
219
+ - [`Legate::Auth::ExchangedCredential`](./exchanged_credential): Container for exchanged credentials
220
+ - [`Legate::Auth::Schemes::OAuth2`](./schemes/oauth2): OAuth2 authentication scheme
221
+ - [`Legate::Auth::ExconMiddleware`](./excon_middleware): HTTP client middleware
@@ -0,0 +1,146 @@
1
+ # Token Store
2
+
3
+ ## Overview
4
+
5
+ The `Legate::Auth::TokenStore` class caches authentication tokens in scoped session state (under the `auth` scope). It serves as the foundation for token management within the Legate authentication system.
6
+
7
+ > **Note:** `TokenStore` does **not** encrypt tokens. `store` persists the plaintext result of `token.to_h` into scoped state, and `get` reads it back as-is. For at-rest encryption, use the opt-in [`Legate::Auth::Encryption`](./encryption) module yourself.
8
+
9
+ ## Class Definition
10
+
11
+ ```ruby
12
+ module Legate
13
+ module Auth
14
+ class TokenStore
15
+ # Token store implementation
16
+ end
17
+ end
18
+ end
19
+ ```
20
+
21
+ ## Key Features
22
+
23
+ - Caching of authentication tokens in scoped session state
24
+ - Automatic expiry check on retrieval (expired tokens are cleared and return `nil`)
25
+ - Integration with Legate session service
26
+ - Token retrieval by key
27
+ - Support for multiple token sets
28
+
29
+ ## Constructor
30
+
31
+ ### `new`
32
+
33
+ Creates a new token store instance.
34
+
35
+ **Parameters:**
36
+ - `session_service` (Legate::SessionService::Base): The session service for persisting token data (positional argument)
37
+
38
+ **Examples:**
39
+
40
+ ```ruby
41
+ # Create a token store with the session service
42
+ token_store = Legate::Auth::TokenStore.new(session_service)
43
+ ```
44
+
45
+ ## Instance Methods
46
+
47
+ ### `store`
48
+
49
+ Stores a token under the given key by serializing it with `token.to_h` and saving it to scoped state. Only `Legate::Auth::ExchangedCredential` instances are accepted; anything else returns `false`.
50
+
51
+ **Parameters:**
52
+ - `key` (String): The key to store the token under
53
+ - `token` (Legate::Auth::ExchangedCredential): The token to store
54
+
55
+ **Returns:**
56
+ - Boolean: `true` if the token was stored, `false` otherwise
57
+
58
+ **Examples:**
59
+
60
+ ```ruby
61
+ token_store.store('oauth2_client123', exchanged_credential)
62
+ ```
63
+
64
+ ### `get`
65
+
66
+ Retrieves the token stored under the specified key, deserializing it back into an `ExchangedCredential`. If the stored token is expired it is cleared and `nil` is returned.
67
+
68
+ **Parameters:**
69
+ - `key` (String): The key to retrieve the token for
70
+
71
+ **Returns:**
72
+ - Legate::Auth::ExchangedCredential, or nil if not found or expired
73
+
74
+ **Examples:**
75
+
76
+ ```ruby
77
+ token = token_store.get('oauth2_client123')
78
+ ```
79
+
80
+ ### `clear`
81
+
82
+ Removes the token stored under the specified key.
83
+
84
+ **Parameters:**
85
+ - `key` (String): The key of the token to remove
86
+
87
+ **Examples:**
88
+
89
+ ```ruby
90
+ token_store.clear('oauth2_client123')
91
+ ```
92
+
93
+ ### `clear_all`
94
+
95
+ Removes all tokens from the token store.
96
+
97
+ **Examples:**
98
+
99
+ ```ruby
100
+ token_store.clear_all
101
+ ```
102
+
103
+ ## Token Storage and At-Rest Encryption
104
+
105
+ The token store persists tokens as plaintext `token.to_h` data in scoped session state. It does **not** encrypt them. The security of stored tokens therefore depends on the underlying session service (for example, in-memory storage in the default container deployment).
106
+
107
+ If you need at-rest encryption, apply the opt-in [`Legate::Auth::Encryption`](./encryption) module in your own storage layer (it requires the `rbnacl` gem and a Base64 key in `LEGATE_AUTH_ENCRYPTION_KEY`).
108
+
109
+ ```ruby
110
+ # Tokens are stored as-is (no automatic encryption)
111
+ token_store.store('client123', token)
112
+
113
+ # Retrieved as-is (expired tokens are cleared and return nil)
114
+ token = token_store.get('client123')
115
+ ```
116
+
117
+ ## Integration with Session Service
118
+
119
+ The token store integrates with the Legate session service to persist tokens across requests:
120
+
121
+ ```ruby
122
+ # Create an in-memory session service
123
+ session_service = Legate::SessionService::InMemory.new
124
+
125
+ # Create a token store with the session service
126
+ token_store = Legate::Auth::TokenStore.new(session_service)
127
+ ```
128
+
129
+ ## Usage with Token Manager
130
+
131
+ The token store is typically used via the `TokenManager` rather than directly:
132
+
133
+ ```ruby
134
+ # Create a token store and manager
135
+ token_store = Legate::Auth::TokenStore.new(session_service)
136
+ token_manager = Legate::Auth::TokenManager.new(token_store)
137
+
138
+ # The token manager uses the store internally
139
+ token = token_manager.get_token(scheme, credential)
140
+ ```
141
+
142
+ ## Related Classes
143
+
144
+ - [`Legate::Auth::TokenManager`](./token_manager): Token lifecycle management
145
+ - [`Legate::Auth::Encryption`](./encryption): Opt-in encryption utilities (not wired into TokenStore)
146
+ - [`Legate::SessionService::Base`](../../core_concepts/legate_session_service): Base session service class
@@ -0,0 +1,166 @@
1
+ # Tool Context Authentication Extensions
2
+
3
+ ## Overview
4
+
5
+ The `Legate::Auth::ToolContextExtension` module extends the `Legate::ToolContext` class with authentication-specific functionality, allowing tools to easily access and manage authentication credentials. This extension is critical for tools that need to authenticate with external APIs.
6
+
7
+ ## Module Definition
8
+
9
+ ```ruby
10
+ module Legate
11
+ module Auth
12
+ module ToolContextExtension
13
+ # Authentication extensions for ToolContext
14
+ end
15
+ end
16
+ end
17
+ ```
18
+
19
+ ## Key Features
20
+
21
+ - Access to authentication runners and token stores
22
+ - Managed authentication sessions
23
+ - Integration with interactive authentication flows
24
+ - Support for all authentication schemes
25
+
26
+ ## Methods
27
+
28
+ ### `auth_runner`
29
+
30
+ Returns the authentication runner for managing authentication flows.
31
+
32
+ **Returns:**
33
+ - The authentication runner instance
34
+
35
+ **Examples:**
36
+
37
+ ```ruby
38
+ # In a tool's implementation
39
+ runner = context.auth_runner
40
+ ```
41
+
42
+ ### `get_token_store`
43
+
44
+ Returns the token store for the current session.
45
+
46
+ **Returns:**
47
+ - Legate::Auth::TokenStore: The token store
48
+
49
+ **Examples:**
50
+
51
+ ```ruby
52
+ token_store = context.get_token_store
53
+ ```
54
+
55
+ ### `with_authentication`
56
+
57
+ Wraps a block with authentication handling. If authentication is required, it will initiate the authentication flow and retry the block once authentication is complete.
58
+
59
+ **Parameters:**
60
+ - `&block` (Block): The block to execute with authentication
61
+
62
+ **Examples:**
63
+
64
+ ```ruby
65
+ # In a tool's implementation
66
+ def perform_execution(params, context)
67
+ context.with_authentication do
68
+ # Make authenticated API calls here
69
+ # If auth fails, the flow will be initiated automatically
70
+ response = make_api_request(context)
71
+ { status: :success, result: response }
72
+ end
73
+ end
74
+ ```
75
+
76
+ ### `auth_session`
77
+
78
+ Creates an authentication session for the given scheme and credential.
79
+
80
+ **Parameters:**
81
+ - `scheme` (Legate::Auth::Scheme): The authentication scheme
82
+ - `credential` (Legate::Auth::Credential): The credential to use
83
+ - `**options` (Hash): Additional options for the authentication session
84
+
85
+ **Returns:**
86
+ - An authentication session object
87
+
88
+ **Examples:**
89
+
90
+ ```ruby
91
+ session = context.auth_session(oauth2_scheme, oauth2_credential)
92
+ ```
93
+
94
+ ### `handle_auth_response`
95
+
96
+ Handles an authentication response from an interactive authentication flow (e.g., OAuth2 callback).
97
+
98
+ **Parameters:**
99
+ - `request_id` (String): The authentication request ID
100
+ - `response` (Hash): The authentication response data
101
+
102
+ **Examples:**
103
+
104
+ ```ruby
105
+ # When the OAuth2 callback is received
106
+ context.handle_auth_response('req_123456', {
107
+ code: params[:code],
108
+ state: params[:state]
109
+ })
110
+ ```
111
+
112
+ ### `cancel_auth_flow`
113
+
114
+ Cancels an in-progress authentication flow.
115
+
116
+ **Parameters:**
117
+ - `request_id` (String): The authentication request ID to cancel
118
+ - `reason` (String, optional): The reason for cancellation (default: nil)
119
+
120
+ **Examples:**
121
+
122
+ ```ruby
123
+ # Cancel an authentication flow
124
+ context.cancel_auth_flow('req_123456', 'User declined')
125
+ ```
126
+
127
+ ## Integration with Tool Implementation
128
+
129
+ Here's a complete example of how to use the tool context extensions in a custom tool:
130
+
131
+ ```ruby
132
+ class MyApiTool < Legate::Tool
133
+ def perform_execution(params, context)
134
+ context.with_authentication do
135
+ # Get a token store for caching
136
+ token_store = context.get_token_store
137
+
138
+ # Create an auth session
139
+ session = context.auth_session(
140
+ Legate::Auth::Schemes::OAuth2.new(
141
+ authorization_url: 'https://auth.example.com/authorize',
142
+ token_url: 'https://auth.example.com/token'
143
+ ),
144
+ Legate::Auth::Credential.new(
145
+ auth_type: :oauth2,
146
+ client_id: ENV['CLIENT_ID'],
147
+ client_secret: ENV['CLIENT_SECRET']
148
+ )
149
+ )
150
+
151
+ # Make authenticated API request
152
+ conn = Excon.new('https://api.example.com')
153
+ response = conn.get(path: '/data')
154
+
155
+ # Process response
156
+ { result: JSON.parse(response.body) }
157
+ end
158
+ end
159
+ end
160
+ ```
161
+
162
+ ## Related Classes
163
+
164
+ - [`Legate::Auth::Config`](./config): Authentication configuration
165
+ - [`Legate::Auth::TokenManager`](./token_manager): Token lifecycle management
166
+ - [`Legate::Auth::Scheme`](./scheme): Base class for authentication schemes