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,118 @@
1
+ # File: lib/legate/errors.rb
2
+ # frozen_string_literal: true
3
+
4
+ # Single authoritative error hierarchy for the Legate framework.
5
+ # All Legate error classes are defined here.
6
+
7
+ module Legate
8
+ # Base error class for all Legate errors.
9
+ class Error < StandardError; end
10
+
11
+ # --- Configuration Errors ---
12
+
13
+ # Raised when a required configuration is missing or invalid.
14
+ class ConfigurationError < Error; end
15
+
16
+ # --- State Errors ---
17
+
18
+ # Raised when an invalid prefix is used in state keys.
19
+ class InvalidPrefixError < Error; end
20
+
21
+ # Raised when state value cannot be serialized.
22
+ class SerializationError < Error; end
23
+
24
+ # --- Tool Errors ---
25
+
26
+ # Base class for errors raised during tool execution.
27
+ # Supports wrapping an original cause exception for debugging.
28
+ class ToolError < Error
29
+ # @param message [String] The error message.
30
+ # @param cause [Exception, nil] The original exception that triggered this error.
31
+ def initialize(message = nil, cause: nil)
32
+ super(message)
33
+ @cause = cause
34
+ set_backtrace(cause.backtrace) if cause&.backtrace
35
+ end
36
+
37
+ # The explicit wrapped cause if one was passed, otherwise Ruby's implicit
38
+ # cause (set automatically when the error is raised inside a rescue). Falling
39
+ # back to `super` means a caller that does `raise ToolError, msg` inside a
40
+ # rescue still surfaces the real cause instead of nil.
41
+ # @return [Exception, nil] The original exception that caused this error.
42
+ def cause
43
+ @cause || super
44
+ end
45
+ end
46
+
47
+ # Raised when tool arguments are invalid (e.g., missing, wrong type).
48
+ class ToolArgumentError < ToolError; end
49
+
50
+ # Raised when a tool encounters a network-related issue (connection failures, DNS, SSL errors).
51
+ class ToolNetworkError < ToolError; end
52
+
53
+ # Raised when SSL/TLS certificate verification fails during an HTTP request.
54
+ class ToolCertificateError < ToolNetworkError; end
55
+
56
+ # Raised when a tool operation times out (connection, read, or write timeout).
57
+ class ToolTimeoutError < ToolError; end
58
+
59
+ # Raised when an HTTP request receives an unsuccessful status code (4xx or 5xx).
60
+ class ToolHttpError < ToolError
61
+ # @return [Object, nil] The HTTP response object (provides status, headers, body).
62
+ attr_reader :response
63
+
64
+ # @param message [String] The error message.
65
+ # @param response [Object, nil] The HTTP response object.
66
+ # @param cause [Exception, nil] The original exception.
67
+ def initialize(message = nil, response: nil, cause: nil)
68
+ super(message, cause: cause)
69
+ @response = response
70
+ end
71
+ end
72
+
73
+ # --- Webhook Errors ---
74
+
75
+ # Raised for webhook configuration or processing errors within the listener.
76
+ class WebhookConfigurationError < Error; end
77
+
78
+ # --- Storage Errors ---
79
+
80
+ # Raised for definition or session storage operation failures.
81
+ class StoreError < Error; end
82
+
83
+ # --- Definition Store Errors ---
84
+ module DefinitionStore
85
+ class Error < Legate::Error; end
86
+ class StoreError < Error; end
87
+ end
88
+
89
+ # --- MCP Errors ---
90
+ module Mcp
91
+ # Base class for MCP-specific errors.
92
+ class Error < Legate::Error; end
93
+
94
+ # Raised when an MCP connection cannot be established.
95
+ class ConnectionError < Error; end
96
+
97
+ # Raised for MCP protocol violations or JSON-RPC formatting errors.
98
+ class ProtocolError < Error; end
99
+
100
+ # Error received from a remote MCP server during a tool call.
101
+ class RemoteToolError < Error
102
+ attr_reader :code, :data
103
+
104
+ def initialize(message, code = nil, data = nil)
105
+ super(message)
106
+ @code = code
107
+ @data = data
108
+ end
109
+
110
+ def to_s
111
+ str = super
112
+ str += " (Code: #{@code})" if @code
113
+ str += " Data: #{@data.inspect}" if @data
114
+ str
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,161 @@
1
+ # File: lib/legate/event.rb
2
+ # frozen_string_literal: true
3
+
4
+ require 'time'
5
+ require 'json' # Needed for serialization examples/potential
6
+ require 'securerandom' # Required for SecureRandom
7
+
8
+ module Legate
9
+ # Represents a single interaction or step within a Session's history.
10
+ # Immutable object after creation.
11
+ #
12
+ # @!attribute [r] role
13
+ # @return [Symbol] The origin of the event (:user, :agent, :tool_request, :tool_result).
14
+ # @!attribute [r] content
15
+ # @return [String, Hash] The payload of the event (e.g., user text, agent text, tool params, tool result hash).
16
+ # @!attribute [r] timestamp
17
+ # @return [Time] The UTC time the event occurred.
18
+ # @!attribute [r] tool_name
19
+ # @return [Symbol, nil] The name of the tool involved (for :tool_request, :tool_result roles).
20
+ # @!attribute [r] state_delta
21
+ # @return [Hash, nil] Optional hash representing state changes associated with this event. Keys should be symbols.
22
+ # @!attribute [r] event_id
23
+ # @return [String] A unique ID for this specific event instance.
24
+ Event = Struct.new(:role, :content, :timestamp, :tool_name, :state_delta, :event_id, keyword_init: true) do
25
+ # @param role [Symbol] :user, :agent, :tool_request, :tool_result
26
+ # @param content [String, Hash] Event payload. Should be JSON-serializable.
27
+ # @param timestamp [Time, nil] Timestamp (defaults to Time.now.utc).
28
+ # @param tool_name [Symbol, nil] Name of the tool if role is tool related.
29
+ # @param state_delta [Hash, nil] State changes to apply with this event.
30
+ # @param event_id [String, nil] Unique event ID (defaults to SecureRandom.uuid).
31
+ def initialize(role:, content:, timestamp: nil, tool_name: nil, state_delta: nil, event_id: nil)
32
+ # Basic validation
33
+ raise ArgumentError, "Invalid role: #{role}. Must be :user, :agent, :tool_request, or :tool_result." unless %i[user agent tool_request tool_result].include?(role)
34
+
35
+ Legate.logger.warn("Event: :#{role} event created without a valid :tool_name symbol.") if %i[tool_request tool_result].include?(role) && (tool_name.nil? || !tool_name.is_a?(Symbol))
36
+
37
+ # Validate state_delta is a Hash or nil
38
+ unless state_delta.nil? || state_delta.is_a?(Hash)
39
+ Legate.logger.warn("Event: :state_delta must be a Hash or nil, received #{state_delta.class}.")
40
+ state_delta = nil # Force to nil if invalid
41
+ end
42
+
43
+ # Ensure content is somewhat reasonable (avoids deep inspection for performance)
44
+ Legate.logger.warn("Event: Content is of unusual type (#{content.class}): #{content.inspect}") unless content.is_a?(String) || content.is_a?(Hash) || content.is_a?(Array) || content.is_a?(NilClass) || content.is_a?(Numeric) || content.is_a?(TrueClass) || content.is_a?(FalseClass)
45
+
46
+ super(
47
+ role: role,
48
+ content: deep_freeze(content),
49
+ timestamp: timestamp || Time.now.utc,
50
+ tool_name: tool_name,
51
+ state_delta: deep_freeze(state_delta&.transform_keys(&:to_sym)),
52
+ event_id: event_id || SecureRandom.uuid
53
+ )
54
+ freeze
55
+ end
56
+
57
+ private
58
+
59
+ def deep_freeze(obj)
60
+ case obj
61
+ when Hash
62
+ obj.each_value { |v| deep_freeze(v) }
63
+ obj.freeze
64
+ when Array
65
+ obj.each { |v| deep_freeze(v) }
66
+ obj.freeze
67
+ when String
68
+ obj.freeze
69
+ else
70
+ obj
71
+ end
72
+ end
73
+
74
+ public
75
+
76
+ # Helper to check if the event represents a final agent response to the user.
77
+ # @return [Boolean]
78
+ def final_agent_response?
79
+ role == :agent
80
+ end
81
+
82
+ # --- Result accessors ---
83
+ # Convenience readers over the standard { status:, result: / error_message: }
84
+ # content hash, so callers don't reach into it. Meaningful on a final agent
85
+ # event (e.g. the return of Agent#ask / #run_task); harmless elsewhere.
86
+
87
+ # @return [Boolean] true if this carries a successful result
88
+ def success?
89
+ content.is_a?(Hash) && content[:status] == :success
90
+ end
91
+
92
+ # @return [Boolean] true if this carries an error result
93
+ def error?
94
+ content.is_a?(Hash) && content[:status] == :error
95
+ end
96
+
97
+ # The successful result value (nil on error). Non-Hash content is returned
98
+ # as-is (e.g. a scalar result stored directly).
99
+ # @return [Object, nil]
100
+ def answer
101
+ content.is_a?(Hash) ? content[:result] : content
102
+ end
103
+
104
+ # @return [String, nil] the error message, or nil when not an error
105
+ def error_message
106
+ content.is_a?(Hash) ? content[:error_message] : nil
107
+ end
108
+
109
+ # Basic serialization for storage (e.g., in Redis).
110
+ # @return [Hash] A hash representation suitable for JSON conversion.
111
+ def to_h
112
+ {
113
+ role: role,
114
+ content: content, # Assumes content is already JSON-serializable
115
+ timestamp: timestamp.iso8601(3), # Use ISO8601 format with milliseconds
116
+ tool_name: tool_name,
117
+ state_delta: state_delta, # Store the hash directly (must be JSON-serializable)
118
+ event_id: event_id
119
+ }
120
+ end
121
+
122
+ # Basic deserialization from a hash (e.g., after reading from JSON).
123
+ # @param hash [Hash] The hash containing event data (uses symbolized keys).
124
+ # @return [Legate::Event] A new Event object.
125
+ def self.from_h(hash)
126
+ # Optimized: Extract fields manually to avoid full hash allocation via transform_keys
127
+ role = hash.key?(:role) ? hash[:role] : hash['role']
128
+ content = hash.key?(:content) ? hash[:content] : hash['content']
129
+ ts_val = hash.key?(:timestamp) ? hash[:timestamp] : hash['timestamp']
130
+ tool_name = hash.key?(:tool_name) ? hash[:tool_name] : hash['tool_name']
131
+ state_delta = hash.key?(:state_delta) ? hash[:state_delta] : hash['state_delta']
132
+
133
+ # Validate state_delta type to preserve strict behavior (fail on invalid type)
134
+ if state_delta && !state_delta.is_a?(Hash)
135
+ Legate.logger.error("Event.from_h: Type error during deserialization (check state_delta?): state_delta must be a Hash. Hash: #{hash.inspect}")
136
+ return nil
137
+ end
138
+
139
+ event_id = hash.key?(:event_id) ? hash[:event_id] : hash['event_id']
140
+
141
+ new(
142
+ role: role&.to_sym,
143
+ content: content,
144
+ # Safely parse timestamp
145
+ timestamp: ts_val ? Time.iso8601(ts_val) : Time.now.utc,
146
+ tool_name: tool_name&.to_sym,
147
+ # Pass state_delta directly; initialize handles validation and symbolization/copy
148
+ state_delta: state_delta,
149
+ event_id: event_id
150
+ )
151
+ rescue ArgumentError => e
152
+ Legate.logger.error("Event.from_h: Failed to parse timestamp or invalid role: #{e.message}. Hash: #{hash.inspect}")
153
+ # Decide on fallback: return nil, raise, or return partial object?
154
+ # Returning nil might be safest to signal deserialization failure.
155
+ nil
156
+ rescue TypeError, NoMethodError => e # Also rescue NoMethodError
157
+ Legate.logger.error("Event.from_h: Type error during deserialization (check state_delta?): #{e.message}. Hash: #{hash.inspect}")
158
+ nil
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Monkey patch for the gemini-ai gem to use the v1beta API endpoint, which
4
+ # exposes newer models. It reaches into gemini-ai's private @service /
5
+ # @service_version / @base_address ivars, so it is written defensively: if a
6
+ # future gemini-ai release renames those internals, the patch degrades to a
7
+ # logged warning instead of crashing planning at require time. gemini-ai is
8
+ # pinned (~> 4.2.0) to keep this stable.
9
+
10
+ require 'gemini-ai'
11
+
12
+ if defined?(Gemini::Controllers::Client)
13
+ module Gemini
14
+ module Controllers
15
+ class Client
16
+ # Store the original initialize method
17
+ alias original_initialize initialize
18
+
19
+ def initialize(config)
20
+ original_initialize(config)
21
+
22
+ # Force v1beta when talking to the generative-language API. Guard the
23
+ # ivar pokes so a gemini-ai internals change can't break construction.
24
+ return unless instance_variable_defined?(:@service) && @service == 'generative-language-api'
25
+
26
+ @service_version = 'v1beta'
27
+ @base_address = "https://generativelanguage.googleapis.com/#{@service_version}"
28
+ Legate.logger&.debug('Gemini AI Client patched to use v1beta API endpoint') if defined?(Legate)
29
+ rescue StandardError => e
30
+ Legate.logger&.warn("Gemini v1beta patch could not apply (gemini-ai internals may have changed): #{e.message}") if defined?(Legate)
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ Legate.logger&.debug('Gemini AI Beta patch loaded - API will use v1beta endpoint') if defined?(Legate) && Legate.respond_to?(:logger)
37
+ elsif defined?(Legate)
38
+ Legate.logger&.warn('Gemini::Controllers::Client not found; skipping v1beta patch (gemini-ai may have changed).')
39
+ end