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,196 @@
|
|
|
1
|
+
"""Context preparation facade that composes compaction primitives.
|
|
2
|
+
|
|
3
|
+
Composes #791 (budget/state), #792 (offload/prune/repair),
|
|
4
|
+
and #793 (compaction) into a single pipeline.
|
|
5
|
+
|
|
6
|
+
Authors:
|
|
7
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from collections.abc import Sequence
|
|
13
|
+
from dataclasses import dataclass, field
|
|
14
|
+
from typing import TYPE_CHECKING, Any
|
|
15
|
+
|
|
16
|
+
from aip_agents.context.budget import (
|
|
17
|
+
CompactionDecision,
|
|
18
|
+
ContextBudgetConfig,
|
|
19
|
+
decide_compaction,
|
|
20
|
+
estimate_message_token_counts,
|
|
21
|
+
)
|
|
22
|
+
from aip_agents.context.compaction import (
|
|
23
|
+
CompactionSummary,
|
|
24
|
+
CompressionResult,
|
|
25
|
+
ContextCompressor,
|
|
26
|
+
)
|
|
27
|
+
from aip_agents.context.offload import (
|
|
28
|
+
OffloadedPayloadRef,
|
|
29
|
+
offload_oversized_payloads,
|
|
30
|
+
prune_duplicate_tool_outputs,
|
|
31
|
+
repair_tool_result_pairing,
|
|
32
|
+
)
|
|
33
|
+
from aip_agents.context.state import CompactionState
|
|
34
|
+
|
|
35
|
+
if TYPE_CHECKING:
|
|
36
|
+
from aip_agents.context.prompt import PromptBuildContext
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
_SUMMARY_MESSAGE_ROLE = "assistant"
|
|
40
|
+
|
|
41
|
+
_ADMIN_TAG = "compact_summary"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass(frozen=True)
|
|
45
|
+
class ContextPreparationResult:
|
|
46
|
+
"""Single output of the context preparation pipeline.
|
|
47
|
+
|
|
48
|
+
Composes all compaction primitives into one result object
|
|
49
|
+
so runtime code calls one facade instead of orchestrating
|
|
50
|
+
budget, offload, prune, repair, and summary individually.
|
|
51
|
+
|
|
52
|
+
Attributes:
|
|
53
|
+
messages: Provider-ready messages after context preparation.
|
|
54
|
+
prompt_context: Prompt assembly context used to build the system prompt.
|
|
55
|
+
decision: Budget decision that determined whether compaction was needed.
|
|
56
|
+
state: Safe compaction metadata for logging and observability.
|
|
57
|
+
offloaded_refs: Payload references produced by lossless offloading.
|
|
58
|
+
summary: Reference-only compaction summary inserted into context, if any.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
messages: list[Any]
|
|
62
|
+
prompt_context: PromptBuildContext | None = None
|
|
63
|
+
decision: CompactionDecision | None = None
|
|
64
|
+
state: CompactionState | None = None
|
|
65
|
+
offloaded_refs: tuple[OffloadedPayloadRef, ...] = field(default_factory=tuple)
|
|
66
|
+
summary: CompactionSummary | None = None
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _build_summary_message(summary: CompactionSummary) -> dict[str, Any]:
|
|
70
|
+
"""Build a replacement message from a compaction summary."""
|
|
71
|
+
return {
|
|
72
|
+
"role": _SUMMARY_MESSAGE_ROLE,
|
|
73
|
+
"content": f"[Previous conversation context summarized: {summary.body}]",
|
|
74
|
+
"type": _ADMIN_TAG,
|
|
75
|
+
"summary_id": summary.summary_id,
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def prepare_context(
|
|
80
|
+
messages: Sequence[Any],
|
|
81
|
+
*,
|
|
82
|
+
config: ContextBudgetConfig | None = None,
|
|
83
|
+
backend: Any | None = None,
|
|
84
|
+
model_context_tokens: int | None = None,
|
|
85
|
+
summarizer: Any | None = None,
|
|
86
|
+
previous_summary: CompactionSummary | None = None,
|
|
87
|
+
focus_topic: str | None = None,
|
|
88
|
+
preserve_topic: str | None = None,
|
|
89
|
+
provider_overflow: bool = False,
|
|
90
|
+
) -> ContextPreparationResult:
|
|
91
|
+
"""Run the full context preparation pipeline.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
messages: Full message sequence to prepare for model invocation.
|
|
95
|
+
config: Budget configuration for compaction decisions.
|
|
96
|
+
backend: Optional backend for offloading oversized payloads.
|
|
97
|
+
model_context_tokens: Provider model context window size, if known.
|
|
98
|
+
summarizer: Optional external summarizer client.
|
|
99
|
+
previous_summary: Previous compaction summary for incremental update.
|
|
100
|
+
focus_topic: Optional focus topic for manual/guided compaction.
|
|
101
|
+
preserve_topic: Alias for focus_topic (overrides focus_topic when set).
|
|
102
|
+
provider_overflow: If True, force compaction for provider-overflow retry
|
|
103
|
+
even when the local estimator is below the normal threshold.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
ContextPreparationResult with processed messages and metadata.
|
|
107
|
+
|
|
108
|
+
Order of operations:
|
|
109
|
+
1. Budget decision (estimate tokens, decide if compaction needed)
|
|
110
|
+
2. Lossless offload (oversized payloads to backend, if backend provided)
|
|
111
|
+
3. Prune duplicate tool outputs
|
|
112
|
+
4. Repair tool-result pairing
|
|
113
|
+
5. Generate compaction summary (if should_compact)
|
|
114
|
+
6. Assemble final messages (head + summary + tail)
|
|
115
|
+
"""
|
|
116
|
+
cfg = config or ContextBudgetConfig()
|
|
117
|
+
|
|
118
|
+
effective_focus_topic = preserve_topic if preserve_topic is not None else focus_topic
|
|
119
|
+
|
|
120
|
+
# 1. Budget decision
|
|
121
|
+
token_counts = list(estimate_message_token_counts(messages))
|
|
122
|
+
estimated_prompt_tokens = sum(token_counts)
|
|
123
|
+
|
|
124
|
+
decision = decide_compaction(
|
|
125
|
+
messages,
|
|
126
|
+
config=cfg,
|
|
127
|
+
model_context_tokens=model_context_tokens,
|
|
128
|
+
provider_overflow=provider_overflow,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# 2-4: Always apply offload/prune/repair
|
|
132
|
+
transformed = list(messages)
|
|
133
|
+
|
|
134
|
+
offloaded_refs: tuple[OffloadedPayloadRef, ...] = ()
|
|
135
|
+
if backend is not None:
|
|
136
|
+
transformed, offloaded_refs = offload_oversized_payloads(
|
|
137
|
+
transformed,
|
|
138
|
+
backend=backend,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
protected_tail_start = (
|
|
142
|
+
decision.summary_insertion_point.protected_tail_start_index
|
|
143
|
+
if decision.summary_insertion_point is not None
|
|
144
|
+
else len(transformed)
|
|
145
|
+
)
|
|
146
|
+
transformed = prune_duplicate_tool_outputs(
|
|
147
|
+
transformed,
|
|
148
|
+
protected_tail_start_index=protected_tail_start,
|
|
149
|
+
)
|
|
150
|
+
transformed = repair_tool_result_pairing(transformed)
|
|
151
|
+
|
|
152
|
+
# 5-6: Compaction summary + assembly
|
|
153
|
+
summary: CompactionSummary | None = None
|
|
154
|
+
state = CompactionState()
|
|
155
|
+
|
|
156
|
+
if decision.should_compact:
|
|
157
|
+
compressor = ContextCompressor(summarizer=summarizer)
|
|
158
|
+
try:
|
|
159
|
+
compression_result: CompressionResult = compressor.compress(
|
|
160
|
+
transformed,
|
|
161
|
+
focus_topic=decision.focus_topic or effective_focus_topic,
|
|
162
|
+
previous_summary=previous_summary,
|
|
163
|
+
)
|
|
164
|
+
summary = compression_result.summary
|
|
165
|
+
|
|
166
|
+
sip = decision.summary_insertion_point
|
|
167
|
+
if sip is not None:
|
|
168
|
+
summary_message = _build_summary_message(summary)
|
|
169
|
+
head = list(transformed[: sip.replace_start_index])
|
|
170
|
+
tail = list(transformed[sip.replace_end_index :])
|
|
171
|
+
transformed = head + [summary_message] + tail
|
|
172
|
+
|
|
173
|
+
post_compact_tokens = sum(estimate_message_token_counts(transformed))
|
|
174
|
+
state = CompactionState(
|
|
175
|
+
compaction_count=1,
|
|
176
|
+
last_summary_status="succeeded",
|
|
177
|
+
offloaded_ref_count=len(offloaded_refs),
|
|
178
|
+
estimated_token_savings=estimated_prompt_tokens - post_compact_tokens,
|
|
179
|
+
last_reason=decision.reason,
|
|
180
|
+
)
|
|
181
|
+
except Exception as exc:
|
|
182
|
+
state = CompactionState(
|
|
183
|
+
compaction_count=1,
|
|
184
|
+
last_summary_status="failed",
|
|
185
|
+
offloaded_ref_count=len(offloaded_refs),
|
|
186
|
+
last_reason=decision.reason,
|
|
187
|
+
last_error_code=str(type(exc).__name__),
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
return ContextPreparationResult(
|
|
191
|
+
messages=transformed,
|
|
192
|
+
decision=decision,
|
|
193
|
+
state=state,
|
|
194
|
+
offloaded_refs=offloaded_refs,
|
|
195
|
+
summary=summary,
|
|
196
|
+
)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Prompt assembly utilities for agent system instructions.
|
|
2
|
+
|
|
3
|
+
Authors:
|
|
4
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass(frozen=True)
|
|
13
|
+
class PromptBuildContext:
|
|
14
|
+
"""Typed context for deterministic system prompt assembly.
|
|
15
|
+
|
|
16
|
+
The field order encodes the canonical layer order. Empty or None values are
|
|
17
|
+
skipped during rendering.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
base_instruction: str
|
|
21
|
+
date_time_context: str | None = None
|
|
22
|
+
runtime_platform_hints: str | None = None
|
|
23
|
+
durable_memory_guidance: str | None = None
|
|
24
|
+
session_recall_guidance: str | None = None
|
|
25
|
+
project_context: str | None = None
|
|
26
|
+
compaction_summary: str | None = None
|
|
27
|
+
model_steering: str | None = None
|
|
28
|
+
middleware_prompts: tuple[str, ...] = ()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def build_system_prompt(context: PromptBuildContext) -> str:
|
|
32
|
+
"""Build a system prompt from ordered context layers.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
context: Prompt context containing ordered optional layers.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
Combined system prompt with non-empty layers joined by double newlines.
|
|
39
|
+
"""
|
|
40
|
+
parts: list[str] = []
|
|
41
|
+
|
|
42
|
+
for layer in (
|
|
43
|
+
context.date_time_context,
|
|
44
|
+
context.base_instruction,
|
|
45
|
+
context.runtime_platform_hints,
|
|
46
|
+
context.durable_memory_guidance,
|
|
47
|
+
context.session_recall_guidance,
|
|
48
|
+
context.project_context,
|
|
49
|
+
context.compaction_summary,
|
|
50
|
+
context.model_steering,
|
|
51
|
+
):
|
|
52
|
+
normalized = layer.strip() if isinstance(layer, str) else layer
|
|
53
|
+
if normalized:
|
|
54
|
+
parts.append(normalized)
|
|
55
|
+
|
|
56
|
+
for middleware_prompt in context.middleware_prompts:
|
|
57
|
+
normalized = middleware_prompt.strip() if isinstance(middleware_prompt, str) else middleware_prompt
|
|
58
|
+
if normalized:
|
|
59
|
+
parts.append(normalized)
|
|
60
|
+
|
|
61
|
+
return "\n\n".join(parts)
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"""Runtime integration helpers for context compaction.
|
|
2
|
+
|
|
3
|
+
Provides overflow detection, session recall derivation,
|
|
4
|
+
and compact-and-retry orchestration for the agent loop.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from collections.abc import Awaitable, Sequence
|
|
10
|
+
from typing import TYPE_CHECKING, Any, Protocol
|
|
11
|
+
|
|
12
|
+
from aip_agents.context.session_recall import (
|
|
13
|
+
SessionRecallSnapshot,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from aip_agents.context.preparation import ContextPreparationResult
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ModelInvoke(Protocol):
|
|
21
|
+
"""Async model invocation callable used by compact_and_retry()."""
|
|
22
|
+
|
|
23
|
+
def __call__(self, messages: Sequence[Any]) -> Awaitable[Any]:
|
|
24
|
+
"""Invoke a model with prepared messages."""
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class PrepareContext(Protocol):
|
|
28
|
+
"""Callable shape for context preparation."""
|
|
29
|
+
|
|
30
|
+
def __call__(
|
|
31
|
+
self,
|
|
32
|
+
messages: Sequence[Any],
|
|
33
|
+
*,
|
|
34
|
+
focus_topic: str | None = None,
|
|
35
|
+
provider_overflow: bool = False,
|
|
36
|
+
**kwargs: Any,
|
|
37
|
+
) -> ContextPreparationResult:
|
|
38
|
+
"""Prepare messages for model invocation."""
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
_OVERFLOW_KEYWORDS = [
|
|
42
|
+
"context_length_exceeded",
|
|
43
|
+
"maximum context length",
|
|
44
|
+
"max tokens exceeded",
|
|
45
|
+
"context window full",
|
|
46
|
+
"too many tokens",
|
|
47
|
+
"token limit reached",
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def detect_context_overflow(error: Exception | str) -> bool:
|
|
52
|
+
"""Return True when an error appears to be a context-window overflow.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
error: Exception or error message string to classify.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
True if the error matches known overflow patterns.
|
|
59
|
+
"""
|
|
60
|
+
error_text = str(error).lower()
|
|
61
|
+
return any(keyword in error_text for keyword in _OVERFLOW_KEYWORDS)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def derive_session_recall(
|
|
65
|
+
messages: Sequence[dict[str, Any]],
|
|
66
|
+
tool_metadata: dict[str, Any] | None = None,
|
|
67
|
+
) -> SessionRecallSnapshot:
|
|
68
|
+
"""Derive a SessionRecallSnapshot from current loop state.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
messages: Current message sequence in the agent loop.
|
|
72
|
+
tool_metadata: Optional metadata about recent tool activity.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Populated SessionRecallSnapshot with supported fields derived from state.
|
|
76
|
+
"""
|
|
77
|
+
active_task = _derive_active_task(messages)
|
|
78
|
+
changed_files = _derive_changed_files(tool_metadata)
|
|
79
|
+
return SessionRecallSnapshot(
|
|
80
|
+
active_task=active_task,
|
|
81
|
+
recent_decisions=(),
|
|
82
|
+
changed_files=changed_files,
|
|
83
|
+
blockers=(),
|
|
84
|
+
handoff_summary=None,
|
|
85
|
+
stale=False,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _derive_active_task(messages: Sequence[dict[str, Any]]) -> str | None:
|
|
90
|
+
if not messages:
|
|
91
|
+
return None
|
|
92
|
+
for message in reversed(messages):
|
|
93
|
+
role = message.get("role", "")
|
|
94
|
+
if role not in ("user", "human"):
|
|
95
|
+
continue
|
|
96
|
+
content = message.get("content", "")
|
|
97
|
+
if isinstance(content, str) and content.strip():
|
|
98
|
+
return content.strip()[:200]
|
|
99
|
+
return None
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _derive_changed_files(
|
|
103
|
+
tool_metadata: dict[str, Any] | None,
|
|
104
|
+
) -> tuple[str, ...]:
|
|
105
|
+
if not tool_metadata:
|
|
106
|
+
return ()
|
|
107
|
+
files = tool_metadata.get("changed_files")
|
|
108
|
+
if isinstance(files, list | tuple):
|
|
109
|
+
return tuple(str(f) for f in files if f)
|
|
110
|
+
return ()
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
async def compact_and_retry(
|
|
114
|
+
messages: Sequence[dict[str, Any]],
|
|
115
|
+
model_invoke: ModelInvoke,
|
|
116
|
+
*,
|
|
117
|
+
prepare_context: PrepareContext,
|
|
118
|
+
recall: SessionRecallSnapshot | None = None,
|
|
119
|
+
) -> tuple[Any, ContextPreparationResult | None]:
|
|
120
|
+
"""Run prepare_context and invoke the model, with one overflow retry.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
messages: Current message sequence.
|
|
124
|
+
model_invoke: Async callable that invokes the model.
|
|
125
|
+
prepare_context: The prepare_context function from preparation module.
|
|
126
|
+
recall: Optional SessionRecallSnapshot for prompt context.
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
Tuple of (model_output, preparation_result).
|
|
130
|
+
"""
|
|
131
|
+
prep_result = prepare_context(
|
|
132
|
+
messages,
|
|
133
|
+
focus_topic=recall.active_task if recall else None,
|
|
134
|
+
)
|
|
135
|
+
first_messages = prep_result.messages if prep_result is not None else list(messages)
|
|
136
|
+
|
|
137
|
+
try:
|
|
138
|
+
output = await model_invoke(first_messages)
|
|
139
|
+
return output, prep_result
|
|
140
|
+
except Exception as exc:
|
|
141
|
+
if detect_context_overflow(exc):
|
|
142
|
+
retry_result = prepare_context(
|
|
143
|
+
first_messages,
|
|
144
|
+
focus_topic=recall.active_task if recall else None,
|
|
145
|
+
provider_overflow=True,
|
|
146
|
+
)
|
|
147
|
+
retry_output = await model_invoke(retry_result.messages)
|
|
148
|
+
return retry_output, retry_result
|
|
149
|
+
raise
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""Session recall seam contracts.
|
|
2
|
+
|
|
3
|
+
This module defines lightweight contracts for short-lived session/task recall
|
|
4
|
+
without coupling them to durable memory persistence.
|
|
5
|
+
|
|
6
|
+
Authors:
|
|
7
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class SessionRecallSnapshot:
|
|
17
|
+
"""Snapshot of short-lived task/session state.
|
|
18
|
+
|
|
19
|
+
This snapshot is intentionally scoped to active work context and should not
|
|
20
|
+
be treated as durable memory by default.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
active_task: str | None = None
|
|
24
|
+
recent_decisions: tuple[str, ...] = field(default_factory=tuple)
|
|
25
|
+
changed_files: tuple[str, ...] = field(default_factory=tuple)
|
|
26
|
+
blockers: tuple[str, ...] = field(default_factory=tuple)
|
|
27
|
+
handoff_summary: str | None = None
|
|
28
|
+
stale: bool = False
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def build_session_recall_guidance(snapshot: SessionRecallSnapshot | None) -> str | None:
|
|
32
|
+
"""Render session recall guidance text from a snapshot.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
snapshot: Optional session recall snapshot.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
A guidance block describing short-lived task/session context, or None
|
|
39
|
+
when no snapshot is available.
|
|
40
|
+
"""
|
|
41
|
+
if snapshot is None:
|
|
42
|
+
return None
|
|
43
|
+
|
|
44
|
+
active_task = snapshot.active_task.strip() if snapshot.active_task else None
|
|
45
|
+
handoff_summary = snapshot.handoff_summary.strip() if snapshot.handoff_summary else None
|
|
46
|
+
recent_decisions = tuple(d.strip() for d in snapshot.recent_decisions if d.strip())
|
|
47
|
+
changed_files = tuple(f.strip() for f in snapshot.changed_files if f.strip())
|
|
48
|
+
blockers = tuple(b.strip() for b in snapshot.blockers if b.strip())
|
|
49
|
+
|
|
50
|
+
lines = ["Session Recall Snapshot:"]
|
|
51
|
+
if active_task:
|
|
52
|
+
lines.append(f"- Active task: {active_task}")
|
|
53
|
+
if recent_decisions:
|
|
54
|
+
lines.append("- Recent decisions:")
|
|
55
|
+
lines.extend(f" - {decision}" for decision in recent_decisions)
|
|
56
|
+
if changed_files:
|
|
57
|
+
lines.append("- Changed files:")
|
|
58
|
+
lines.extend(f" - {path}" for path in changed_files)
|
|
59
|
+
if blockers:
|
|
60
|
+
lines.append("- Blockers:")
|
|
61
|
+
lines.extend(f" - {blocker}" for blocker in blockers)
|
|
62
|
+
if handoff_summary:
|
|
63
|
+
lines.append(f"- Handoff summary: {handoff_summary}")
|
|
64
|
+
if snapshot.stale:
|
|
65
|
+
lines.append("- Recall freshness: stale")
|
|
66
|
+
|
|
67
|
+
if len(lines) == 1:
|
|
68
|
+
return None
|
|
69
|
+
return "\n".join(lines)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""State contracts for context compaction decisions.
|
|
2
|
+
|
|
3
|
+
Authors:
|
|
4
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from typing import Literal
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True)
|
|
14
|
+
class SummaryInsertionPoint:
|
|
15
|
+
"""Index metadata describing where a reference summary can be inserted.
|
|
16
|
+
|
|
17
|
+
Attributes:
|
|
18
|
+
protected_head_indexes: Initial message indexes preserved unchanged.
|
|
19
|
+
protected_tail_start_index: First recent-tail message index preserved unchanged.
|
|
20
|
+
replace_start_index: First message index replaced by the reference summary.
|
|
21
|
+
replace_end_index: Last message index replaced by the reference summary.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
protected_head_indexes: tuple[int, ...]
|
|
25
|
+
protected_tail_start_index: int
|
|
26
|
+
replace_start_index: int
|
|
27
|
+
replace_end_index: int
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass(frozen=True)
|
|
31
|
+
class CompactionState:
|
|
32
|
+
"""Observed compaction metadata tracked outside mutable agent state.
|
|
33
|
+
|
|
34
|
+
Attributes:
|
|
35
|
+
compaction_count: Number of compaction attempts observed for the current scope.
|
|
36
|
+
last_summary_status: Outcome of the latest summary attempt.
|
|
37
|
+
offloaded_ref_count: Number of payload references produced by offloading.
|
|
38
|
+
estimated_token_savings: Estimated token reduction from the latest compaction.
|
|
39
|
+
last_reason: Stable reason code from the latest compaction decision.
|
|
40
|
+
last_error_code: Safe error code for the latest failed compaction step.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
compaction_count: int = 0
|
|
44
|
+
last_summary_status: Literal["none", "succeeded", "failed", "skipped"] = "none"
|
|
45
|
+
offloaded_ref_count: int = 0
|
|
46
|
+
estimated_token_savings: int | None = None
|
|
47
|
+
last_reason: str | None = None
|
|
48
|
+
last_error_code: str | None = None
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Shared context utilities for token estimation, redaction, and safe preview.
|
|
2
|
+
|
|
3
|
+
Authors:
|
|
4
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import re
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def estimate_tokens(text: str, chars_per_token: int = 4) -> int:
|
|
13
|
+
"""Estimate token count for a text string."""
|
|
14
|
+
if not text:
|
|
15
|
+
return 0
|
|
16
|
+
safe_ratio = max(chars_per_token, 1)
|
|
17
|
+
return max(1, (len(text) + safe_ratio - 1) // safe_ratio)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
_secret_kv_pattern = re.compile(r"(?i)(api[_-]?key|token|password|secret)\s*[:=]\s*[^\s]+")
|
|
21
|
+
_long_base64_pattern = re.compile(r"(?=[^+/=]*[+/=])[A-Za-z0-9+/=]{120,}")
|
|
22
|
+
_auth_header_pattern = re.compile(r"(?i)(Authorization|X-API-Key|Cookie)\s*:\s*[^\n]+")
|
|
23
|
+
_credential_query_pattern = re.compile(r"(?i)(api_key|token|secret|key|password|signature)=[^\s&]+")
|
|
24
|
+
_signed_url_pattern = re.compile(r"(?i)\b(x-amz-signature|sig|signature)\s*=\s*[^\s&]+")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def redact_sensitive(text: str) -> tuple[str, bool]:
|
|
28
|
+
"""Redact sensitive content from text."""
|
|
29
|
+
redacted = _secret_kv_pattern.sub(lambda m: f"{m.group(1)}=[REDACTED]", text)
|
|
30
|
+
redacted = _long_base64_pattern.sub("[BASE64_REDACTED]", redacted)
|
|
31
|
+
redacted = _auth_header_pattern.sub(r"\1: [REDACTED]", redacted)
|
|
32
|
+
redacted = _credential_query_pattern.sub(r"\1=[REDACTED]", redacted)
|
|
33
|
+
redacted = _signed_url_pattern.sub(lambda m: f"{m.group(1)}=[REDACTED]", redacted)
|
|
34
|
+
redaction_applied = redacted != text
|
|
35
|
+
return redacted, redaction_applied
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def safe_preview(content: str, *, max_chars: int) -> tuple[str, bool]:
|
|
39
|
+
"""Create a redacted preview of content."""
|
|
40
|
+
redacted, redaction_applied = redact_sensitive(content)
|
|
41
|
+
clipped = redacted[:max_chars]
|
|
42
|
+
if len(redacted) > max_chars:
|
|
43
|
+
clipped += "..."
|
|
44
|
+
return clipped, redaction_applied
|