langfun 0.1.2.dev202510290805__tar.gz → 0.1.2.dev202510300805__tar.gz
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.
Potentially problematic release.
This version of langfun might be problematic. Click here for more details.
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/PKG-INFO +1 -1
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/agentic/action.py +31 -3
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/agentic/action_test.py +25 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/gemini.py +3 -3
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/env/__init__.py +4 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/env/base_sandbox.py +41 -239
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/env/base_test.py +15 -25
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/env/interface.py +112 -4
- langfun-0.1.2.dev202510300805/langfun/env/interface_test.py +122 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/env/load_balancers_test.py +17 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/env/test_utils.py +6 -6
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun.egg-info/PKG-INFO +1 -1
- langfun-0.1.2.dev202510290805/langfun/env/interface_test.py +0 -44
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/LICENSE +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/README.md +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/__init__.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/assistant/capabilities/gui/__init__.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/assistant/capabilities/gui/bounding_box_parser.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/assistant/capabilities/gui/bounding_box_parser_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/assistant/capabilities/gui/drawing.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/assistant/capabilities/gui/drawing_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/assistant/capabilities/gui/location.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/assistant/capabilities/gui/location_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/__init__.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/agentic/__init__.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/agentic/action_eval.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/agentic/action_eval_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/async_support.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/async_support_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/coding/__init__.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/coding/python/__init__.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/coding/python/correction.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/coding/python/correction_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/coding/python/execution.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/coding/python/execution_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/coding/python/generation.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/coding/python/generation_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/coding/python/parsing.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/coding/python/parsing_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/coding/python/sandboxing.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/coding/python/sandboxing_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/component.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/component_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/concurrent.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/concurrent_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/console.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/console_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/data/__init__.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/data/conversion/__init__.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/data/conversion/anthropic.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/data/conversion/anthropic_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/data/conversion/gemini.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/data/conversion/gemini_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/data/conversion/openai.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/data/conversion/openai_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/__init__.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/base.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/base_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/matching.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/matching_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/patching.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/patching_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/scoring.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/scoring_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/__init__.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/checkpointing.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/checkpointing_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/eval_test_helper.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/evaluation.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/evaluation_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/example.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/example_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/experiment.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/experiment_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/metric_values.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/metric_values_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/metrics.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/metrics_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/progress.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/progress_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/progress_tracking.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/progress_tracking_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/reporting.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/reporting_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/runners.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/eval/v2/runners_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/langfunc.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/langfunc_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/language_model.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/language_model_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/__init__.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/anthropic.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/anthropic_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/azure_openai.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/azure_openai_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/cache/__init__.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/cache/base.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/cache/in_memory.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/cache/in_memory_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/compositional.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/compositional_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/deepseek.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/deepseek_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/fake.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/fake_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/gemini_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/google_genai.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/google_genai_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/groq.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/groq_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/llama_cpp.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/llama_cpp_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/openai.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/openai_compatible.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/openai_compatible_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/openai_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/rest.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/rest_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/vertexai.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/llms/vertexai_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/logging.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/logging_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/mcp/__init__.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/mcp/client.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/mcp/client_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/mcp/session.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/mcp/session_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/mcp/testing/simple_mcp_client.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/mcp/testing/simple_mcp_server.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/mcp/tool.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/mcp/tool_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/memories/__init__.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/memories/conversation_history.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/memories/conversation_history_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/memory.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/message.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/message_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/modalities/__init__.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/modalities/audio.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/modalities/audio_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/modalities/image.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/modalities/image_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/modalities/mime.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/modalities/mime_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/modalities/pdf.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/modalities/pdf_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/modalities/video.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/modalities/video_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/modality.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/modality_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/natural_language.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/natural_language_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/sampling.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/sampling_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/__init__.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/completion.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/completion_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/description.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/description_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/function_generation.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/function_generation_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/mapping.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/mapping_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/parsing.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/parsing_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/querying.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/querying_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/schema.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/schema_generation.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/schema_generation_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/schema_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/scoring.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/scoring_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/tokenization.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/structured/tokenization_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/subscription.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/subscription_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/template.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/template_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/templates/__init__.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/templates/completion.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/templates/completion_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/templates/conversation.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/templates/conversation_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/templates/demonstration.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/templates/demonstration_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/templates/selfplay.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/templates/selfplay_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/env/base_environment.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/env/base_feature.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/env/event_handlers/__init__.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/env/event_handlers/base.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/env/event_handlers/event_logger.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/env/event_handlers/event_logger_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/env/event_handlers/metric_writer.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/env/event_handlers/metric_writer_test.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/env/load_balancers.py +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun.egg-info/SOURCES.txt +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun.egg-info/dependency_links.txt +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun.egg-info/requires.txt +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun.egg-info/top_level.txt +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/setup.cfg +0 -0
- {langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/setup.py +0 -0
{langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/agentic/action.py
RENAMED
|
@@ -538,6 +538,18 @@ class ExecutionTrace(pg.Object, pg.views.html.HtmlTreeView.Extension):
|
|
|
538
538
|
remove_class=['not-started'],
|
|
539
539
|
)
|
|
540
540
|
|
|
541
|
+
def remove(self, item: TracedItem) -> None:
|
|
542
|
+
"""Removes an item from the sequence."""
|
|
543
|
+
index = self.items.index(item)
|
|
544
|
+
if index == -1:
|
|
545
|
+
raise ValueError(f'Item not found in execution trace: {item!r}')
|
|
546
|
+
|
|
547
|
+
with pg.notify_on_change(False):
|
|
548
|
+
self.items.pop(index)
|
|
549
|
+
|
|
550
|
+
if self._tab_control is not None:
|
|
551
|
+
self._tab_control.remove(index)
|
|
552
|
+
|
|
541
553
|
def extend(self, items: Iterable[TracedItem]) -> None:
|
|
542
554
|
"""Extends the sequence with a list of items."""
|
|
543
555
|
for item in items:
|
|
@@ -1648,13 +1660,20 @@ class Session(pg.Object, pg.views.html.HtmlTreeView.Extension):
|
|
|
1648
1660
|
@contextlib.contextmanager
|
|
1649
1661
|
def track_queries(
|
|
1650
1662
|
self,
|
|
1651
|
-
phase: str | None = None
|
|
1663
|
+
phase: str | None = None,
|
|
1664
|
+
track_if: Callable[
|
|
1665
|
+
[lf_structured.QueryInvocation],
|
|
1666
|
+
bool
|
|
1667
|
+
] | None = None,
|
|
1652
1668
|
) -> Iterator[list[lf_structured.QueryInvocation]]:
|
|
1653
1669
|
"""Tracks `lf.query` made within the context.
|
|
1654
1670
|
|
|
1655
1671
|
Args:
|
|
1656
1672
|
phase: The name of a new phase to track the queries in. If not provided,
|
|
1657
1673
|
the queries will be tracked in the parent phase.
|
|
1674
|
+
track_if: A function that takes a `lf_structured.QueryInvocation` and
|
|
1675
|
+
returns True if the query should be included in the result. If None,
|
|
1676
|
+
all queries (including failed queries) will be included.
|
|
1658
1677
|
|
|
1659
1678
|
Yields:
|
|
1660
1679
|
A list of `lf.QueryInvocation` objects, each for a single `lf.query`
|
|
@@ -1673,6 +1692,11 @@ class Session(pg.Object, pg.views.html.HtmlTreeView.Extension):
|
|
|
1673
1692
|
self.event_handler.on_query_start(self, self._current_action, invocation)
|
|
1674
1693
|
|
|
1675
1694
|
def _query_end(invocation: lf_structured.QueryInvocation):
|
|
1695
|
+
if track_if is not None and not track_if(invocation):
|
|
1696
|
+
self._current_execution.remove(invocation)
|
|
1697
|
+
# Even if the query is not included in the execution trace, we still
|
|
1698
|
+
# count the usage summary to the current execution and trigger the
|
|
1699
|
+
# event handler to log the query.
|
|
1676
1700
|
self._current_execution.merge_usage_summary(invocation.usage_summary)
|
|
1677
1701
|
self.event_handler.on_query_end(self, self._current_action, invocation)
|
|
1678
1702
|
|
|
@@ -1705,8 +1729,9 @@ class Session(pg.Object, pg.views.html.HtmlTreeView.Extension):
|
|
|
1705
1729
|
*,
|
|
1706
1730
|
lm: lf.LanguageModel,
|
|
1707
1731
|
examples: list[lf_structured.MappingExample] | None = None,
|
|
1732
|
+
track_if: Callable[[lf_structured.QueryInvocation], bool] | None = None,
|
|
1708
1733
|
**kwargs
|
|
1709
|
-
|
|
1734
|
+
) -> Any:
|
|
1710
1735
|
"""Calls `lf.query` and associates it with the current invocation.
|
|
1711
1736
|
|
|
1712
1737
|
The following code are equivalent:
|
|
@@ -1731,12 +1756,15 @@ class Session(pg.Object, pg.views.html.HtmlTreeView.Extension):
|
|
|
1731
1756
|
default: The default value to return if the query fails.
|
|
1732
1757
|
lm: The language model to use for the query.
|
|
1733
1758
|
examples: The examples to use for the query.
|
|
1759
|
+
track_if: A function that takes a `lf_structured.QueryInvocation`
|
|
1760
|
+
and returns True if the query should be tracked.
|
|
1761
|
+
If None, all queries (including failed queries) will be tracked.
|
|
1734
1762
|
**kwargs: Additional keyword arguments to pass to `lf.query`.
|
|
1735
1763
|
|
|
1736
1764
|
Returns:
|
|
1737
1765
|
The result of the query.
|
|
1738
1766
|
"""
|
|
1739
|
-
with self.track_queries():
|
|
1767
|
+
with self.track_queries(track_if=track_if):
|
|
1740
1768
|
return lf_structured.query(
|
|
1741
1769
|
prompt,
|
|
1742
1770
|
schema=schema,
|
{langfun-0.1.2.dev202510290805 → langfun-0.1.2.dev202510300805}/langfun/core/agentic/action_test.py
RENAMED
|
@@ -530,6 +530,31 @@ class SessionTest(unittest.TestCase):
|
|
|
530
530
|
self.assertIn('agent@', session.id)
|
|
531
531
|
self.assertIsInstance(session.as_message(), lf.AIMessage)
|
|
532
532
|
|
|
533
|
+
def test_query_with_track_if(self):
|
|
534
|
+
lm = fake.StaticResponse('lm response')
|
|
535
|
+
session = action_lib.Session()
|
|
536
|
+
|
|
537
|
+
# Render session to trigger javascript updates to the HTML when
|
|
538
|
+
# operating on the session.
|
|
539
|
+
_ = session.to_html()
|
|
540
|
+
with session:
|
|
541
|
+
# This query will succeed.
|
|
542
|
+
session.query(
|
|
543
|
+
'prompt1',
|
|
544
|
+
schema=None,
|
|
545
|
+
lm=lm,
|
|
546
|
+
track_if=lambda q: not q.has_error,
|
|
547
|
+
default=None)
|
|
548
|
+
# This query will fail during parsing.
|
|
549
|
+
session.query(
|
|
550
|
+
'prompt2',
|
|
551
|
+
schema=int,
|
|
552
|
+
lm=lm,
|
|
553
|
+
track_if=lambda q: not q.has_error,
|
|
554
|
+
default=None)
|
|
555
|
+
self.assertEqual(len(session.root.queries), 1)
|
|
556
|
+
self.assertIsNone(session.root.queries[0].error)
|
|
557
|
+
|
|
533
558
|
|
|
534
559
|
if __name__ == '__main__':
|
|
535
560
|
unittest.main()
|
|
@@ -830,9 +830,9 @@ class Gemini(rest.REST):
|
|
|
830
830
|
)
|
|
831
831
|
|
|
832
832
|
def _error(self, status_code: int, content: str) -> lf.LMError:
|
|
833
|
-
if (
|
|
834
|
-
|
|
835
|
-
|
|
833
|
+
if status_code == 400 and (
|
|
834
|
+
b'exceeds the maximum number of tokens' in content
|
|
835
|
+
or b'Reduce the input token count and try again.' in content
|
|
836
836
|
):
|
|
837
837
|
return lf.ContextLimitError(f'{status_code}: {content}')
|
|
838
838
|
return super()._error(status_code, content)
|
|
@@ -24,6 +24,10 @@ from langfun.env.interface import Environment
|
|
|
24
24
|
from langfun.env.interface import Sandbox
|
|
25
25
|
from langfun.env.interface import Feature
|
|
26
26
|
|
|
27
|
+
# Decorators for sandbox/feature methods.
|
|
28
|
+
from langfun.env.interface import treat_as_sandbox_state_error
|
|
29
|
+
from langfun.env.interface import log_sandbox_activity
|
|
30
|
+
|
|
27
31
|
from langfun.env.base_environment import BaseEnvironment
|
|
28
32
|
from langfun.env.base_sandbox import BaseSandbox
|
|
29
33
|
from langfun.env.base_feature import BaseFeature
|
|
@@ -26,7 +26,7 @@ import contextlib
|
|
|
26
26
|
import functools
|
|
27
27
|
import threading
|
|
28
28
|
import time
|
|
29
|
-
from typing import Annotated, Any,
|
|
29
|
+
from typing import Annotated, Any, Iterator
|
|
30
30
|
|
|
31
31
|
from langfun.env import interface
|
|
32
32
|
from langfun.env.event_handlers import base as event_handler_base
|
|
@@ -100,10 +100,9 @@ class BaseSandbox(interface.Sandbox):
|
|
|
100
100
|
self._status = status
|
|
101
101
|
self._status_start_time = time.time()
|
|
102
102
|
|
|
103
|
-
def
|
|
103
|
+
def report_state_error(self, e: interface.SandboxStateError) -> None:
|
|
104
104
|
"""Reports sandbox state errors."""
|
|
105
|
-
if
|
|
106
|
-
and e not in self._state_errors):
|
|
105
|
+
if e not in self._state_errors:
|
|
107
106
|
self._state_errors.append(e)
|
|
108
107
|
|
|
109
108
|
def _setup_features(self) -> None:
|
|
@@ -141,7 +140,8 @@ class BaseSandbox(interface.Sandbox):
|
|
|
141
140
|
try:
|
|
142
141
|
feature.teardown()
|
|
143
142
|
except BaseException as e: # pylint: disable=broad-except
|
|
144
|
-
|
|
143
|
+
if isinstance(e, interface.SandboxStateError):
|
|
144
|
+
self.report_state_error(e)
|
|
145
145
|
errors[feature.name] = e
|
|
146
146
|
if errors:
|
|
147
147
|
return interface.FeatureTeardownError(sandbox=self, errors=errors)
|
|
@@ -175,7 +175,8 @@ class BaseSandbox(interface.Sandbox):
|
|
|
175
175
|
try:
|
|
176
176
|
feature.teardown_session()
|
|
177
177
|
except BaseException as e: # pylint: disable=broad-except
|
|
178
|
-
|
|
178
|
+
if isinstance(e, interface.SandboxStateError):
|
|
179
|
+
self.report_state_error(e)
|
|
179
180
|
feature_teardown_errors[name] = e
|
|
180
181
|
|
|
181
182
|
return interface.SessionTeardownError(
|
|
@@ -277,28 +278,6 @@ class BaseSandbox(interface.Sandbox):
|
|
|
277
278
|
"""Returns the features in the sandbox."""
|
|
278
279
|
return self._features
|
|
279
280
|
|
|
280
|
-
def _enter_service_call(self) -> bool:
|
|
281
|
-
"""Enters a service call.
|
|
282
|
-
|
|
283
|
-
Returns:
|
|
284
|
-
True if the service call is at the top of the call stack.
|
|
285
|
-
"""
|
|
286
|
-
v = getattr(self._tls_state, 'service_call_depth', None)
|
|
287
|
-
if v is None:
|
|
288
|
-
v = 0
|
|
289
|
-
setattr(self._tls_state, 'service_call_depth', v + 1)
|
|
290
|
-
return v == 0
|
|
291
|
-
|
|
292
|
-
def _exit_service_call(self) -> bool:
|
|
293
|
-
"""Exits a service call.
|
|
294
|
-
|
|
295
|
-
Returns:
|
|
296
|
-
True if the service call is at the top of the call stack.
|
|
297
|
-
"""
|
|
298
|
-
v = getattr(self._tls_state, 'service_call_depth')
|
|
299
|
-
setattr(self._tls_state, 'service_call_depth', v - 1)
|
|
300
|
-
return v == 1
|
|
301
|
-
|
|
302
281
|
#
|
|
303
282
|
# Sandbox start/shutdown.
|
|
304
283
|
#
|
|
@@ -369,7 +348,8 @@ class BaseSandbox(interface.Sandbox):
|
|
|
369
348
|
'[%s]: Sandbox failed to start in %.2f seconds: %s',
|
|
370
349
|
self.id, duration, e
|
|
371
350
|
)
|
|
372
|
-
|
|
351
|
+
if isinstance(e, interface.SandboxStateError):
|
|
352
|
+
self.report_state_error(e)
|
|
373
353
|
self.on_start(duration, e)
|
|
374
354
|
self.shutdown()
|
|
375
355
|
raise e
|
|
@@ -442,7 +422,8 @@ class BaseSandbox(interface.Sandbox):
|
|
|
442
422
|
shutdown_error = None
|
|
443
423
|
except BaseException as e: # pylint: disable=broad-except
|
|
444
424
|
shutdown_error = e
|
|
445
|
-
|
|
425
|
+
if isinstance(e, interface.SandboxStateError):
|
|
426
|
+
self.report_state_error(e)
|
|
446
427
|
self._set_status(interface.Sandbox.Status.OFFLINE)
|
|
447
428
|
pg.logging.error(
|
|
448
429
|
'[%s]: Sandbox shutdown with error: %s',
|
|
@@ -540,7 +521,8 @@ class BaseSandbox(interface.Sandbox):
|
|
|
540
521
|
self._set_status(self.Status.IN_SESSION)
|
|
541
522
|
self.on_session_start(session_id, time.time() - self._session_start_time)
|
|
542
523
|
except BaseException as e: # pylint: disable=broad-except
|
|
543
|
-
|
|
524
|
+
if isinstance(e, interface.SandboxStateError):
|
|
525
|
+
self.report_state_error(e)
|
|
544
526
|
self.on_session_start(
|
|
545
527
|
session_id, time.time() - self._session_start_time, e
|
|
546
528
|
)
|
|
@@ -626,7 +608,8 @@ class BaseSandbox(interface.Sandbox):
|
|
|
626
608
|
self.id,
|
|
627
609
|
e
|
|
628
610
|
)
|
|
629
|
-
|
|
611
|
+
if isinstance(e, interface.SandboxStateError):
|
|
612
|
+
self.report_state_error(e)
|
|
630
613
|
self.shutdown()
|
|
631
614
|
|
|
632
615
|
# End session before setting up the next session.
|
|
@@ -677,6 +660,30 @@ class BaseSandbox(interface.Sandbox):
|
|
|
677
660
|
and end_session_error.has_non_sandbox_state_error):
|
|
678
661
|
raise end_session_error # pylint: disable=raising-bad-type
|
|
679
662
|
|
|
663
|
+
@contextlib.contextmanager
|
|
664
|
+
def track_activity(
|
|
665
|
+
self,
|
|
666
|
+
name: str,
|
|
667
|
+
feature: interface.Feature | None = None,
|
|
668
|
+
**kwargs: Any
|
|
669
|
+
) -> Iterator[None]:
|
|
670
|
+
"""Tracks an activity for the sandbox."""
|
|
671
|
+
start_time = time.time()
|
|
672
|
+
error = None
|
|
673
|
+
try:
|
|
674
|
+
yield None
|
|
675
|
+
except BaseException as e: # pylint: disable=broad-except
|
|
676
|
+
error = e
|
|
677
|
+
raise
|
|
678
|
+
finally:
|
|
679
|
+
self.on_activity(
|
|
680
|
+
name=name,
|
|
681
|
+
feature=feature,
|
|
682
|
+
duration=time.time() - start_time,
|
|
683
|
+
error=error,
|
|
684
|
+
**kwargs
|
|
685
|
+
)
|
|
686
|
+
|
|
680
687
|
#
|
|
681
688
|
# Housekeeping.
|
|
682
689
|
#
|
|
@@ -722,7 +729,7 @@ class BaseSandbox(interface.Sandbox):
|
|
|
722
729
|
str(e)
|
|
723
730
|
)
|
|
724
731
|
self._housekeep_counter += 1
|
|
725
|
-
self.
|
|
732
|
+
self.report_state_error(e)
|
|
726
733
|
self.on_housekeep(time.time() - housekeep_start, e)
|
|
727
734
|
self.shutdown()
|
|
728
735
|
break
|
|
@@ -744,7 +751,7 @@ class BaseSandbox(interface.Sandbox):
|
|
|
744
751
|
feature.name,
|
|
745
752
|
e,
|
|
746
753
|
)
|
|
747
|
-
self.
|
|
754
|
+
self.report_state_error(e)
|
|
748
755
|
self._housekeep_counter += 1
|
|
749
756
|
self.on_housekeep(time.time() - housekeep_start, e)
|
|
750
757
|
self.shutdown()
|
|
@@ -917,208 +924,3 @@ class BaseSandbox(interface.Sandbox):
|
|
|
917
924
|
handler.on_session_end(
|
|
918
925
|
self.environment, self, session_id, duration, lifetime, error
|
|
919
926
|
)
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
#
|
|
923
|
-
# Sandbox service decorator.
|
|
924
|
-
#
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
def sandbox_service(
|
|
928
|
-
critical_errors: Sequence[
|
|
929
|
-
Type[BaseException] | tuple[Type[BaseException], str]
|
|
930
|
-
] | None = None
|
|
931
|
-
) -> Callable[..., Any]:
|
|
932
|
-
"""Decorator for Sandbox/Feature methods exposed as sandbox services.
|
|
933
|
-
|
|
934
|
-
This decorator will catch errors and map to `SandboxStateError` if the
|
|
935
|
-
error matches any of the critical errors. Consequently, the sandbox will be
|
|
936
|
-
shutdown automatically when the error is raised.
|
|
937
|
-
|
|
938
|
-
Example:
|
|
939
|
-
|
|
940
|
-
```
|
|
941
|
-
with env:
|
|
942
|
-
with env.sandbox() as sb:
|
|
943
|
-
try:
|
|
944
|
-
sb.test_feature.do_something_with_non_state_error()
|
|
945
|
-
except ValueError:
|
|
946
|
-
# sandbox will not be shutdown.
|
|
947
|
-
pass
|
|
948
|
-
|
|
949
|
-
try:
|
|
950
|
-
sb.test_feature.do_something_with_state_error()
|
|
951
|
-
except ValueError:
|
|
952
|
-
assert sb.state == sb.Status.OFFLINE
|
|
953
|
-
```
|
|
954
|
-
|
|
955
|
-
If the decorated method returns a context manager, a wrapper context manager
|
|
956
|
-
will be returned, which will end the session when exiting the context.
|
|
957
|
-
|
|
958
|
-
Example:
|
|
959
|
-
|
|
960
|
-
```
|
|
961
|
-
with env:
|
|
962
|
-
with env.test_feature.do_something_with_context_manager() as result:
|
|
963
|
-
# sandbox will be alive during the whole context manager cycle.
|
|
964
|
-
```
|
|
965
|
-
|
|
966
|
-
For sandbox service methods, an optional `session_id` argument can be passed
|
|
967
|
-
to create a new session for the service call, even its signature does not
|
|
968
|
-
contain a `session_id` argument.
|
|
969
|
-
|
|
970
|
-
Args:
|
|
971
|
-
critical_errors: A sequence of exception types or tuples of exception type
|
|
972
|
-
and error messages (described in regular expression), when matched, treat
|
|
973
|
-
the sandbox as in a bad state, which will trigger a shutdown.
|
|
974
|
-
|
|
975
|
-
Returns:
|
|
976
|
-
The decorator function.
|
|
977
|
-
"""
|
|
978
|
-
critical_errors = critical_errors or []
|
|
979
|
-
|
|
980
|
-
def decorator(func):
|
|
981
|
-
signature = pg.typing.get_signature(func)
|
|
982
|
-
if 'session_id' in signature.arg_names:
|
|
983
|
-
raise ValueError(
|
|
984
|
-
'`session_id` should not be used as argument for sandbox '
|
|
985
|
-
'service method. Please use `self.session_id` instead.'
|
|
986
|
-
)
|
|
987
|
-
|
|
988
|
-
def to_kwargs(*args, **kwargs):
|
|
989
|
-
num_non_self_args = len(signature.arg_names) - 1
|
|
990
|
-
if len(args) > num_non_self_args:
|
|
991
|
-
assert signature.varargs is not None, (signature, args)
|
|
992
|
-
kwargs[signature.varargs.name] = tuple(args[num_non_self_args:])
|
|
993
|
-
args = args[:num_non_self_args]
|
|
994
|
-
for i in range(len(args)):
|
|
995
|
-
# The first argument is `self`.
|
|
996
|
-
kwargs[signature.arg_names[i + 1]] = args[i]
|
|
997
|
-
return kwargs
|
|
998
|
-
|
|
999
|
-
@functools.wraps(func)
|
|
1000
|
-
def method_wrapper(self, *args, **kwargs) -> Any:
|
|
1001
|
-
"""Helper function to safely execute logics in the sandbox."""
|
|
1002
|
-
|
|
1003
|
-
assert isinstance(self, (BaseSandbox, interface.Feature)), self
|
|
1004
|
-
sandbox = self.sandbox if isinstance(self, interface.Feature) else self
|
|
1005
|
-
|
|
1006
|
-
# We count the service call stack depth so we could shutdown the sandbox
|
|
1007
|
-
# at the top upon sandbox state error.
|
|
1008
|
-
sandbox._enter_service_call() # pylint: disable=protected-access
|
|
1009
|
-
|
|
1010
|
-
# When a capability is directly accessed from the environment,
|
|
1011
|
-
# we create a new session for the capability call. This
|
|
1012
|
-
# prevents the sandbox from being reused for other feature calls.
|
|
1013
|
-
if sandbox.status == interface.Sandbox.Status.ACQUIRED:
|
|
1014
|
-
new_session = True
|
|
1015
|
-
new_session_id = kwargs.get('session_id')
|
|
1016
|
-
if new_session_id is None:
|
|
1017
|
-
new_session_id = sandbox.environment.new_session_id()
|
|
1018
|
-
|
|
1019
|
-
# If it's a feature method called from the environment, start a new
|
|
1020
|
-
# session for the feature call.
|
|
1021
|
-
sandbox.start_session(new_session_id)
|
|
1022
|
-
else:
|
|
1023
|
-
new_session = False
|
|
1024
|
-
|
|
1025
|
-
kwargs.pop('session_id', None)
|
|
1026
|
-
result = None
|
|
1027
|
-
error = None
|
|
1028
|
-
start_time = time.time()
|
|
1029
|
-
|
|
1030
|
-
try:
|
|
1031
|
-
# Execute the service function.
|
|
1032
|
-
result = func(self, *args, **kwargs)
|
|
1033
|
-
|
|
1034
|
-
# If the result is a context manager, wrap it with a context manager
|
|
1035
|
-
# to end the session when exiting.
|
|
1036
|
-
if isinstance(result, contextlib.AbstractContextManager):
|
|
1037
|
-
return _service_context_manager_wrapper(
|
|
1038
|
-
service=result,
|
|
1039
|
-
sandbox_or_feature=self,
|
|
1040
|
-
sandbox=sandbox,
|
|
1041
|
-
name=func.__name__,
|
|
1042
|
-
kwargs=to_kwargs(*args, **kwargs),
|
|
1043
|
-
start_time=start_time,
|
|
1044
|
-
new_session=new_session
|
|
1045
|
-
)
|
|
1046
|
-
|
|
1047
|
-
# Otherwise, return the result and end the session in the finally block.
|
|
1048
|
-
return result
|
|
1049
|
-
except BaseException as e:
|
|
1050
|
-
error = e
|
|
1051
|
-
sandbox.report_maybe_state_error(e)
|
|
1052
|
-
if pg.match_error(e, critical_errors):
|
|
1053
|
-
state_error = interface.SandboxStateError(
|
|
1054
|
-
'Sandbox encountered an unexpected error executing '
|
|
1055
|
-
f'`{func.__name__}` (args={args!r}, kwargs={kwargs!r}): {e}',
|
|
1056
|
-
sandbox=self
|
|
1057
|
-
)
|
|
1058
|
-
sandbox.report_maybe_state_error(state_error)
|
|
1059
|
-
raise state_error from e
|
|
1060
|
-
raise
|
|
1061
|
-
finally:
|
|
1062
|
-
is_topmost_call = sandbox._exit_service_call() # pylint: disable=protected-access
|
|
1063
|
-
if not isinstance(result, contextlib.AbstractContextManager):
|
|
1064
|
-
self.on_activity(
|
|
1065
|
-
name=func.__name__,
|
|
1066
|
-
duration=time.time() - start_time,
|
|
1067
|
-
error=error,
|
|
1068
|
-
**to_kwargs(*args, **kwargs),
|
|
1069
|
-
)
|
|
1070
|
-
if new_session:
|
|
1071
|
-
assert is_topmost_call
|
|
1072
|
-
|
|
1073
|
-
# End the session if it's from a feature method and the result
|
|
1074
|
-
# is not a context manager.
|
|
1075
|
-
sandbox.end_session()
|
|
1076
|
-
|
|
1077
|
-
# Shutdown the sandbox if it is at the top of the service call stack and
|
|
1078
|
-
# has state errors.
|
|
1079
|
-
if (is_topmost_call
|
|
1080
|
-
and sandbox.state_errors
|
|
1081
|
-
# Sandbox service method might be called during shutting down, in
|
|
1082
|
-
# that case we don't want to shutdown the sandbox again.
|
|
1083
|
-
and not sandbox.is_shutting_down):
|
|
1084
|
-
sandbox.shutdown()
|
|
1085
|
-
|
|
1086
|
-
return method_wrapper
|
|
1087
|
-
return decorator
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
@contextlib.contextmanager
|
|
1091
|
-
def _service_context_manager_wrapper(
|
|
1092
|
-
service: contextlib.AbstractContextManager[Any],
|
|
1093
|
-
sandbox_or_feature: BaseSandbox | interface.Feature,
|
|
1094
|
-
sandbox: interface.Sandbox,
|
|
1095
|
-
name: str,
|
|
1096
|
-
kwargs: dict[str, Any],
|
|
1097
|
-
new_session: bool,
|
|
1098
|
-
start_time: float,
|
|
1099
|
-
) -> Iterator[Any]:
|
|
1100
|
-
"""Context manager wrapper for ending a sandbox session when exiting."""
|
|
1101
|
-
error = None
|
|
1102
|
-
sandbox._enter_service_call() # pylint: disable=protected-access
|
|
1103
|
-
|
|
1104
|
-
try:
|
|
1105
|
-
with service as result:
|
|
1106
|
-
yield result
|
|
1107
|
-
except BaseException as e:
|
|
1108
|
-
error = e
|
|
1109
|
-
sandbox.report_maybe_state_error(error)
|
|
1110
|
-
raise
|
|
1111
|
-
finally:
|
|
1112
|
-
sandbox_or_feature.on_activity(
|
|
1113
|
-
name=name,
|
|
1114
|
-
error=error,
|
|
1115
|
-
duration=time.time() - start_time,
|
|
1116
|
-
**kwargs,
|
|
1117
|
-
)
|
|
1118
|
-
is_topmost_call = sandbox._exit_service_call() # pylint: disable=protected-access
|
|
1119
|
-
|
|
1120
|
-
if new_session:
|
|
1121
|
-
assert is_topmost_call
|
|
1122
|
-
sandbox.end_session()
|
|
1123
|
-
elif isinstance(error, interface.SandboxStateError):
|
|
1124
|
-
sandbox.shutdown()
|
|
@@ -15,7 +15,6 @@ import time
|
|
|
15
15
|
from typing import Any
|
|
16
16
|
import unittest
|
|
17
17
|
|
|
18
|
-
from langfun.env import base_sandbox
|
|
19
18
|
from langfun.env import interface
|
|
20
19
|
from langfun.env import test_utils
|
|
21
20
|
from langfun.env.event_handlers import base as event_handler_base
|
|
@@ -460,10 +459,11 @@ class EnvironmentTests(unittest.TestCase):
|
|
|
460
459
|
simulate_setup_error=interface.SandboxStateError,
|
|
461
460
|
skip_notification=True
|
|
462
461
|
)
|
|
463
|
-
with
|
|
464
|
-
with
|
|
462
|
+
with self.assertRaises(interface.SandboxStateError):
|
|
463
|
+
with env.sandbox() as sb:
|
|
465
464
|
sb.shell('bad command', raise_error=interface.SandboxStateError)
|
|
466
465
|
self.assertEqual(sb.status, interface.Sandbox.Status.OFFLINE)
|
|
466
|
+
self.assertEqual(len(sb.state_errors), 1)
|
|
467
467
|
sb_offline_time = time.time()
|
|
468
468
|
while time.time() - sb_offline_time < 10:
|
|
469
469
|
if not env.is_online:
|
|
@@ -1250,12 +1250,11 @@ class SandboxStatusTests(unittest.TestCase):
|
|
|
1250
1250
|
},
|
|
1251
1251
|
)
|
|
1252
1252
|
with env:
|
|
1253
|
-
with
|
|
1254
|
-
with
|
|
1253
|
+
with self.assertRaises(interface.SandboxStateError):
|
|
1254
|
+
with env.sandbox(session_id='session1') as sb:
|
|
1255
1255
|
sb.shell('echo foo', raise_error=RuntimeError)
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
sb.shell('echo bar')
|
|
1256
|
+
self.assertEqual(len(sb.state_errors), 1)
|
|
1257
|
+
self.assertEqual(sb.status, interface.Sandbox.Status.OFFLINE)
|
|
1259
1258
|
self.assertEqual(
|
|
1260
1259
|
self.event_handler.logs,
|
|
1261
1260
|
[
|
|
@@ -1282,7 +1281,6 @@ class SandboxStatusTests(unittest.TestCase):
|
|
|
1282
1281
|
'[testing-env/test_image:0:0/feature1] feature teardown',
|
|
1283
1282
|
'[testing-env/test_image:0:0] shutting_down -> offline',
|
|
1284
1283
|
'[testing-env/test_image:0:0] sandbox shutdown',
|
|
1285
|
-
'[testing-env/test_image:0:0] shell: echo bar',
|
|
1286
1284
|
# pylint: enable=line-too-long
|
|
1287
1285
|
]
|
|
1288
1286
|
)
|
|
@@ -1306,11 +1304,6 @@ class SandboxActivityTests(unittest.TestCase):
|
|
|
1306
1304
|
r'test_feature-session-[0-9a-f]{7}'
|
|
1307
1305
|
)
|
|
1308
1306
|
|
|
1309
|
-
with self.assertRaisesRegex(ValueError, '`session_id` should not be used'):
|
|
1310
|
-
@base_sandbox.sandbox_service()
|
|
1311
|
-
def foo(session_id: str):
|
|
1312
|
-
del session_id
|
|
1313
|
-
|
|
1314
1307
|
def test_ping_error(self):
|
|
1315
1308
|
env = TestingEnvironment(
|
|
1316
1309
|
features={'test_feature': TestingFeature(housekeep_interval=0)},
|
|
@@ -1487,10 +1480,11 @@ class SandboxServiceTests(unittest.TestCase):
|
|
|
1487
1480
|
|
|
1488
1481
|
def test_service_call_from_feature_with_error(self):
|
|
1489
1482
|
with self.env:
|
|
1490
|
-
with self.
|
|
1491
|
-
with self.
|
|
1483
|
+
with self.assertRaises(interface.SandboxStateError):
|
|
1484
|
+
with self.env.sandbox(session_id='session1') as sb:
|
|
1492
1485
|
sb.test_feature.bad_shell_call()
|
|
1493
|
-
|
|
1486
|
+
self.assertEqual(sb.status, interface.Sandbox.Status.OFFLINE)
|
|
1487
|
+
self.assertEqual(len(sb.state_errors), 1)
|
|
1494
1488
|
|
|
1495
1489
|
self.assertEqual(
|
|
1496
1490
|
self.event_handler.logs,
|
|
@@ -1584,7 +1578,6 @@ class SandboxServiceTests(unittest.TestCase):
|
|
|
1584
1578
|
'[testing-env/test_image:0/session1] shell: "test_feature" setup session',
|
|
1585
1579
|
"[testing-env/test_image:0] session 'session1' started",
|
|
1586
1580
|
'[testing-env/test_image:0/session1] shell: hello',
|
|
1587
|
-
'[testing-env/test_image:0/session1/test_feature] test_feature.my_service: None',
|
|
1588
1581
|
'[testing-env/test_image:0/session1] shell: foo',
|
|
1589
1582
|
'[testing-env/test_image:0/session1] shell: "test_feature" teardown session',
|
|
1590
1583
|
"[testing-env/test_image:0] session 'session1' ended",
|
|
@@ -1598,11 +1591,12 @@ class SandboxServiceTests(unittest.TestCase):
|
|
|
1598
1591
|
|
|
1599
1592
|
def test_service_context_manager_from_feature_with_error(self):
|
|
1600
1593
|
with self.env:
|
|
1601
|
-
with self.
|
|
1602
|
-
with self.
|
|
1594
|
+
with self.assertRaises(interface.SandboxStateError):
|
|
1595
|
+
with self.env.sandbox(session_id='session1') as sb:
|
|
1603
1596
|
with sb.test_feature.my_service() as service:
|
|
1604
1597
|
service.do('hello', raise_error=interface.SandboxStateError)
|
|
1605
|
-
|
|
1598
|
+
self.assertEqual(sb.status, interface.Sandbox.Status.OFFLINE)
|
|
1599
|
+
self.assertEqual(len(sb.state_errors), 1)
|
|
1606
1600
|
self.assertEqual(
|
|
1607
1601
|
self.event_handler.logs,
|
|
1608
1602
|
[
|
|
@@ -1614,7 +1608,6 @@ class SandboxServiceTests(unittest.TestCase):
|
|
|
1614
1608
|
'[testing-env/test_image:0/session1] shell: "test_feature" setup session',
|
|
1615
1609
|
"[testing-env/test_image:0] session 'session1' started",
|
|
1616
1610
|
'[testing-env/test_image:0/session1] shell: hello with SandboxStateError',
|
|
1617
|
-
'[testing-env/test_image:0/session1/test_feature] test_feature.my_service: None with SandboxStateError',
|
|
1618
1611
|
'[testing-env/test_image:0/session1] shell: "test_feature" teardown session',
|
|
1619
1612
|
"[testing-env/test_image:0] session 'session1' ended with SandboxStateError",
|
|
1620
1613
|
'[testing-env/test_image:0] shell: "test_feature" teardown',
|
|
@@ -1645,7 +1638,6 @@ class SandboxServiceTests(unittest.TestCase):
|
|
|
1645
1638
|
'[testing-env/test_image:0/session1] shell: "test_feature" setup session',
|
|
1646
1639
|
"[testing-env/test_image:0] session 'session1' started",
|
|
1647
1640
|
'[testing-env/test_image:0/session1] shell: foo',
|
|
1648
|
-
'[testing-env/test_image:0/session1/test_feature] test_feature.my_service: None',
|
|
1649
1641
|
'[testing-env/test_image:0/session1] shell: "test_feature" teardown session',
|
|
1650
1642
|
"[testing-env/test_image:0] session 'session1' ended",
|
|
1651
1643
|
'[testing-env/test_image:0] shell: "test_feature" teardown',
|
|
@@ -1657,7 +1649,6 @@ class SandboxServiceTests(unittest.TestCase):
|
|
|
1657
1649
|
'[testing-env/test_image:1/test_feature-session-2291d8c] shell: "test_feature" setup session',
|
|
1658
1650
|
"[testing-env/test_image:1] session 'test_feature-session-2291d8c' started",
|
|
1659
1651
|
'[testing-env/test_image:1/test_feature-session-2291d8c] shell: bar',
|
|
1660
|
-
'[testing-env/test_image:1/test_feature-session-2291d8c/test_feature] test_feature.my_service: None',
|
|
1661
1652
|
'[testing-env/test_image:1/test_feature-session-2291d8c] shell: "test_feature" teardown session',
|
|
1662
1653
|
"[testing-env/test_image:1] session 'test_feature-session-2291d8c' ended",
|
|
1663
1654
|
'[testing-env/test_image:1] shell: "test_feature" teardown',
|
|
@@ -1685,7 +1676,6 @@ class SandboxServiceTests(unittest.TestCase):
|
|
|
1685
1676
|
'[testing-env/test_image:0/test_feature-session-2291d8c] shell: "test_feature" setup session',
|
|
1686
1677
|
"[testing-env/test_image:0] session 'test_feature-session-2291d8c' started",
|
|
1687
1678
|
'[testing-env/test_image:0/test_feature-session-2291d8c] shell: hello with SandboxStateError',
|
|
1688
|
-
'[testing-env/test_image:0/test_feature-session-2291d8c/test_feature] test_feature.my_service: None with SandboxStateError',
|
|
1689
1679
|
'[testing-env/test_image:0/test_feature-session-2291d8c] shell: "test_feature" teardown session',
|
|
1690
1680
|
"[testing-env/test_image:0] session 'test_feature-session-2291d8c' ended with SandboxStateError",
|
|
1691
1681
|
'[testing-env/test_image:0] shell: "test_feature" teardown',
|