aip-agents-binary 0.0.0b2__py3-none-any.whl → 0.5.12__py3-none-any.whl
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.
- aip_agents/__init__.py +65 -0
- aip_agents/a2a/__init__.py +19 -0
- aip_agents/a2a/server/__init__.py +10 -0
- aip_agents/a2a/server/base_executor.py +1086 -0
- aip_agents/a2a/server/google_adk_executor.py +198 -0
- aip_agents/a2a/server/langflow_executor.py +180 -0
- aip_agents/a2a/server/langgraph_executor.py +270 -0
- aip_agents/a2a/types.py +232 -0
- aip_agents/agent/__init__.py +27 -0
- aip_agents/agent/base_agent.py +970 -0
- aip_agents/agent/base_langgraph_agent.py +2942 -0
- aip_agents/agent/google_adk_agent.py +926 -0
- aip_agents/agent/google_adk_constants.py +6 -0
- aip_agents/agent/hitl/__init__.py +24 -0
- aip_agents/agent/hitl/config.py +28 -0
- aip_agents/agent/hitl/langgraph_hitl_mixin.py +515 -0
- aip_agents/agent/hitl/manager.py +532 -0
- aip_agents/agent/hitl/models.py +18 -0
- aip_agents/agent/hitl/prompt/__init__.py +9 -0
- aip_agents/agent/hitl/prompt/base.py +42 -0
- aip_agents/agent/hitl/prompt/deferred.py +73 -0
- aip_agents/agent/hitl/registry.py +149 -0
- aip_agents/agent/{interface.pyi → interface.py} +70 -13
- aip_agents/agent/interfaces.py +65 -0
- aip_agents/agent/langflow_agent.py +464 -0
- aip_agents/agent/langgraph_memory_enhancer_agent.py +433 -0
- aip_agents/agent/langgraph_react_agent.py +2514 -0
- aip_agents/agent/system_instruction_context.py +34 -0
- aip_agents/clients/__init__.py +10 -0
- aip_agents/clients/langflow/__init__.py +10 -0
- aip_agents/clients/langflow/client.py +477 -0
- aip_agents/clients/langflow/types.py +18 -0
- aip_agents/constants.py +23 -0
- aip_agents/credentials/manager.py +132 -0
- aip_agents/examples/__init__.py +5 -0
- aip_agents/examples/compare_streaming_client.py +783 -0
- aip_agents/examples/compare_streaming_server.py +142 -0
- aip_agents/examples/demo_memory_recall.py +401 -0
- aip_agents/examples/hello_world_a2a_google_adk_client.py +49 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_agent.py +48 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_streaming.py +60 -0
- aip_agents/examples/hello_world_a2a_google_adk_server.py +79 -0
- aip_agents/examples/hello_world_a2a_langchain_client.py +39 -0
- aip_agents/examples/hello_world_a2a_langchain_client_agent.py +39 -0
- aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.py +37 -0
- aip_agents/examples/hello_world_a2a_langchain_client_streaming.py +41 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.py +60 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_server.py +105 -0
- aip_agents/examples/hello_world_a2a_langchain_server.py +79 -0
- aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.py +78 -0
- aip_agents/examples/hello_world_a2a_langflow_client.py +83 -0
- aip_agents/examples/hello_world_a2a_langflow_server.py +82 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client.py +73 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.py +76 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_server.py +92 -0
- aip_agents/examples/hello_world_a2a_langgraph_client.py +54 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_agent.py +54 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.py +32 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming.py +50 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.py +44 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.py +92 -0
- aip_agents/examples/hello_world_a2a_langgraph_server.py +84 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.py +79 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.py +132 -0
- aip_agents/examples/hello_world_a2a_mcp_langgraph.py +196 -0
- aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.py +244 -0
- aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.py +251 -0
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.py +57 -0
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.py +80 -0
- aip_agents/examples/hello_world_google_adk.py +41 -0
- aip_agents/examples/hello_world_google_adk_mcp_http.py +34 -0
- aip_agents/examples/hello_world_google_adk_mcp_http_stream.py +40 -0
- aip_agents/examples/hello_world_google_adk_mcp_sse.py +44 -0
- aip_agents/examples/hello_world_google_adk_mcp_sse_stream.py +48 -0
- aip_agents/examples/hello_world_google_adk_mcp_stdio.py +44 -0
- aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.py +48 -0
- aip_agents/examples/hello_world_google_adk_stream.py +44 -0
- aip_agents/examples/hello_world_langchain.py +28 -0
- aip_agents/examples/hello_world_langchain_lm_invoker.py +15 -0
- aip_agents/examples/hello_world_langchain_mcp_http.py +34 -0
- aip_agents/examples/hello_world_langchain_mcp_http_interactive.py +130 -0
- aip_agents/examples/hello_world_langchain_mcp_http_stream.py +42 -0
- aip_agents/examples/hello_world_langchain_mcp_multi_server.py +155 -0
- aip_agents/examples/hello_world_langchain_mcp_sse.py +34 -0
- aip_agents/examples/hello_world_langchain_mcp_sse_stream.py +40 -0
- aip_agents/examples/hello_world_langchain_mcp_stdio.py +30 -0
- aip_agents/examples/hello_world_langchain_mcp_stdio_stream.py +41 -0
- aip_agents/examples/hello_world_langchain_stream.py +36 -0
- aip_agents/examples/hello_world_langchain_stream_lm_invoker.py +39 -0
- aip_agents/examples/hello_world_langflow_agent.py +163 -0
- aip_agents/examples/hello_world_langgraph.py +39 -0
- aip_agents/examples/hello_world_langgraph_bosa_twitter.py +41 -0
- aip_agents/examples/hello_world_langgraph_mcp_http.py +31 -0
- aip_agents/examples/hello_world_langgraph_mcp_http_stream.py +34 -0
- aip_agents/examples/hello_world_langgraph_mcp_sse.py +35 -0
- aip_agents/examples/hello_world_langgraph_mcp_sse_stream.py +50 -0
- aip_agents/examples/hello_world_langgraph_mcp_stdio.py +35 -0
- aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.py +50 -0
- aip_agents/examples/hello_world_langgraph_stream.py +43 -0
- aip_agents/examples/hello_world_langgraph_stream_lm_invoker.py +37 -0
- aip_agents/examples/hello_world_model_switch_cli.py +210 -0
- aip_agents/examples/hello_world_multi_agent_adk.py +75 -0
- aip_agents/examples/hello_world_multi_agent_langchain.py +54 -0
- aip_agents/examples/hello_world_multi_agent_langgraph.py +66 -0
- aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.py +69 -0
- aip_agents/examples/hello_world_pii_logger.py +21 -0
- aip_agents/examples/hello_world_sentry.py +133 -0
- aip_agents/examples/hello_world_step_limits.py +273 -0
- aip_agents/examples/hello_world_stock_a2a_server.py +103 -0
- aip_agents/examples/hello_world_tool_output_client.py +46 -0
- aip_agents/examples/hello_world_tool_output_server.py +114 -0
- aip_agents/examples/hitl_demo.py +724 -0
- aip_agents/examples/mcp_configs/configs.py +63 -0
- aip_agents/examples/mcp_servers/common.py +76 -0
- aip_agents/examples/mcp_servers/mcp_name.py +29 -0
- aip_agents/examples/mcp_servers/mcp_server_http.py +19 -0
- aip_agents/examples/mcp_servers/mcp_server_sse.py +19 -0
- aip_agents/examples/mcp_servers/mcp_server_stdio.py +19 -0
- aip_agents/examples/mcp_servers/mcp_time.py +10 -0
- aip_agents/examples/pii_demo_langgraph_client.py +69 -0
- aip_agents/examples/pii_demo_langgraph_server.py +126 -0
- aip_agents/examples/pii_demo_multi_agent_client.py +80 -0
- aip_agents/examples/pii_demo_multi_agent_server.py +247 -0
- aip_agents/examples/todolist_planning_a2a_langchain_client.py +70 -0
- aip_agents/examples/todolist_planning_a2a_langgraph_server.py +88 -0
- aip_agents/examples/tools/__init__.py +27 -0
- aip_agents/examples/tools/{adk_arithmetic_tools.pyi → adk_arithmetic_tools.py} +12 -0
- aip_agents/examples/tools/adk_weather_tool.py +60 -0
- aip_agents/examples/tools/data_generator_tool.py +103 -0
- aip_agents/examples/tools/data_visualization_tool.py +312 -0
- aip_agents/examples/tools/image_artifact_tool.py +136 -0
- aip_agents/examples/tools/langchain_arithmetic_tools.py +26 -0
- aip_agents/examples/tools/langchain_currency_exchange_tool.py +88 -0
- aip_agents/examples/tools/langchain_graph_artifact_tool.py +172 -0
- aip_agents/examples/tools/langchain_weather_tool.py +48 -0
- aip_agents/examples/tools/langgraph_streaming_tool.py +130 -0
- aip_agents/examples/tools/mock_retrieval_tool.py +56 -0
- aip_agents/examples/tools/pii_demo_tools.py +189 -0
- aip_agents/examples/tools/random_chart_tool.py +142 -0
- aip_agents/examples/tools/serper_tool.py +202 -0
- aip_agents/examples/tools/stock_tools.py +82 -0
- aip_agents/examples/tools/table_generator_tool.py +167 -0
- aip_agents/examples/tools/time_tool.py +82 -0
- aip_agents/examples/tools/weather_forecast_tool.py +38 -0
- aip_agents/executor/agent_executor.py +473 -0
- aip_agents/executor/base.py +48 -0
- aip_agents/mcp/__init__.py +1 -0
- aip_agents/mcp/client/__init__.py +14 -0
- aip_agents/mcp/client/base_mcp_client.py +369 -0
- aip_agents/mcp/client/connection_manager.py +193 -0
- aip_agents/mcp/client/google_adk/__init__.py +11 -0
- aip_agents/mcp/client/google_adk/client.py +381 -0
- aip_agents/mcp/client/langchain/__init__.py +11 -0
- aip_agents/mcp/client/langchain/client.py +265 -0
- aip_agents/mcp/client/persistent_session.py +359 -0
- aip_agents/mcp/client/session_pool.py +351 -0
- aip_agents/mcp/client/transports.py +215 -0
- aip_agents/mcp/utils/__init__.py +7 -0
- aip_agents/mcp/utils/config_validator.py +139 -0
- aip_agents/memory/__init__.py +14 -0
- aip_agents/memory/adapters/__init__.py +10 -0
- aip_agents/memory/adapters/base_adapter.py +717 -0
- aip_agents/memory/adapters/mem0.py +84 -0
- aip_agents/memory/{base.pyi → base.py} +40 -5
- aip_agents/memory/constants.py +49 -0
- aip_agents/memory/factory.py +86 -0
- aip_agents/memory/guidance.py +20 -0
- aip_agents/memory/simple_memory.py +47 -0
- aip_agents/middleware/__init__.py +17 -0
- aip_agents/middleware/base.py +88 -0
- aip_agents/middleware/manager.py +128 -0
- aip_agents/middleware/todolist.py +274 -0
- aip_agents/schema/__init__.py +69 -0
- aip_agents/schema/a2a.py +56 -0
- aip_agents/schema/agent.py +111 -0
- aip_agents/schema/hitl.py +157 -0
- aip_agents/schema/langgraph.py +37 -0
- aip_agents/schema/model_id.py +97 -0
- aip_agents/schema/step_limit.py +108 -0
- aip_agents/schema/storage.py +40 -0
- aip_agents/sentry/__init__.py +11 -0
- aip_agents/sentry/sentry.py +151 -0
- aip_agents/storage/__init__.py +41 -0
- aip_agents/storage/{base.pyi → base.py} +30 -4
- aip_agents/storage/clients/__init__.py +12 -0
- aip_agents/storage/clients/minio_client.py +318 -0
- aip_agents/storage/config.py +62 -0
- aip_agents/storage/providers/__init__.py +15 -0
- aip_agents/storage/providers/{base.pyi → base.py} +23 -6
- aip_agents/storage/providers/{memory.pyi → memory.py} +38 -3
- aip_agents/storage/providers/object_storage.py +214 -0
- aip_agents/tools/__init__.py +6 -0
- aip_agents/tools/bosa_tools.py +105 -0
- aip_agents/tools/browser_use/__init__.py +82 -0
- aip_agents/tools/browser_use/action_parser.py +103 -0
- aip_agents/tools/browser_use/browser_use_tool.py +1112 -0
- aip_agents/tools/browser_use/llm_config.py +120 -0
- aip_agents/tools/browser_use/minio_storage.py +198 -0
- aip_agents/tools/browser_use/schemas.py +119 -0
- aip_agents/tools/browser_use/session.py +76 -0
- aip_agents/tools/browser_use/session_errors.py +132 -0
- aip_agents/tools/browser_use/steel_session_recording.py +317 -0
- aip_agents/tools/browser_use/streaming.py +813 -0
- aip_agents/tools/browser_use/structured_data_parser.py +257 -0
- aip_agents/tools/browser_use/structured_data_recovery.py +204 -0
- aip_agents/tools/browser_use/types.py +78 -0
- aip_agents/tools/code_sandbox/__init__.py +26 -0
- aip_agents/tools/code_sandbox/constant.py +13 -0
- aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.py +257 -0
- aip_agents/tools/code_sandbox/e2b_sandbox_tool.py +411 -0
- aip_agents/tools/constants.py +165 -0
- aip_agents/tools/document_loader/__init__.py +37 -0
- aip_agents/tools/document_loader/base_reader.py +262 -0
- aip_agents/tools/document_loader/docx_reader_tool.py +53 -0
- aip_agents/tools/document_loader/excel_reader_tool.py +160 -0
- aip_agents/tools/document_loader/pdf_reader_tool.py +67 -0
- aip_agents/tools/document_loader/pdf_splitter.py +169 -0
- aip_agents/tools/gl_connector/__init__.py +5 -0
- aip_agents/tools/gl_connector/tool.py +351 -0
- aip_agents/tools/memory_search/__init__.py +22 -0
- aip_agents/tools/memory_search/base.py +200 -0
- aip_agents/tools/memory_search/mem0.py +258 -0
- aip_agents/tools/memory_search/schema.py +48 -0
- aip_agents/tools/memory_search_tool.py +26 -0
- aip_agents/tools/tool_config_injector.py +300 -0
- aip_agents/tools/web_search/__init__.py +15 -0
- aip_agents/tools/web_search/serper_tool.py +187 -0
- aip_agents/types/__init__.py +70 -0
- aip_agents/types/a2a_events.py +13 -0
- aip_agents/utils/__init__.py +79 -0
- aip_agents/utils/a2a_connector.py +1757 -0
- aip_agents/utils/artifact_helpers.py +502 -0
- aip_agents/utils/constants.py +22 -0
- aip_agents/utils/datetime/__init__.py +34 -0
- aip_agents/utils/datetime/normalization.py +231 -0
- aip_agents/utils/datetime/timezone.py +206 -0
- aip_agents/utils/env_loader.py +27 -0
- aip_agents/utils/event_handler_registry.py +58 -0
- aip_agents/utils/file_prompt_utils.py +176 -0
- aip_agents/utils/final_response_builder.py +211 -0
- aip_agents/utils/formatter_llm_client.py +231 -0
- aip_agents/utils/langgraph/__init__.py +19 -0
- aip_agents/utils/langgraph/converter.py +128 -0
- aip_agents/utils/langgraph/tool_managers/__init__.py +15 -0
- aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.py +99 -0
- aip_agents/utils/langgraph/tool_managers/{base_tool_manager.pyi → base_tool_manager.py} +25 -8
- aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.py +1071 -0
- aip_agents/utils/langgraph/tool_output_management.py +967 -0
- aip_agents/utils/logger.py +195 -0
- aip_agents/utils/metadata/__init__.py +27 -0
- aip_agents/utils/metadata/activity_metadata_helper.py +407 -0
- aip_agents/utils/metadata/activity_narrative/__init__.py +35 -0
- aip_agents/utils/metadata/activity_narrative/builder.py +817 -0
- aip_agents/utils/metadata/activity_narrative/constants.py +51 -0
- aip_agents/utils/metadata/activity_narrative/context.py +49 -0
- aip_agents/utils/metadata/activity_narrative/formatters.py +230 -0
- aip_agents/utils/metadata/activity_narrative/utils.py +35 -0
- aip_agents/utils/metadata/schemas/__init__.py +16 -0
- aip_agents/utils/metadata/schemas/activity_schema.py +29 -0
- aip_agents/utils/metadata/schemas/thinking_schema.py +31 -0
- aip_agents/utils/metadata/thinking_metadata_helper.py +38 -0
- aip_agents/utils/metadata_helper.py +358 -0
- aip_agents/utils/name_preprocessor/__init__.py +17 -0
- aip_agents/utils/name_preprocessor/{base_name_preprocessor.pyi → base_name_preprocessor.py} +22 -2
- aip_agents/utils/name_preprocessor/google_name_preprocessor.py +100 -0
- aip_agents/utils/name_preprocessor/name_preprocessor.py +87 -0
- aip_agents/utils/name_preprocessor/{openai_name_preprocessor.pyi → openai_name_preprocessor.py} +19 -5
- aip_agents/utils/pii/__init__.py +25 -0
- aip_agents/utils/pii/pii_handler.py +397 -0
- aip_agents/utils/pii/pii_helper.py +207 -0
- aip_agents/utils/pii/uuid_deanonymizer_mapping.py +195 -0
- aip_agents/utils/reference_helper.py +273 -0
- aip_agents/utils/sse_chunk_transformer.py +831 -0
- aip_agents/utils/step_limit_manager.py +265 -0
- aip_agents/utils/token_usage_helper.py +156 -0
- aip_agents_binary-0.5.12.dist-info/METADATA +689 -0
- aip_agents_binary-0.5.12.dist-info/RECORD +279 -0
- {aip_agents_binary-0.0.0b2.dist-info → aip_agents_binary-0.5.12.dist-info}/WHEEL +2 -1
- aip_agents_binary-0.5.12.dist-info/top_level.txt +1 -0
- aip_agents/__init__.pyi +0 -0
- aip_agents/a2a/__init__.pyi +0 -3
- aip_agents/a2a/server/__init__.pyi +0 -4
- aip_agents/a2a/server/base_executor.pyi +0 -63
- aip_agents/a2a/server/google_adk_executor.pyi +0 -51
- aip_agents/a2a/server/langgraph_executor.pyi +0 -48
- aip_agents/a2a/types.pyi +0 -125
- aip_agents/agent/__init__.pyi +0 -7
- aip_agents/agent/base_agent.pyi +0 -205
- aip_agents/agent/base_langgraph_agent.pyi +0 -164
- aip_agents/agent/google_adk_agent.pyi +0 -128
- aip_agents/agent/langgraph_react_agent.pyi +0 -131
- aip_agents/agent/types.pyi +0 -106
- aip_agents/constants.pyi +0 -6
- aip_agents/examples/__init__.pyi +0 -0
- aip_agents/examples/hello_world_a2a_google_adk_client.pyi +0 -9
- aip_agents/examples/hello_world_a2a_google_adk_client_agent.pyi +0 -9
- aip_agents/examples/hello_world_a2a_google_adk_client_streaming.pyi +0 -9
- aip_agents/examples/hello_world_a2a_google_adk_server.pyi +0 -10
- aip_agents/examples/hello_world_a2a_langchain_client.pyi +0 -5
- aip_agents/examples/hello_world_a2a_langchain_client_agent.pyi +0 -5
- aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.pyi +0 -5
- aip_agents/examples/hello_world_a2a_langchain_client_streaming.pyi +0 -5
- aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.pyi +0 -5
- aip_agents/examples/hello_world_a2a_langchain_reference_server.pyi +0 -10
- aip_agents/examples/hello_world_a2a_langchain_server.pyi +0 -10
- aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.pyi +0 -10
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client.pyi +0 -5
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.pyi +0 -5
- aip_agents/examples/hello_world_a2a_langgraph_artifact_server.pyi +0 -11
- aip_agents/examples/hello_world_a2a_langgraph_client.pyi +0 -9
- aip_agents/examples/hello_world_a2a_langgraph_client_agent.pyi +0 -9
- aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.pyi +0 -2
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming.pyi +0 -9
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.pyi +0 -5
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.pyi +0 -5
- aip_agents/examples/hello_world_a2a_langgraph_server.pyi +0 -9
- aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.pyi +0 -10
- aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.pyi +0 -10
- aip_agents/examples/hello_world_a2a_mcp_langgraph.pyi +0 -48
- aip_agents/examples/hello_world_a2a_multi_agent_coordinator_client.pyi +0 -15
- aip_agents/examples/hello_world_a2a_multi_agent_coordinator_client_streaming.pyi +0 -5
- aip_agents/examples/hello_world_a2a_multi_agent_coordinator_server.pyi +0 -11
- aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.pyi +0 -23
- aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.pyi +0 -17
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.pyi +0 -5
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.pyi +0 -10
- aip_agents/examples/hello_world_google_adk.pyi +0 -5
- aip_agents/examples/hello_world_google_adk_mcp_http.pyi +0 -5
- aip_agents/examples/hello_world_google_adk_mcp_http_stream.pyi +0 -5
- aip_agents/examples/hello_world_google_adk_mcp_sse.pyi +0 -5
- aip_agents/examples/hello_world_google_adk_mcp_sse_stream.pyi +0 -5
- aip_agents/examples/hello_world_google_adk_mcp_stdio.pyi +0 -5
- aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.pyi +0 -5
- aip_agents/examples/hello_world_google_adk_stream.pyi +0 -5
- aip_agents/examples/hello_world_langchain.pyi +0 -5
- aip_agents/examples/hello_world_langchain_lm_invoker.pyi +0 -2
- aip_agents/examples/hello_world_langchain_mcp_http.pyi +0 -5
- aip_agents/examples/hello_world_langchain_mcp_http_stream.pyi +0 -5
- aip_agents/examples/hello_world_langchain_mcp_sse.pyi +0 -5
- aip_agents/examples/hello_world_langchain_mcp_sse_stream.pyi +0 -5
- aip_agents/examples/hello_world_langchain_mcp_stdio.pyi +0 -5
- aip_agents/examples/hello_world_langchain_mcp_stdio_stream.pyi +0 -5
- aip_agents/examples/hello_world_langchain_stream.pyi +0 -5
- aip_agents/examples/hello_world_langchain_stream_lm_invoker.pyi +0 -5
- aip_agents/examples/hello_world_langgraph.pyi +0 -5
- aip_agents/examples/hello_world_langgraph_bosa.pyi +0 -5
- aip_agents/examples/hello_world_langgraph_bosa_twitter.pyi +0 -5
- aip_agents/examples/hello_world_langgraph_mcp_http.pyi +0 -5
- aip_agents/examples/hello_world_langgraph_mcp_http_stream.pyi +0 -5
- aip_agents/examples/hello_world_langgraph_mcp_sse.pyi +0 -5
- aip_agents/examples/hello_world_langgraph_mcp_sse_stream.pyi +0 -5
- aip_agents/examples/hello_world_langgraph_mcp_stdio.pyi +0 -5
- aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.pyi +0 -5
- aip_agents/examples/hello_world_langgraph_stream.pyi +0 -5
- aip_agents/examples/hello_world_langgraph_stream_lm_invoker.pyi +0 -5
- aip_agents/examples/hello_world_model_switch_cli.pyi +0 -15
- aip_agents/examples/hello_world_multi_agent_adk.pyi +0 -6
- aip_agents/examples/hello_world_multi_agent_langchain.pyi +0 -5
- aip_agents/examples/hello_world_multi_agent_langgraph.pyi +0 -5
- aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.pyi +0 -5
- aip_agents/examples/hello_world_pii_logger.pyi +0 -5
- aip_agents/examples/hello_world_sentry.pyi +0 -21
- aip_agents/examples/hello_world_stock_a2a_server.pyi +0 -12
- aip_agents/examples/hello_world_tool_output_client.pyi +0 -5
- aip_agents/examples/hello_world_tool_output_server.pyi +0 -14
- aip_agents/examples/tools/__init__.pyi +0 -7
- aip_agents/examples/tools/adk_weather_tool.pyi +0 -18
- aip_agents/examples/tools/data_generator_tool.pyi +0 -15
- aip_agents/examples/tools/data_visualization_tool.pyi +0 -17
- aip_agents/examples/tools/image_artifact_tool.pyi +0 -24
- aip_agents/examples/tools/langchain_arithmetic_tools.pyi +0 -10
- aip_agents/examples/tools/langchain_currency_exchange_tool.pyi +0 -21
- aip_agents/examples/tools/langchain_graph_artifact_tool.pyi +0 -23
- aip_agents/examples/tools/langchain_weather_tool.pyi +0 -19
- aip_agents/examples/tools/langgraph_streaming_tool.pyi +0 -43
- aip_agents/examples/tools/pr_details_bosa_tool.pyi +0 -26
- aip_agents/examples/tools/serper_tool.pyi +0 -16
- aip_agents/examples/tools/stock_tools.pyi +0 -21
- aip_agents/examples/tools/table_generator_tool.pyi +0 -22
- aip_agents/examples/tools/time_tool.pyi +0 -15
- aip_agents/examples/tools/weather_forecast_tool.pyi +0 -14
- aip_agents/mcp/__init__.pyi +0 -0
- aip_agents/mcp/client/__init__.pyi +0 -4
- aip_agents/mcp/client/google_adk/__init__.pyi +0 -3
- aip_agents/mcp/client/google_adk/client.pyi +0 -38
- aip_agents/mcp/client/langchain/__init__.pyi +0 -3
- aip_agents/mcp/client/langchain/client.pyi +0 -3
- aip_agents/memory/__init__.pyi +0 -0
- aip_agents/memory/simple_memory.pyi +0 -22
- aip_agents/sentry/__init__.pyi +0 -3
- aip_agents/sentry/sentry.pyi +0 -48
- aip_agents/storage/__init__.pyi +0 -8
- aip_agents/storage/clients/__init__.pyi +0 -3
- aip_agents/storage/clients/minio_client.pyi +0 -137
- aip_agents/storage/config.pyi +0 -66
- aip_agents/storage/providers/__init__.pyi +0 -5
- aip_agents/storage/providers/object_storage.pyi +0 -98
- aip_agents/tools/__init__.pyi +0 -3
- aip_agents/tools/base.pyi +0 -44
- aip_agents/tools/base_bosa_tools.pyi +0 -12
- aip_agents/tools/bosa_connector.pyi +0 -30
- aip_agents/tools/bosa_tools.pyi +0 -37
- aip_agents/tools/bosa_tools_interface.pyi +0 -26
- aip_agents/tools/constants.pyi +0 -130
- aip_agents/tools/nested_agent_tool.pyi +0 -45
- aip_agents/tools/tool_config_injector.pyi +0 -26
- aip_agents/types/__init__.pyi +0 -3
- aip_agents/types/a2a_events.pyi +0 -74
- aip_agents/utils/__init__.pyi +0 -5
- aip_agents/utils/a2a_connector.pyi +0 -135
- aip_agents/utils/artifact_helpers.pyi +0 -179
- aip_agents/utils/langgraph/__init__.pyi +0 -3
- aip_agents/utils/langgraph/converter.pyi +0 -49
- aip_agents/utils/langgraph/tool_managers/__init__.pyi +0 -5
- aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.pyi +0 -35
- aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.pyi +0 -50
- aip_agents/utils/langgraph/tool_output_management.pyi +0 -310
- aip_agents/utils/logger_manager.pyi +0 -151
- aip_agents/utils/metadata_helper.pyi +0 -110
- aip_agents/utils/name_preprocessor/__init__.pyi +0 -6
- aip_agents/utils/name_preprocessor/google_name_preprocessor.pyi +0 -38
- aip_agents/utils/name_preprocessor/name_preprocessor.pyi +0 -41
- aip_agents/utils/reference_helper.pyi +0 -49
- aip_agents/utils/token_usage_helper.pyi +0 -60
- aip_agents_binary-0.0.0b2.dist-info/METADATA +0 -277
- aip_agents_binary-0.0.0b2.dist-info/RECORD +0 -157
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Tool to read and extract text from PDF files.
|
|
2
|
+
|
|
3
|
+
Authors:
|
|
4
|
+
Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
|
|
5
|
+
|
|
6
|
+
References:
|
|
7
|
+
https://github.com/GDP-ADMIN/gdplabs-exploration/blob/ai-agent-app/backend/aip_agents/tools/
|
|
8
|
+
reader/pdf_reader_tool.py
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from gllm_docproc.loader.pdf import PDFPlumberLoader, PyMuPDFLoader
|
|
12
|
+
|
|
13
|
+
from aip_agents.tools.document_loader.base_reader import BaseDocumentReaderTool
|
|
14
|
+
from aip_agents.tools.document_loader.pdf_splitter import PDFSplitter
|
|
15
|
+
from aip_agents.utils.logger import get_logger
|
|
16
|
+
|
|
17
|
+
logger = get_logger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class PDFReaderTool(BaseDocumentReaderTool):
|
|
21
|
+
"""Tool to read and extract text from PDF files."""
|
|
22
|
+
|
|
23
|
+
name: str = "pdf_reader_tool"
|
|
24
|
+
description: str = "Read a PDF file and extract its text content. Input should be the path to the PDF file."
|
|
25
|
+
|
|
26
|
+
def _setup_loader(self):
|
|
27
|
+
self.loader.add_loader(PyMuPDFLoader())
|
|
28
|
+
self.loader.add_loader(PDFPlumberLoader())
|
|
29
|
+
|
|
30
|
+
def _split_file(self, file_path: str, batch_size: int) -> list[str]:
|
|
31
|
+
"""Split PDF file into temporary files for batch processing.
|
|
32
|
+
|
|
33
|
+
This method uses PDFSplitter.split_by_pages to split the PDF into
|
|
34
|
+
temporary files containing the specified number of pages per batch.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
file_path: Path to the PDF file to be split
|
|
38
|
+
batch_size: Number of pages to include in each split file (1-10)
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
List of temporary file paths containing the split content
|
|
42
|
+
|
|
43
|
+
Raises:
|
|
44
|
+
FileNotFoundError: If the input PDF file doesn't exist
|
|
45
|
+
ValueError: If batch_size is invalid or PDF processing fails
|
|
46
|
+
Exception: For other unexpected errors during PDF splitting
|
|
47
|
+
"""
|
|
48
|
+
logger.info(f"Splitting PDF file '{file_path}' with batch_size={batch_size}")
|
|
49
|
+
|
|
50
|
+
try:
|
|
51
|
+
# Use PDFSplitter utility to split the PDF by pages
|
|
52
|
+
temp_files = PDFSplitter.split_by_pages(file_path, batch_size)
|
|
53
|
+
|
|
54
|
+
logger.info(f"Successfully split PDF into {len(temp_files)} batch files")
|
|
55
|
+
logger.debug(f"Created temporary files: {temp_files}")
|
|
56
|
+
|
|
57
|
+
return temp_files
|
|
58
|
+
|
|
59
|
+
except FileNotFoundError:
|
|
60
|
+
logger.error(f"PDF file not found: {file_path}")
|
|
61
|
+
raise
|
|
62
|
+
except ValueError as e:
|
|
63
|
+
logger.error(f"Invalid parameters or corrupted PDF: {str(e)}")
|
|
64
|
+
raise
|
|
65
|
+
except Exception as e:
|
|
66
|
+
logger.error(f"Unexpected error splitting PDF '{file_path}': {str(e)}")
|
|
67
|
+
raise Exception(f"Failed to split PDF file: {str(e)}") from e
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"""PDF splitting utility for batching optimization.
|
|
2
|
+
|
|
3
|
+
Authors
|
|
4
|
+
Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import tempfile
|
|
9
|
+
|
|
10
|
+
from PyPDF2 import PdfReader, PdfWriter
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class PDFSplitter:
|
|
14
|
+
"""Utility class for splitting PDF files into page-based temporary files."""
|
|
15
|
+
|
|
16
|
+
@staticmethod
|
|
17
|
+
def split_by_pages(file_path: str, batch_size: int) -> list[str]:
|
|
18
|
+
"""Split PDF into temporary files containing batch_size pages each.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
file_path: Path to the PDF file to split
|
|
22
|
+
batch_size: Number of pages to include in each batch (1-10)
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
List of temporary file paths containing the split PDF batches
|
|
26
|
+
|
|
27
|
+
Raises:
|
|
28
|
+
FileNotFoundError: If the input PDF file doesn't exist
|
|
29
|
+
ValueError: If batch_size is invalid or PDF is corrupted
|
|
30
|
+
Exception: For other PDF processing errors
|
|
31
|
+
"""
|
|
32
|
+
PDFSplitter._validate_inputs(file_path, batch_size)
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
reader = PdfReader(file_path)
|
|
36
|
+
PDFSplitter._validate_pdf_content(reader, file_path)
|
|
37
|
+
|
|
38
|
+
temp_files = []
|
|
39
|
+
|
|
40
|
+
# Split PDF into batches
|
|
41
|
+
for i in range(0, len(reader.pages), batch_size):
|
|
42
|
+
batch_number = i // batch_size + 1
|
|
43
|
+
temp_path = PDFSplitter._create_batch_file(reader, i, batch_size, batch_number, temp_files)
|
|
44
|
+
temp_files.append(temp_path)
|
|
45
|
+
|
|
46
|
+
return temp_files
|
|
47
|
+
|
|
48
|
+
except Exception as e:
|
|
49
|
+
# Handle corrupted or invalid PDF files
|
|
50
|
+
if "temp_files" in locals():
|
|
51
|
+
PDFSplitter._cleanup_temp_files(temp_files)
|
|
52
|
+
|
|
53
|
+
if isinstance(e, FileNotFoundError | ValueError):
|
|
54
|
+
raise
|
|
55
|
+
else:
|
|
56
|
+
raise ValueError(f"Error processing PDF file {file_path}: {str(e)}") from e
|
|
57
|
+
|
|
58
|
+
@staticmethod
|
|
59
|
+
def _validate_inputs(file_path: str, batch_size: int) -> None:
|
|
60
|
+
"""Validate input parameters.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
file_path: Path to the PDF file to validate
|
|
64
|
+
batch_size: Batch size to validate
|
|
65
|
+
|
|
66
|
+
Raises:
|
|
67
|
+
FileNotFoundError: If the input PDF file doesn't exist
|
|
68
|
+
ValueError: If batch_size is invalid
|
|
69
|
+
"""
|
|
70
|
+
if not os.path.exists(file_path):
|
|
71
|
+
raise FileNotFoundError(f"PDF file not found: {file_path}")
|
|
72
|
+
|
|
73
|
+
@staticmethod
|
|
74
|
+
def _validate_pdf_content(reader: PdfReader, file_path: str) -> None:
|
|
75
|
+
"""Validate PDF content has pages.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
reader: PdfReader instance to validate
|
|
79
|
+
file_path: Path to the PDF file for error messages
|
|
80
|
+
|
|
81
|
+
Raises:
|
|
82
|
+
ValueError: If PDF has no pages
|
|
83
|
+
"""
|
|
84
|
+
if len(reader.pages) == 0:
|
|
85
|
+
raise ValueError(f"PDF file has no pages: {file_path}")
|
|
86
|
+
|
|
87
|
+
@staticmethod
|
|
88
|
+
def _create_batch_file(
|
|
89
|
+
reader: PdfReader,
|
|
90
|
+
start_page: int,
|
|
91
|
+
batch_size: int,
|
|
92
|
+
batch_number: int,
|
|
93
|
+
temp_files: list[str],
|
|
94
|
+
) -> str:
|
|
95
|
+
"""Create a temporary file containing a batch of PDF pages.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
reader: PdfReader instance containing the source pages
|
|
99
|
+
start_page: Starting page index for this batch
|
|
100
|
+
batch_size: Number of pages to include in the batch
|
|
101
|
+
batch_number: Batch number for file naming
|
|
102
|
+
temp_files: List of existing temp files for cleanup on error
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
Path to the created temporary file
|
|
106
|
+
|
|
107
|
+
Raises:
|
|
108
|
+
ValueError: If page processing or file writing fails
|
|
109
|
+
"""
|
|
110
|
+
writer = PdfWriter()
|
|
111
|
+
|
|
112
|
+
# Add pages to this batch
|
|
113
|
+
batch_end = min(start_page + batch_size, len(reader.pages))
|
|
114
|
+
for j in range(start_page, batch_end):
|
|
115
|
+
try:
|
|
116
|
+
writer.add_page(reader.pages[j])
|
|
117
|
+
except Exception as e:
|
|
118
|
+
# Clean up any created temp files before re-raising
|
|
119
|
+
PDFSplitter._cleanup_temp_files(temp_files)
|
|
120
|
+
raise ValueError(f"Error processing page {j + 1}: {str(e)}") from e
|
|
121
|
+
|
|
122
|
+
# Create and write temporary file
|
|
123
|
+
return PDFSplitter._write_batch_to_temp_file(writer, batch_number, temp_files)
|
|
124
|
+
|
|
125
|
+
@staticmethod
|
|
126
|
+
def _write_batch_to_temp_file(writer: PdfWriter, batch_number: int, temp_files: list[str]) -> str:
|
|
127
|
+
"""Write a PDF batch to a temporary file.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
writer: PdfWriter instance containing the batch pages
|
|
131
|
+
batch_number: Batch number for file naming
|
|
132
|
+
temp_files: List of existing temp files for cleanup on error
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
Path to the created temporary file
|
|
136
|
+
|
|
137
|
+
Raises:
|
|
138
|
+
ValueError: If file writing fails
|
|
139
|
+
"""
|
|
140
|
+
# Create temporary file with proper naming
|
|
141
|
+
temp_fd, temp_path = tempfile.mkstemp(suffix=f"_batch_{batch_number}.pdf", prefix="pdf_split_")
|
|
142
|
+
|
|
143
|
+
try:
|
|
144
|
+
with os.fdopen(temp_fd, "wb") as temp_file:
|
|
145
|
+
writer.write(temp_file)
|
|
146
|
+
return temp_path
|
|
147
|
+
except Exception as e:
|
|
148
|
+
# Close the file descriptor if write fails
|
|
149
|
+
try:
|
|
150
|
+
os.close(temp_fd)
|
|
151
|
+
except OSError:
|
|
152
|
+
pass
|
|
153
|
+
# Clean up any created temp files
|
|
154
|
+
PDFSplitter._cleanup_temp_files(temp_files)
|
|
155
|
+
raise ValueError(f"Error writing batch {batch_number}: {str(e)}") from e
|
|
156
|
+
|
|
157
|
+
@staticmethod
|
|
158
|
+
def _cleanup_temp_files(temp_files: list[str]) -> None:
|
|
159
|
+
"""Clean up temporary files.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
temp_files: List of temporary file paths to clean up
|
|
163
|
+
"""
|
|
164
|
+
for temp_file in temp_files:
|
|
165
|
+
try:
|
|
166
|
+
if os.path.exists(temp_file):
|
|
167
|
+
os.unlink(temp_file)
|
|
168
|
+
except OSError:
|
|
169
|
+
pass
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
"""GL Connector tool wrapper for BOSA connector tools.
|
|
2
|
+
|
|
3
|
+
Authors:
|
|
4
|
+
Saul Sayers (saul.sayers@gdplabs.id)
|
|
5
|
+
|
|
6
|
+
Reference:
|
|
7
|
+
https://gl-docs.gitbook.io/bosa/gl-connector/gl-connector
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
from collections.abc import Iterable
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
from bosa_connectors import BosaConnector, BOSAConnectorToolGenerator
|
|
17
|
+
from langchain_core.runnables import RunnableConfig
|
|
18
|
+
from langchain_core.tools import BaseTool
|
|
19
|
+
from pydantic import ConfigDict, PrivateAttr
|
|
20
|
+
|
|
21
|
+
from aip_agents.tools.constants import ToolType
|
|
22
|
+
|
|
23
|
+
_REQUIRED_ENV_VARS: tuple[str, ...] = (
|
|
24
|
+
"BOSA_BASE_URL",
|
|
25
|
+
"BOSA_API_KEY",
|
|
26
|
+
"BOSA_USERNAME",
|
|
27
|
+
"BOSA_PASSWORD",
|
|
28
|
+
)
|
|
29
|
+
_TOP_LEVEL_KEYS: tuple[str, ...] = (
|
|
30
|
+
"token",
|
|
31
|
+
"identifier",
|
|
32
|
+
"timeout",
|
|
33
|
+
"request",
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class _InjectedTool(BaseTool):
|
|
38
|
+
"""Wrap a BaseTool to inject token and optional identifier into inputs."""
|
|
39
|
+
|
|
40
|
+
_base_tool: BaseTool = PrivateAttr()
|
|
41
|
+
_token: str = PrivateAttr()
|
|
42
|
+
_identifier: str | None = PrivateAttr(default=None)
|
|
43
|
+
|
|
44
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
45
|
+
|
|
46
|
+
def __init__(self, base_tool: BaseTool, token: str, identifier: str | None) -> None:
|
|
47
|
+
"""Initialize the injected tool wrapper.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
base_tool: The base tool to wrap.
|
|
51
|
+
token: Authentication token to inject into tool inputs.
|
|
52
|
+
identifier: Optional identifier to inject into tool inputs.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
None
|
|
56
|
+
"""
|
|
57
|
+
base_fields = {field: getattr(base_tool, field) for field in BaseTool.model_fields}
|
|
58
|
+
super().__init__(**base_fields)
|
|
59
|
+
self._base_tool = base_tool
|
|
60
|
+
self._token = token
|
|
61
|
+
self._identifier = identifier
|
|
62
|
+
|
|
63
|
+
def _run(self, *args: Any, **kwargs: Any) -> Any:
|
|
64
|
+
"""Execute the wrapped tool synchronously.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
*args: Positional arguments to pass to the base tool.
|
|
68
|
+
**kwargs: Keyword arguments to pass to the base tool.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
The result of executing the base tool.
|
|
72
|
+
"""
|
|
73
|
+
return self._base_tool._run(*args, **kwargs)
|
|
74
|
+
|
|
75
|
+
async def _arun(self, *args: Any, **kwargs: Any) -> Any:
|
|
76
|
+
"""Execute the wrapped tool asynchronously.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
*args: Positional arguments to pass to the base tool.
|
|
80
|
+
**kwargs: Keyword arguments to pass to the base tool.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
The result of executing the base tool.
|
|
84
|
+
"""
|
|
85
|
+
return await self._base_tool._arun(*args, **kwargs)
|
|
86
|
+
|
|
87
|
+
def invoke(self, input: Any, config: RunnableConfig | None = None, **kwargs: Any) -> Any:
|
|
88
|
+
"""Invoke the tool with token and optional identifier injected.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
input: Tool input to process.
|
|
92
|
+
config: Optional runnable configuration.
|
|
93
|
+
**kwargs: Additional keyword arguments.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
The result of invoking the tool with injected parameters.
|
|
97
|
+
"""
|
|
98
|
+
injected = _inject_params(input, self._token, self._identifier, self._base_tool)
|
|
99
|
+
return super().invoke(injected, config=config, **kwargs)
|
|
100
|
+
|
|
101
|
+
async def ainvoke(self, input: Any, config: RunnableConfig | None = None, **kwargs: Any) -> Any:
|
|
102
|
+
"""Invoke the tool asynchronously with token and optional identifier injected.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
input: Tool input to process.
|
|
106
|
+
config: Optional runnable configuration.
|
|
107
|
+
**kwargs: Additional keyword arguments.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
The result of invoking the tool with injected parameters.
|
|
111
|
+
"""
|
|
112
|
+
injected = _inject_params(input, self._token, self._identifier, self._base_tool)
|
|
113
|
+
return await super().ainvoke(injected, config=config, **kwargs)
|
|
114
|
+
|
|
115
|
+
def run(self, tool_input: Any, **kwargs: Any) -> Any:
|
|
116
|
+
"""Run the tool with token and optional identifier injected.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
tool_input: Tool input to process.
|
|
120
|
+
**kwargs: Additional keyword arguments.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
The result of running the tool with injected parameters.
|
|
124
|
+
"""
|
|
125
|
+
injected = _inject_params(tool_input, self._token, self._identifier, self._base_tool)
|
|
126
|
+
return super().run(injected, **kwargs)
|
|
127
|
+
|
|
128
|
+
async def arun(self, tool_input: Any, **kwargs: Any) -> Any:
|
|
129
|
+
"""Run the tool asynchronously with token and optional identifier injected.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
tool_input: Tool input to process.
|
|
133
|
+
**kwargs: Additional keyword arguments.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
The result of running the tool with injected parameters.
|
|
137
|
+
"""
|
|
138
|
+
injected = _inject_params(tool_input, self._token, self._identifier, self._base_tool)
|
|
139
|
+
return await super().arun(injected, **kwargs)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def GLConnectorTool(
|
|
143
|
+
tool_name: str,
|
|
144
|
+
*,
|
|
145
|
+
api_key: str | None = None,
|
|
146
|
+
identifier: str | None = None,
|
|
147
|
+
) -> BaseTool:
|
|
148
|
+
"""Create a single GL Connector tool by exact tool name.
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
tool_name: Exact tool name (not module name).
|
|
152
|
+
api_key: Optional override for BOSA API key.
|
|
153
|
+
identifier: Optional override for BOSA identifier.
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
A single LangChain BaseTool with token injection.
|
|
157
|
+
"""
|
|
158
|
+
if not tool_name or not tool_name.strip():
|
|
159
|
+
raise ValueError("tool_name must be a non-empty string")
|
|
160
|
+
|
|
161
|
+
env_values = _load_env(api_key=api_key, identifier=identifier)
|
|
162
|
+
connector = BosaConnector(api_base_url=env_values["BOSA_BASE_URL"], api_key=env_values["BOSA_API_KEY"])
|
|
163
|
+
|
|
164
|
+
modules = _get_available_modules(connector)
|
|
165
|
+
module_name = _resolve_module(tool_name, modules)
|
|
166
|
+
|
|
167
|
+
generator = BOSAConnectorToolGenerator(
|
|
168
|
+
api_base_url=env_values["BOSA_BASE_URL"],
|
|
169
|
+
api_key=env_values["BOSA_API_KEY"],
|
|
170
|
+
app_name=module_name,
|
|
171
|
+
)
|
|
172
|
+
tools = generator.generate_tools(tool_type=ToolType.LANGCHAIN)
|
|
173
|
+
|
|
174
|
+
matching = [tool for tool in tools if getattr(tool, "name", None) == tool_name]
|
|
175
|
+
if not matching:
|
|
176
|
+
raise ValueError(f"Tool '{tool_name}' not found in module '{module_name}'")
|
|
177
|
+
if len(matching) > 1:
|
|
178
|
+
raise ValueError(f"Multiple tools named '{tool_name}' found in module '{module_name}'")
|
|
179
|
+
|
|
180
|
+
token = _create_token(connector, env_values["BOSA_USERNAME"], env_values["BOSA_PASSWORD"])
|
|
181
|
+
return _InjectedTool(matching[0], token, env_values.get("BOSA_IDENTIFIER"))
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _load_env(*, api_key: str | None, identifier: str | None) -> dict[str, str]:
|
|
185
|
+
"""Load and validate environment configuration for connector access.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
api_key: Optional override for BOSA API key.
|
|
189
|
+
identifier: Optional override for BOSA identifier.
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
Dictionary containing environment configuration values.
|
|
193
|
+
|
|
194
|
+
Raises:
|
|
195
|
+
ValueError: If required environment variables are missing.
|
|
196
|
+
"""
|
|
197
|
+
env = {key: os.getenv(key) for key in _REQUIRED_ENV_VARS}
|
|
198
|
+
|
|
199
|
+
resolved_api_key = api_key or env["BOSA_API_KEY"]
|
|
200
|
+
env["BOSA_API_KEY"] = resolved_api_key
|
|
201
|
+
|
|
202
|
+
optional_identifier = identifier or os.getenv("BOSA_IDENTIFIER")
|
|
203
|
+
|
|
204
|
+
if optional_identifier:
|
|
205
|
+
env["BOSA_IDENTIFIER"] = optional_identifier
|
|
206
|
+
|
|
207
|
+
missing = [key for key, value in env.items() if key in _REQUIRED_ENV_VARS and not value]
|
|
208
|
+
if missing:
|
|
209
|
+
raise ValueError(f"Missing required environment variables: {', '.join(missing)}")
|
|
210
|
+
|
|
211
|
+
return {key: value for key, value in env.items() if value is not None}
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def _get_available_modules(connector: BosaConnector) -> list[str]:
|
|
215
|
+
"""Return available connector modules or raise an actionable error.
|
|
216
|
+
|
|
217
|
+
Args:
|
|
218
|
+
connector: BOSA connector instance to query for modules.
|
|
219
|
+
|
|
220
|
+
Returns:
|
|
221
|
+
List of available module names.
|
|
222
|
+
|
|
223
|
+
Raises:
|
|
224
|
+
ValueError: If module fetching fails or no modules are available.
|
|
225
|
+
"""
|
|
226
|
+
try:
|
|
227
|
+
modules = list(connector.get_available_modules())
|
|
228
|
+
except Exception as exc:
|
|
229
|
+
raise ValueError("Failed to fetch available connector modules") from exc
|
|
230
|
+
|
|
231
|
+
if not modules:
|
|
232
|
+
raise ValueError("No connector modules available")
|
|
233
|
+
return modules
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def _resolve_module(tool_name: str, modules: Iterable[str]) -> str:
|
|
237
|
+
"""Resolve the module name by longest prefix match.
|
|
238
|
+
|
|
239
|
+
Args:
|
|
240
|
+
tool_name: Name of the tool to resolve module for.
|
|
241
|
+
modules: Iterable of available module names.
|
|
242
|
+
|
|
243
|
+
Returns:
|
|
244
|
+
The resolved module name.
|
|
245
|
+
|
|
246
|
+
Raises:
|
|
247
|
+
ValueError: If no matching module is found or multiple ambiguous matches exist.
|
|
248
|
+
"""
|
|
249
|
+
candidates = [module for module in modules if tool_name == module or tool_name.startswith(f"{module}_")]
|
|
250
|
+
if not candidates:
|
|
251
|
+
raise ValueError(f"Unable to resolve module for tool '{tool_name}'. Available modules: {', '.join(modules)}")
|
|
252
|
+
|
|
253
|
+
candidates.sort(key=len, reverse=True)
|
|
254
|
+
if len(candidates) > 1 and len(candidates[0]) == len(candidates[1]):
|
|
255
|
+
raise ValueError(f"Ambiguous module match for tool '{tool_name}'. Matches: {', '.join(candidates)}")
|
|
256
|
+
return candidates[0]
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def _create_token(connector: BosaConnector, username: str, password: str) -> str:
|
|
260
|
+
"""Authenticate the connector user and return a user token.
|
|
261
|
+
|
|
262
|
+
Args:
|
|
263
|
+
connector: BOSA connector instance for authentication.
|
|
264
|
+
username: BOSA username for authentication.
|
|
265
|
+
password: BOSA password for authentication.
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
Authentication token string.
|
|
269
|
+
|
|
270
|
+
Raises:
|
|
271
|
+
ValueError: If authentication fails or token is missing.
|
|
272
|
+
"""
|
|
273
|
+
try:
|
|
274
|
+
user = connector.authenticate_bosa_user(username, password)
|
|
275
|
+
except Exception as exc:
|
|
276
|
+
raise ValueError("Failed to authenticate BOSA user") from exc
|
|
277
|
+
|
|
278
|
+
token = getattr(user, "token", None)
|
|
279
|
+
if not token:
|
|
280
|
+
raise ValueError("BOSA user token missing after authentication")
|
|
281
|
+
return token
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def _inject_params(tool_input: Any, token: str, identifier: str | None, base_tool: BaseTool) -> dict[str, Any]:
|
|
285
|
+
"""Inject token and optional identifier into tool input.
|
|
286
|
+
|
|
287
|
+
Args:
|
|
288
|
+
tool_input: Original tool input dictionary.
|
|
289
|
+
token: Authentication token to inject.
|
|
290
|
+
identifier: Optional identifier to inject.
|
|
291
|
+
base_tool: Base tool instance for schema inspection.
|
|
292
|
+
|
|
293
|
+
Returns:
|
|
294
|
+
Dictionary with token and optional identifier injected.
|
|
295
|
+
|
|
296
|
+
Raises:
|
|
297
|
+
TypeError: If tool_input is not a dictionary.
|
|
298
|
+
"""
|
|
299
|
+
if tool_input is None:
|
|
300
|
+
tool_input = {}
|
|
301
|
+
|
|
302
|
+
if not isinstance(tool_input, dict):
|
|
303
|
+
raise TypeError("Connector tool input must be a dict to inject token")
|
|
304
|
+
|
|
305
|
+
if "args" in tool_input and isinstance(tool_input.get("args"), dict):
|
|
306
|
+
injected_args = dict(tool_input["args"])
|
|
307
|
+
injected_args["token"] = token
|
|
308
|
+
if identifier:
|
|
309
|
+
injected_args["identifier"] = identifier
|
|
310
|
+
injected = dict(tool_input)
|
|
311
|
+
injected["args"] = injected_args
|
|
312
|
+
return injected
|
|
313
|
+
|
|
314
|
+
injected = dict(tool_input)
|
|
315
|
+
injected = _wrap_request_if_needed(injected, base_tool)
|
|
316
|
+
injected["token"] = token
|
|
317
|
+
if identifier:
|
|
318
|
+
injected["identifier"] = identifier
|
|
319
|
+
return injected
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def _wrap_request_if_needed(tool_input: dict[str, Any], base_tool: BaseTool) -> dict[str, Any]:
|
|
323
|
+
"""Wrap flat inputs into a 'request' payload when required by schema.
|
|
324
|
+
|
|
325
|
+
Args:
|
|
326
|
+
tool_input: Tool input dictionary to potentially wrap.
|
|
327
|
+
base_tool: Base tool instance for schema inspection.
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
Dictionary with inputs wrapped in 'request' key if needed, otherwise unchanged.
|
|
331
|
+
"""
|
|
332
|
+
args_schema = getattr(base_tool, "args_schema", None)
|
|
333
|
+
if not (isinstance(args_schema, dict) and "request" in args_schema.get("properties", {})):
|
|
334
|
+
return tool_input
|
|
335
|
+
|
|
336
|
+
request_payload = {}
|
|
337
|
+
existing_request = tool_input.get("request")
|
|
338
|
+
if isinstance(existing_request, dict):
|
|
339
|
+
request_payload.update(existing_request)
|
|
340
|
+
|
|
341
|
+
for key, value in tool_input.items():
|
|
342
|
+
if key in _TOP_LEVEL_KEYS:
|
|
343
|
+
continue
|
|
344
|
+
request_payload.setdefault(key, value)
|
|
345
|
+
|
|
346
|
+
wrapped = dict(tool_input)
|
|
347
|
+
wrapped["request"] = request_payload
|
|
348
|
+
for key in list(wrapped.keys()):
|
|
349
|
+
if key not in _TOP_LEVEL_KEYS:
|
|
350
|
+
wrapped.pop(key, None)
|
|
351
|
+
return wrapped
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Memory search tool package exposing shared schemas and implementations.
|
|
2
|
+
|
|
3
|
+
Authors:
|
|
4
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from aip_agents.tools.memory_search.base import LongTermMemorySearchTool
|
|
8
|
+
from aip_agents.tools.memory_search.mem0 import (
|
|
9
|
+
MEMORY_SEARCH_TOOL_NAME,
|
|
10
|
+
Mem0SearchInput,
|
|
11
|
+
Mem0SearchTool,
|
|
12
|
+
)
|
|
13
|
+
from aip_agents.tools.memory_search.schema import LongTermMemorySearchInput, MemoryConfig
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"MemoryConfig",
|
|
17
|
+
"LongTermMemorySearchInput",
|
|
18
|
+
"LongTermMemorySearchTool",
|
|
19
|
+
"Mem0SearchInput",
|
|
20
|
+
"Mem0SearchTool",
|
|
21
|
+
"MEMORY_SEARCH_TOOL_NAME",
|
|
22
|
+
]
|