activeagent 0.6.3 → 1.0.0.rc1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +210 -2
- data/README.md +15 -24
- data/lib/active_agent/base.rb +389 -39
- data/lib/active_agent/concerns/callbacks.rb +251 -0
- data/lib/active_agent/concerns/observers.rb +147 -0
- data/lib/active_agent/concerns/parameterized.rb +292 -0
- data/lib/active_agent/concerns/provider.rb +120 -0
- data/lib/active_agent/concerns/queueing.rb +36 -0
- data/lib/active_agent/concerns/rescue.rb +64 -0
- data/lib/active_agent/concerns/streaming.rb +282 -0
- data/lib/active_agent/concerns/tooling.rb +23 -0
- data/lib/active_agent/concerns/view.rb +150 -0
- data/lib/active_agent/configuration.rb +442 -20
- data/lib/active_agent/generation.rb +141 -47
- data/lib/active_agent/generation_provider/open_router/types.rb +505 -0
- data/lib/active_agent/generation_provider/xai_provider.rb +144 -0
- data/lib/active_agent/providers/_base_provider.rb +410 -0
- data/lib/active_agent/providers/anthropic/_types.rb +63 -0
- data/lib/active_agent/providers/anthropic/options.rb +53 -0
- data/lib/active_agent/providers/anthropic/request.rb +109 -0
- data/lib/active_agent/providers/anthropic/requests/_types.rb +190 -0
- data/lib/active_agent/providers/anthropic/requests/container_params.rb +19 -0
- data/lib/active_agent/providers/anthropic/requests/content/base.rb +21 -0
- data/lib/active_agent/providers/anthropic/requests/content/sources/base.rb +22 -0
- data/lib/active_agent/providers/anthropic/requests/context_management_config.rb +18 -0
- data/lib/active_agent/providers/anthropic/requests/messages/_types.rb +189 -0
- data/lib/active_agent/providers/anthropic/requests/messages/assistant.rb +23 -0
- data/lib/active_agent/providers/anthropic/requests/messages/base.rb +63 -0
- data/lib/active_agent/providers/anthropic/requests/messages/content/_types.rb +143 -0
- data/lib/active_agent/providers/anthropic/requests/messages/content/base.rb +21 -0
- data/lib/active_agent/providers/anthropic/requests/messages/content/document.rb +26 -0
- data/lib/active_agent/providers/anthropic/requests/messages/content/image.rb +23 -0
- data/lib/active_agent/providers/anthropic/requests/messages/content/redacted_thinking.rb +21 -0
- data/lib/active_agent/providers/anthropic/requests/messages/content/search_result.rb +27 -0
- data/lib/active_agent/providers/anthropic/requests/messages/content/sources/_types.rb +171 -0
- data/lib/active_agent/providers/anthropic/requests/messages/content/sources/base.rb +22 -0
- data/lib/active_agent/providers/anthropic/requests/messages/content/sources/document_base64.rb +25 -0
- data/lib/active_agent/providers/anthropic/requests/messages/content/sources/document_file.rb +23 -0
- data/lib/active_agent/providers/anthropic/requests/messages/content/sources/document_text.rb +25 -0
- data/lib/active_agent/providers/anthropic/requests/messages/content/sources/document_url.rb +23 -0
- data/lib/active_agent/providers/anthropic/requests/messages/content/sources/image_base64.rb +27 -0
- data/lib/active_agent/providers/anthropic/requests/messages/content/sources/image_file.rb +23 -0
- data/lib/active_agent/providers/anthropic/requests/messages/content/sources/image_url.rb +23 -0
- data/lib/active_agent/providers/anthropic/requests/messages/content/text.rb +22 -0
- data/lib/active_agent/providers/anthropic/requests/messages/content/thinking.rb +23 -0
- data/lib/active_agent/providers/anthropic/requests/messages/content/tool_result.rb +24 -0
- data/lib/active_agent/providers/anthropic/requests/messages/content/tool_use.rb +28 -0
- data/lib/active_agent/providers/anthropic/requests/messages/user.rb +21 -0
- data/lib/active_agent/providers/anthropic/requests/metadata.rb +18 -0
- data/lib/active_agent/providers/anthropic/requests/response_format.rb +22 -0
- data/lib/active_agent/providers/anthropic/requests/thinking_config/_types.rb +60 -0
- data/lib/active_agent/providers/anthropic/requests/thinking_config/base.rb +20 -0
- data/lib/active_agent/providers/anthropic/requests/thinking_config/disabled.rb +16 -0
- data/lib/active_agent/providers/anthropic/requests/thinking_config/enabled.rb +20 -0
- data/lib/active_agent/providers/anthropic/requests/tool_choice/_types.rb +78 -0
- data/lib/active_agent/providers/anthropic/requests/tool_choice/any.rb +17 -0
- data/lib/active_agent/providers/anthropic/requests/tool_choice/auto.rb +17 -0
- data/lib/active_agent/providers/anthropic/requests/tool_choice/base.rb +20 -0
- data/lib/active_agent/providers/anthropic/requests/tool_choice/none.rb +16 -0
- data/lib/active_agent/providers/anthropic/requests/tool_choice/tool.rb +20 -0
- data/lib/active_agent/providers/anthropic_provider.rb +211 -0
- data/lib/active_agent/providers/common/messages/_types.rb +124 -0
- data/lib/active_agent/providers/common/messages/assistant.rb +57 -0
- data/lib/active_agent/providers/common/messages/base.rb +17 -0
- data/lib/active_agent/providers/common/messages/system.rb +20 -0
- data/lib/active_agent/providers/common/messages/tool.rb +21 -0
- data/lib/active_agent/providers/common/messages/user.rb +20 -0
- data/lib/active_agent/providers/common/model.rb +361 -0
- data/lib/active_agent/providers/common/response.rb +13 -0
- data/lib/active_agent/providers/common/responses/_types.rb +51 -0
- data/lib/active_agent/providers/common/responses/base.rb +151 -0
- data/lib/active_agent/providers/common/responses/embed.rb +33 -0
- data/lib/active_agent/providers/common/responses/format.rb +31 -0
- data/lib/active_agent/providers/common/responses/message.rb +3 -0
- data/lib/active_agent/providers/common/responses/prompt.rb +42 -0
- data/lib/active_agent/providers/concerns/exception_handler.rb +72 -0
- data/lib/active_agent/providers/concerns/previewable.rb +150 -0
- data/lib/active_agent/providers/log_subscriber.rb +360 -0
- data/lib/active_agent/providers/mock/_types.rb +77 -0
- data/lib/active_agent/providers/mock/embedding_request.rb +17 -0
- data/lib/active_agent/providers/mock/messages/_types.rb +103 -0
- data/lib/active_agent/providers/mock/messages/assistant.rb +26 -0
- data/lib/active_agent/providers/mock/messages/base.rb +63 -0
- data/lib/active_agent/providers/mock/messages/user.rb +18 -0
- data/lib/active_agent/providers/mock/options.rb +30 -0
- data/lib/active_agent/providers/mock/request.rb +38 -0
- data/lib/active_agent/providers/mock_provider.rb +311 -0
- data/lib/active_agent/providers/ollama/_types.rb +5 -0
- data/lib/active_agent/providers/ollama/chat/_types.rb +44 -0
- data/lib/active_agent/providers/ollama/chat/request.rb +70 -0
- data/lib/active_agent/providers/ollama/chat/requests/_types.rb +3 -0
- data/lib/active_agent/providers/ollama/chat/requests/messages/_types.rb +116 -0
- data/lib/active_agent/providers/ollama/chat/requests/messages/assistant.rb +19 -0
- data/lib/active_agent/providers/ollama/chat/requests/messages/user.rb +19 -0
- data/lib/active_agent/providers/ollama/embedding/_types.rb +44 -0
- data/lib/active_agent/providers/ollama/embedding/request.rb +77 -0
- data/lib/active_agent/providers/ollama/embedding/requests/_types.rb +83 -0
- data/lib/active_agent/providers/ollama/embedding/requests/options.rb +104 -0
- data/lib/active_agent/providers/ollama/options.rb +27 -0
- data/lib/active_agent/providers/ollama_provider.rb +95 -0
- data/lib/active_agent/providers/open_ai/_base.rb +58 -0
- data/lib/active_agent/providers/open_ai/_types.rb +5 -0
- data/lib/active_agent/providers/open_ai/chat/_types.rb +44 -0
- data/lib/active_agent/providers/open_ai/chat/request.rb +215 -0
- data/lib/active_agent/providers/open_ai/chat/requests/_types.rb +229 -0
- data/lib/active_agent/providers/open_ai/chat/requests/audio.rb +24 -0
- data/lib/active_agent/providers/open_ai/chat/requests/messages/_types.rb +123 -0
- data/lib/active_agent/providers/open_ai/chat/requests/messages/assistant.rb +42 -0
- data/lib/active_agent/providers/open_ai/chat/requests/messages/base.rb +78 -0
- data/lib/active_agent/providers/open_ai/chat/requests/messages/content/_types.rb +133 -0
- data/lib/active_agent/providers/open_ai/chat/requests/messages/content/audio.rb +35 -0
- data/lib/active_agent/providers/open_ai/chat/requests/messages/content/base.rb +24 -0
- data/lib/active_agent/providers/open_ai/chat/requests/messages/content/file.rb +26 -0
- data/lib/active_agent/providers/open_ai/chat/requests/messages/content/files/_types.rb +60 -0
- data/lib/active_agent/providers/open_ai/chat/requests/messages/content/files/details.rb +41 -0
- data/lib/active_agent/providers/open_ai/chat/requests/messages/content/image.rb +37 -0
- data/lib/active_agent/providers/open_ai/chat/requests/messages/content/refusal.rb +25 -0
- data/lib/active_agent/providers/open_ai/chat/requests/messages/content/text.rb +25 -0
- data/lib/active_agent/providers/open_ai/chat/requests/messages/developer.rb +25 -0
- data/lib/active_agent/providers/open_ai/chat/requests/messages/function.rb +25 -0
- data/lib/active_agent/providers/open_ai/chat/requests/messages/system.rb +25 -0
- data/lib/active_agent/providers/open_ai/chat/requests/messages/tool.rb +26 -0
- data/lib/active_agent/providers/open_ai/chat/requests/messages/user.rb +32 -0
- data/lib/active_agent/providers/open_ai/chat/requests/prediction.rb +46 -0
- data/lib/active_agent/providers/open_ai/chat/requests/response_format.rb +53 -0
- data/lib/active_agent/providers/open_ai/chat/requests/stream_options.rb +24 -0
- data/lib/active_agent/providers/open_ai/chat/requests/tool_choice.rb +26 -0
- data/lib/active_agent/providers/open_ai/chat/requests/tools/_types.rb +5 -0
- data/lib/active_agent/providers/open_ai/chat/requests/tools/base.rb +22 -0
- data/lib/active_agent/providers/open_ai/chat/requests/tools/custom_tool.rb +41 -0
- data/lib/active_agent/providers/open_ai/chat/requests/tools/function_tool.rb +51 -0
- data/lib/active_agent/providers/open_ai/chat/requests/web_search_options.rb +45 -0
- data/lib/active_agent/providers/open_ai/chat_provider.rb +198 -0
- data/lib/active_agent/providers/open_ai/embedding/_types.rb +45 -0
- data/lib/active_agent/providers/open_ai/embedding/request.rb +85 -0
- data/lib/active_agent/providers/open_ai/embedding/requests/_types.rb +49 -0
- data/lib/active_agent/providers/open_ai/options.rb +74 -0
- data/lib/active_agent/providers/open_ai/responses/_types.rb +50 -0
- data/lib/active_agent/providers/open_ai/responses/request.rb +163 -0
- data/lib/active_agent/providers/open_ai/responses/requests/_types.rb +231 -0
- data/lib/active_agent/providers/open_ai/responses/requests/conversation.rb +23 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/_types.rb +264 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/assistant_message.rb +22 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/base.rb +89 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/code_interpreter_tool_call.rb +30 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/computer_tool_call.rb +28 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/computer_tool_call_output.rb +33 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/_types.rb +207 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/base.rb +22 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/input_audio.rb +26 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/input_file.rb +28 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/input_image.rb +28 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/input_text.rb +25 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/custom_tool_call.rb +28 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/custom_tool_call_output.rb +27 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/developer_message.rb +20 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/file_search_tool_call.rb +25 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/function_call_output.rb +32 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/function_tool_call.rb +28 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/image_gen_tool_call.rb +27 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/input_message.rb +31 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/item_reference.rb +23 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/local_shell_tool_call.rb +26 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/local_shell_tool_call_output.rb +33 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/mcp_approval_request.rb +30 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/mcp_approval_response.rb +28 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/mcp_list_tools.rb +29 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/mcp_tool_call.rb +35 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/output_message.rb +35 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/reasoning.rb +33 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/system_message.rb +20 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/tool_call_base.rb +27 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/tool_message.rb +23 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/user_message.rb +20 -0
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/web_search_tool_call.rb +24 -0
- data/lib/active_agent/providers/open_ai/responses/requests/prompt_reference.rb +23 -0
- data/lib/active_agent/providers/open_ai/responses/requests/reasoning.rb +23 -0
- data/lib/active_agent/providers/open_ai/responses/requests/stream_options.rb +20 -0
- data/lib/active_agent/providers/open_ai/responses/requests/text/_types.rb +89 -0
- data/lib/active_agent/providers/open_ai/responses/requests/text/base.rb +22 -0
- data/lib/active_agent/providers/open_ai/responses/requests/text/json_object.rb +20 -0
- data/lib/active_agent/providers/open_ai/responses/requests/text/json_schema.rb +48 -0
- data/lib/active_agent/providers/open_ai/responses/requests/text/plain.rb +20 -0
- data/lib/active_agent/providers/open_ai/responses/requests/text.rb +41 -0
- data/lib/active_agent/providers/open_ai/responses/requests/tool_choice.rb +26 -0
- data/lib/active_agent/providers/open_ai/responses/requests/tools/_types.rb +112 -0
- data/lib/active_agent/providers/open_ai/responses/requests/tools/base.rb +25 -0
- data/lib/active_agent/providers/open_ai/responses/requests/tools/code_interpreter_tool.rb +23 -0
- data/lib/active_agent/providers/open_ai/responses/requests/tools/computer_tool.rb +27 -0
- data/lib/active_agent/providers/open_ai/responses/requests/tools/custom_tool.rb +28 -0
- data/lib/active_agent/providers/open_ai/responses/requests/tools/file_search_tool.rb +27 -0
- data/lib/active_agent/providers/open_ai/responses/requests/tools/function_tool.rb +29 -0
- data/lib/active_agent/providers/open_ai/responses/requests/tools/image_generation_tool.rb +37 -0
- data/lib/active_agent/providers/open_ai/responses/requests/tools/local_shell_tool.rb +21 -0
- data/lib/active_agent/providers/open_ai/responses/requests/tools/mcp_tool.rb +41 -0
- data/lib/active_agent/providers/open_ai/responses/requests/tools/web_search_preview_tool.rb +24 -0
- data/lib/active_agent/providers/open_ai/responses/requests/tools/web_search_tool.rb +25 -0
- data/lib/active_agent/providers/open_ai/responses_provider.rb +153 -0
- data/lib/active_agent/providers/open_ai/schema.yml +65937 -0
- data/lib/active_agent/providers/open_ai_provider.rb +97 -0
- data/lib/active_agent/providers/open_router/_types.rb +45 -0
- data/lib/active_agent/providers/open_router/options.rb +93 -0
- data/lib/active_agent/providers/open_router/request.rb +83 -0
- data/lib/active_agent/providers/open_router/requests/_types.rb +198 -0
- data/lib/active_agent/providers/open_router/requests/message.rb +1 -0
- data/lib/active_agent/providers/open_router/requests/messages/_types.rb +59 -0
- data/lib/active_agent/providers/open_router/requests/messages/assistant.rb +20 -0
- data/lib/active_agent/providers/open_router/requests/messages/content/_types.rb +97 -0
- data/lib/active_agent/providers/open_router/requests/messages/content/file.rb +27 -0
- data/lib/active_agent/providers/open_router/requests/messages/content/files/_types.rb +61 -0
- data/lib/active_agent/providers/open_router/requests/messages/content/files/details.rb +26 -0
- data/lib/active_agent/providers/open_router/requests/messages/user.rb +30 -0
- data/lib/active_agent/providers/open_router/requests/plugin.rb +25 -0
- data/lib/active_agent/providers/open_router/requests/plugins/_types.rb +46 -0
- data/lib/active_agent/providers/open_router/requests/plugins/pdf_config.rb +29 -0
- data/lib/active_agent/providers/open_router/requests/prediction.rb +17 -0
- data/lib/active_agent/providers/open_router/requests/provider_preferences/_types.rb +44 -0
- data/lib/active_agent/providers/open_router/requests/provider_preferences/max_price.rb +30 -0
- data/lib/active_agent/providers/open_router/requests/provider_preferences.rb +64 -0
- data/lib/active_agent/providers/open_router/requests/response_format.rb +49 -0
- data/lib/active_agent/providers/open_router_provider.rb +53 -0
- data/lib/active_agent/providers/openai_provider.rb +2 -0
- data/lib/active_agent/providers/openrouter_provider.rb +2 -0
- data/lib/active_agent/railtie.rb +8 -6
- data/lib/active_agent/schema_generator.rb +333 -166
- data/lib/active_agent/version.rb +1 -1
- data/lib/active_agent.rb +112 -36
- data/lib/generators/active_agent/agent/USAGE +78 -0
- data/lib/generators/active_agent/{agent_generator.rb → agent/agent_generator.rb} +14 -4
- data/lib/generators/active_agent/install/USAGE +25 -0
- data/lib/generators/active_agent/{install_generator.rb → install/install_generator.rb} +1 -19
- data/lib/generators/active_agent/templates/agent.rb.tt +7 -3
- data/lib/generators/active_agent/templates/application_agent.rb.tt +0 -2
- data/lib/generators/erb/agent_generator.rb +31 -16
- data/lib/generators/erb/templates/instructions.md.erb.tt +3 -0
- data/lib/generators/erb/templates/instructions.md.tt +3 -0
- data/lib/generators/erb/templates/instructions.text.tt +1 -0
- data/lib/generators/erb/templates/message.md.erb.tt +5 -0
- data/lib/generators/erb/templates/schema.json.tt +10 -0
- data/lib/generators/test_unit/agent_generator.rb +1 -1
- data/lib/generators/test_unit/templates/functional_test.rb.tt +4 -2
- metadata +320 -65
- data/lib/active_agent/action_prompt/action.rb +0 -13
- data/lib/active_agent/action_prompt/base.rb +0 -623
- data/lib/active_agent/action_prompt/message.rb +0 -126
- data/lib/active_agent/action_prompt/prompt.rb +0 -136
- data/lib/active_agent/action_prompt.rb +0 -19
- data/lib/active_agent/callbacks.rb +0 -33
- data/lib/active_agent/generation_provider/anthropic_provider.rb +0 -163
- data/lib/active_agent/generation_provider/base.rb +0 -55
- data/lib/active_agent/generation_provider/base_adapter.rb +0 -19
- data/lib/active_agent/generation_provider/error_handling.rb +0 -167
- data/lib/active_agent/generation_provider/log_subscriber.rb +0 -92
- data/lib/active_agent/generation_provider/message_formatting.rb +0 -107
- data/lib/active_agent/generation_provider/ollama_provider.rb +0 -66
- data/lib/active_agent/generation_provider/open_ai_provider.rb +0 -279
- data/lib/active_agent/generation_provider/open_router_provider.rb +0 -385
- data/lib/active_agent/generation_provider/parameter_builder.rb +0 -119
- data/lib/active_agent/generation_provider/response.rb +0 -75
- data/lib/active_agent/generation_provider/responses_adapter.rb +0 -44
- data/lib/active_agent/generation_provider/stream_processing.rb +0 -58
- data/lib/active_agent/generation_provider/tool_management.rb +0 -142
- data/lib/active_agent/generation_provider.rb +0 -67
- data/lib/active_agent/log_subscriber.rb +0 -44
- data/lib/active_agent/parameterized.rb +0 -75
- data/lib/active_agent/prompt_helper.rb +0 -19
- data/lib/active_agent/queued_generation.rb +0 -12
- data/lib/active_agent/rescuable.rb +0 -34
- data/lib/active_agent/sanitizers.rb +0 -40
- data/lib/active_agent/streaming.rb +0 -34
- data/lib/active_agent/test_case.rb +0 -125
- data/lib/generators/USAGE +0 -47
- data/lib/generators/active_agent/USAGE +0 -56
- data/lib/generators/erb/install_generator.rb +0 -44
- data/lib/generators/erb/templates/layout.html.erb.tt +0 -1
- data/lib/generators/erb/templates/layout.json.erb.tt +0 -1
- data/lib/generators/erb/templates/layout.text.erb.tt +0 -1
- data/lib/generators/erb/templates/view.html.erb.tt +0 -5
- data/lib/generators/erb/templates/view.json.erb.tt +0 -16
- /data/lib/active_agent/{preview.rb → concerns/preview.rb} +0 -0
- /data/lib/generators/erb/templates/{view.text.erb.tt → message.text.erb.tt} +0 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "messages/_types"
|
|
4
|
+
require_relative "thinking_config/_types"
|
|
5
|
+
require_relative "tool_choice/_types"
|
|
6
|
+
require_relative "tool_choice/_types"
|
|
7
|
+
|
|
8
|
+
require_relative "container_params"
|
|
9
|
+
require_relative "context_management_config"
|
|
10
|
+
require_relative "metadata"
|
|
11
|
+
require_relative "response_format"
|
|
12
|
+
|
|
13
|
+
module ActiveAgent
|
|
14
|
+
module Providers
|
|
15
|
+
module Anthropic
|
|
16
|
+
module Requests
|
|
17
|
+
# ActiveModel type for casting and serializing ContainerParams objects.
|
|
18
|
+
#
|
|
19
|
+
# Supports string shortcut for container ID: `"container_id"` casts to `{ id: "container_id" }`.
|
|
20
|
+
class ContainerParamsType < ActiveModel::Type::Value
|
|
21
|
+
# @param value [ContainerParams, Hash, String, nil]
|
|
22
|
+
# @return [ContainerParams, nil]
|
|
23
|
+
# @raise [ArgumentError] when value cannot be cast
|
|
24
|
+
def cast(value)
|
|
25
|
+
case value
|
|
26
|
+
when ContainerParams
|
|
27
|
+
value
|
|
28
|
+
when Hash
|
|
29
|
+
ContainerParams.new(**value.deep_symbolize_keys)
|
|
30
|
+
when String
|
|
31
|
+
# Allow string as container ID shortcut
|
|
32
|
+
ContainerParams.new(id: value)
|
|
33
|
+
when nil
|
|
34
|
+
nil
|
|
35
|
+
else
|
|
36
|
+
raise ArgumentError, "Cannot cast #{value.class} to ContainerParams"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @param value [ContainerParams, Hash, nil]
|
|
41
|
+
# @return [Hash, nil]
|
|
42
|
+
# @raise [ArgumentError] when value cannot be serialized
|
|
43
|
+
def serialize(value)
|
|
44
|
+
case value
|
|
45
|
+
when ContainerParams
|
|
46
|
+
value.serialize
|
|
47
|
+
when Hash
|
|
48
|
+
value
|
|
49
|
+
when nil
|
|
50
|
+
nil
|
|
51
|
+
else
|
|
52
|
+
raise ArgumentError, "Cannot serialize #{value.class}"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @param value [Object]
|
|
57
|
+
# @return [ContainerParams, nil]
|
|
58
|
+
def deserialize(value)
|
|
59
|
+
cast(value)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# ActiveModel type for casting and serializing ContextManagementConfig objects.
|
|
64
|
+
class ContextManagementConfigType < ActiveModel::Type::Value
|
|
65
|
+
# @param value [ContextManagementConfig, Hash, nil]
|
|
66
|
+
# @return [ContextManagementConfig, nil]
|
|
67
|
+
# @raise [ArgumentError] when value cannot be cast
|
|
68
|
+
def cast(value)
|
|
69
|
+
case value
|
|
70
|
+
when ContextManagementConfig
|
|
71
|
+
value
|
|
72
|
+
when Hash
|
|
73
|
+
ContextManagementConfig.new(**value.deep_symbolize_keys)
|
|
74
|
+
when nil
|
|
75
|
+
nil
|
|
76
|
+
else
|
|
77
|
+
raise ArgumentError, "Cannot cast #{value.class} to ContextManagementConfig"
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# @param value [ContextManagementConfig, Hash, nil]
|
|
82
|
+
# @return [Hash, nil]
|
|
83
|
+
# @raise [ArgumentError] when value cannot be serialized
|
|
84
|
+
def serialize(value)
|
|
85
|
+
case value
|
|
86
|
+
when ContextManagementConfig
|
|
87
|
+
value.serialize
|
|
88
|
+
when Hash
|
|
89
|
+
value
|
|
90
|
+
when nil
|
|
91
|
+
nil
|
|
92
|
+
else
|
|
93
|
+
raise ArgumentError, "Cannot serialize #{value.class}"
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# @param value [Object]
|
|
98
|
+
# @return [ContextManagementConfig, nil]
|
|
99
|
+
def deserialize(value)
|
|
100
|
+
cast(value)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# ActiveModel type for casting and serializing Metadata objects.
|
|
105
|
+
class MetadataType < ActiveModel::Type::Value
|
|
106
|
+
# @param value [Metadata, Hash, nil]
|
|
107
|
+
# @return [Metadata, nil]
|
|
108
|
+
# @raise [ArgumentError] when value cannot be cast
|
|
109
|
+
def cast(value)
|
|
110
|
+
case value
|
|
111
|
+
when Metadata
|
|
112
|
+
value
|
|
113
|
+
when Hash
|
|
114
|
+
Metadata.new(**value.deep_symbolize_keys)
|
|
115
|
+
when nil
|
|
116
|
+
nil
|
|
117
|
+
else
|
|
118
|
+
raise ArgumentError, "Cannot cast #{value.class} to Metadata"
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# @param value [Metadata, Hash, nil]
|
|
123
|
+
# @return [Hash, nil]
|
|
124
|
+
# @raise [ArgumentError] when value cannot be serialized
|
|
125
|
+
def serialize(value)
|
|
126
|
+
case value
|
|
127
|
+
when Metadata
|
|
128
|
+
value.serialize
|
|
129
|
+
when Hash
|
|
130
|
+
value
|
|
131
|
+
when nil
|
|
132
|
+
nil
|
|
133
|
+
else
|
|
134
|
+
raise ArgumentError, "Cannot serialize #{value.class}"
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# @param value [Object]
|
|
139
|
+
# @return [Metadata, nil]
|
|
140
|
+
def deserialize(value)
|
|
141
|
+
cast(value)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# ActiveModel type for casting and serializing ResponseFormat objects.
|
|
146
|
+
#
|
|
147
|
+
# @see ResponseFormat
|
|
148
|
+
class ResponseFormatType < ActiveModel::Type::Value
|
|
149
|
+
# @param value [ResponseFormat, Hash, nil]
|
|
150
|
+
# @return [ResponseFormat, nil]
|
|
151
|
+
# @raise [ArgumentError] when value cannot be cast
|
|
152
|
+
def cast(value)
|
|
153
|
+
case value
|
|
154
|
+
when ResponseFormat
|
|
155
|
+
value
|
|
156
|
+
when Hash
|
|
157
|
+
ResponseFormat.new(**value.deep_symbolize_keys)
|
|
158
|
+
when nil
|
|
159
|
+
nil
|
|
160
|
+
else
|
|
161
|
+
raise ArgumentError, "Cannot cast #{value.class} to ResponseFormat"
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# @param value [ResponseFormat, Hash, nil]
|
|
166
|
+
# @return [Hash, nil]
|
|
167
|
+
# @raise [ArgumentError] when value cannot be serialized
|
|
168
|
+
def serialize(value)
|
|
169
|
+
case value
|
|
170
|
+
when ResponseFormat
|
|
171
|
+
value.serialize
|
|
172
|
+
when Hash
|
|
173
|
+
value
|
|
174
|
+
when nil
|
|
175
|
+
nil
|
|
176
|
+
else
|
|
177
|
+
raise ArgumentError, "Cannot serialize #{value.class}"
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# @param value [Object]
|
|
182
|
+
# @return [ResponseFormat, nil]
|
|
183
|
+
def deserialize(value)
|
|
184
|
+
cast(value)
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_agent/providers/common/model"
|
|
4
|
+
|
|
5
|
+
module ActiveAgent
|
|
6
|
+
module Providers
|
|
7
|
+
module Anthropic
|
|
8
|
+
module Requests
|
|
9
|
+
# Container parameters for code execution and skills
|
|
10
|
+
class ContainerParams < Common::BaseModel
|
|
11
|
+
attribute :id, :string
|
|
12
|
+
attribute :skills, default: -> { [] } # Array of skill specifications
|
|
13
|
+
|
|
14
|
+
validates :skills, length: { maximum: 8 }, allow_nil: true
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_agent/providers/common/model"
|
|
4
|
+
require_relative "sources/_types"
|
|
5
|
+
|
|
6
|
+
module ActiveAgent
|
|
7
|
+
module Providers
|
|
8
|
+
module Anthropic
|
|
9
|
+
module Requests
|
|
10
|
+
module Content
|
|
11
|
+
# Base class for all content items
|
|
12
|
+
class Base < Common::BaseModel
|
|
13
|
+
attribute :type, :string
|
|
14
|
+
|
|
15
|
+
validates :type, presence: true
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_agent/providers/common/model"
|
|
4
|
+
|
|
5
|
+
module ActiveAgent
|
|
6
|
+
module Providers
|
|
7
|
+
module Anthropic
|
|
8
|
+
module Requests
|
|
9
|
+
module Content
|
|
10
|
+
module Sources
|
|
11
|
+
# Base class for all content sources
|
|
12
|
+
class Base < Common::BaseModel
|
|
13
|
+
attribute :type, :string
|
|
14
|
+
|
|
15
|
+
validates :type, presence: true
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_agent/providers/common/model"
|
|
4
|
+
|
|
5
|
+
module ActiveAgent
|
|
6
|
+
module Providers
|
|
7
|
+
module Anthropic
|
|
8
|
+
module Requests
|
|
9
|
+
# Context management configuration
|
|
10
|
+
class ContextManagementConfig < Common::BaseModel
|
|
11
|
+
attribute :edits, default: -> { [] } # Array of edit configurations
|
|
12
|
+
|
|
13
|
+
validates :edits, presence: true
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Load required dependencies
|
|
4
|
+
require_relative "base"
|
|
5
|
+
require_relative "user"
|
|
6
|
+
require_relative "assistant"
|
|
7
|
+
require_relative "content/_types"
|
|
8
|
+
|
|
9
|
+
module ActiveAgent
|
|
10
|
+
module Providers
|
|
11
|
+
module Anthropic
|
|
12
|
+
module Requests
|
|
13
|
+
module Messages
|
|
14
|
+
# Type for Messages array
|
|
15
|
+
class MessagesType < ActiveModel::Type::Value
|
|
16
|
+
def initialize
|
|
17
|
+
super
|
|
18
|
+
@message_type = MessageType.new
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def cast(value)
|
|
22
|
+
case value
|
|
23
|
+
when Array
|
|
24
|
+
value.map { |v| @message_type.cast(v) }
|
|
25
|
+
when nil
|
|
26
|
+
nil
|
|
27
|
+
else
|
|
28
|
+
raise ArgumentError, "Cannot cast #{value.class} to Messages array"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def serialize(value)
|
|
33
|
+
case value
|
|
34
|
+
when Array
|
|
35
|
+
grouped = []
|
|
36
|
+
|
|
37
|
+
value.each do |message|
|
|
38
|
+
if grouped.empty? || grouped.last.role != message.role
|
|
39
|
+
grouped << message.deep_dup
|
|
40
|
+
else
|
|
41
|
+
grouped.last.content += message.content.deep_dup
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
grouped.map { |v| @message_type.serialize(v) }
|
|
46
|
+
when nil
|
|
47
|
+
nil
|
|
48
|
+
else
|
|
49
|
+
raise ArgumentError, "Cannot serialize #{value.class}"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def deserialize(value)
|
|
54
|
+
cast(value)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Type for individual Message
|
|
59
|
+
class MessageType < ActiveModel::Type::Value
|
|
60
|
+
def cast(value)
|
|
61
|
+
case value
|
|
62
|
+
when Base
|
|
63
|
+
value
|
|
64
|
+
when String
|
|
65
|
+
User.new(content: value)
|
|
66
|
+
when Hash
|
|
67
|
+
hash = value.deep_symbolize_keys
|
|
68
|
+
role = hash[:role]&.to_sym
|
|
69
|
+
|
|
70
|
+
case role
|
|
71
|
+
when :user, nil
|
|
72
|
+
User.new(**hash)
|
|
73
|
+
when :assistant
|
|
74
|
+
Assistant.new(**hash)
|
|
75
|
+
else
|
|
76
|
+
raise ArgumentError, "Unknown message role: #{role}"
|
|
77
|
+
end
|
|
78
|
+
when nil
|
|
79
|
+
nil
|
|
80
|
+
else
|
|
81
|
+
raise ArgumentError, "Cannot cast #{value.class} to Message"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def serialize(value)
|
|
86
|
+
case value
|
|
87
|
+
when Base
|
|
88
|
+
hash = value.serialize
|
|
89
|
+
# Compress single text content to string
|
|
90
|
+
if hash[:content].is_a?(Array) && hash[:content].one? && hash[:content].first.is_a?(Hash) && hash[:content].first[:type] == "text"
|
|
91
|
+
hash[:content] = hash[:content].first[:text]
|
|
92
|
+
end
|
|
93
|
+
hash
|
|
94
|
+
when Hash
|
|
95
|
+
value
|
|
96
|
+
when nil
|
|
97
|
+
nil
|
|
98
|
+
else
|
|
99
|
+
raise ArgumentError, "Cannot serialize #{value.class}"
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def deserialize(value)
|
|
104
|
+
cast(value)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Type for System content - converts strings to arrays of text blocks
|
|
109
|
+
class SystemType < ActiveModel::Type::Value
|
|
110
|
+
def cast(value)
|
|
111
|
+
case value
|
|
112
|
+
when Array
|
|
113
|
+
# Already an array - validate and return
|
|
114
|
+
value.map { |block| cast_system_block(block) }
|
|
115
|
+
when String
|
|
116
|
+
# Convert string to array of text blocks
|
|
117
|
+
[
|
|
118
|
+
{
|
|
119
|
+
type: "text",
|
|
120
|
+
text: value
|
|
121
|
+
}
|
|
122
|
+
]
|
|
123
|
+
when nil
|
|
124
|
+
nil
|
|
125
|
+
else
|
|
126
|
+
raise ArgumentError, "Cannot cast #{value.class} to System content"
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def serialize(value)
|
|
131
|
+
case value
|
|
132
|
+
when Array
|
|
133
|
+
serialized = value.map { |block| serialize_system_block(block) }
|
|
134
|
+
# Compress single text block to string
|
|
135
|
+
if serialized.one? && serialized.first.is_a?(Hash) && serialized.first[:type] == "text"
|
|
136
|
+
serialized.first[:text]
|
|
137
|
+
else
|
|
138
|
+
serialized
|
|
139
|
+
end
|
|
140
|
+
when nil
|
|
141
|
+
nil
|
|
142
|
+
else
|
|
143
|
+
raise ArgumentError, "Cannot serialize #{value.class}"
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def deserialize(value)
|
|
148
|
+
cast(value)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
private
|
|
152
|
+
|
|
153
|
+
def cast_system_block(value)
|
|
154
|
+
case value
|
|
155
|
+
when Content::Base
|
|
156
|
+
value
|
|
157
|
+
when String
|
|
158
|
+
Content::Text.new(text: value)
|
|
159
|
+
when Hash
|
|
160
|
+
hash = value.deep_symbolize_keys
|
|
161
|
+
type = hash[:type]&.to_sym
|
|
162
|
+
|
|
163
|
+
case type
|
|
164
|
+
when :text
|
|
165
|
+
Content::Text.new(**hash)
|
|
166
|
+
else
|
|
167
|
+
raise ArgumentError, "Unknown system block type: #{type}"
|
|
168
|
+
end
|
|
169
|
+
else
|
|
170
|
+
raise ArgumentError, "Cannot cast #{value.class} to system block"
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def serialize_system_block(value)
|
|
175
|
+
case value
|
|
176
|
+
when Content::Base
|
|
177
|
+
value.serialize
|
|
178
|
+
when Hash
|
|
179
|
+
value
|
|
180
|
+
else
|
|
181
|
+
raise ArgumentError, "Cannot serialize #{value.class}"
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveAgent
|
|
4
|
+
module Providers
|
|
5
|
+
module Anthropic
|
|
6
|
+
module Requests
|
|
7
|
+
module Messages
|
|
8
|
+
# Assistant message - messages sent by the model
|
|
9
|
+
class Assistant < Base
|
|
10
|
+
attribute :role, :string, as: "assistant"
|
|
11
|
+
|
|
12
|
+
# Content can be:
|
|
13
|
+
# - A string (shorthand for single text block)
|
|
14
|
+
# - An array of content blocks (text, thinking, tool_use, etc.)
|
|
15
|
+
validates :content, presence: true
|
|
16
|
+
|
|
17
|
+
drop_attributes :usage, :id, :model, :stop_reason, :stop_sequence, :type
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_agent/providers/common/model"
|
|
4
|
+
require_relative "content/_types"
|
|
5
|
+
|
|
6
|
+
module ActiveAgent
|
|
7
|
+
module Providers
|
|
8
|
+
module Anthropic
|
|
9
|
+
module Requests
|
|
10
|
+
module Messages
|
|
11
|
+
# Base class for Anthropic messages.
|
|
12
|
+
#
|
|
13
|
+
# Provides common message structure and conversion utilities for
|
|
14
|
+
# Anthropic's message format, including content extraction.
|
|
15
|
+
class Base < Common::BaseModel
|
|
16
|
+
attribute :role, :string
|
|
17
|
+
attribute :content, Content::ContentsType.new
|
|
18
|
+
|
|
19
|
+
validates :role, presence: true, inclusion: { in: %w[user assistant] }
|
|
20
|
+
|
|
21
|
+
# Define content setter methods for different content types
|
|
22
|
+
%i[text image document].each do |content_type|
|
|
23
|
+
define_method(:"#{content_type}=") do |value|
|
|
24
|
+
self.content ||= []
|
|
25
|
+
self.content += [ { content_type => value } ]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Converts to common format.
|
|
30
|
+
#
|
|
31
|
+
# @return [Hash] message in canonical format with role and text content
|
|
32
|
+
def to_common
|
|
33
|
+
{
|
|
34
|
+
role: role,
|
|
35
|
+
content: extract_text_content,
|
|
36
|
+
name: nil
|
|
37
|
+
}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
# Extracts text content from Anthropic's content structure.
|
|
43
|
+
#
|
|
44
|
+
# @return [String] extracted text content
|
|
45
|
+
def extract_text_content
|
|
46
|
+
case content
|
|
47
|
+
when String
|
|
48
|
+
content
|
|
49
|
+
when Array
|
|
50
|
+
# Join all text blocks
|
|
51
|
+
content.select { |block| block.type == "text" }
|
|
52
|
+
.map(&:text)
|
|
53
|
+
.join("\n")
|
|
54
|
+
else
|
|
55
|
+
content.to_s
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base"
|
|
4
|
+
require_relative "text"
|
|
5
|
+
require_relative "image"
|
|
6
|
+
require_relative "document"
|
|
7
|
+
require_relative "tool_use"
|
|
8
|
+
require_relative "tool_result"
|
|
9
|
+
require_relative "thinking"
|
|
10
|
+
require_relative "redacted_thinking"
|
|
11
|
+
require_relative "search_result"
|
|
12
|
+
|
|
13
|
+
module ActiveAgent
|
|
14
|
+
module Providers
|
|
15
|
+
module Anthropic
|
|
16
|
+
module Requests
|
|
17
|
+
module Content
|
|
18
|
+
# Type for contents array (always an array of content items)
|
|
19
|
+
class ContentsType < ActiveModel::Type::Value
|
|
20
|
+
def initialize
|
|
21
|
+
super
|
|
22
|
+
@content_type = ContentType.new
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def cast(value)
|
|
26
|
+
case value
|
|
27
|
+
when String
|
|
28
|
+
# Convert string to array of text content
|
|
29
|
+
[ Text.new(text: value) ]
|
|
30
|
+
when Array
|
|
31
|
+
# Array of content items - cast each item
|
|
32
|
+
value.map { |item| @content_type.cast(item) }
|
|
33
|
+
when Hash
|
|
34
|
+
# Single hash becomes array with one content item
|
|
35
|
+
[ @content_type.cast(value) ]
|
|
36
|
+
when nil
|
|
37
|
+
nil
|
|
38
|
+
else
|
|
39
|
+
raise ArgumentError, "Cannot cast #{value.class} to Contents array"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def serialize(value)
|
|
44
|
+
case value
|
|
45
|
+
when Array
|
|
46
|
+
serialized = value.map { |item| @content_type.serialize(item) }
|
|
47
|
+
# Compress single text item to string
|
|
48
|
+
if serialized.one? && serialized.first.is_a?(Hash) && serialized.first[:type] == "text"
|
|
49
|
+
serialized.first[:text]
|
|
50
|
+
else
|
|
51
|
+
serialized
|
|
52
|
+
end
|
|
53
|
+
when nil
|
|
54
|
+
nil
|
|
55
|
+
else
|
|
56
|
+
# Should not happen if cast is working correctly, but handle gracefully
|
|
57
|
+
raise ArgumentError, "Cannot serialize #{value.class}"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def deserialize(value)
|
|
62
|
+
cast(value)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Type for individual content items
|
|
67
|
+
class ContentType < ActiveModel::Type::Value
|
|
68
|
+
def cast(value)
|
|
69
|
+
case value
|
|
70
|
+
when Base
|
|
71
|
+
# Already a Content object, return as-is
|
|
72
|
+
value
|
|
73
|
+
when Hash
|
|
74
|
+
hash = value.deep_symbolize_keys
|
|
75
|
+
type = hash[:type]&.to_sym
|
|
76
|
+
|
|
77
|
+
case type
|
|
78
|
+
when :text
|
|
79
|
+
Text.new(**hash)
|
|
80
|
+
when :image
|
|
81
|
+
Image.new(**hash)
|
|
82
|
+
when :document
|
|
83
|
+
Document.new(**hash)
|
|
84
|
+
when :tool_use
|
|
85
|
+
ToolUse.new(**hash)
|
|
86
|
+
when :tool_result
|
|
87
|
+
ToolResult.new(**hash)
|
|
88
|
+
when :thinking
|
|
89
|
+
Thinking.new(**hash)
|
|
90
|
+
when :redacted_thinking
|
|
91
|
+
RedactedThinking.new(**hash)
|
|
92
|
+
when :search_result
|
|
93
|
+
SearchResult.new(**hash)
|
|
94
|
+
when nil
|
|
95
|
+
# No type specified - infer from keys present
|
|
96
|
+
if hash.key?(:text)
|
|
97
|
+
Text.new(**hash)
|
|
98
|
+
elsif hash.key?(:image)
|
|
99
|
+
# Move image key under source
|
|
100
|
+
Image.new(**hash.merge(source: hash.extract!(:image)))
|
|
101
|
+
elsif hash.key?(:document)
|
|
102
|
+
# Move document key under source
|
|
103
|
+
Document.new(**hash.merge(source: hash.extract!(:document)))
|
|
104
|
+
else
|
|
105
|
+
raise ArgumentError, "Cannot cast hash without type to Content: #{hash.inspect}"
|
|
106
|
+
end
|
|
107
|
+
else
|
|
108
|
+
raise ArgumentError, "Unknown content type: #{type}"
|
|
109
|
+
end
|
|
110
|
+
when String
|
|
111
|
+
# Plain text string becomes text content item
|
|
112
|
+
Text.new(text: value)
|
|
113
|
+
when nil
|
|
114
|
+
nil
|
|
115
|
+
else
|
|
116
|
+
raise ArgumentError, "Cannot cast #{value.class} to Content"
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def serialize(value)
|
|
121
|
+
case value
|
|
122
|
+
when Base
|
|
123
|
+
value.serialize
|
|
124
|
+
when Hash
|
|
125
|
+
value
|
|
126
|
+
when String
|
|
127
|
+
{ type: "text", text: value }
|
|
128
|
+
when nil
|
|
129
|
+
nil
|
|
130
|
+
else
|
|
131
|
+
raise ArgumentError, "Cannot serialize #{value.class} as Content"
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def deserialize(value)
|
|
136
|
+
cast(value)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|