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
|
@@ -1,623 +0,0 @@
|
|
|
1
|
-
require "active_agent/collector"
|
|
2
|
-
require "active_support/core_ext/string/inflections"
|
|
3
|
-
require "active_support/core_ext/hash/except"
|
|
4
|
-
require "active_support/core_ext/module/anonymous"
|
|
5
|
-
require "active_agent/action_prompt/message"
|
|
6
|
-
require "active_agent/action_prompt/action"
|
|
7
|
-
|
|
8
|
-
# require "active_agent/log_subscriber"
|
|
9
|
-
require "active_agent/rescuable"
|
|
10
|
-
module ActiveAgent
|
|
11
|
-
module ActionPrompt
|
|
12
|
-
class Base < AbstractController::Base
|
|
13
|
-
include Callbacks
|
|
14
|
-
include GenerationProvider
|
|
15
|
-
include Streaming
|
|
16
|
-
include QueuedGeneration
|
|
17
|
-
include Rescuable
|
|
18
|
-
include Parameterized
|
|
19
|
-
include Previews
|
|
20
|
-
# include FormBuilder
|
|
21
|
-
|
|
22
|
-
abstract!
|
|
23
|
-
|
|
24
|
-
include AbstractController::Rendering
|
|
25
|
-
|
|
26
|
-
include AbstractController::Logger
|
|
27
|
-
include AbstractController::Helpers
|
|
28
|
-
include AbstractController::Translation
|
|
29
|
-
include AbstractController::AssetPaths
|
|
30
|
-
include AbstractController::Callbacks
|
|
31
|
-
include AbstractController::Caching
|
|
32
|
-
|
|
33
|
-
include ActionView::Layouts
|
|
34
|
-
|
|
35
|
-
PROTECTED_IVARS = AbstractController::Rendering::DEFAULT_PROTECTED_INSTANCE_VARIABLES + [ :@_action_has_layout ]
|
|
36
|
-
|
|
37
|
-
helper ActiveAgent::PromptHelper
|
|
38
|
-
|
|
39
|
-
# Delegate response to generation_provider for easy access in callbacks
|
|
40
|
-
delegate :response, to: :generation_provider, allow_nil: true
|
|
41
|
-
|
|
42
|
-
class_attribute :options
|
|
43
|
-
|
|
44
|
-
class_attribute :default_params, default: {
|
|
45
|
-
mime_version: "1.0",
|
|
46
|
-
charset: "UTF-8",
|
|
47
|
-
content_type: "text/plain",
|
|
48
|
-
parts_order: [ "text/plain", "text/enriched", "text/html" ]
|
|
49
|
-
}.freeze
|
|
50
|
-
|
|
51
|
-
class << self
|
|
52
|
-
# Register one or more Observers which will be notified when prompt is generated.
|
|
53
|
-
def register_observers(*observers)
|
|
54
|
-
observers.flatten.compact.each { |observer| register_observer(observer) }
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# Unregister one or more previously registered Observers.
|
|
58
|
-
def unregister_observers(*observers)
|
|
59
|
-
observers.flatten.compact.each { |observer| unregister_observer(observer) }
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
# Register one or more Interceptors which will be called before prompt is sent.
|
|
63
|
-
def register_interceptors(*interceptors)
|
|
64
|
-
interceptors.flatten.compact.each { |interceptor| register_interceptor(interceptor) }
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# Unregister one or more previously registered Interceptors.
|
|
68
|
-
def unregister_interceptors(*interceptors)
|
|
69
|
-
interceptors.flatten.compact.each { |interceptor| unregister_interceptor(interceptor) }
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# Register an Observer which will be notified when prompt is generated.
|
|
73
|
-
# Either a class, string, or symbol can be passed in as the Observer.
|
|
74
|
-
# If a string or symbol is passed in it will be camelized and constantized.
|
|
75
|
-
def register_observer(observer)
|
|
76
|
-
Prompt.register_observer(observer_class_for(observer))
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
# Unregister a previously registered Observer.
|
|
80
|
-
# Either a class, string, or symbol can be passed in as the Observer.
|
|
81
|
-
# If a string or symbol is passed in it will be camelized and constantized.
|
|
82
|
-
def unregister_observer(observer)
|
|
83
|
-
Prompt.unregister_observer(observer_class_for(observer))
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
# Register an Interceptor which will be called before prompt is sent.
|
|
87
|
-
# Either a class, string, or symbol can be passed in as the Interceptor.
|
|
88
|
-
# If a string or symbol is passed in it will be camelized and constantized.
|
|
89
|
-
def register_interceptor(interceptor)
|
|
90
|
-
Prompt.register_interceptor(observer_class_for(interceptor))
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# Unregister a previously registered Interceptor.
|
|
94
|
-
# Either a class, string, or symbol can be passed in as the Interceptor.
|
|
95
|
-
# If a string or symbol is passed in it will be camelized and constantized.
|
|
96
|
-
def unregister_interceptor(interceptor)
|
|
97
|
-
Prompt.unregister_interceptor(observer_class_for(interceptor))
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def observer_class_for(value) # :nodoc:
|
|
101
|
-
case value
|
|
102
|
-
when String, Symbol
|
|
103
|
-
value.to_s.camelize.constantize
|
|
104
|
-
else
|
|
105
|
-
value
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
private :observer_class_for
|
|
109
|
-
|
|
110
|
-
# Define how the agent should generate content
|
|
111
|
-
def generate_with(provider, **options)
|
|
112
|
-
self.generation_provider = provider
|
|
113
|
-
if options.has_key?(:instructions) || (self.options || {}).empty?
|
|
114
|
-
# Either instructions explicitly provided, or no inherited options exist
|
|
115
|
-
self.options = (self.options || {}).merge(options)
|
|
116
|
-
else
|
|
117
|
-
# Don't inherit instructions from parent if not explicitly set
|
|
118
|
-
inherited_options = (self.options || {}).except(:instructions)
|
|
119
|
-
self.options = inherited_options.merge(options)
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
def stream_with(&stream)
|
|
124
|
-
self.options = (options || {}).merge(stream: stream)
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
# Returns the name of the current agent. This method is also being used as a path for a view lookup.
|
|
128
|
-
# If this is an anonymous agent, this method will return +anonymous+ instead.
|
|
129
|
-
def agent_name
|
|
130
|
-
@agent_name ||= anonymous? ? "anonymous" : name.underscore
|
|
131
|
-
end
|
|
132
|
-
# Allows to set the name of current agent.
|
|
133
|
-
attr_writer :agent_name
|
|
134
|
-
alias_method :controller_path, :agent_name
|
|
135
|
-
|
|
136
|
-
# Sets the defaults through app configuration:
|
|
137
|
-
#
|
|
138
|
-
# config.action_agent.default(from: "no-reply@example.org")
|
|
139
|
-
#
|
|
140
|
-
# Aliased by ::default_options=
|
|
141
|
-
def default(value = nil)
|
|
142
|
-
self.default_params = default_params.merge(value).freeze if value
|
|
143
|
-
default_params
|
|
144
|
-
end
|
|
145
|
-
# Allows to set defaults through app configuration:
|
|
146
|
-
#
|
|
147
|
-
# config.action_agent.default_options = { from: "no-reply@example.org" }
|
|
148
|
-
alias_method :default_options=, :default
|
|
149
|
-
|
|
150
|
-
# Wraps a prompt generation inside of ActiveSupport::Notifications instrumentation.
|
|
151
|
-
#
|
|
152
|
-
# This method is actually called by the +ActionPrompt::Prompt+ object itself
|
|
153
|
-
# through a callback when you call <tt>:generate_prompt</tt> on the +ActionPrompt::Prompt+,
|
|
154
|
-
# calling +generate_prompt+ directly and passing an +ActionPrompt::Prompt+ will do
|
|
155
|
-
# nothing except tell the logger you generated the prompt.
|
|
156
|
-
def generate_prompt(prompt) # :nodoc:
|
|
157
|
-
ActiveSupport::Notifications.instrument("deliver.active_agent") do |payload|
|
|
158
|
-
set_payload_for_prompt(payload, prompt)
|
|
159
|
-
yield # Let Prompt do the generation actions
|
|
160
|
-
end
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
private
|
|
164
|
-
|
|
165
|
-
def set_payload_for_prompt(payload, prompt)
|
|
166
|
-
payload[:prompt] = prompt.encoded
|
|
167
|
-
payload[:agent] = agent_name
|
|
168
|
-
payload[:message_id] = prompt.message_id
|
|
169
|
-
payload[:date] = prompt.date
|
|
170
|
-
payload[:perform_generations] = prompt.perform_generations
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
def method_missing(method_name, ...)
|
|
174
|
-
if action_methods.include?(method_name.name)
|
|
175
|
-
Generation.new(self, method_name, ...)
|
|
176
|
-
else
|
|
177
|
-
super
|
|
178
|
-
end
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
def respond_to_missing?(method, include_all = false)
|
|
182
|
-
action_methods.include?(method.name) || super
|
|
183
|
-
end
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
attr_internal :context
|
|
187
|
-
|
|
188
|
-
def agent_stream
|
|
189
|
-
proc do |message, delta, stop, action_name|
|
|
190
|
-
@_action_name = action_name
|
|
191
|
-
|
|
192
|
-
run_stream_callbacks(message, delta, stop) do |message, delta, stop|
|
|
193
|
-
yield message, delta, stop if block_given?
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
def embed
|
|
199
|
-
context.options.merge(options)
|
|
200
|
-
generation_provider.embed(context) if context && generation_provider
|
|
201
|
-
handle_response(generation_provider.response)
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
# Add embedding capability to Message class
|
|
205
|
-
ActiveAgent::ActionPrompt::Message.class_eval do
|
|
206
|
-
def embed
|
|
207
|
-
agent_class = ApplicationAgent
|
|
208
|
-
agent = agent_class.new
|
|
209
|
-
agent.context = ActiveAgent::ActionPrompt::Prompt.new(message: self, agent_instance: agent)
|
|
210
|
-
agent.embed
|
|
211
|
-
self
|
|
212
|
-
end
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
# Make context accessible for chaining
|
|
216
|
-
# attr_accessor :context
|
|
217
|
-
|
|
218
|
-
def perform_generation
|
|
219
|
-
generation_provider.generate(context) if context && generation_provider
|
|
220
|
-
handle_response(generation_provider.response)
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
def handle_response(response)
|
|
224
|
-
return response unless response.message.requested_actions.present?
|
|
225
|
-
|
|
226
|
-
# The assistant message with tool_calls is already added by update_context in the provider
|
|
227
|
-
# Now perform the requested actions which will add tool response messages
|
|
228
|
-
perform_actions(requested_actions: response.message.requested_actions)
|
|
229
|
-
|
|
230
|
-
# Continue generation with updated context
|
|
231
|
-
continue_generation
|
|
232
|
-
end
|
|
233
|
-
|
|
234
|
-
def continue_generation
|
|
235
|
-
# Continue generating with the updated context that includes tool results
|
|
236
|
-
generation_provider.generate(context) if context && generation_provider
|
|
237
|
-
handle_response(generation_provider.response)
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
def update_context(response)
|
|
241
|
-
ActiveAgent::GenerationProvider::Response.new(prompt: context)
|
|
242
|
-
end
|
|
243
|
-
|
|
244
|
-
def perform_actions(requested_actions:)
|
|
245
|
-
requested_actions.each do |action|
|
|
246
|
-
perform_action(action)
|
|
247
|
-
end
|
|
248
|
-
end
|
|
249
|
-
|
|
250
|
-
def perform_action(action)
|
|
251
|
-
# Save the current messages to preserve conversation history
|
|
252
|
-
original_messages = context.messages.dup
|
|
253
|
-
original_params = context.params || {}
|
|
254
|
-
|
|
255
|
-
if action.params.is_a?(Hash)
|
|
256
|
-
self.params = original_params.merge(action.params)
|
|
257
|
-
else
|
|
258
|
-
self.params = original_params
|
|
259
|
-
end
|
|
260
|
-
|
|
261
|
-
# Save the current prompt_was_called state and reset it so the action can render
|
|
262
|
-
original_prompt_was_called = @_prompt_was_called
|
|
263
|
-
@_prompt_was_called = false
|
|
264
|
-
|
|
265
|
-
# Process the action, which will render the view and populate context
|
|
266
|
-
process(action.name)
|
|
267
|
-
|
|
268
|
-
# The action should have called prompt which populates context.message
|
|
269
|
-
# Create a tool message from the rendered response
|
|
270
|
-
tool_message = context.message.dup
|
|
271
|
-
tool_message.role = :tool
|
|
272
|
-
tool_message.action_id = action.id
|
|
273
|
-
tool_message.action_name = action.name
|
|
274
|
-
tool_message.generation_id = action.id
|
|
275
|
-
|
|
276
|
-
# Restore the messages with the new tool message
|
|
277
|
-
context.messages = original_messages + [ tool_message ]
|
|
278
|
-
|
|
279
|
-
# Restore the prompt_was_called state
|
|
280
|
-
@_prompt_was_called = original_prompt_was_called
|
|
281
|
-
end
|
|
282
|
-
|
|
283
|
-
def initialize # :nodoc:
|
|
284
|
-
super
|
|
285
|
-
@_prompt_was_called = false
|
|
286
|
-
@_context = ActiveAgent::ActionPrompt::Prompt.new(options: self.class.options&.deep_dup || {}, agent_instance: self)
|
|
287
|
-
end
|
|
288
|
-
|
|
289
|
-
def process(method_name, *args) # :nodoc:
|
|
290
|
-
payload = {
|
|
291
|
-
agent: self.class.name,
|
|
292
|
-
action: method_name,
|
|
293
|
-
args: args
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
ActiveSupport::Notifications.instrument("process.active_agent", payload) do
|
|
297
|
-
super
|
|
298
|
-
@_context = ActiveAgent::ActionPrompt::Prompt.new(agent_instance: self) unless @_prompt_was_called
|
|
299
|
-
end
|
|
300
|
-
end
|
|
301
|
-
ruby2_keywords(:process)
|
|
302
|
-
|
|
303
|
-
class NullPrompt # :nodoc:
|
|
304
|
-
def message
|
|
305
|
-
""
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
def header
|
|
309
|
-
{}
|
|
310
|
-
end
|
|
311
|
-
|
|
312
|
-
def respond_to?(string, include_all = false)
|
|
313
|
-
true
|
|
314
|
-
end
|
|
315
|
-
|
|
316
|
-
def method_missing(...)
|
|
317
|
-
nil
|
|
318
|
-
end
|
|
319
|
-
end
|
|
320
|
-
|
|
321
|
-
# Returns the name of the agent object.
|
|
322
|
-
def agent_name
|
|
323
|
-
self.class.agent_name
|
|
324
|
-
end
|
|
325
|
-
|
|
326
|
-
def headers(args = nil)
|
|
327
|
-
if args
|
|
328
|
-
@_context.headers(args)
|
|
329
|
-
else
|
|
330
|
-
@_context
|
|
331
|
-
end
|
|
332
|
-
end
|
|
333
|
-
|
|
334
|
-
def prompt_with(*)
|
|
335
|
-
context.update_context(*)
|
|
336
|
-
end
|
|
337
|
-
|
|
338
|
-
def prompt(headers = {}, &block)
|
|
339
|
-
return context if @_prompt_was_called && headers.blank? && !block
|
|
340
|
-
# Apply option hierarchy: prompt options > agent options > config options
|
|
341
|
-
merged_options = merge_options(headers[:options] || {})
|
|
342
|
-
|
|
343
|
-
raw_instructions = headers.has_key?(:instructions) ? headers[:instructions] : context.options[:instructions]
|
|
344
|
-
|
|
345
|
-
context.instructions = prepare_instructions(raw_instructions)
|
|
346
|
-
|
|
347
|
-
context.options.merge!(merged_options)
|
|
348
|
-
context.options[:stream] = agent_stream if context.options[:stream]
|
|
349
|
-
content_type = headers[:content_type]
|
|
350
|
-
|
|
351
|
-
headers = apply_defaults(headers)
|
|
352
|
-
context.messages = headers[:messages] || []
|
|
353
|
-
context.mcp_servers = headers[:mcp_servers] || []
|
|
354
|
-
context.context_id = headers[:context_id]
|
|
355
|
-
context.params = params
|
|
356
|
-
context.action_name = action_name
|
|
357
|
-
|
|
358
|
-
context.output_schema = render_schema(headers[:output_schema], set_prefixes(headers[:output_schema], lookup_context.prefixes))
|
|
359
|
-
|
|
360
|
-
context.charset = charset = headers[:charset]
|
|
361
|
-
|
|
362
|
-
headers = prepare_message(headers)
|
|
363
|
-
# wrap_generation_behavior!(headers[:generation_method], headers[:generation_method_options])
|
|
364
|
-
# assign_headers_to_context(context, headers)
|
|
365
|
-
responses = collect_responses(headers, &block)
|
|
366
|
-
|
|
367
|
-
@_prompt_was_called = true
|
|
368
|
-
|
|
369
|
-
create_parts_from_responses(context, responses)
|
|
370
|
-
|
|
371
|
-
context.content_type = set_content_type(context, content_type, headers[:content_type])
|
|
372
|
-
|
|
373
|
-
context.charset = charset
|
|
374
|
-
context.actions = headers[:actions] || action_schemas
|
|
375
|
-
|
|
376
|
-
context
|
|
377
|
-
end
|
|
378
|
-
|
|
379
|
-
def action_methods
|
|
380
|
-
super - ActiveAgent::Base.public_instance_methods(false).map(&:to_s) - [ action_name ]
|
|
381
|
-
end
|
|
382
|
-
|
|
383
|
-
def action_schemas
|
|
384
|
-
prefixes = set_prefixes(action_name, lookup_context.prefixes)
|
|
385
|
-
|
|
386
|
-
action_methods.map do |action|
|
|
387
|
-
render_schema(action, prefixes)
|
|
388
|
-
end.compact
|
|
389
|
-
end
|
|
390
|
-
|
|
391
|
-
private
|
|
392
|
-
def prepare_message(headers)
|
|
393
|
-
if headers[:message].present? && headers[:message].is_a?(ActiveAgent::ActionPrompt::Message)
|
|
394
|
-
headers[:body] = headers[:message].content
|
|
395
|
-
headers[:role] = headers[:message].role
|
|
396
|
-
elsif headers[:message].present? && headers[:message].is_a?(Array)
|
|
397
|
-
# Handle array of multipart content like [{type: "text", text: "..."}, {type: "file", file: {...}}]
|
|
398
|
-
headers[:body] = headers[:message]
|
|
399
|
-
headers[:role] = :user
|
|
400
|
-
elsif headers[:message].present? && headers[:message].is_a?(String)
|
|
401
|
-
headers[:body] = headers[:message]
|
|
402
|
-
headers[:role] = :user
|
|
403
|
-
end
|
|
404
|
-
load_input_data(headers)
|
|
405
|
-
|
|
406
|
-
headers
|
|
407
|
-
end
|
|
408
|
-
|
|
409
|
-
def load_input_data(headers)
|
|
410
|
-
if headers[:image_data].present?
|
|
411
|
-
headers[:body] = [
|
|
412
|
-
ActiveAgent::ActionPrompt::Message.new(content: headers[:image_data], content_type: "image_data"),
|
|
413
|
-
ActiveAgent::ActionPrompt::Message.new(content: headers[:body], content_type: "input_text")
|
|
414
|
-
]
|
|
415
|
-
elsif headers[:file_data].present?
|
|
416
|
-
headers[:body] = [
|
|
417
|
-
ActiveAgent::ActionPrompt::Message.new(content: headers[:file_data], metadata: { filename: "resume.pdf" }, content_type: "file_data"),
|
|
418
|
-
ActiveAgent::ActionPrompt::Message.new(content: headers[:body], content_type: "input_text")
|
|
419
|
-
]
|
|
420
|
-
end
|
|
421
|
-
headers
|
|
422
|
-
end
|
|
423
|
-
|
|
424
|
-
def set_prefixes(action, prefixes)
|
|
425
|
-
prefixes = lookup_context.prefixes | [ self.class.agent_name ]
|
|
426
|
-
end
|
|
427
|
-
|
|
428
|
-
def render_schema(schema_or_action, prefixes)
|
|
429
|
-
# If it's already a hash (direct schema), return it
|
|
430
|
-
return schema_or_action if schema_or_action.is_a?(Hash)
|
|
431
|
-
|
|
432
|
-
# Otherwise try to load from template
|
|
433
|
-
return unless lookup_context.template_exists?(schema_or_action, prefixes, false, formats: [ :json ])
|
|
434
|
-
|
|
435
|
-
JSON.parse render_to_string(locals: { action_name: schema_or_action }, action: schema_or_action, formats: :json)
|
|
436
|
-
end
|
|
437
|
-
|
|
438
|
-
def merge_options(prompt_options)
|
|
439
|
-
config_options = generation_provider&.config || {}
|
|
440
|
-
agent_options = (self.class.options || {}).deep_dup # Defensive copy to prevent mutation
|
|
441
|
-
|
|
442
|
-
parent_options = self.class.superclass.respond_to?(:options) ? (self.class.superclass.options || {}) : {}
|
|
443
|
-
|
|
444
|
-
# Extract runtime options from prompt_options (exclude instructions as it has special template logic)
|
|
445
|
-
runtime_options = prompt_options.slice(
|
|
446
|
-
:model, :temperature, :max_tokens, :stream, :top_p, :frequency_penalty,
|
|
447
|
-
:presence_penalty, :response_format, :seed, :stop, :tools_choice, :plugins,
|
|
448
|
-
|
|
449
|
-
# OpenRouter Provider Settings
|
|
450
|
-
:data_collection, :require_parameters, :only, :ignore, :quantizations, :sort, :max_price,
|
|
451
|
-
|
|
452
|
-
# Built-in Tools Support (OpenAI Responses API)
|
|
453
|
-
:tools
|
|
454
|
-
)
|
|
455
|
-
# Handle explicit options parameter
|
|
456
|
-
explicit_options = prompt_options[:options] || {}
|
|
457
|
-
|
|
458
|
-
# Merge with proper precedence: config < agent < explicit_options
|
|
459
|
-
# Don't include instructions in automatic merging as it has special template fallback logic
|
|
460
|
-
config_options_filtered = config_options.except(:instructions)
|
|
461
|
-
agent_options_filtered = agent_options.except(:instructions)
|
|
462
|
-
explicit_options_filtered = explicit_options.except(:instructions)
|
|
463
|
-
|
|
464
|
-
merged = config_options_filtered.merge(agent_options_filtered).merge(explicit_options_filtered)
|
|
465
|
-
|
|
466
|
-
# Only merge runtime options that are actually present (not nil)
|
|
467
|
-
runtime_options.each do |key, value|
|
|
468
|
-
next if value.nil?
|
|
469
|
-
|
|
470
|
-
merged[key] = value
|
|
471
|
-
end
|
|
472
|
-
|
|
473
|
-
merged
|
|
474
|
-
end
|
|
475
|
-
|
|
476
|
-
def set_content_type(prompt_context, user_content_type, class_default) # :doc:
|
|
477
|
-
if user_content_type.present?
|
|
478
|
-
user_content_type
|
|
479
|
-
elsif context.multimodal?
|
|
480
|
-
"multipart/mixed"
|
|
481
|
-
elsif prompt_context.body.is_a?(Array)
|
|
482
|
-
prompt_context.content_type || class_default
|
|
483
|
-
end
|
|
484
|
-
end
|
|
485
|
-
|
|
486
|
-
# Translates the +subject+ using \Rails I18n class under <tt>[agent_scope, action_name]</tt> scope.
|
|
487
|
-
# If it does not find a translation for the +subject+ under the specified scope it will default to a
|
|
488
|
-
# humanized version of the <tt>action_name</tt>.
|
|
489
|
-
# If the subject has interpolations, you can pass them through the +interpolations+ parameter.
|
|
490
|
-
def default_i18n_subject(interpolations = {}) # :doc:
|
|
491
|
-
agent_scope = self.class.agent_name.tr("/", ".")
|
|
492
|
-
I18n.t(:subject, **interpolations.merge(scope: [ agent_scope, action_name ], default: action_name.humanize))
|
|
493
|
-
end
|
|
494
|
-
|
|
495
|
-
def apply_defaults(headers)
|
|
496
|
-
default_values = self.class.default.except(*headers.keys).transform_values do |value|
|
|
497
|
-
compute_default(value)
|
|
498
|
-
end
|
|
499
|
-
|
|
500
|
-
headers.reverse_merge(default_values)
|
|
501
|
-
end
|
|
502
|
-
|
|
503
|
-
def compute_default(value)
|
|
504
|
-
return value unless value.is_a?(Proc)
|
|
505
|
-
|
|
506
|
-
if value.arity == 1
|
|
507
|
-
instance_exec(self, &value)
|
|
508
|
-
else
|
|
509
|
-
instance_exec(&value)
|
|
510
|
-
end
|
|
511
|
-
end
|
|
512
|
-
|
|
513
|
-
def assign_headers_to_context(context, headers)
|
|
514
|
-
assignable = headers.except(:parts_order, :content_type, :body, :role, :template_name,
|
|
515
|
-
:template_path, :delivery_method, :delivery_method_options)
|
|
516
|
-
|
|
517
|
-
assignable.each { |k, v| context.send(k, v) if context.respond_to?(k) }
|
|
518
|
-
end
|
|
519
|
-
|
|
520
|
-
def collect_responses(headers, &)
|
|
521
|
-
if block_given?
|
|
522
|
-
collect_responses_from_block(headers, &)
|
|
523
|
-
elsif headers[:body]
|
|
524
|
-
collect_responses_from_text(headers)
|
|
525
|
-
else
|
|
526
|
-
collect_responses_from_templates(headers)
|
|
527
|
-
end
|
|
528
|
-
end
|
|
529
|
-
|
|
530
|
-
def collect_responses_from_block(headers)
|
|
531
|
-
templates_name = headers[:template_name] || action_name
|
|
532
|
-
collector = ActiveAgent::Collector.new(lookup_context) { render(templates_name) }
|
|
533
|
-
yield(collector)
|
|
534
|
-
collector.responses
|
|
535
|
-
end
|
|
536
|
-
|
|
537
|
-
def collect_responses_from_text(headers)
|
|
538
|
-
[ {
|
|
539
|
-
body: headers.delete(:body),
|
|
540
|
-
content_type: headers[:content_type] || "text/plain"
|
|
541
|
-
} ]
|
|
542
|
-
end
|
|
543
|
-
|
|
544
|
-
def collect_responses_from_templates(headers)
|
|
545
|
-
templates_path = headers[:template_path] || self.class.agent_name
|
|
546
|
-
templates_name = headers[:template_name] || action_name
|
|
547
|
-
each_template(Array(templates_path), templates_name).map do |template|
|
|
548
|
-
next if template.format == :json && headers[:format] != :json
|
|
549
|
-
format = template.format || formats.first
|
|
550
|
-
{
|
|
551
|
-
body: render(template: template, formats: [ format ]),
|
|
552
|
-
content_type: Mime[format].to_s
|
|
553
|
-
}
|
|
554
|
-
end.compact
|
|
555
|
-
end
|
|
556
|
-
|
|
557
|
-
def each_template(paths, name, &)
|
|
558
|
-
templates = lookup_context.find_all(name, paths)
|
|
559
|
-
if templates.empty?
|
|
560
|
-
raise ActionView::MissingTemplate.new(paths, name, paths, false, "agent")
|
|
561
|
-
else
|
|
562
|
-
templates.uniq(&:format).each(&)
|
|
563
|
-
end
|
|
564
|
-
end
|
|
565
|
-
|
|
566
|
-
def create_parts_from_responses(context, responses)
|
|
567
|
-
if responses.size > 1
|
|
568
|
-
responses.each { |r| insert_part(context, r, context.charset) }
|
|
569
|
-
else
|
|
570
|
-
responses.each { |r| insert_part(context, r, context.charset) }
|
|
571
|
-
end
|
|
572
|
-
end
|
|
573
|
-
|
|
574
|
-
def insert_part(context, response, charset)
|
|
575
|
-
message = ActiveAgent::ActionPrompt::Message.new(
|
|
576
|
-
content: response[:body],
|
|
577
|
-
content_type: response[:content_type],
|
|
578
|
-
charset: charset
|
|
579
|
-
)
|
|
580
|
-
context.add_part(message)
|
|
581
|
-
end
|
|
582
|
-
|
|
583
|
-
def prepare_instructions(instructions)
|
|
584
|
-
case instructions
|
|
585
|
-
when Hash
|
|
586
|
-
raise ArgumentError, "Expected `:template` key in instructions hash" unless instructions[:template]
|
|
587
|
-
return unless lookup_context.exists?(instructions[:template], agent_name, false, [], formats: [ :text ])
|
|
588
|
-
|
|
589
|
-
template = lookup_context.find_template(instructions[:template], agent_name, false, [], formats: [ :text ])
|
|
590
|
-
render_to_string(template: template.virtual_path, locals: instructions[:locals] || {}, layout: false)
|
|
591
|
-
when String
|
|
592
|
-
instructions
|
|
593
|
-
when NilClass
|
|
594
|
-
default_template_name = "instructions"
|
|
595
|
-
return unless lookup_context.exists?(default_template_name, agent_name, false, [], formats: [ :text ])
|
|
596
|
-
|
|
597
|
-
template = lookup_context.find_template(default_template_name, agent_name, false, [], formats: [ :text ])
|
|
598
|
-
render_to_string(template: template.virtual_path, layout: false)
|
|
599
|
-
else
|
|
600
|
-
raise ArgumentError, "Instructions must be Hash, String or NilClass objects"
|
|
601
|
-
end
|
|
602
|
-
end
|
|
603
|
-
|
|
604
|
-
# This and #instrument_name is for caching instrument
|
|
605
|
-
def instrument_payload(key)
|
|
606
|
-
{
|
|
607
|
-
agent: agent_name,
|
|
608
|
-
key: key
|
|
609
|
-
}
|
|
610
|
-
end
|
|
611
|
-
|
|
612
|
-
def instrument_name
|
|
613
|
-
"active_agent"
|
|
614
|
-
end
|
|
615
|
-
|
|
616
|
-
def _protected_ivars
|
|
617
|
-
PROTECTED_IVARS
|
|
618
|
-
end
|
|
619
|
-
|
|
620
|
-
ActiveSupport.run_load_hooks(:active_agent, self)
|
|
621
|
-
end
|
|
622
|
-
end
|
|
623
|
-
end
|