sycommon-python-lib 0.2.7a4__tar.gz → 0.2.7a5__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.
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/PKG-INFO +1 -1
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/pyproject.toml +1 -1
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/deep_agent.py +87 -61
- sycommon_python_lib-0.2.7a5/src/sycommon/agent/middleware/sitecustomize.py +146 -0
- sycommon_python_lib-0.2.7a5/src/sycommon/agent/middleware/skill_api_whitelist.py +253 -0
- sycommon_python_lib-0.2.7a5/src/sycommon/agent/middleware/skill_wl_check.py +123 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/sandbox/http_sandbox_backend.py +77 -17
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/config/Config.py +2 -1
- sycommon_python_lib-0.2.7a5/src/sycommon/config/SkillApiWhitelistConfig.py +82 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/middleware/sandbox.py +31 -5
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon_python_lib.egg-info/PKG-INFO +1 -1
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon_python_lib.egg-info/SOURCES.txt +4 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/README.md +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/setup.cfg +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/cli.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/core/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/core/console.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/core/models.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/core/project.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/core/utils.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/agent/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/agent/main_agent.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/agent/nodes/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/agent/nodes/example_node.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/agent/states/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/agent/states/agent_state.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/api/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/api/query.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/api/sse/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/api/sse/agent.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/client/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/db/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/db/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/db/model/entity.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/db/service.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/model/parse.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/tools/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/agent/tools/mq.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/base/.env.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/base/.gitignore.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/base/Dockerfile.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/base/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/base/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/base/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/base/app.yaml.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/base/client/FileServiceClient.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/base/client/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/base/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/base/model/file_info.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/base/requirements.txt.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/cli/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/cli/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/cli/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/cli/commands/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/cli/commands/hello.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/cli/pyproject.toml.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/cli/tools/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/web/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/web/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/web/api/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/web/api/echo.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/web/api/sse/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/web/api/sse/echo.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/web/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/web/client/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/web/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/web/tools/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/command/templates/web/tools/mq.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/nexus/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/__main__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/acp/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/acp/config.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/acp/executor.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/acp/registry.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/acp/server.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/agents/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/agents/factory.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/agents/prompts.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/cdp/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/cdp/browser.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/cdp/capabilities/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/cdp/capabilities/console.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/cdp/capabilities/dom.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/cdp/capabilities/network.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/cdp/capabilities/page_errors.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/cdp/capabilities/performance.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/cdp/capabilities/screenshot.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/cdp/client.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/cdp/protocol.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/cdp/repl.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/cli.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/commands/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/commands/acp_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/commands/cdp_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/commands/chat_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/commands/create_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/commands/evaluate_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/commands/init_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/commands/memory_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/commands/resume_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/commands/rollback_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/commands/run_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/core/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/core/backend.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/core/config.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/core/display.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/core/git_integration.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/core/llm.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/core/state.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/evaluate/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/evaluate/api_evaluator.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/memory/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/memory/compressor.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/memory/full.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/memory/hot.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/memory/manager.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/memory/warm.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/mode/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/mode/create.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/mode/optimize.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/models/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/models/config_models.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/rl/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/rl/baseline_tests.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/rl/checkpoint.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/rl/convergence.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/rl/diagnosis.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/rl/engine.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/rl/environment.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/rl/experience.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/rl/harness_prompts.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/rl/history.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/rl/optimization_logger.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/rl/pre_validation.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/rl/reward.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/rl/strategy_bandit.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/rl/strategy_generator.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/rl/strategy_prompts.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/simple_chat_agent.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycli/skills/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/acp/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/acp/client.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/acp/fetch.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/acp/ssh_init.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/acp/tool.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/agent_manager.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/chat_events.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/mcp/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/mcp/models.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/mcp/tool_loader.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/multi_agent_team.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/sandbox/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/sandbox/consistent_hash.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/sandbox/file_ops.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/sandbox/minio_sync.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/sandbox/sandbox_pool.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/sandbox/sandbox_recovery.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/sandbox/session.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/summarization_utils.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/auth/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/auth/ldap_service.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/auth/oa_cache.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/auth/oa_crypto.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/auth/oa_service.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/auth/wecom_ldap_service.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/config/ACPAgentConfig.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/config/DatabaseConfig.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/config/ElasticsearchConfig.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/config/EmbeddingConfig.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/config/LLMConfig.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/config/LangfuseConfig.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/config/MQConfig.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/config/PgConfig.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/config/RedisConfig.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/config/RerankerConfig.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/config/SentryConfig.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/config/XxlJobConfig.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/config/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/config/config_change_notifier.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/database/async_base_db_service.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/database/async_database_service.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/database/base_db_service.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/database/database_service.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/database/elasticsearch_service.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/database/pg_checkpoint_service.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/database/redis_service.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/database/resilient_pg_saver.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/database/token_usage_db_service.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/health/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/health/health_check.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/health/metrics.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/health/ping.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/heartbeat_process/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/heartbeat_process/heartbeat_config.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/heartbeat_process/heartbeat_process_manager.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/heartbeat_process/heartbeat_process_worker.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/llm/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/llm/embedding.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/llm/get_llm.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/llm/llm_logger.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/llm/llm_tokens.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/llm/llm_with_token_tracking.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/llm/native_with_fallback_runnable.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/llm/output_fixing_runnable.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/llm/struct_token.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/llm/sy_langfuse.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/llm/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/llm/tiktoken_cache/fb374d419588a4632f3f557e76b4b70aebbca790 +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/llm/token_usage_es_service.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/llm/token_usage_mysql_service.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/llm/token_utils.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/llm/usage_token.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/logging/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/logging/async_sql_logger.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/logging/kafka_log.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/logging/log_masker.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/logging/logger_levels.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/logging/logger_wrapper.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/logging/process_logger.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/logging/sql_logger.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/mcp_server/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/mcp_server/server.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/middleware/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/middleware/context.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/middleware/cors.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/middleware/docs.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/middleware/exception.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/middleware/middleware.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/middleware/monitor_memory.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/middleware/mq.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/middleware/timeout.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/middleware/token_tracking.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/middleware/tool_result_truncation.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/middleware/traceid.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/models/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/models/base_http.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/models/log.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/models/mcp_server_config.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/models/mqlistener_config.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/models/mqmsg_model.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/models/mqsend_config.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/models/sandbox.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/models/sso_user.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/models/token_usage.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/models/token_usage_mysql.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/models/xxljob_handler_config.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/notice/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/notice/uvicorn_monitor.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/notice/wecom_message.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/rabbitmq/process_pool_consumer.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/rabbitmq/rabbitmq_client.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/rabbitmq/rabbitmq_pool.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/rabbitmq/rabbitmq_service.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/rabbitmq/rabbitmq_service_client_manager.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/rabbitmq/rabbitmq_service_connection_monitor.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/rabbitmq/rabbitmq_service_consumer_manager.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/rabbitmq/rabbitmq_service_core.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/rabbitmq/rabbitmq_service_producer_manager.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/sentry/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/sentry/sy_sentry.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/services.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/sse/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/sse/event.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/sse/sse.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/synacos/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/synacos/example.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/synacos/example2.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/synacos/feign.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/synacos/feign_client.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/synacos/nacos_client_base.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/synacos/nacos_config_manager.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/synacos/nacos_heartbeat_manager.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/synacos/nacos_service.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/synacos/nacos_service_discovery.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/synacos/nacos_service_registration.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/synacos/param.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tests/deep_agent_server.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tests/test_consistent_hash.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tests/test_consumer_loss_rootcause.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tests/test_consumer_recovery.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tests/test_deep_agent.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tests/test_dynamic_max_tokens.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tests/test_email.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tests/test_encoding_cache.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tests/test_fix_verification.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tests/test_mcp_server.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tests/test_minimax_reasoning.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tests/test_mq.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tests/test_oa_login.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tests/test_queue_priority_fallback.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tests/test_real_summarization.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tests/test_summarization_config.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tests/test_summarization_real.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tests/test_summary_leak_e2e.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tools/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tools/async_utils.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tools/docs.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tools/env.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tools/merge_headers.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tools/snowflake.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tools/syemail.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/tools/timing.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/xxljob/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/xxljob/xxljob_service.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon_python_lib.egg-info/dependency_links.txt +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon_python_lib.egg-info/entry_points.txt +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon_python_lib.egg-info/requires.txt +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon_python_lib.egg-info/top_level.txt +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/tests/test_acp_tool.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/tests/test_asyncio_logging.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/tests/test_config_change_notifier.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/tests/test_hotreload_snapshot.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/tests/test_log_masker.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/tests/test_resilient_pg_saver.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/tests/test_simple_chat_agent.py +0 -0
- {sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/tests/test_sycli.py +0 -0
{sycommon_python_lib-0.2.7a4 → sycommon_python_lib-0.2.7a5}/src/sycommon/agent/deep_agent.py
RENAMED
|
@@ -50,6 +50,7 @@ from langchain_core.tools import BaseTool, tool
|
|
|
50
50
|
|
|
51
51
|
from sycommon.logging.kafka_log import SYLogger
|
|
52
52
|
from sycommon.tools.snowflake import Snowflake
|
|
53
|
+
from sycommon.tools.env import check_env_flag
|
|
53
54
|
from sycommon.llm.get_llm import get_llm
|
|
54
55
|
from sycommon.agent.sandbox.http_sandbox_backend import HTTPSandboxBackend
|
|
55
56
|
from sycommon.agent.sandbox.sandbox_recovery import SandboxRecoveryManager
|
|
@@ -59,6 +60,11 @@ from sycommon.middleware.tool_result_truncation import ToolResultTruncationMiddl
|
|
|
59
60
|
from deepagents.middleware.summarization import create_summarization_tool_middleware # noqa: F401 保留 re-export
|
|
60
61
|
from sycommon.agent.summarization_utils import build_summarization_middleware
|
|
61
62
|
|
|
63
|
+
# 流式逐 token 诊断日志开关(默认关)。开启后每个 chunk 都打印
|
|
64
|
+
# chunk_type/content 等(仅供排障)。LLM 最终结果已由 LLMLogger.on_llm_end
|
|
65
|
+
# 统一记录,正常无需打开此开关,避免流式日志刷屏。
|
|
66
|
+
_STREAM_DEBUG = check_env_flag(['DEEP_AGENT_STREAM_DEBUG'], default='false')
|
|
67
|
+
|
|
62
68
|
if TYPE_CHECKING:
|
|
63
69
|
from deepagents.graph import CompiledStateGraph
|
|
64
70
|
from langchain.agents.middleware.types import AgentState, ContextT, ModelRequest, ModelResponse, ResponseT
|
|
@@ -465,38 +471,27 @@ class DeepAgent:
|
|
|
465
471
|
input_state = {"messages": [HumanMessage(content=message)]}
|
|
466
472
|
if rubric:
|
|
467
473
|
input_state["rubric"] = rubric
|
|
468
|
-
|
|
469
|
-
|
|
474
|
+
if _STREAM_DEBUG:
|
|
475
|
+
print(
|
|
476
|
+
f"[DeepAgent] chat() starting stream, message={repr(message[:80])}", flush=True)
|
|
470
477
|
async for chunk in self._astream_with_retry(
|
|
471
478
|
input_state,
|
|
472
479
|
max_retries=3,
|
|
473
480
|
base_delay=1.0,
|
|
474
481
|
):
|
|
475
|
-
# 🔑
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
_content = repr(str(getattr(_msg, 'content', ''))[:80])
|
|
489
|
-
_node = _meta.get('langgraph_node', '?') if isinstance(
|
|
490
|
-
_meta, dict) else '?'
|
|
491
|
-
_step = _meta.get('langgraph_step', '?') if isinstance(
|
|
492
|
-
_meta, dict) else '?'
|
|
493
|
-
print(
|
|
494
|
-
f"[DeepAgent] 2tuple: ns={_ns} msg={_msg_type} node={_node} step={_step} content={_content}", flush=True)
|
|
495
|
-
elif isinstance(chunk, tuple) and _chunk_len == 3:
|
|
496
|
-
namespace_p, _tag_p, payload_p = chunk
|
|
497
|
-
if isinstance(payload_p, tuple) and len(payload_p) == 2:
|
|
498
|
-
_msg = payload_p[0]
|
|
499
|
-
_meta = payload_p[1]
|
|
482
|
+
# 🔑 逐 token 诊断日志:仅在 DEEP_AGENT_STREAM_DEBUG=true 时打印
|
|
483
|
+
if _STREAM_DEBUG:
|
|
484
|
+
_chunk_len = len(chunk) if isinstance(chunk, tuple) else '?'
|
|
485
|
+
if isinstance(chunk, tuple) and _chunk_len == 2:
|
|
486
|
+
# 2-tuple: either (namespace, (msg, meta)) or (msg, meta)
|
|
487
|
+
if isinstance(chunk[1], tuple) and len(chunk[1]) == 2:
|
|
488
|
+
_ns = repr(chunk[0])[:30]
|
|
489
|
+
_msg = chunk[1][0]
|
|
490
|
+
_meta = chunk[1][1]
|
|
491
|
+
else:
|
|
492
|
+
_ns = '()'
|
|
493
|
+
_msg = chunk[0]
|
|
494
|
+
_meta = chunk[1]
|
|
500
495
|
_msg_type = type(_msg).__name__
|
|
501
496
|
_content = repr(str(getattr(_msg, 'content', ''))[:80])
|
|
502
497
|
_node = _meta.get('langgraph_node', '?') if isinstance(
|
|
@@ -504,13 +499,26 @@ class DeepAgent:
|
|
|
504
499
|
_step = _meta.get('langgraph_step', '?') if isinstance(
|
|
505
500
|
_meta, dict) else '?'
|
|
506
501
|
print(
|
|
507
|
-
f"[DeepAgent]
|
|
502
|
+
f"[DeepAgent] 2tuple: ns={_ns} msg={_msg_type} node={_node} step={_step} content={_content}", flush=True)
|
|
503
|
+
elif isinstance(chunk, tuple) and _chunk_len == 3:
|
|
504
|
+
namespace_p, _tag_p, payload_p = chunk
|
|
505
|
+
if isinstance(payload_p, tuple) and len(payload_p) == 2:
|
|
506
|
+
_msg = payload_p[0]
|
|
507
|
+
_meta = payload_p[1]
|
|
508
|
+
_msg_type = type(_msg).__name__
|
|
509
|
+
_content = repr(str(getattr(_msg, 'content', ''))[:80])
|
|
510
|
+
_node = _meta.get('langgraph_node', '?') if isinstance(
|
|
511
|
+
_meta, dict) else '?'
|
|
512
|
+
_step = _meta.get('langgraph_step', '?') if isinstance(
|
|
513
|
+
_meta, dict) else '?'
|
|
514
|
+
print(
|
|
515
|
+
f"[DeepAgent] 3tuple: ns={repr(namespace_p)[:30]} msg={_msg_type} node={_node} step={_step} content={_content}", flush=True)
|
|
516
|
+
else:
|
|
517
|
+
print(
|
|
518
|
+
f"[DeepAgent] 3tuple: payload_type={type(payload_p).__name__}", flush=True)
|
|
508
519
|
else:
|
|
509
520
|
print(
|
|
510
|
-
f"[DeepAgent]
|
|
511
|
-
else:
|
|
512
|
-
print(
|
|
513
|
-
f"[DeepAgent] chunk: type={type(chunk).__name__}", flush=True)
|
|
521
|
+
f"[DeepAgent] chunk: type={type(chunk).__name__}", flush=True)
|
|
514
522
|
# 检查取消
|
|
515
523
|
if cancel_event and cancel_event.is_set():
|
|
516
524
|
event = ChatEventBuilder.cancelled("任务已取消")
|
|
@@ -541,22 +549,23 @@ class DeepAgent:
|
|
|
541
549
|
|
|
542
550
|
stream_step += 1
|
|
543
551
|
|
|
544
|
-
# =====
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
552
|
+
# ===== 逐 chunk 诊断日志:默认关闭,DEEP_AGENT_STREAM_DEBUG=true 时开启 =====
|
|
553
|
+
if _STREAM_DEBUG:
|
|
554
|
+
_chunk_type = type(chunk).__name__
|
|
555
|
+
_msg_type = getattr(
|
|
556
|
+
msg, '__class__.__name__', '?') if msg else 'None'
|
|
557
|
+
_ns = namespace if namespace else '()'
|
|
558
|
+
_node = metadata.get(
|
|
559
|
+
"langgraph_node", "?") if metadata else "?"
|
|
560
|
+
_step = metadata.get(
|
|
561
|
+
"langgraph_step", "?") if metadata else "?"
|
|
562
|
+
_content_preview = ""
|
|
563
|
+
if isinstance(msg, BaseMessage):
|
|
564
|
+
_c = msg.content or ""
|
|
565
|
+
_content_preview = repr(_c[:80]) if _c else "(empty)"
|
|
566
|
+
SYLogger.info(
|
|
567
|
+
f"[DeepAgent #{stream_step}] chunk_type={_chunk_type} msg_type={_msg_type} "
|
|
568
|
+
f"ns={_ns} node={_node} step={_step} content={_content_preview}")
|
|
560
569
|
|
|
561
570
|
# ===== 日志(仅关键节点) =====
|
|
562
571
|
if isinstance(msg, BaseMessage):
|
|
@@ -653,12 +662,14 @@ class DeepAgent:
|
|
|
653
662
|
await on_event(event)
|
|
654
663
|
yield event
|
|
655
664
|
|
|
656
|
-
|
|
657
|
-
|
|
665
|
+
if _STREAM_DEBUG:
|
|
666
|
+
print(
|
|
667
|
+
f"[DeepAgent] post-yield: msg_type={type(msg).__name__}, is_BaseMessage={isinstance(msg, BaseMessage)}", flush=True)
|
|
658
668
|
|
|
659
669
|
if not isinstance(msg, BaseMessage):
|
|
660
|
-
|
|
661
|
-
|
|
670
|
+
if _STREAM_DEBUG:
|
|
671
|
+
print(
|
|
672
|
+
f"[DeepAgent] SKIPPING non-BaseMessage: {type(msg).__name__}", flush=True)
|
|
662
673
|
continue
|
|
663
674
|
|
|
664
675
|
msg_type = msg.__class__.__name__
|
|
@@ -899,8 +910,9 @@ class DeepAgent:
|
|
|
899
910
|
SYLogger.debug(
|
|
900
911
|
f"[DeepAgent] AI chunk done | {repr(ai_chunk_buffer[:100])}...")
|
|
901
912
|
|
|
902
|
-
|
|
903
|
-
|
|
913
|
+
if _STREAM_DEBUG:
|
|
914
|
+
print(
|
|
915
|
+
f"[DeepAgent] FOR LOOP ENDED. stream_step={stream_step}, ai_text_content={repr(ai_text_content[:100])}, tool_calls={len(current_tool_calls)}", flush=True)
|
|
904
916
|
|
|
905
917
|
# 空响应检测:模型被调用但没有产出任何文本
|
|
906
918
|
if not ai_text_content and not ai_chunk_buffer:
|
|
@@ -1000,8 +1012,9 @@ class DeepAgent:
|
|
|
1000
1012
|
while True:
|
|
1001
1013
|
for attempt in range(max_retries):
|
|
1002
1014
|
try:
|
|
1003
|
-
|
|
1004
|
-
|
|
1015
|
+
if _STREAM_DEBUG:
|
|
1016
|
+
print(
|
|
1017
|
+
f"[DeepAgent] _astream_with_retry: attempt={attempt}, starting astream...", flush=True)
|
|
1005
1018
|
chunk_count = 0
|
|
1006
1019
|
async for chunk in self.agent.astream(
|
|
1007
1020
|
input_data,
|
|
@@ -1010,13 +1023,16 @@ class DeepAgent:
|
|
|
1010
1023
|
subgraphs=True
|
|
1011
1024
|
):
|
|
1012
1025
|
chunk_count += 1
|
|
1013
|
-
|
|
1014
|
-
|
|
1026
|
+
if _STREAM_DEBUG:
|
|
1027
|
+
print(
|
|
1028
|
+
f"[DeepAgent] _astream yielding chunk #{chunk_count}", flush=True)
|
|
1015
1029
|
yield chunk
|
|
1030
|
+
if _STREAM_DEBUG:
|
|
1031
|
+
print(
|
|
1032
|
+
f"[DeepAgent] _astream yield returned, consumer processed chunk #{chunk_count}", flush=True)
|
|
1033
|
+
if _STREAM_DEBUG:
|
|
1016
1034
|
print(
|
|
1017
|
-
f"[DeepAgent]
|
|
1018
|
-
print(
|
|
1019
|
-
f"[DeepAgent] _astream_with_retry: stream ended normally, total_chunks={chunk_count}", flush=True)
|
|
1035
|
+
f"[DeepAgent] _astream_with_retry: stream ended normally, total_chunks={chunk_count}", flush=True)
|
|
1020
1036
|
return
|
|
1021
1037
|
except BadRequestError as e:
|
|
1022
1038
|
# BadRequestError(含 ContextOverflowError)不重试:
|
|
@@ -1191,6 +1207,16 @@ async def create_deep_agent(
|
|
|
1191
1207
|
on_evaluation=rubric_eval_collector.on_evaluation,
|
|
1192
1208
|
))
|
|
1193
1209
|
|
|
1210
|
+
# SkillApiWhitelistMiddleware:按子技能注入接口白名单(拦 execute 工具,
|
|
1211
|
+
# export SKILL_API_WHITELIST + 推送 sitecustomize 到沙箱做 path 级校验)
|
|
1212
|
+
if sandbox_backend:
|
|
1213
|
+
try:
|
|
1214
|
+
from sycommon.agent.middleware.skill_api_whitelist import (
|
|
1215
|
+
SkillApiWhitelistMiddleware)
|
|
1216
|
+
middleware_list.append(SkillApiWhitelistMiddleware(sandbox_backend))
|
|
1217
|
+
except Exception as _wl_err:
|
|
1218
|
+
SYLogger.warning(f"[DeepAgent] 技能接口白名单中间件加载失败(忽略): {_wl_err}")
|
|
1219
|
+
|
|
1194
1220
|
agent_kwargs = {
|
|
1195
1221
|
"model": raw_model,
|
|
1196
1222
|
"tools": config.tools or [get_current_date],
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"""技能接口白名单客户端注入脚本(部署到沙箱 site-packages)。
|
|
2
|
+
|
|
3
|
+
Python 解释器启动时(未传 -S)自动 import 本模块。它负责 Python HTTP 库的
|
|
4
|
+
请求拦截:
|
|
5
|
+
|
|
6
|
+
1. 读环境变量 SKILL_API_WHITELIST(JSON)。无此 env → 不管控(全放行,fail-open)。
|
|
7
|
+
2. monkeypatch urllib / httpx / requests / aiohttp,发请求前做 path 级前缀匹配,
|
|
8
|
+
未命中抛 PermissionError(LLM 能看到清晰错误)。
|
|
9
|
+
|
|
10
|
+
⚠️ shell 命令(curl/wget 等)的拦截【不】在本文件处理——sitecustomize 只在
|
|
11
|
+
`python` 启动时执行,纯 shell 命令不会触发它。shell 拦截由主进程中间件把
|
|
12
|
+
curl/wget 包装函数【内联】到每条 execute 命令前缀实现(见 skill_api_whitelist.py)。
|
|
13
|
+
|
|
14
|
+
URL 匹配核心逻辑复用同目录 skill_wl_check.py。
|
|
15
|
+
|
|
16
|
+
注意:本模块在沙箱子进程里运行,不依赖主进程内存。白名单数据全部来自环境变量。
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import json
|
|
20
|
+
import os
|
|
21
|
+
import sys
|
|
22
|
+
|
|
23
|
+
# SKILL_API_WHITELIST 存在即「启用管控」;allowlist 为空时「全拦截」。
|
|
24
|
+
_ENABLED = "SKILL_API_WHITELIST" in os.environ
|
|
25
|
+
|
|
26
|
+
# 把沙箱 site-packages 里存放本模块的目录加入 sys.path,以便 import skill_wl_check。
|
|
27
|
+
_HERE = os.path.dirname(os.path.abspath(__file__))
|
|
28
|
+
if _HERE not in sys.path:
|
|
29
|
+
sys.path.insert(0, _HERE)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _load_check():
|
|
33
|
+
"""加载同目录 skill_wl_check,返回其 match 函数;失败返回 None。"""
|
|
34
|
+
try:
|
|
35
|
+
import skill_wl_check # type: ignore
|
|
36
|
+
return skill_wl_check
|
|
37
|
+
except Exception as e: # pragma: no cover
|
|
38
|
+
sys.stderr.write("[sitecustomize] 加载 skill_wl_check 失败,白名单禁用: %s\n" % e)
|
|
39
|
+
return None
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _patch_urllib(match):
|
|
43
|
+
import urllib.request
|
|
44
|
+
|
|
45
|
+
_orig = urllib.request.urlopen
|
|
46
|
+
|
|
47
|
+
def _urlopen(url, *args, **kwargs):
|
|
48
|
+
actual = url.full_url if isinstance(url, urllib.request.Request) else url
|
|
49
|
+
if actual and not match(str(actual)):
|
|
50
|
+
raise PermissionError(
|
|
51
|
+
"[SkillApiWhitelist] 拦截: URL 不在白名单内 (urlopen, %s)" % actual)
|
|
52
|
+
return _orig(url, *args, **kwargs)
|
|
53
|
+
|
|
54
|
+
urllib.request.urlopen = _urlopen
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _patch_httpx(match):
|
|
58
|
+
try:
|
|
59
|
+
import httpx
|
|
60
|
+
except ImportError:
|
|
61
|
+
return
|
|
62
|
+
|
|
63
|
+
_orig_sync = httpx.Client.send
|
|
64
|
+
|
|
65
|
+
def _send(self, request, **kwargs):
|
|
66
|
+
if not match(str(request.url)):
|
|
67
|
+
raise PermissionError(
|
|
68
|
+
"[SkillApiWhitelist] 拦截: URL 不在白名单内 (httpx, %s)" % request.url)
|
|
69
|
+
return _orig_sync(self, request, **kwargs)
|
|
70
|
+
|
|
71
|
+
httpx.Client.send = _send
|
|
72
|
+
|
|
73
|
+
if hasattr(httpx, "AsyncClient"):
|
|
74
|
+
_orig_async = httpx.AsyncClient.send
|
|
75
|
+
|
|
76
|
+
async def _asend(self, request, **kwargs):
|
|
77
|
+
if not match(str(request.url)):
|
|
78
|
+
raise PermissionError(
|
|
79
|
+
"[SkillApiWhitelist] 拦截: URL 不在白名单内 (httpx.async, %s)" % request.url)
|
|
80
|
+
return await _orig_async(self, request, **kwargs)
|
|
81
|
+
|
|
82
|
+
httpx.AsyncClient.send = _asend
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _patch_requests(match):
|
|
86
|
+
try:
|
|
87
|
+
import requests
|
|
88
|
+
except ImportError:
|
|
89
|
+
return
|
|
90
|
+
|
|
91
|
+
_orig = requests.Session.request
|
|
92
|
+
|
|
93
|
+
def _request(self, method, url, *args, **kwargs):
|
|
94
|
+
if not match(str(url)):
|
|
95
|
+
raise PermissionError(
|
|
96
|
+
"[SkillApiWhitelist] 拦截: URL 不在白名单内 (requests %s, %s)"
|
|
97
|
+
% (method.upper(), url))
|
|
98
|
+
return _orig(self, method, url, *args, **kwargs)
|
|
99
|
+
|
|
100
|
+
requests.Session.request = _request
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _patch_aiohttp(match):
|
|
104
|
+
try:
|
|
105
|
+
import aiohttp
|
|
106
|
+
except ImportError:
|
|
107
|
+
return
|
|
108
|
+
if not hasattr(aiohttp.ClientSession, "_request"):
|
|
109
|
+
return
|
|
110
|
+
|
|
111
|
+
_orig = aiohttp.ClientSession._request
|
|
112
|
+
|
|
113
|
+
async def _request(self, method, str_or_url, **kwargs):
|
|
114
|
+
if not match(str(str_or_url)):
|
|
115
|
+
raise PermissionError(
|
|
116
|
+
"[SkillApiWhitelist] 拦截: URL 不在白名单内 (aiohttp %s, %s)"
|
|
117
|
+
% (method, str_or_url))
|
|
118
|
+
return await _orig(self, method, str_or_url, **kwargs)
|
|
119
|
+
|
|
120
|
+
aiohttp.ClientSession._request = _request
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _install():
|
|
124
|
+
if not _ENABLED:
|
|
125
|
+
return
|
|
126
|
+
check = _load_check()
|
|
127
|
+
if check is None:
|
|
128
|
+
return
|
|
129
|
+
# allowlist 为空(明确禁止)时也走校验——match 必然 False,从而全拦截。
|
|
130
|
+
match = check.match
|
|
131
|
+
_patch_urllib(match)
|
|
132
|
+
_patch_httpx(match)
|
|
133
|
+
_patch_requests(match)
|
|
134
|
+
_patch_aiohttp(match)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
# 保留解析结果(供排查)
|
|
138
|
+
try:
|
|
139
|
+
_WHITELIST_RAW = json.loads(os.environ.get("SKILL_API_WHITELIST", "{}"))
|
|
140
|
+
except Exception:
|
|
141
|
+
_WHITELIST_RAW = {}
|
|
142
|
+
|
|
143
|
+
try:
|
|
144
|
+
_install()
|
|
145
|
+
except Exception as _e: # 任何 patch 失败都不能阻断进程启动
|
|
146
|
+
sys.stderr.write("[sitecustomize] 白名单安装失败(fail-open): %s\n" % _e)
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"""技能接口白名单中间件。
|
|
2
|
+
|
|
3
|
+
拦截 `execute` 工具(FilesystemMiddleware 注册的 shell 执行工具),做两件事:
|
|
4
|
+
|
|
5
|
+
1. 从命令路径推断子技能名(skills/<域>/<子技能>/scripts/ → <子技能>),
|
|
6
|
+
查 SkillApiWhitelist 配置得到该子技能的白名单,把占位符 ${VAR} 在主进程
|
|
7
|
+
解析成完整 URL,序列化成 JSON 后以 `export SKILL_API_WHITELIST='<json>'`
|
|
8
|
+
前缀注入命令——供沙箱内 sitecustomize.py 读取并 monkeypatch urllib/
|
|
9
|
+
httpx/requests/aiohttp。
|
|
10
|
+
|
|
11
|
+
2. 命令前缀内联 curl/wget 的 shell 函数包装:纯 shell 命令(不走 Python)
|
|
12
|
+
不会触发 sitecustomize,故用 shell 函数在执行 curl/wget 前调
|
|
13
|
+
`python -m skill_wl_check <url>` 做校验,未命中则 return 1 拦截。
|
|
14
|
+
|
|
15
|
+
3. 首次惰性把 sitecustomize.py + skill_wl_check.py 推进沙箱 site-packages,
|
|
16
|
+
使 Python 启动时自动 import sitecustomize。
|
|
17
|
+
|
|
18
|
+
语义:子技能未配置 / enabled:false → 不注入(全放行,向后兼容);
|
|
19
|
+
allowlist:[] 空数组 → 注入空白名单(全拦截)。
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
import json
|
|
23
|
+
import os
|
|
24
|
+
import re
|
|
25
|
+
import shlex
|
|
26
|
+
from typing import Optional
|
|
27
|
+
|
|
28
|
+
from langchain.agents.middleware.types import AgentMiddleware
|
|
29
|
+
from langgraph.prebuilt.tool_node import ToolCallRequest
|
|
30
|
+
|
|
31
|
+
from sycommon.logging.kafka_log import SYLogger
|
|
32
|
+
|
|
33
|
+
# 命令路径形如 skills/sy-oa-skill/workflow-todo/scripts/x.py
|
|
34
|
+
# skills/sy-syt-skill/shengye-platform-zhongdeng/SKILL.md
|
|
35
|
+
# skills/sy-syt-skill/generate-plan/... (有/无 scripts/ 都识别)
|
|
36
|
+
# 取「skills/<域>/<子技能>/」的第二段作子技能名,不限 scripts/,覆盖文档目录型子技能。
|
|
37
|
+
# 用 (?:/|$) 锚定第二段结尾,避免误吞后续路径段。
|
|
38
|
+
_SKILL_NESTED_RE = re.compile(r'skills/[A-Za-z0-9_\-]+/([A-Za-z0-9_\-]+)(?:/|$)')
|
|
39
|
+
_SKILL_FLAT_RE = re.compile(r'/skills/([A-Za-z0-9_\-]+)(?:/|$)')
|
|
40
|
+
|
|
41
|
+
# BASE_URL 占位符 ${VAR}
|
|
42
|
+
_PLACEHOLDER_RE = re.compile(r'\$\{([A-Z_][A-Z0-9_]*)\}')
|
|
43
|
+
|
|
44
|
+
# 推送到沙箱 workspace 内的 .wl 目录(沙箱强制路径隔离,绝对路径会被映射进 workspace,
|
|
45
|
+
# 故用相对 POSIX 路径,落地为 {workspace}/.wl/,再 export PYTHONPATH 让 Python 自动 import)
|
|
46
|
+
_PUSH_FILES = [
|
|
47
|
+
("sitecustomize.py", ".wl/sitecustomize.py"),
|
|
48
|
+
("skill_wl_check.py", ".wl/skill_wl_check.py"),
|
|
49
|
+
]
|
|
50
|
+
# workspace 内白名单目录的 shell 形式(init_script 已 export $_SANDBOX_WORKSPACE,运行期展开)
|
|
51
|
+
_WL_DIR = "$_SANDBOX_WORKSPACE/.wl"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _resolve_placeholders(pattern: str, env_lookup) -> Optional[str]:
|
|
55
|
+
"""把 ${VAR} 替换为解析后的值。任一 VAR 不存在返回 None(配置错误)。
|
|
56
|
+
|
|
57
|
+
env_lookup: callable(var_name) -> str|None。中间件传入「先查主进程 os.environ,
|
|
58
|
+
再查 sandbox env 字典(含 SYT_BASE_URL 等运行时算出/从 Nacos 读出的值)」的查找器。
|
|
59
|
+
"""
|
|
60
|
+
missing = []
|
|
61
|
+
|
|
62
|
+
def _sub(m):
|
|
63
|
+
val = env_lookup(m.group(1))
|
|
64
|
+
if val is None:
|
|
65
|
+
missing.append(m.group(1))
|
|
66
|
+
return ""
|
|
67
|
+
return str(val).rstrip("/")
|
|
68
|
+
|
|
69
|
+
expanded = _PLACEHOLDER_RE.sub(_sub, pattern)
|
|
70
|
+
if missing:
|
|
71
|
+
SYLogger.warning(
|
|
72
|
+
"[Whitelist] 占位符未定义 %s,丢弃规则 %s", missing, pattern)
|
|
73
|
+
return None
|
|
74
|
+
return expanded
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _load_resource_bytes(filename: str) -> bytes:
|
|
78
|
+
"""从本包读取注入脚本源码(package_data)。"""
|
|
79
|
+
try:
|
|
80
|
+
from importlib.resources import files
|
|
81
|
+
return (files("sycommon.agent.middleware").joinpath(filename).read_bytes())
|
|
82
|
+
except Exception as e:
|
|
83
|
+
raise RuntimeError(
|
|
84
|
+
f"读取注入脚本 {filename} 失败,请确认已随包安装(package_data): {e}") from e
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _build_shell_guard() -> str:
|
|
88
|
+
"""生成内联到命令前缀的 curl/wget 包装函数(shell)。
|
|
89
|
+
|
|
90
|
+
在 SKILL_API_WHITELIST 已 export 的命令里生效:调用 curl/wget 前先抽取
|
|
91
|
+
参数里首个 http(s) URL,用沙箱 python3 调 skill_wl_check.match 校验,
|
|
92
|
+
未命中则 return 1 拦截。skill_wl_check 与 sitecustomize 同处 site-packages,
|
|
93
|
+
python3 启动时 sitecustomize 会 import 它并把该目录加入 sys.path。
|
|
94
|
+
|
|
95
|
+
覆盖 curl / wget;其它 shell 出网方式(nc/裸 /dev/tcp 等)不覆盖。
|
|
96
|
+
"""
|
|
97
|
+
check_cmd = (
|
|
98
|
+
'python3 -c \'import skill_wl_check,sys; '
|
|
99
|
+
'sys.exit(0 if skill_wl_check.match(sys.argv[1]) else 1)\' "$_u"'
|
|
100
|
+
)
|
|
101
|
+
# 单个命令的函数体模板:抽取 URL → 校验 → 通过则 command <CMD> "$@"
|
|
102
|
+
body = (
|
|
103
|
+
'() { local _u; for _a in "$@"; do '
|
|
104
|
+
'case "$_a" in http://*|https://*) _u="$_a";; esac; done; '
|
|
105
|
+
f'if [ -n "$_u" ] && ! {check_cmd}; then '
|
|
106
|
+
'echo "[SkillApiWhitelist] 拦截 shell 请求: $_u" 1>&2; return 1; fi; '
|
|
107
|
+
'command {CMD} "$@"; };'
|
|
108
|
+
)
|
|
109
|
+
guard = "curl" + body.replace("{CMD}", "curl") + " wget" + body.replace("{CMD}", "wget")
|
|
110
|
+
return guard.rstrip(";") # 末尾不带分号:由调用方按需拼接分隔符
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class SkillApiWhitelistMiddleware(AgentMiddleware):
|
|
114
|
+
"""按子技能动态注入接口白名单环境变量 + shell 包装。
|
|
115
|
+
|
|
116
|
+
AgentMiddleware 协议钩子:实现 `awrap_tool_call`(异步版本),在 execute
|
|
117
|
+
工具真正执行前注入白名单。框架对工具调用走 astream/ainvoke 异步链路,故
|
|
118
|
+
只需实现异步钩子(与现有 TokenTrackingMiddleware/ToolResultTruncationMiddleware 一致)。
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
def __init__(self, sandbox_backend):
|
|
122
|
+
self._backend = sandbox_backend
|
|
123
|
+
self._pushed: bool = False # 注入脚本是否已推送(每 backend 实例一次)
|
|
124
|
+
|
|
125
|
+
def _env_lookup(self):
|
|
126
|
+
"""构造占位符查找器:先查主进程 os.environ,再查 sandbox env 字典。
|
|
127
|
+
|
|
128
|
+
SYT_BASE_URL / XINGHAN_BASE_URL / YEALINK_BASE_URL 等不在主进程 os.environ 里,
|
|
129
|
+
而是放在传给 sandbox backend 的 env 字典中(tools/config.py.build_sandbox_env 构造)。
|
|
130
|
+
MultiSandboxRouter/HTTPSandboxBackend 都暴露 `_env`,这里统一兜底取值。
|
|
131
|
+
"""
|
|
132
|
+
sandbox_env = {}
|
|
133
|
+
b = self._backend
|
|
134
|
+
for attr in ("_env",):
|
|
135
|
+
v = getattr(b, attr, None)
|
|
136
|
+
if isinstance(v, dict):
|
|
137
|
+
sandbox_env.update(v)
|
|
138
|
+
else:
|
|
139
|
+
# RoutingBackend 等代理对象:尝试 default/local/remote 子 backend
|
|
140
|
+
pass
|
|
141
|
+
# 再尝试 default backend(MultiSandboxRouter._default._env)
|
|
142
|
+
default = getattr(b, "_default", None)
|
|
143
|
+
if default is not None:
|
|
144
|
+
v = getattr(default, "_env", None)
|
|
145
|
+
if isinstance(v, dict):
|
|
146
|
+
sandbox_env.update(v)
|
|
147
|
+
|
|
148
|
+
def lookup(var):
|
|
149
|
+
val = os.environ.get(var)
|
|
150
|
+
if val is None:
|
|
151
|
+
val = sandbox_env.get(var)
|
|
152
|
+
return val
|
|
153
|
+
|
|
154
|
+
return lookup
|
|
155
|
+
|
|
156
|
+
# ---- 懒加载:把注入脚本推进沙箱 workspace/.wl ----
|
|
157
|
+
async def _ensure_sitecustomize(self) -> bool:
|
|
158
|
+
"""把 sitecustomize.py + skill_wl_check.py 推到沙箱 workspace 内的 .wl 目录。
|
|
159
|
+
|
|
160
|
+
沙箱强制路径隔离:任何绝对路径都会被 resolve_sandbox_path 映射进用户 workspace,
|
|
161
|
+
真实 site-packages 无法写入。故改用「推到 workspace/.wl/ + export PYTHONPATH」
|
|
162
|
+
的方案:Python 启动时若 .wl 在 PYTHONPATH 上,会自动 import sitecustomize。
|
|
163
|
+
|
|
164
|
+
幂等:每个 backend 实例只推一次(_pushed 标记)。失败 fail-open(不阻塞业务)。
|
|
165
|
+
"""
|
|
166
|
+
if self._pushed:
|
|
167
|
+
return True
|
|
168
|
+
backend = self._backend
|
|
169
|
+
if backend is None:
|
|
170
|
+
return False
|
|
171
|
+
try:
|
|
172
|
+
files = []
|
|
173
|
+
for src, dst in _PUSH_FILES:
|
|
174
|
+
content = _load_resource_bytes(src)
|
|
175
|
+
files.append((dst, content))
|
|
176
|
+
await backend.aupload_files(files)
|
|
177
|
+
self._pushed = True
|
|
178
|
+
SYLogger.info("[Whitelist] 注入脚本已推送至沙箱 %s", _WL_DIR)
|
|
179
|
+
return True
|
|
180
|
+
except Exception as e:
|
|
181
|
+
SYLogger.error("[Whitelist] 推送 sitecustomize 失败(fail-open): %s", e)
|
|
182
|
+
return False
|
|
183
|
+
|
|
184
|
+
# ---- 子技能名提取 ----
|
|
185
|
+
def _extract_skill_name(self, command: str) -> Optional[str]:
|
|
186
|
+
m = _SKILL_NESTED_RE.search(command)
|
|
187
|
+
if m:
|
|
188
|
+
return m.group(1)
|
|
189
|
+
m = _SKILL_FLAT_RE.search(command)
|
|
190
|
+
if m:
|
|
191
|
+
return m.group(1)
|
|
192
|
+
return None
|
|
193
|
+
|
|
194
|
+
# ---- 主入口(AgentMiddleware 异步钩子)----
|
|
195
|
+
async def awrap_tool_call(
|
|
196
|
+
self,
|
|
197
|
+
request: ToolCallRequest,
|
|
198
|
+
handler,
|
|
199
|
+
):
|
|
200
|
+
tc = request.tool_call
|
|
201
|
+
if tc.get("name") != "execute":
|
|
202
|
+
return await handler(request)
|
|
203
|
+
|
|
204
|
+
args = tc.get("args", {}) or {}
|
|
205
|
+
command = args.get("command", "") if isinstance(args, dict) else ""
|
|
206
|
+
if not command:
|
|
207
|
+
return await handler(request)
|
|
208
|
+
|
|
209
|
+
skill_name = self._extract_skill_name(command)
|
|
210
|
+
if skill_name is None:
|
|
211
|
+
# 非技能命令(无 skills/.../scripts/)→ 不管控
|
|
212
|
+
return await handler(request)
|
|
213
|
+
|
|
214
|
+
# 延迟导入避免模块加载期循环依赖
|
|
215
|
+
from sycommon.config.SkillApiWhitelistConfig import SkillApiWhitelistConfig
|
|
216
|
+
cfg = SkillApiWhitelistConfig.from_config(skill_name)
|
|
217
|
+
if cfg is None or not cfg.enabled:
|
|
218
|
+
# 未配置 / 禁用 → 全放行(向后兼容)
|
|
219
|
+
return await handler(request)
|
|
220
|
+
|
|
221
|
+
# 主进程解析占位符 ${VAR}(数据源:os.environ + sandbox env 字典)
|
|
222
|
+
env_lookup = self._env_lookup()
|
|
223
|
+
resolved = []
|
|
224
|
+
for pat in cfg.allowlist:
|
|
225
|
+
if "${" in pat:
|
|
226
|
+
expanded = _resolve_placeholders(pat, env_lookup)
|
|
227
|
+
if expanded:
|
|
228
|
+
resolved.append(expanded)
|
|
229
|
+
else:
|
|
230
|
+
resolved.append(pat)
|
|
231
|
+
|
|
232
|
+
# 推送注入脚本(惰性,每后端实例一次)
|
|
233
|
+
await self._ensure_sitecustomize()
|
|
234
|
+
|
|
235
|
+
# 序列化白名单 + PYTHONPATH(shell 启动 python 时自动 import sitecustomize)
|
|
236
|
+
# + shell guard(curl/wget 拦截) + export SKILL_API_WHITELIST
|
|
237
|
+
payload = json.dumps({"skill": skill_name, "allowlist": resolved},
|
|
238
|
+
ensure_ascii=False)
|
|
239
|
+
guard = _build_shell_guard()
|
|
240
|
+
prefix_parts = [
|
|
241
|
+
f"export SKILL_API_WHITELIST={shlex.quote(payload)}",
|
|
242
|
+
f'export PYTHONPATH="{_WL_DIR}:$PYTHONPATH"',
|
|
243
|
+
guard,
|
|
244
|
+
]
|
|
245
|
+
# 每个 part 之间用 '; ' 分隔(而非空格)—— export 语句之间、函数定义与后续命令
|
|
246
|
+
# 之间都需要语句分隔符;末尾留一个 ';' 与原命令隔开。
|
|
247
|
+
prefix = "; ".join(prefix_parts) + "; "
|
|
248
|
+
|
|
249
|
+
new_command = prefix + command
|
|
250
|
+
new_args = {**args, "command": new_command} if isinstance(args, dict) else args
|
|
251
|
+
new_tc = {**tc, "args": new_args}
|
|
252
|
+
SYLogger.info("[Whitelist] 注入子技能 %s 白名单(%d 条)", skill_name, len(resolved))
|
|
253
|
+
return await handler(request.override(tool_call=new_tc))
|