aip-agents-binary 0.0.0__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 +66 -0
- aip_agents/a2a/__init__.py +19 -0
- aip_agents/a2a/server/__init__.py +10 -0
- aip_agents/a2a/server/base_executor.py +1125 -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/a2ui/__init__.py +26 -0
- aip_agents/a2ui/catalog_provider.py +109 -0
- aip_agents/a2ui/examples/0.8/booking_form.json +1 -0
- aip_agents/a2ui/examples/0.8/confirmation.json +1 -0
- aip_agents/a2ui/examples/0.8/single_column_list.json +1 -0
- aip_agents/a2ui/examples/0.9/booking_form.json +1 -0
- aip_agents/a2ui/examples/0.9/confirmation.json +1 -0
- aip_agents/a2ui/examples/0.9/single_column_list.json +1 -0
- aip_agents/a2ui/middleware.py +754 -0
- aip_agents/a2ui/models.py +153 -0
- aip_agents/a2ui/public_url.py +138 -0
- aip_agents/a2ui/stream_filter.py +67 -0
- aip_agents/agent/__init__.py +72 -0
- aip_agents/agent/base_agent.py +1437 -0
- aip_agents/agent/base_langgraph_agent.py +4048 -0
- aip_agents/agent/google_adk_agent.py +932 -0
- aip_agents/agent/google_adk_constants.py +11 -0
- aip_agents/agent/graph_runtime.py +185 -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.py +138 -0
- aip_agents/agent/interfaces.py +65 -0
- aip_agents/agent/langflow_agent.py +464 -0
- aip_agents/agent/langgraph_react_agent.py +3741 -0
- aip_agents/agent/model_invocation_adapter.py +346 -0
- aip_agents/agent/system_instruction_context.py +34 -0
- aip_agents/agent/tool_execution_engine.py +587 -0
- aip_agents/audio_interface/__init__.py +30 -0
- aip_agents/audio_interface/audio_agent_adapter.py +254 -0
- aip_agents/audio_interface/config.py +146 -0
- aip_agents/audio_interface/errors.py +15 -0
- aip_agents/audio_interface/livekit_audio_session.py +504 -0
- aip_agents/audio_interface/livekit_realtime_audio_session.py +142 -0
- aip_agents/audio_interface/session_factory.py +40 -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/common/__init__.py +5 -0
- aip_agents/common/callable_introspection.py +17 -0
- aip_agents/constants.py +23 -0
- aip_agents/context/__init__.py +5 -0
- aip_agents/context/budget.py +237 -0
- aip_agents/context/compaction.py +339 -0
- aip_agents/context/metadata.py +169 -0
- aip_agents/context/offload.py +449 -0
- aip_agents/context/preparation.py +196 -0
- aip_agents/context/prompt.py +61 -0
- aip_agents/context/runtime.py +149 -0
- aip_agents/context/session_recall.py +69 -0
- aip_agents/context/state.py +48 -0
- aip_agents/context/utils.py +44 -0
- aip_agents/credentials/manager.py +132 -0
- aip_agents/examples/__init__.py +5 -0
- aip_agents/examples/audio_livekit_session.py +116 -0
- aip_agents/examples/compare_streaming_client.py +783 -0
- aip_agents/examples/compare_streaming_server.py +141 -0
- aip_agents/examples/gl_connectors_smoke.py +148 -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 +78 -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 +104 -0
- aip_agents/examples/hello_world_a2a_langchain_server.py +78 -0
- aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.py +77 -0
- aip_agents/examples/hello_world_a2a_langflow_client.py +83 -0
- aip_agents/examples/hello_world_a2a_langflow_server.py +80 -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 +91 -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 +83 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.py +78 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.py +131 -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 +250 -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 +79 -0
- aip_agents/examples/hello_world_filesystem.py +162 -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_gl_connector_twitter.py +44 -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_skills.py +62 -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_multi_agent_tool_output_client.py +57 -0
- aip_agents/examples/hello_world_multi_agent_tool_output_server.py +131 -0
- aip_agents/examples/hello_world_pii_logger.py +21 -0
- aip_agents/examples/hello_world_ptc.py +49 -0
- aip_agents/examples/hello_world_ptc_custom_tools.py +83 -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 +100 -0
- aip_agents/examples/hello_world_tool_output_client.py +55 -0
- aip_agents/examples/hello_world_tool_output_server.py +113 -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 +125 -0
- aip_agents/examples/pii_demo_multi_agent_client.py +80 -0
- aip_agents/examples/pii_demo_multi_agent_server.py +246 -0
- aip_agents/examples/todolist_planning_a2a_langchain_client.py +70 -0
- aip_agents/examples/todolist_planning_a2a_langgraph_server.py +87 -0
- aip_agents/examples/tools/__init__.py +27 -0
- aip_agents/examples/tools/adk_arithmetic_tools.py +36 -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/multiply_tool.py +43 -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/guardrails/__init__.py +83 -0
- aip_agents/guardrails/engines/__init__.py +69 -0
- aip_agents/guardrails/engines/base.py +90 -0
- aip_agents/guardrails/engines/nemo.py +101 -0
- aip_agents/guardrails/engines/phrase_matcher.py +113 -0
- aip_agents/guardrails/exceptions.py +39 -0
- aip_agents/guardrails/manager.py +163 -0
- aip_agents/guardrails/middleware.py +199 -0
- aip_agents/guardrails/schemas.py +63 -0
- aip_agents/guardrails/utils.py +45 -0
- aip_agents/integration/__init__.py +43 -0
- aip_agents/integration/agent.py +58 -0
- aip_agents/integration/guardrails.py +52 -0
- aip_agents/integration/hitl.py +71 -0
- aip_agents/integration/ptc.py +95 -0
- aip_agents/integration/skills.py +37 -0
- aip_agents/integration/storage.py +81 -0
- aip_agents/integration/version.py +103 -0
- aip_agents/mcp/__init__.py +1 -0
- aip_agents/mcp/client/__init__.py +60 -0
- aip_agents/mcp/client/base_mcp_client.py +377 -0
- aip_agents/mcp/client/connection_manager.py +231 -0
- aip_agents/mcp/client/errors.py +119 -0
- aip_agents/mcp/client/google_adk/__init__.py +45 -0
- aip_agents/mcp/client/google_adk/client.py +383 -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 +704 -0
- aip_agents/mcp/client/session_pool.py +358 -0
- aip_agents/mcp/client/transports.py +288 -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 +815 -0
- aip_agents/memory/adapters/mem0.py +286 -0
- aip_agents/memory/base.py +84 -0
- 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 +65 -0
- aip_agents/middleware/backends/__init__.py +72 -0
- aip_agents/middleware/backends/in_memory.py +578 -0
- aip_agents/middleware/backends/local_disk.py +1203 -0
- aip_agents/middleware/backends/protocol.py +353 -0
- aip_agents/middleware/backends/sandbox.py +1431 -0
- aip_agents/middleware/backends/sandbox_files.py +113 -0
- aip_agents/middleware/backends/utils.py +293 -0
- aip_agents/middleware/base.py +239 -0
- aip_agents/middleware/filesystem.py +690 -0
- aip_agents/middleware/manager.py +291 -0
- aip_agents/middleware/memory.py +532 -0
- aip_agents/middleware/pii_middleware.py +192 -0
- aip_agents/middleware/schema.py +19 -0
- aip_agents/middleware/skills.py +872 -0
- aip_agents/middleware/task_delegation.py +1656 -0
- aip_agents/middleware/todolist.py +276 -0
- aip_agents/middleware/tools/__init__.py +23 -0
- aip_agents/middleware/tools/edit_file.py +70 -0
- aip_agents/middleware/tools/execute.py +428 -0
- aip_agents/middleware/tools/grep_file.py +79 -0
- aip_agents/middleware/tools/ls.py +71 -0
- aip_agents/middleware/tools/read_file.py +239 -0
- aip_agents/middleware/tools/skill_load.py +193 -0
- aip_agents/middleware/tools/skill_resource.py +338 -0
- aip_agents/middleware/tools/write_file.py +114 -0
- aip_agents/middleware/vision.py +322 -0
- aip_agents/ptc/__init__.py +87 -0
- aip_agents/ptc/custom_tools.py +511 -0
- aip_agents/ptc/custom_tools_payload.py +499 -0
- aip_agents/ptc/custom_tools_templates/__init__.py +1 -0
- aip_agents/ptc/custom_tools_templates/custom_build_function.py.template +24 -0
- aip_agents/ptc/custom_tools_templates/custom_init.py.template +26 -0
- aip_agents/ptc/custom_tools_templates/custom_invoke.py.template +149 -0
- aip_agents/ptc/custom_tools_templates/custom_registry.py.template +112 -0
- aip_agents/ptc/custom_tools_templates/custom_sources_init.py.template +7 -0
- aip_agents/ptc/custom_tools_templates/custom_wrapper.py.template +87 -0
- aip_agents/ptc/doc_gen.py +122 -0
- aip_agents/ptc/exceptions.py +57 -0
- aip_agents/ptc/executor.py +627 -0
- aip_agents/ptc/mcp/__init__.py +45 -0
- aip_agents/ptc/mcp/sandbox_bridge.py +679 -0
- aip_agents/ptc/mcp/templates/__init__.py +1 -0
- aip_agents/ptc/mcp/templates/mcp_client.py.template +240 -0
- aip_agents/ptc/naming.py +430 -0
- aip_agents/ptc/payload.py +26 -0
- aip_agents/ptc/prompt_builder.py +674 -0
- aip_agents/ptc/ptc_helper.py +16 -0
- aip_agents/ptc/sandbox_bridge.py +297 -0
- aip_agents/ptc/template_utils.py +33 -0
- aip_agents/ptc/templates/__init__.py +1 -0
- aip_agents/ptc/templates/ptc_helper.py.template +134 -0
- aip_agents/ptc/tool_def_helpers.py +101 -0
- aip_agents/ptc/tool_enrichment.py +163 -0
- aip_agents/resilience/__init__.py +10 -0
- aip_agents/resilience/base.py +46 -0
- aip_agents/resilience/tool.py +1661 -0
- aip_agents/sandbox/__init__.py +62 -0
- aip_agents/sandbox/defaults.py +220 -0
- aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2-1-datasaur.Dockerfile +120 -0
- aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2-1.Dockerfile +100 -0
- aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2-2-datasaur.Dockerfile +143 -0
- aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2-2.Dockerfile +119 -0
- aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2-3-datasaur.Dockerfile +173 -0
- aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2-3.Dockerfile +130 -0
- aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2-4-runner-managed.Dockerfile +164 -0
- aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2-4-runner-managed.patch_js_context.py +41 -0
- aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2-4-runner-managed.requirements.txt +29 -0
- aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2.Dockerfile +87 -0
- aip_agents/sandbox/e2b_runtime.py +27 -0
- aip_agents/sandbox/image_registry.py +98 -0
- aip_agents/sandbox/providers/__init__.py +76 -0
- aip_agents/sandbox/providers/base.py +392 -0
- aip_agents/sandbox/providers/bedrock.py +28 -0
- aip_agents/sandbox/providers/e2b.py +230 -0
- aip_agents/sandbox/providers/opensandbox.py +163 -0
- aip_agents/sandbox/sandbox_runtime.py +967 -0
- aip_agents/sandbox/template_builder.py +240 -0
- aip_agents/sandbox/types.py +141 -0
- aip_agents/sandbox/validation.py +50 -0
- aip_agents/schema/__init__.py +106 -0
- aip_agents/schema/a2a.py +58 -0
- aip_agents/schema/agent.py +117 -0
- aip_agents/schema/artifacts.py +75 -0
- aip_agents/schema/attachments.py +425 -0
- aip_agents/schema/hitl.py +157 -0
- aip_agents/schema/langgraph.py +47 -0
- aip_agents/schema/model_id.py +103 -0
- aip_agents/schema/model_usage.py +50 -0
- aip_agents/schema/runtime_metadata.py +78 -0
- aip_agents/schema/step_limit.py +108 -0
- aip_agents/schema/storage.py +40 -0
- aip_agents/schema/tool_payloads.py +68 -0
- aip_agents/sentry/__init__.py +11 -0
- aip_agents/sentry/sentry.py +267 -0
- aip_agents/skills/__init__.py +30 -0
- aip_agents/skills/errors.py +110 -0
- aip_agents/skills/installer.py +479 -0
- aip_agents/skills/models.py +769 -0
- aip_agents/skills/stager.py +224 -0
- aip_agents/skills/validation.py +53 -0
- aip_agents/storage/__init__.py +41 -0
- aip_agents/storage/base.py +85 -0
- 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.py +106 -0
- aip_agents/storage/providers/memory.py +114 -0
- aip_agents/storage/providers/object_storage.py +214 -0
- aip_agents/tools/__init__.py +65 -0
- aip_agents/tools/agent_schedule_tool.py +392 -0
- aip_agents/tools/browser_use/__init__.py +83 -0
- aip_agents/tools/browser_use/action_parser.py +104 -0
- aip_agents/tools/browser_use/browser_use_tool.py +1118 -0
- aip_agents/tools/browser_use/llm_config.py +120 -0
- aip_agents/tools/browser_use/minio_storage.py +203 -0
- aip_agents/tools/browser_use/schemas.py +121 -0
- aip_agents/tools/browser_use/session.py +13 -0
- aip_agents/tools/browser_use/session_errors.py +132 -0
- aip_agents/tools/browser_use/steel_session_recording.py +321 -0
- aip_agents/tools/browser_use/streaming.py +263 -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 +37 -0
- aip_agents/tools/code_sandbox/__init__.py +48 -0
- aip_agents/tools/code_sandbox/code_sandbox_tool.py +350 -0
- aip_agents/tools/code_sandbox/constant.py +13 -0
- aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.py +346 -0
- aip_agents/tools/code_sandbox/e2b_sandbox_tool.py +65 -0
- aip_agents/tools/computer_use/__init__.py +75 -0
- aip_agents/tools/computer_use/computer_use_tool.py +910 -0
- aip_agents/tools/computer_use/schemas.py +78 -0
- aip_agents/tools/computer_use/streaming.py +198 -0
- aip_agents/tools/computer_use/types.py +32 -0
- aip_agents/tools/constants.py +177 -0
- aip_agents/tools/date_range_tool.py +554 -0
- aip_agents/tools/document_loader/__init__.py +44 -0
- aip_agents/tools/document_loader/base_reader.py +302 -0
- aip_agents/tools/document_loader/docx_reader_tool.py +68 -0
- aip_agents/tools/document_loader/excel_reader_tool.py +171 -0
- aip_agents/tools/document_loader/pdf_reader_tool.py +79 -0
- aip_agents/tools/document_loader/pdf_splitter.py +169 -0
- aip_agents/tools/execute_ptc_code.py +582 -0
- aip_agents/tools/gl_connector/__init__.py +5 -0
- aip_agents/tools/gl_connector/tool.py +518 -0
- aip_agents/tools/gl_connector_tools.py +170 -0
- aip_agents/tools/memory_search/__init__.py +29 -0
- aip_agents/tools/memory_search/base.py +213 -0
- aip_agents/tools/memory_search/mem0.py +424 -0
- aip_agents/tools/memory_search/schema.py +81 -0
- aip_agents/tools/memory_search_tool.py +34 -0
- aip_agents/tools/streaming_common.py +577 -0
- aip_agents/tools/time_tool.py +117 -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 +73 -0
- aip_agents/types/a2a_events.py +13 -0
- aip_agents/utils/__init__.py +91 -0
- aip_agents/utils/a2a_connector.py +1758 -0
- aip_agents/utils/artifact_helpers.py +542 -0
- aip_agents/utils/artifacts/__init__.py +20 -0
- aip_agents/utils/artifacts/tracker.py +367 -0
- aip_agents/utils/attachment_helpers.py +178 -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 +276 -0
- aip_agents/utils/file_watchers/__init__.py +33 -0
- aip_agents/utils/file_watchers/base.py +46 -0
- aip_agents/utils/file_watchers/e2b.py +128 -0
- aip_agents/utils/file_watchers/factory.py +39 -0
- aip_agents/utils/file_watchers/ls_diff.py +88 -0
- aip_agents/utils/file_watchers/sandbox.py +66 -0
- aip_agents/utils/file_watchers/watchdog.py +97 -0
- aip_agents/utils/final_response_builder.py +211 -0
- aip_agents/utils/formatter_llm_client.py +258 -0
- aip_agents/utils/langgraph/__init__.py +19 -0
- aip_agents/utils/langgraph/converter.py +399 -0
- aip_agents/utils/langgraph/delegation_context.py +22 -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.py +66 -0
- aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.py +1329 -0
- aip_agents/utils/langgraph/tool_output_management.py +1047 -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 +822 -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 +363 -0
- aip_agents/utils/name_preprocessor/__init__.py +17 -0
- aip_agents/utils/name_preprocessor/base_name_preprocessor.py +73 -0
- 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.py +48 -0
- aip_agents/utils/pii/__init__.py +29 -0
- aip_agents/utils/pii/pii_handler.py +555 -0
- aip_agents/utils/pii/pii_helper.py +225 -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 +836 -0
- aip_agents/utils/step_limit_manager.py +265 -0
- aip_agents/utils/token_usage_helper.py +531 -0
- aip_agents_binary-0.0.0.dist-info/METADATA +825 -0
- aip_agents_binary-0.0.0.dist-info/RECORD +447 -0
- aip_agents_binary-0.0.0.dist-info/WHEEL +5 -0
- aip_agents_binary-0.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"""Adapter that routes transcripts into an AIP agent."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import inspect
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
import uuid
|
|
9
|
+
from collections.abc import Awaitable, Callable
|
|
10
|
+
from typing import Any, cast
|
|
11
|
+
|
|
12
|
+
from aip_agents.schema.a2a import A2AStreamEventType
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class AIPAudioAgentAdapter:
|
|
16
|
+
"""Adapter that turns transcript text into agent replies.
|
|
17
|
+
|
|
18
|
+
This wrapper:
|
|
19
|
+
- calls the agent's `arun(...)` method
|
|
20
|
+
- injects a stable thread id via `configurable` for conversation persistence
|
|
21
|
+
- optionally prints internal LangGraph step events when `AIP_AUDIO_DEBUG=1`
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self, agent: Any) -> None:
|
|
25
|
+
"""Create an adapter around an async-capable agent."""
|
|
26
|
+
self._agent = agent
|
|
27
|
+
self._thread_id = str(uuid.uuid4())
|
|
28
|
+
self._debug = os.environ.get("AIP_AUDIO_DEBUG") == "1"
|
|
29
|
+
|
|
30
|
+
async def generate_reply(
|
|
31
|
+
self,
|
|
32
|
+
text: str,
|
|
33
|
+
*,
|
|
34
|
+
on_a2a_event: Callable[[dict[str, Any]], Awaitable[None]] | None = None,
|
|
35
|
+
prefer_a2a_stream: bool = False,
|
|
36
|
+
**kwargs: Any,
|
|
37
|
+
) -> str:
|
|
38
|
+
"""Generate an agent reply for a single user transcript.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
text: Final transcript text.
|
|
42
|
+
on_a2a_event: Optional async callback invoked for each A2A stream event.
|
|
43
|
+
prefer_a2a_stream: When True, uses `arun_a2a_stream(...)` if available even
|
|
44
|
+
when debug mode is disabled.
|
|
45
|
+
**kwargs: Passed through to the underlying agent call.
|
|
46
|
+
"""
|
|
47
|
+
self._ensure_thread_id(kwargs)
|
|
48
|
+
|
|
49
|
+
arun_a2a_stream = getattr(self._agent, "arun_a2a_stream", None)
|
|
50
|
+
if callable(arun_a2a_stream) and (prefer_a2a_stream or self._debug):
|
|
51
|
+
return await self._arun_via_a2a_stream(
|
|
52
|
+
text,
|
|
53
|
+
arun_a2a_stream=arun_a2a_stream,
|
|
54
|
+
on_a2a_event=on_a2a_event,
|
|
55
|
+
debug=self._debug,
|
|
56
|
+
**kwargs,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
if not self._debug:
|
|
60
|
+
return await self._arun_basic(text, **kwargs)
|
|
61
|
+
|
|
62
|
+
# Debug fallback for agents without A2A streaming support.
|
|
63
|
+
if not hasattr(self._agent, "_compiled_graph"):
|
|
64
|
+
return await self._arun_basic(text, **kwargs)
|
|
65
|
+
|
|
66
|
+
create_cfg = getattr(self._agent, "_create_graph_config", None)
|
|
67
|
+
get_tid = getattr(self._agent, "_get_thread_id_from_config", None)
|
|
68
|
+
prep_input = getattr(self._agent, "_prepare_graph_input", None)
|
|
69
|
+
fmt_output = getattr(self._agent, "_format_graph_output", None)
|
|
70
|
+
if not (callable(create_cfg) and callable(get_tid) and callable(prep_input) and callable(fmt_output)):
|
|
71
|
+
return await self._arun_basic(text, **kwargs)
|
|
72
|
+
|
|
73
|
+
return await self._arun_with_compiled_graph_steps(text, **kwargs)
|
|
74
|
+
|
|
75
|
+
def _ensure_thread_id(self, kwargs: dict[str, Any]) -> None:
|
|
76
|
+
"""Ensure a stable thread_id is injected into kwargs for persistence."""
|
|
77
|
+
configurable = kwargs.get("configurable")
|
|
78
|
+
if not isinstance(configurable, dict):
|
|
79
|
+
configurable = {}
|
|
80
|
+
kwargs["configurable"] = configurable
|
|
81
|
+
|
|
82
|
+
thread_id_key = getattr(self._agent, "thread_id_key", "thread_id") or "thread_id"
|
|
83
|
+
configurable.setdefault(thread_id_key, self._thread_id)
|
|
84
|
+
|
|
85
|
+
async def _arun_basic(self, text: str, **kwargs: Any) -> str:
|
|
86
|
+
arun = getattr(self._agent, "arun", None)
|
|
87
|
+
if not callable(arun):
|
|
88
|
+
raise TypeError(f"Agent does not support arun(): {type(self._agent).__name__}")
|
|
89
|
+
|
|
90
|
+
maybe = arun(text, **kwargs)
|
|
91
|
+
if inspect.isawaitable(maybe):
|
|
92
|
+
result = await cast(Awaitable[Any], maybe)
|
|
93
|
+
else:
|
|
94
|
+
result = maybe
|
|
95
|
+
|
|
96
|
+
if isinstance(result, dict) and isinstance(result.get("output"), str):
|
|
97
|
+
return result["output"]
|
|
98
|
+
return str(result)
|
|
99
|
+
|
|
100
|
+
async def _arun_with_steps(self, text: str, **kwargs: Any) -> str:
|
|
101
|
+
"""Backwards-compatible alias for debug mode."""
|
|
102
|
+
return await self.generate_reply(text, prefer_a2a_stream=True, **kwargs)
|
|
103
|
+
|
|
104
|
+
async def _arun_with_compiled_graph_steps(self, text: str, **kwargs: Any) -> str:
|
|
105
|
+
"""Fallback debug streaming for agents without A2A streaming support."""
|
|
106
|
+
# Create config and get thread_id using agent's internal logic.
|
|
107
|
+
config = self._agent._create_graph_config(**kwargs)
|
|
108
|
+
thread_id = self._agent._get_thread_id_from_config(config)
|
|
109
|
+
graph_input = self._agent._prepare_graph_input(text, thread_id=thread_id, **kwargs)
|
|
110
|
+
|
|
111
|
+
final_state: Any | None = None
|
|
112
|
+
async for event in self._agent._compiled_graph.astream_events(graph_input, config=config, version="v2"):
|
|
113
|
+
final_state = self._process_compiled_graph_event(event, final_state)
|
|
114
|
+
|
|
115
|
+
if final_state is None:
|
|
116
|
+
return await self._arun_basic(text, **kwargs)
|
|
117
|
+
|
|
118
|
+
# We must use the agent's internal formatter to preserve consistent output formatting.
|
|
119
|
+
return self._agent._format_graph_output(final_state)
|
|
120
|
+
|
|
121
|
+
def _process_compiled_graph_event(self, event: dict[str, Any], final_state: Any | None) -> Any | None:
|
|
122
|
+
"""Print step events and return updated final state when it becomes available."""
|
|
123
|
+
kind = event.get("event")
|
|
124
|
+
name = event.get("name")
|
|
125
|
+
data = event.get("data", {}) or {}
|
|
126
|
+
|
|
127
|
+
if kind == "on_chat_model_start":
|
|
128
|
+
print("[aip-step] agent: Thinking...")
|
|
129
|
+
return final_state
|
|
130
|
+
|
|
131
|
+
if kind == "on_tool_start":
|
|
132
|
+
inputs = data.get("input", {})
|
|
133
|
+
try:
|
|
134
|
+
inputs_str = json.dumps(inputs)
|
|
135
|
+
except (TypeError, ValueError):
|
|
136
|
+
inputs_str = str(inputs)
|
|
137
|
+
print(f"[aip-step] tool: Using '{name}' with inputs: {inputs_str}")
|
|
138
|
+
return final_state
|
|
139
|
+
|
|
140
|
+
if kind == "on_tool_end":
|
|
141
|
+
print(f"[aip-step] tool: '{name}' finished")
|
|
142
|
+
return final_state
|
|
143
|
+
|
|
144
|
+
if kind == "on_chain_end" and not event.get("parent_id"):
|
|
145
|
+
return data.get("output")
|
|
146
|
+
|
|
147
|
+
return final_state
|
|
148
|
+
|
|
149
|
+
async def _arun_via_a2a_stream(
|
|
150
|
+
self,
|
|
151
|
+
text: str,
|
|
152
|
+
*,
|
|
153
|
+
arun_a2a_stream: Any,
|
|
154
|
+
on_a2a_event: Callable[[dict[str, Any]], Awaitable[None]] | None,
|
|
155
|
+
debug: bool,
|
|
156
|
+
**kwargs: Any,
|
|
157
|
+
) -> str:
|
|
158
|
+
"""Run the agent using the public A2A event stream.
|
|
159
|
+
|
|
160
|
+
This method intentionally drains the full stream (even after FINAL_RESPONSE)
|
|
161
|
+
so LangGraph checkpointing can complete.
|
|
162
|
+
"""
|
|
163
|
+
output_chunks: list[str] = []
|
|
164
|
+
final_reply: str | None = None
|
|
165
|
+
|
|
166
|
+
handlers = self._build_a2a_handlers(output_chunks) if debug else {}
|
|
167
|
+
|
|
168
|
+
async for event in arun_a2a_stream(text, **kwargs):
|
|
169
|
+
if on_a2a_event is not None and isinstance(event, dict):
|
|
170
|
+
await on_a2a_event(event)
|
|
171
|
+
|
|
172
|
+
self._check_stream_error(event)
|
|
173
|
+
self._handle_stream_event(event, output_chunks, handlers)
|
|
174
|
+
|
|
175
|
+
# Capture final response but continue draining
|
|
176
|
+
if self._is_final_response(event):
|
|
177
|
+
content = str(event.get("content") or "")
|
|
178
|
+
final_reply = content if content else "".join(output_chunks)
|
|
179
|
+
|
|
180
|
+
if final_reply is not None:
|
|
181
|
+
return final_reply
|
|
182
|
+
|
|
183
|
+
return await self._arun_basic(text, **kwargs)
|
|
184
|
+
|
|
185
|
+
def _check_stream_error(self, event: dict[str, Any]) -> None:
|
|
186
|
+
"""Raise RuntimeError if the event indicates an error."""
|
|
187
|
+
raw_type = event.get("event_type")
|
|
188
|
+
event_type = raw_type.value if hasattr(raw_type, "value") else str(raw_type)
|
|
189
|
+
if event_type in (A2AStreamEventType.ERROR.value, A2AStreamEventType.STEP_LIMIT_EXCEEDED.value):
|
|
190
|
+
content = str(event.get("content") or "")
|
|
191
|
+
raise RuntimeError(content or "Streaming failed")
|
|
192
|
+
|
|
193
|
+
def _is_final_response(self, event: dict[str, Any]) -> bool:
|
|
194
|
+
"""Check if event is a final response."""
|
|
195
|
+
raw_type = event.get("event_type")
|
|
196
|
+
event_type = raw_type.value if hasattr(raw_type, "value") else str(raw_type)
|
|
197
|
+
return event_type == A2AStreamEventType.FINAL_RESPONSE.value
|
|
198
|
+
|
|
199
|
+
def _handle_stream_event(
|
|
200
|
+
self,
|
|
201
|
+
event: dict[str, Any],
|
|
202
|
+
output_chunks: list[str],
|
|
203
|
+
handlers: dict[str, Callable[[str, dict[str, Any]], None]],
|
|
204
|
+
) -> None:
|
|
205
|
+
"""Process a single stream event: update chunks and invoke debug handlers."""
|
|
206
|
+
raw_type = event.get("event_type")
|
|
207
|
+
event_type = raw_type.value if hasattr(raw_type, "value") else str(raw_type)
|
|
208
|
+
content = str(event.get("content") or "")
|
|
209
|
+
tool_info = event.get("tool_info")
|
|
210
|
+
tool_info_dict = tool_info if isinstance(tool_info, dict) else {}
|
|
211
|
+
|
|
212
|
+
if event_type == A2AStreamEventType.CONTENT_CHUNK.value and content:
|
|
213
|
+
output_chunks.append(content)
|
|
214
|
+
|
|
215
|
+
handler = handlers.get(event_type)
|
|
216
|
+
if handler is not None:
|
|
217
|
+
handler(content, tool_info_dict)
|
|
218
|
+
|
|
219
|
+
def _build_a2a_handlers(self, _output_chunks: list[str]) -> dict[str, Callable[[str, dict[str, Any]], None]]:
|
|
220
|
+
"""Return event handlers for debug A2A streaming."""
|
|
221
|
+
|
|
222
|
+
def _status_update(content: str, _tool_info: dict[str, Any]) -> None:
|
|
223
|
+
msg = content.strip()
|
|
224
|
+
if msg:
|
|
225
|
+
print(f"[aip-step] agent: {msg}")
|
|
226
|
+
return None
|
|
227
|
+
|
|
228
|
+
def _tool_call(_content: str, tool_info: dict[str, Any]) -> None:
|
|
229
|
+
calls = tool_info.get("tool_calls")
|
|
230
|
+
if not isinstance(calls, list):
|
|
231
|
+
return None
|
|
232
|
+
for call in calls:
|
|
233
|
+
if not isinstance(call, dict):
|
|
234
|
+
continue
|
|
235
|
+
name = call.get("name")
|
|
236
|
+
args = call.get("args")
|
|
237
|
+
args_dict = args if isinstance(args, dict) else {}
|
|
238
|
+
try:
|
|
239
|
+
inputs_str = json.dumps(args_dict)
|
|
240
|
+
except (TypeError, ValueError):
|
|
241
|
+
inputs_str = str(args_dict)
|
|
242
|
+
print(f"[aip-step] tool: Using '{name}' with inputs: {inputs_str}")
|
|
243
|
+
return None
|
|
244
|
+
|
|
245
|
+
def _tool_result(_content: str, tool_info: dict[str, Any]) -> None:
|
|
246
|
+
name = tool_info.get("name")
|
|
247
|
+
print(f"[aip-step] tool: '{name}' finished")
|
|
248
|
+
return None
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
A2AStreamEventType.STATUS_UPDATE.value: _status_update,
|
|
252
|
+
A2AStreamEventType.TOOL_CALL.value: _tool_call,
|
|
253
|
+
A2AStreamEventType.TOOL_RESULT.value: _tool_result,
|
|
254
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"""Typed config objects for audio sessions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import re
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from aip_agents.audio_interface.errors import AudioConfigError
|
|
11
|
+
|
|
12
|
+
_ENV_REF_RE = re.compile(r"^\$\{([A-Z0-9_]+)\}$")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _resolve_env_ref(value: str | None) -> str | None:
|
|
16
|
+
if value is None:
|
|
17
|
+
return None
|
|
18
|
+
m = _ENV_REF_RE.match(value.strip())
|
|
19
|
+
if not m:
|
|
20
|
+
return value
|
|
21
|
+
return os.environ.get(m.group(1))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True, slots=True)
|
|
25
|
+
class AudioIOConfig:
|
|
26
|
+
"""I/O toggles and device hints for an audio session."""
|
|
27
|
+
|
|
28
|
+
input_enabled: bool = True
|
|
29
|
+
output_enabled: bool = True
|
|
30
|
+
input_device: str | None = None
|
|
31
|
+
output_device: str | None = None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass(frozen=True, slots=True)
|
|
35
|
+
class AudioModelConfig:
|
|
36
|
+
"""Model selection for provider-specific audio components.
|
|
37
|
+
|
|
38
|
+
For OpenAI STT/TTS wiring in the LiveKit provider:
|
|
39
|
+
provider="openai", voice="echo"
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
provider: str | None = None
|
|
43
|
+
model: str | None = None
|
|
44
|
+
voice: str | None = None
|
|
45
|
+
credentials: str | None = None
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass(frozen=True, slots=True)
|
|
49
|
+
class LiveKitConfig:
|
|
50
|
+
"""Connection and provider configuration for LiveKit audio sessions."""
|
|
51
|
+
|
|
52
|
+
url: str
|
|
53
|
+
api_key: str | None = None
|
|
54
|
+
api_secret: str | None = None
|
|
55
|
+
room_name: str | None = None
|
|
56
|
+
identity: str | None = None
|
|
57
|
+
|
|
58
|
+
# Optional: OpenAI STT/TTS via livekit-plugins-openai
|
|
59
|
+
openai_stt_model: str | None = None
|
|
60
|
+
openai_tts_model: str | None = None
|
|
61
|
+
openai_voice: str | None = None
|
|
62
|
+
openai_use_realtime_stt: bool = True
|
|
63
|
+
openai_api_key: str | None = None
|
|
64
|
+
openai_base_url: str | None = None
|
|
65
|
+
|
|
66
|
+
def resolve_api_key(self) -> str:
|
|
67
|
+
"""Resolve the LiveKit API key from config/env."""
|
|
68
|
+
val = _resolve_env_ref(self.api_key) or os.environ.get("LIVEKIT_API_KEY")
|
|
69
|
+
if not val:
|
|
70
|
+
raise AudioConfigError("LIVEKIT_API_KEY missing")
|
|
71
|
+
return val
|
|
72
|
+
|
|
73
|
+
def resolve_api_secret(self) -> str:
|
|
74
|
+
"""Resolve the LiveKit API secret from config/env."""
|
|
75
|
+
val = _resolve_env_ref(self.api_secret) or os.environ.get("LIVEKIT_API_SECRET")
|
|
76
|
+
if not val:
|
|
77
|
+
raise AudioConfigError("LIVEKIT_API_SECRET missing")
|
|
78
|
+
return val
|
|
79
|
+
|
|
80
|
+
def resolve_openai_api_key(self) -> str:
|
|
81
|
+
"""Resolve OpenAI API key used by livekit-plugins-openai."""
|
|
82
|
+
val = _resolve_env_ref(self.openai_api_key) or os.environ.get("OPENAI_API_KEY")
|
|
83
|
+
if not val:
|
|
84
|
+
raise AudioConfigError("OPENAI_API_KEY missing (required for OpenAI STT/TTS)")
|
|
85
|
+
return val
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@dataclass(frozen=True, slots=True)
|
|
89
|
+
class AudioSessionConfig:
|
|
90
|
+
"""Top-level audio session config as used by the audio interface."""
|
|
91
|
+
|
|
92
|
+
provider: str = "livekit"
|
|
93
|
+
io: AudioIOConfig = AudioIOConfig()
|
|
94
|
+
model: AudioModelConfig | None = None
|
|
95
|
+
provider_config: LiveKitConfig | dict[str, Any] | None = None
|
|
96
|
+
|
|
97
|
+
@staticmethod
|
|
98
|
+
def from_agent_config_audio(raw: dict[str, Any]) -> AudioSessionConfig:
|
|
99
|
+
"""Parse the `agent_config.audio` section into a typed config."""
|
|
100
|
+
if not isinstance(raw, dict):
|
|
101
|
+
raise AudioConfigError("agent_config.audio must be a dict")
|
|
102
|
+
|
|
103
|
+
provider = raw.get("provider") or "livekit"
|
|
104
|
+
io_raw = raw.get("io") or {}
|
|
105
|
+
io = AudioIOConfig(
|
|
106
|
+
input_enabled=bool(io_raw.get("input_enabled", True)),
|
|
107
|
+
output_enabled=bool(io_raw.get("output_enabled", True)),
|
|
108
|
+
input_device=io_raw.get("input_device"),
|
|
109
|
+
output_device=io_raw.get("output_device"),
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
model_raw = raw.get("model")
|
|
113
|
+
model: AudioModelConfig | None = None
|
|
114
|
+
if isinstance(model_raw, dict):
|
|
115
|
+
model = AudioModelConfig(
|
|
116
|
+
provider=model_raw.get("provider"),
|
|
117
|
+
model=model_raw.get("model"),
|
|
118
|
+
voice=model_raw.get("voice"),
|
|
119
|
+
credentials=model_raw.get("credentials"),
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
provider_cfg: LiveKitConfig | dict[str, Any] | None = None
|
|
123
|
+
if provider in {"livekit", "livekit_realtime"}:
|
|
124
|
+
lk = raw.get(provider) or raw.get("livekit")
|
|
125
|
+
if not isinstance(lk, dict):
|
|
126
|
+
raise AudioConfigError(f"{provider}.url is required")
|
|
127
|
+
url = lk.get("url")
|
|
128
|
+
if not url:
|
|
129
|
+
raise AudioConfigError(f"{provider}.url is required")
|
|
130
|
+
provider_cfg = LiveKitConfig(
|
|
131
|
+
url=str(url),
|
|
132
|
+
api_key=lk.get("api_key"),
|
|
133
|
+
api_secret=lk.get("api_secret"),
|
|
134
|
+
room_name=lk.get("room_name"),
|
|
135
|
+
identity=lk.get("identity"),
|
|
136
|
+
openai_stt_model=lk.get("openai_stt_model"),
|
|
137
|
+
openai_tts_model=lk.get("openai_tts_model"),
|
|
138
|
+
openai_voice=lk.get("openai_voice"),
|
|
139
|
+
openai_use_realtime_stt=bool(lk.get("openai_use_realtime_stt", True)),
|
|
140
|
+
openai_api_key=lk.get("openai_api_key"),
|
|
141
|
+
openai_base_url=lk.get("openai_base_url"),
|
|
142
|
+
)
|
|
143
|
+
elif isinstance(raw.get(provider), dict):
|
|
144
|
+
provider_cfg = dict(raw[provider])
|
|
145
|
+
|
|
146
|
+
return AudioSessionConfig(provider=provider, io=io, model=model, provider_config=provider_cfg)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Audio interface errors (local-only, optional deps)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AudioInterfaceError(RuntimeError):
|
|
7
|
+
"""Base error for audio interface."""
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AudioSessionUnavailableError(AudioInterfaceError):
|
|
11
|
+
"""Provider deps are missing or incompatible."""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class AudioConfigError(AudioInterfaceError, ValueError):
|
|
15
|
+
"""Audio config is missing or invalid."""
|