sycommon-python-lib 0.2.7a47__tar.gz → 0.2.7a48__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.7a47 → sycommon_python_lib-0.2.7a48}/PKG-INFO +1 -1
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/pyproject.toml +1 -1
- sycommon_python_lib-0.2.7a48/src/sycommon/agent/middleware/sitecustomize.py +300 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/middleware/skill_api_whitelist.py +111 -47
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/rabbitmq/rabbitmq_client.py +75 -6
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/rabbitmq/rabbitmq_pool.py +4 -3
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/rabbitmq/rabbitmq_service_connection_monitor.py +27 -4
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/rabbitmq/rabbitmq_service_consumer_manager.py +5 -1
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/rabbitmq/rabbitmq_service_core.py +8 -0
- sycommon_python_lib-0.2.7a48/src/sycommon/tests/test_consume_dedup.py +194 -0
- sycommon_python_lib-0.2.7a48/src/sycommon/tests/test_consumer_recovery_fix.py +334 -0
- sycommon_python_lib-0.2.7a48/src/sycommon/tests/test_consumer_tags_sync.py +151 -0
- sycommon_python_lib-0.2.7a48/src/sycommon/tests/test_exp_concurrent_migrate.py +174 -0
- sycommon_python_lib-0.2.7a48/src/sycommon/tests/test_exp_delete_queue_with_consumers.py +145 -0
- sycommon_python_lib-0.2.7a48/src/sycommon/tests/test_fault_injection_real.py +502 -0
- sycommon_python_lib-0.2.7a48/src/sycommon/tests/test_heartbeat_timeout.py +282 -0
- sycommon_python_lib-0.2.7a48/src/sycommon/tests/test_integration_real_broker.py +381 -0
- sycommon_python_lib-0.2.7a48/src/sycommon/tests/test_mq_config_driven.py +238 -0
- sycommon_python_lib-0.2.7a48/src/sycommon/tests/test_queue_priority_upgrade_timing.py +257 -0
- sycommon_python_lib-0.2.7a48/src/sycommon/tests/test_reconnect_scenarios.py +336 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon_python_lib.egg-info/PKG-INFO +1 -1
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon_python_lib.egg-info/SOURCES.txt +11 -0
- sycommon_python_lib-0.2.7a47/src/sycommon/agent/middleware/sitecustomize.py +0 -146
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/README.md +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/setup.cfg +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/cli.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/core/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/core/console.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/core/models.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/core/project.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/core/utils.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/agent/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/agent/main_agent.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/agent/nodes/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/agent/nodes/example_node.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/agent/states/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/agent/states/agent_state.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/api/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/api/query.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/api/sse/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/api/sse/agent.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/client/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/db/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/db/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/db/model/entity.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/db/service.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/model/parse.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/tools/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/agent/tools/mq.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/base/.env.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/base/.gitignore.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/base/Dockerfile.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/base/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/base/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/base/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/base/app.yaml.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/base/client/FileServiceClient.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/base/client/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/base/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/base/model/file_info.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/base/requirements.txt.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/cli/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/cli/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/cli/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/cli/commands/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/cli/commands/hello.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/cli/pyproject.toml.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/cli/tools/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/web/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/web/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/web/api/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/web/api/echo.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/web/api/sse/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/web/api/sse/echo.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/web/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/web/client/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/web/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/web/tools/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/command/templates/web/tools/mq.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/nexus/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/__main__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/acp/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/acp/config.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/acp/executor.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/acp/registry.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/acp/server.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/agents/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/agents/factory.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/agents/prompts.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/cdp/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/cdp/browser.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/cdp/capabilities/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/cdp/capabilities/console.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/cdp/capabilities/dom.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/cdp/capabilities/network.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/cdp/capabilities/page_errors.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/cdp/capabilities/performance.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/cdp/capabilities/screenshot.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/cdp/client.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/cdp/protocol.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/cdp/repl.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/cli.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/commands/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/commands/acp_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/commands/cdp_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/commands/chat_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/commands/create_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/commands/evaluate_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/commands/init_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/commands/memory_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/commands/resume_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/commands/rollback_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/commands/run_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/core/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/core/backend.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/core/config.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/core/display.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/core/git_integration.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/core/llm.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/core/state.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/evaluate/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/evaluate/api_evaluator.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/memory/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/memory/compressor.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/memory/full.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/memory/hot.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/memory/manager.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/memory/warm.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/mode/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/mode/create.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/mode/optimize.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/models/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/models/config_models.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/rl/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/rl/baseline_tests.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/rl/checkpoint.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/rl/convergence.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/rl/diagnosis.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/rl/engine.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/rl/environment.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/rl/experience.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/rl/harness_prompts.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/rl/history.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/rl/optimization_logger.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/rl/pre_validation.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/rl/reward.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/rl/strategy_bandit.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/rl/strategy_generator.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/rl/strategy_prompts.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/simple_chat_agent.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycli/skills/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/acp/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/acp/client.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/acp/fetch.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/acp/ssh_init.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/acp/tool.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/agent_manager.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/chat_events.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/deep_agent.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/mcp/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/mcp/models.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/mcp/tool_loader.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/middleware/sandbox_path_guard.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/middleware/sensitive_guard.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/middleware/skill_wl_check.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/middleware/skill_write_guard.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/multi_agent_team.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/reasoning_content_patch.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/resume_compactor.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/sandbox/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/sandbox/consistent_hash.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/sandbox/file_ops.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/sandbox/http_sandbox_backend.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/sandbox/minio_sync.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/sandbox/sandbox_pool.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/sandbox/sandbox_recovery.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/sandbox/session.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/agent/summarization_utils.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/auth/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/auth/ldap_service.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/auth/oa_cache.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/auth/oa_crypto.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/auth/oa_service.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/auth/wecom_ldap_service.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/config/ACPAgentConfig.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/config/Config.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/config/DatabaseConfig.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/config/ElasticsearchConfig.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/config/EmbeddingConfig.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/config/LLMConfig.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/config/LangfuseConfig.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/config/MQConfig.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/config/PgConfig.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/config/RedisConfig.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/config/RerankerConfig.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/config/SentryConfig.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/config/SkillApiWhitelistConfig.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/config/XxlJobConfig.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/config/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/config/config_change_notifier.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/database/async_base_db_service.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/database/async_database_service.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/database/base_db_service.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/database/database_service.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/database/elasticsearch_service.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/database/pg_checkpoint_service.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/database/redis_service.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/database/resilient_pg_saver.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/database/token_usage_db_service.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/health/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/health/health_check.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/health/metrics.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/health/ping.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/heartbeat_process/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/heartbeat_process/heartbeat_config.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/heartbeat_process/heartbeat_process_manager.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/heartbeat_process/heartbeat_process_worker.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/llm/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/llm/embedding.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/llm/get_llm.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/llm/llm_logger.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/llm/llm_tokens.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/llm/llm_with_token_tracking.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/llm/native_with_fallback_runnable.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/llm/output_fixing_runnable.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/llm/struct_token.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/llm/sy_langfuse.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/llm/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/llm/tiktoken_cache/fb374d419588a4632f3f557e76b4b70aebbca790 +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/llm/token_usage_es_service.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/llm/token_usage_mysql_service.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/llm/token_utils.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/llm/usage_token.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/logging/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/logging/async_sql_logger.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/logging/kafka_log.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/logging/log_masker.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/logging/logger_levels.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/logging/logger_wrapper.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/logging/process_logger.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/logging/sql_logger.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/mcp_server/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/mcp_server/server.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/middleware/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/middleware/context.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/middleware/cors.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/middleware/docs.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/middleware/exception.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/middleware/middleware.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/middleware/monitor_memory.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/middleware/mq.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/middleware/sandbox.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/middleware/timeout.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/middleware/token_tracking.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/middleware/tool_result_truncation.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/middleware/traceid.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/models/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/models/base_http.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/models/log.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/models/mcp_server_config.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/models/mqlistener_config.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/models/mqmsg_model.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/models/mqsend_config.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/models/sandbox.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/models/sso_user.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/models/token_usage.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/models/token_usage_mysql.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/models/xxljob_handler_config.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/notice/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/notice/uvicorn_monitor.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/notice/wecom_message.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/rabbitmq/process_pool_consumer.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/rabbitmq/rabbitmq_service.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/rabbitmq/rabbitmq_service_client_manager.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/rabbitmq/rabbitmq_service_producer_manager.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/sentry/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/sentry/sy_sentry.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/services.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/sse/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/sse/event.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/sse/sse.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/synacos/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/synacos/example.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/synacos/example2.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/synacos/feign.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/synacos/feign_client.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/synacos/nacos_client_base.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/synacos/nacos_config_manager.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/synacos/nacos_heartbeat_manager.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/synacos/nacos_service.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/synacos/nacos_service_discovery.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/synacos/nacos_service_registration.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/synacos/param.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/deep_agent_server.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_consistent_hash.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_consumer_loss_rootcause.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_consumer_recovery.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_deep_agent.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_dynamic_max_tokens.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_email.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_encoding_cache.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_fix_verification.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_mcp_server.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_minimax_reasoning.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_mq.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_oa_login.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_queue_priority_fallback.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_real_summarization.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_summarization_config.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_summarization_real.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_summary_leak_e2e.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_upgrade_aio_pika.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_upgrade_langgraph_stream.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tests/test_upgrade_verification.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tools/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tools/async_utils.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tools/docs.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tools/env.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tools/merge_headers.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tools/snowflake.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tools/syemail.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/tools/timing.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/xxljob/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/xxljob/xxljob_service.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon_python_lib.egg-info/dependency_links.txt +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon_python_lib.egg-info/entry_points.txt +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon_python_lib.egg-info/requires.txt +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon_python_lib.egg-info/top_level.txt +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/tests/test_acp_tool.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/tests/test_asyncio_logging.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/tests/test_config_change_notifier.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/tests/test_hotreload_snapshot.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/tests/test_llm_apikey_contextvar.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/tests/test_log_masker.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/tests/test_resilient_pg_saver.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/tests/test_sandbox_path_guard.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/tests/test_sensitive_guard.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/tests/test_simple_chat_agent.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/tests/test_skill_regex_upgrade.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/tests/test_skill_write_guard.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/tests/test_sycli.py +0 -0
- {sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/tests/test_sync_skills_to_sandbox.py +0 -0
|
@@ -0,0 +1,300 @@
|
|
|
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
|
+
另外提供【独立于白名单】的 header 注入:当环境变量 SYT_API_AUTHZ 非空时,
|
|
17
|
+
对 host 命中 SYT_BASE_URL 的请求自动补 X-Sy-Api-Authz 头。这是云平台网关的
|
|
18
|
+
鉴权要求,对所有沙箱技能请求生效(不门控白名单),由中间件无条件 export
|
|
19
|
+
SYT_API_AUTHZ + 推送本 sitecustomize 触发。
|
|
20
|
+
|
|
21
|
+
注意:本模块在沙箱子进程里运行,不依赖主进程内存。配置全部来自环境变量。
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import json
|
|
25
|
+
import os
|
|
26
|
+
import sys
|
|
27
|
+
from urllib.parse import urlparse
|
|
28
|
+
|
|
29
|
+
# SKILL_API_WHITELIST 存在即「启用管控」;allowlist 为空时「全拦截」。
|
|
30
|
+
_ENABLED = "SKILL_API_WHITELIST" in os.environ
|
|
31
|
+
|
|
32
|
+
# 把沙箱 site-packages 里存放本模块的目录加入 sys.path,以便 import skill_wl_check。
|
|
33
|
+
_HERE = os.path.dirname(os.path.abspath(__file__))
|
|
34
|
+
if _HERE not in sys.path:
|
|
35
|
+
sys.path.insert(0, _HERE)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _load_check():
|
|
39
|
+
"""加载同目录 skill_wl_check,返回其 match 函数;失败返回 None。"""
|
|
40
|
+
try:
|
|
41
|
+
import skill_wl_check # type: ignore
|
|
42
|
+
return skill_wl_check
|
|
43
|
+
except Exception as e: # pragma: no cover
|
|
44
|
+
sys.stderr.write("[sitecustomize] 加载 skill_wl_check 失败,白名单禁用: %s\n" % e)
|
|
45
|
+
return None
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _patch_urllib(match):
|
|
49
|
+
import urllib.request
|
|
50
|
+
|
|
51
|
+
_orig = urllib.request.urlopen
|
|
52
|
+
|
|
53
|
+
def _urlopen(url, *args, **kwargs):
|
|
54
|
+
actual = url.full_url if isinstance(url, urllib.request.Request) else url
|
|
55
|
+
if actual and not match(str(actual)):
|
|
56
|
+
raise PermissionError(
|
|
57
|
+
"[SkillApiWhitelist] 拦截: URL 不在白名单内 (urlopen, %s)" % actual)
|
|
58
|
+
return _orig(url, *args, **kwargs)
|
|
59
|
+
|
|
60
|
+
urllib.request.urlopen = _urlopen
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _patch_httpx(match):
|
|
64
|
+
try:
|
|
65
|
+
import httpx
|
|
66
|
+
except ImportError:
|
|
67
|
+
return
|
|
68
|
+
|
|
69
|
+
_orig_sync = httpx.Client.send
|
|
70
|
+
|
|
71
|
+
def _send(self, request, **kwargs):
|
|
72
|
+
if not match(str(request.url)):
|
|
73
|
+
raise PermissionError(
|
|
74
|
+
"[SkillApiWhitelist] 拦截: URL 不在白名单内 (httpx, %s)" % request.url)
|
|
75
|
+
return _orig_sync(self, request, **kwargs)
|
|
76
|
+
|
|
77
|
+
httpx.Client.send = _send
|
|
78
|
+
|
|
79
|
+
if hasattr(httpx, "AsyncClient"):
|
|
80
|
+
_orig_async = httpx.AsyncClient.send
|
|
81
|
+
|
|
82
|
+
async def _asend(self, request, **kwargs):
|
|
83
|
+
if not match(str(request.url)):
|
|
84
|
+
raise PermissionError(
|
|
85
|
+
"[SkillApiWhitelist] 拦截: URL 不在白名单内 (httpx.async, %s)" % request.url)
|
|
86
|
+
return await _orig_async(self, request, **kwargs)
|
|
87
|
+
|
|
88
|
+
httpx.AsyncClient.send = _asend
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _patch_requests(match):
|
|
92
|
+
try:
|
|
93
|
+
import requests
|
|
94
|
+
except ImportError:
|
|
95
|
+
return
|
|
96
|
+
|
|
97
|
+
_orig = requests.Session.request
|
|
98
|
+
|
|
99
|
+
def _request(self, method, url, *args, **kwargs):
|
|
100
|
+
if not match(str(url)):
|
|
101
|
+
raise PermissionError(
|
|
102
|
+
"[SkillApiWhitelist] 拦截: URL 不在白名单内 (requests %s, %s)"
|
|
103
|
+
% (method.upper(), url))
|
|
104
|
+
return _orig(self, method, url, *args, **kwargs)
|
|
105
|
+
|
|
106
|
+
requests.Session.request = _request
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _patch_aiohttp(match):
|
|
110
|
+
try:
|
|
111
|
+
import aiohttp
|
|
112
|
+
except ImportError:
|
|
113
|
+
return
|
|
114
|
+
if not hasattr(aiohttp.ClientSession, "_request"):
|
|
115
|
+
return
|
|
116
|
+
|
|
117
|
+
_orig = aiohttp.ClientSession._request
|
|
118
|
+
|
|
119
|
+
async def _request(self, method, str_or_url, **kwargs):
|
|
120
|
+
if not match(str(str_or_url)):
|
|
121
|
+
raise PermissionError(
|
|
122
|
+
"[SkillApiWhitelist] 拦截: URL 不在白名单内 (aiohttp %s, %s)"
|
|
123
|
+
% (method, str_or_url))
|
|
124
|
+
return await _orig(self, method, str_or_url, **kwargs)
|
|
125
|
+
|
|
126
|
+
aiohttp.ClientSession._request = _request
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
# =============== header 注入(独立于白名单)===============
|
|
130
|
+
# 云平台网关要求请求带 X-Sy-Api-Authz 头。仅当 host 命中 SYT_BASE_URL 的 host
|
|
131
|
+
# 才补该头,其它域名(内网 OCR / 企微 / 合同比对内网 / MCP 后端等)不注入。
|
|
132
|
+
# 门控:环境变量 SYT_API_AUTHZ 非空。调用方已显式设过同名头则不覆盖。
|
|
133
|
+
|
|
134
|
+
_AUTHZ_HEADER = "X-Sy-Api-Authz"
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def _syt_host():
|
|
138
|
+
"""解析 SYT_BASE_URL 的 host(小写)。失败返回 None。"""
|
|
139
|
+
base = os.environ.get("SYT_BASE_URL", "").strip()
|
|
140
|
+
if not base:
|
|
141
|
+
return None
|
|
142
|
+
try:
|
|
143
|
+
return (urlparse(base).hostname or "").lower() or None
|
|
144
|
+
except Exception:
|
|
145
|
+
return None
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _host_matches_syt(url) -> bool:
|
|
149
|
+
"""请求 URL 的 host 是否等于 SYT_BASE_URL 的 host。"""
|
|
150
|
+
host = _syt_host()
|
|
151
|
+
if not host:
|
|
152
|
+
return False
|
|
153
|
+
try:
|
|
154
|
+
return (urlparse(str(url)).hostname or "").lower() == host
|
|
155
|
+
except Exception:
|
|
156
|
+
return False
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def _patch_urllib_hdr():
|
|
160
|
+
import urllib.request
|
|
161
|
+
|
|
162
|
+
_orig = urllib.request.urlopen
|
|
163
|
+
|
|
164
|
+
def _urlopen(url, *args, **kwargs):
|
|
165
|
+
# 只能给 Request 对象补头;裸 str URL 在 urlopen 层无 headers 概念,跳过
|
|
166
|
+
if isinstance(url, urllib.request.Request) and _host_matches_syt(url.full_url):
|
|
167
|
+
url.add_header(_AUTHZ_HEADER, os.environ["SYT_API_AUTHZ"])
|
|
168
|
+
return _orig(url, *args, **kwargs)
|
|
169
|
+
|
|
170
|
+
urllib.request.urlopen = _urlopen
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def _patch_requests_hdr():
|
|
174
|
+
try:
|
|
175
|
+
import requests
|
|
176
|
+
except ImportError:
|
|
177
|
+
return
|
|
178
|
+
|
|
179
|
+
_orig = requests.Session.request
|
|
180
|
+
|
|
181
|
+
def _request(self, method, url, *args, **kwargs):
|
|
182
|
+
if _host_matches_syt(url):
|
|
183
|
+
headers = kwargs.get("headers")
|
|
184
|
+
if headers is None:
|
|
185
|
+
headers = {}
|
|
186
|
+
if isinstance(headers, dict):
|
|
187
|
+
if _AUTHZ_HEADER not in headers:
|
|
188
|
+
headers[_AUTHZ_HEADER] = os.environ["SYT_API_AUTHZ"]
|
|
189
|
+
kwargs["headers"] = headers
|
|
190
|
+
else:
|
|
191
|
+
# list / 其它形态:保守起见交给底层,避免破坏既有结构
|
|
192
|
+
pass
|
|
193
|
+
return _orig(self, method, url, *args, **kwargs)
|
|
194
|
+
|
|
195
|
+
requests.Session.request = _request
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def _patch_httpx_hdr():
|
|
199
|
+
try:
|
|
200
|
+
import httpx
|
|
201
|
+
except ImportError:
|
|
202
|
+
return
|
|
203
|
+
|
|
204
|
+
def _apply(request):
|
|
205
|
+
if request is not None and _host_matches_syt(request.url):
|
|
206
|
+
request.headers.setdefault(_AUTHZ_HEADER, os.environ["SYT_API_AUTHZ"])
|
|
207
|
+
|
|
208
|
+
_orig_sync = httpx.Client.send
|
|
209
|
+
|
|
210
|
+
def _send(self, request, **kwargs):
|
|
211
|
+
_apply(request)
|
|
212
|
+
return _orig_sync(self, request, **kwargs)
|
|
213
|
+
|
|
214
|
+
httpx.Client.send = _send
|
|
215
|
+
|
|
216
|
+
if hasattr(httpx, "AsyncClient"):
|
|
217
|
+
_orig_async = httpx.AsyncClient.send
|
|
218
|
+
|
|
219
|
+
async def _asend(self, request, **kwargs):
|
|
220
|
+
_apply(request)
|
|
221
|
+
return await _orig_async(self, request, **kwargs)
|
|
222
|
+
|
|
223
|
+
httpx.AsyncClient.send = _asend
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def _patch_aiohttp_hdr():
|
|
227
|
+
try:
|
|
228
|
+
import aiohttp
|
|
229
|
+
except ImportError:
|
|
230
|
+
return
|
|
231
|
+
if not hasattr(aiohttp.ClientSession, "_request"):
|
|
232
|
+
return
|
|
233
|
+
|
|
234
|
+
_orig = aiohttp.ClientSession._request
|
|
235
|
+
|
|
236
|
+
async def _request(self, method, str_or_url, **kwargs):
|
|
237
|
+
if _host_matches_syt(str_or_url):
|
|
238
|
+
headers = kwargs.get("headers")
|
|
239
|
+
if isinstance(headers, dict):
|
|
240
|
+
if _AUTHZ_HEADER not in headers:
|
|
241
|
+
headers[_AUTHZ_HEADER] = os.environ["SYT_API_AUTHZ"]
|
|
242
|
+
elif headers is None:
|
|
243
|
+
kwargs["headers"] = {_AUTHZ_HEADER: os.environ["SYT_API_AUTHZ"]}
|
|
244
|
+
else:
|
|
245
|
+
# list / CIMultiDict 等其它形态:跳过,避免破坏结构
|
|
246
|
+
pass
|
|
247
|
+
return await _orig(self, method, str_or_url, **kwargs)
|
|
248
|
+
|
|
249
|
+
aiohttp.ClientSession._request = _request
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def _install_header_injection():
|
|
253
|
+
"""装 header 注入 patch(独立于白名单)。
|
|
254
|
+
|
|
255
|
+
门控:环境变量 SYT_API_AUTHZ 非空。任一库 import 失败都不阻断。
|
|
256
|
+
"""
|
|
257
|
+
val = os.environ.get("SYT_API_AUTHZ", "").strip()
|
|
258
|
+
if not val:
|
|
259
|
+
return
|
|
260
|
+
if not _syt_host():
|
|
261
|
+
sys.stderr.write(
|
|
262
|
+
"[sitecustomize] SYT_API_AUTHZ 已设置但 SYT_BASE_URL 无法解析 host,"
|
|
263
|
+
"跳过 header 注入\n")
|
|
264
|
+
return
|
|
265
|
+
_patch_urllib_hdr()
|
|
266
|
+
_patch_requests_hdr()
|
|
267
|
+
_patch_httpx_hdr()
|
|
268
|
+
_patch_aiohttp_hdr()
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def _install():
|
|
272
|
+
if not _ENABLED:
|
|
273
|
+
return
|
|
274
|
+
check = _load_check()
|
|
275
|
+
if check is None:
|
|
276
|
+
return
|
|
277
|
+
# allowlist 为空(明确禁止)时也走校验——match 必然 False,从而全拦截。
|
|
278
|
+
match = check.match
|
|
279
|
+
_patch_urllib(match)
|
|
280
|
+
_patch_httpx(match)
|
|
281
|
+
_patch_requests(match)
|
|
282
|
+
_patch_aiohttp(match)
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
# 保留解析结果(供排查)
|
|
286
|
+
try:
|
|
287
|
+
_WHITELIST_RAW = json.loads(os.environ.get("SKILL_API_WHITELIST", "{}"))
|
|
288
|
+
except Exception:
|
|
289
|
+
_WHITELIST_RAW = {}
|
|
290
|
+
|
|
291
|
+
try:
|
|
292
|
+
_install()
|
|
293
|
+
except Exception as _e: # 任何 patch 失败都不能阻断进程启动
|
|
294
|
+
sys.stderr.write("[sitecustomize] 白名单安装失败(fail-open): %s\n" % _e)
|
|
295
|
+
|
|
296
|
+
# header 注入独立于白名单,单独 try/except,互不影响
|
|
297
|
+
try:
|
|
298
|
+
_install_header_injection()
|
|
299
|
+
except Exception as _e:
|
|
300
|
+
sys.stderr.write("[sitecustomize] header 注入安装失败(fail-open): %s\n" % _e)
|
|
@@ -26,6 +26,7 @@ import os
|
|
|
26
26
|
import re
|
|
27
27
|
import shlex
|
|
28
28
|
from typing import Optional
|
|
29
|
+
from urllib.parse import urlparse
|
|
29
30
|
|
|
30
31
|
from langchain.agents.middleware.types import AgentMiddleware
|
|
31
32
|
from langchain_core.messages import ToolMessage
|
|
@@ -35,12 +36,17 @@ from sycommon.logging.kafka_log import SYLogger
|
|
|
35
36
|
|
|
36
37
|
# 命令路径形如 skills/system/sy-oa-skill/workflow-todo/scripts/x.py
|
|
37
38
|
# skills/user/sy-oa-skill/SKILL.md
|
|
38
|
-
#
|
|
39
|
-
#
|
|
40
|
-
#
|
|
39
|
+
# _SKILL_TOP_RE:白名单配置提取用——限定 system|user|shengye-platform 三层后取第二段
|
|
40
|
+
# 作域级技能名(如 sy-oa-skill / oa),配合 SkillApiWhitelist 按顶级域配置。
|
|
41
|
+
# (?<![\w]) 否定左查找:要求 skills 前不是单词字符,避免误匹配 myskills/。
|
|
41
42
|
_SKILL_TOP_RE = re.compile(
|
|
42
43
|
r'(?<![\w])skills/(?:system|user|shengye-platform)/([A-Za-z0-9_\-]+)(?:/|$)')
|
|
43
44
|
|
|
45
|
+
# _SKILL_ANY_RE:技能命令判定用(宽松)——匹配任意 skills/<...>/ 前缀。
|
|
46
|
+
# 用于 header 注入等对所有技能命令(含用户自行拷贝到非 system 目录的技能)生效的能力,
|
|
47
|
+
# 与白名单配置是否启用解耦。同样 (?<![\w]) 避免误匹配 myskills/。
|
|
48
|
+
_SKILL_ANY_RE = re.compile(r'(?<![\w])skills/[A-Za-z0-9_\-]+(?:/|$)')
|
|
49
|
+
|
|
44
50
|
# BASE_URL 占位符 ${VAR}
|
|
45
51
|
_PLACEHOLDER_RE = re.compile(r'\$\{([A-Z_][A-Z0-9_]*)\}')
|
|
46
52
|
|
|
@@ -167,26 +173,51 @@ def _load_resource_bytes(filename: str) -> bytes:
|
|
|
167
173
|
f"读取注入脚本 {filename} 失败,请确认已随包安装(package_data): {e}") from e
|
|
168
174
|
|
|
169
175
|
|
|
170
|
-
def _build_shell_guard(
|
|
176
|
+
def _build_shell_guard(with_whitelist: bool = False,
|
|
177
|
+
with_header: bool = False) -> str:
|
|
171
178
|
"""生成内联到命令前缀的 curl/wget 包装函数(shell)。
|
|
172
179
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
180
|
+
抽取参数里【最后一个】 http(s) URL 到 _u,按需承担两类职责(可同时启用,
|
|
181
|
+
先白名单校验、再注入 header):
|
|
182
|
+
- with_whitelist:用沙箱 python3 调 skill_wl_check.match 校验 _u,未命中 return 1。
|
|
183
|
+
- with_header:_u 的 host 命中 $__SYT_HOST__ 时追加 -H "X-Sy-Api-Authz:
|
|
184
|
+
$SYT_API_AUTHZ"(原参数已含同名头则不重复加)。
|
|
177
185
|
|
|
178
|
-
|
|
186
|
+
skill_wl_check 与 sitecustomize 同处 site-packages,python3 启动时 sitecustomize
|
|
187
|
+
会 import 它并把该目录加入 sys.path。覆盖 curl / wget;其它 shell 出网方式
|
|
188
|
+
(nc/裸 /dev/tcp 等)不覆盖。
|
|
179
189
|
"""
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
190
|
+
wl_block = ""
|
|
191
|
+
if with_whitelist:
|
|
192
|
+
check_cmd = (
|
|
193
|
+
'python3 -c \'import skill_wl_check,sys; '
|
|
194
|
+
'sys.exit(0 if skill_wl_check.match(sys.argv[1]) else 1)\' "$_u"'
|
|
195
|
+
)
|
|
196
|
+
wl_block = (
|
|
197
|
+
f'if [ -n "$_u" ] && ! {check_cmd}; then '
|
|
198
|
+
'echo "[SkillApiWhitelist] 拦截 shell 请求: $_u" 1>&2; return 1; fi; '
|
|
199
|
+
)
|
|
200
|
+
hdr_block = ""
|
|
201
|
+
if with_header:
|
|
202
|
+
# 从 _u 取 host(小写):剥 scheme/path/query/fragment/userinfo/port
|
|
203
|
+
hdr_block = (
|
|
204
|
+
'if [ -n "$_u" ] && [ -n "$__SYT_HOST__" ] && [ -n "$SYT_API_AUTHZ" ]; then '
|
|
205
|
+
'_h="${_u#*://}"; _h="${_h%%/*}"; _h="${_h%%\\?*}"; _h="${_h%%#*}"; '
|
|
206
|
+
'_h="${_h##*@}"; _h="${_h%%:*}"; '
|
|
207
|
+
'case "$(printf "%s" "$_h" | tr "A-Z" "a-z")" in '
|
|
208
|
+
'"$__SYT_HOST__") '
|
|
209
|
+
'case " $* " in *"X-Sy-Api-Authz"*) :;; *) '
|
|
210
|
+
'set -- "$@" -H "X-Sy-Api-Authz: $SYT_API_AUTHZ";; '
|
|
211
|
+
'esac;; '
|
|
212
|
+
'esac; '
|
|
213
|
+
'fi; '
|
|
214
|
+
)
|
|
215
|
+
if not wl_block and not hdr_block:
|
|
216
|
+
return ""
|
|
185
217
|
body = (
|
|
186
|
-
'() { local _u; for _a in "$@"; do '
|
|
218
|
+
'() { local _u _a _h; for _a in "$@"; do '
|
|
187
219
|
'case "$_a" in http://*|https://*) _u="$_a";; esac; done; '
|
|
188
|
-
|
|
189
|
-
'echo "[SkillApiWhitelist] 拦截 shell 请求: $_u" 1>&2; return 1; fi; '
|
|
220
|
+
+ wl_block + hdr_block +
|
|
190
221
|
'command {CMD} "$@"; };'
|
|
191
222
|
)
|
|
192
223
|
guard = "curl" + body.replace("{CMD}", "curl") + " wget" + body.replace("{CMD}", "wget")
|
|
@@ -329,42 +360,69 @@ class SkillApiWhitelistMiddleware(AgentMiddleware):
|
|
|
329
360
|
if not command:
|
|
330
361
|
return await handler(request)
|
|
331
362
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
363
|
+
# 技能命令判定(宽松):任意 skills/.../ 前缀即算(含用户拷贝到非 system
|
|
364
|
+
# 目录的技能)。header 注入等对所有技能命令生效的能力以此为门控。
|
|
365
|
+
if not _SKILL_ANY_RE.search(command):
|
|
366
|
+
# 非技能命令 → 不注入任何前缀
|
|
335
367
|
return await handler(request)
|
|
336
368
|
|
|
337
|
-
#
|
|
369
|
+
# 白名单配置提取(限定三层后取第二段)
|
|
370
|
+
skill_name = self._extract_skill_name(command)
|
|
338
371
|
from sycommon.config.SkillApiWhitelistConfig import SkillApiWhitelistConfig
|
|
339
|
-
cfg = SkillApiWhitelistConfig.from_config(skill_name)
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
return await handler(request)
|
|
372
|
+
cfg = (SkillApiWhitelistConfig.from_config(skill_name)
|
|
373
|
+
if skill_name is not None else None)
|
|
374
|
+
whitelist_on = bool(cfg and cfg.enabled)
|
|
343
375
|
|
|
344
376
|
# 主进程解析占位符 ${VAR}(数据源:os.environ + sandbox env 字典)
|
|
345
377
|
env_lookup = self._env_lookup()
|
|
346
378
|
resolved = []
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
379
|
+
if whitelist_on:
|
|
380
|
+
for pat in cfg.allowlist:
|
|
381
|
+
if "${" in pat:
|
|
382
|
+
expanded = _resolve_placeholders(pat, env_lookup)
|
|
383
|
+
if expanded:
|
|
384
|
+
resolved.append(expanded)
|
|
385
|
+
else:
|
|
386
|
+
resolved.append(pat)
|
|
387
|
+
|
|
388
|
+
# header 注入所需:SYT_API_AUTHZ(缺则不注入)+ SYT_BASE_URL 的 host
|
|
389
|
+
syt_authz = env_lookup("SYT_API_AUTHZ")
|
|
390
|
+
header_on = bool(syt_authz and syt_authz.strip())
|
|
391
|
+
syt_host = ""
|
|
392
|
+
if header_on:
|
|
393
|
+
syt_base = env_lookup("SYT_BASE_URL") or ""
|
|
394
|
+
try:
|
|
395
|
+
syt_host = (urlparse(syt_base).hostname or "").lower()
|
|
396
|
+
except Exception:
|
|
397
|
+
syt_host = ""
|
|
398
|
+
header_on = bool(syt_host)
|
|
399
|
+
|
|
400
|
+
# 推送注入脚本(惰性,每后端实例一次)。
|
|
401
|
+
# 只要【白名单 或 header 注入】任一启用就要推 .wl(sitecustomize)。
|
|
402
|
+
if whitelist_on or header_on:
|
|
403
|
+
await self._ensure_sitecustomize()
|
|
404
|
+
|
|
405
|
+
# 组装命令前缀
|
|
406
|
+
prefix_parts: list[str] = []
|
|
407
|
+
if whitelist_on:
|
|
408
|
+
payload = json.dumps({"skill": skill_name, "allowlist": resolved},
|
|
409
|
+
ensure_ascii=False)
|
|
410
|
+
prefix_parts.append(f"export SKILL_API_WHITELIST={shlex.quote(payload)}")
|
|
411
|
+
if header_on:
|
|
412
|
+
prefix_parts.append(
|
|
413
|
+
f"export SYT_API_AUTHZ={shlex.quote(syt_authz)}")
|
|
414
|
+
prefix_parts.append(f'export __SYT_HOST__={shlex.quote(syt_host)}')
|
|
415
|
+
if whitelist_on or header_on:
|
|
416
|
+
# PYTHONPATH(shell 启动 python 时自动 import sitecustomize)
|
|
417
|
+
prefix_parts.append(f'export PYTHONPATH="{_WL_DIR}:$PYTHONPATH"')
|
|
418
|
+
guard = _build_shell_guard(with_whitelist=whitelist_on,
|
|
419
|
+
with_header=header_on)
|
|
420
|
+
if guard:
|
|
421
|
+
prefix_parts.append(guard)
|
|
422
|
+
|
|
423
|
+
if not prefix_parts:
|
|
424
|
+
return await handler(request)
|
|
425
|
+
|
|
368
426
|
# 每个 part 之间用 '; ' 分隔(而非空格)—— export 语句之间、函数定义与后续命令
|
|
369
427
|
# 之间都需要语句分隔符;末尾留一个 ';' 与原命令隔开。
|
|
370
428
|
prefix = "; ".join(prefix_parts) + "; "
|
|
@@ -372,5 +430,11 @@ class SkillApiWhitelistMiddleware(AgentMiddleware):
|
|
|
372
430
|
new_command = prefix + command
|
|
373
431
|
new_args = {**args, "command": new_command} if isinstance(args, dict) else args
|
|
374
432
|
new_tc = {**tc, "args": new_args}
|
|
375
|
-
|
|
433
|
+
tags = []
|
|
434
|
+
if whitelist_on:
|
|
435
|
+
tags.append(f"白名单({len(resolved)}条)")
|
|
436
|
+
if header_on:
|
|
437
|
+
tags.append("Authz头注入")
|
|
438
|
+
SYLogger.info("[Whitelist] 技能 %s 注入: %s", skill_name or "<user>",
|
|
439
|
+
"+".join(tags) if tags else "(空)")
|
|
376
440
|
return await handler(request.override(tool_call=new_tc))
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import inspect
|
|
3
3
|
import json
|
|
4
|
-
from typing import Optional, Callable,
|
|
4
|
+
from typing import Optional, Callable, Dict, Any, Union
|
|
5
5
|
from aio_pika import Message, DeliveryMode, ExchangeType
|
|
6
6
|
from aio_pika.abc import (
|
|
7
7
|
AbstractChannel,
|
|
@@ -165,12 +165,14 @@ class RabbitMQClient:
|
|
|
165
165
|
f"开始迁移队列 '{self.queue_name}',添加 x-max-priority={self.max_priority}")
|
|
166
166
|
|
|
167
167
|
# 删除旧队列(空且无消费者,安全)
|
|
168
|
+
# if_unused/if_empty=True 兜底:探测到删除之间若有消息进入或消费者上线,
|
|
169
|
+
# 服务端会拒绝删除(406)而不是静默丢消息,消除 TOCTOU 窗口。
|
|
168
170
|
channel, _ = await self.connection_pool.acquire_channel()
|
|
169
171
|
try:
|
|
170
172
|
await channel.queue_delete(
|
|
171
173
|
queue_name=self.queue_name,
|
|
172
|
-
if_unused=
|
|
173
|
-
if_empty=
|
|
174
|
+
if_unused=True,
|
|
175
|
+
if_empty=True,
|
|
174
176
|
)
|
|
175
177
|
finally:
|
|
176
178
|
await channel.close()
|
|
@@ -336,12 +338,46 @@ class RabbitMQClient:
|
|
|
336
338
|
if was_consuming and self._message_handler:
|
|
337
339
|
if self._queue:
|
|
338
340
|
logger.info("🔄 检测到重连前处于消费状态,尝试自动恢复消费...")
|
|
341
|
+
# 复用旧 consumer_tag(哨兵 "__recovering__" 除外):
|
|
342
|
+
# 避免 aio-pika RobustQueue._consumers 里残留旧 tag 导致
|
|
343
|
+
# aiormq DuplicateConsumerTag,或产生双消费者/幽灵回调。
|
|
344
|
+
recover_tag = (
|
|
345
|
+
self._consumer_tag
|
|
346
|
+
if self._consumer_tag and self._consumer_tag != "__recovering__"
|
|
347
|
+
else None
|
|
348
|
+
)
|
|
339
349
|
try:
|
|
340
|
-
self._consumer_tag = await self.start_consuming(
|
|
350
|
+
self._consumer_tag = await self.start_consuming(
|
|
351
|
+
consumer_tag=recover_tag)
|
|
341
352
|
logger.info(f"✅ 消费已自动恢复: {self._consumer_tag}")
|
|
342
353
|
except Exception as e:
|
|
354
|
+
# 恢复失败必须置 None(而不是留哨兵),
|
|
355
|
+
# 否则监控 health check(_consumer_tag is None)永远失效,
|
|
356
|
+
# 消费者真丢了却显示健康。
|
|
357
|
+
self._consumer_tag = None
|
|
343
358
|
logger.error(f"❌ 自动恢复消费失败: {e}")
|
|
359
|
+
|
|
360
|
+
# 恢复后要同步监控侧的 _consumer_tags,否则:
|
|
361
|
+
# - consume_task 已在跑但 _consumer_tags 无记录(此前 finally 已清)
|
|
362
|
+
# - 监控 _restart_consumer_if_needed 会误判"假死"把健康的
|
|
363
|
+
# consume_task cancel 重启,造成不必要的消费者抖动。
|
|
364
|
+
# 用 self.queue_name 反查 client_name(监控以 client_name 为键)。
|
|
365
|
+
if self._consumer_tag:
|
|
366
|
+
try:
|
|
367
|
+
from sycommon.rabbitmq.rabbitmq_service_consumer_manager import (
|
|
368
|
+
RabbitMQConsumerManager,
|
|
369
|
+
)
|
|
370
|
+
for name, mgr_client in getattr(
|
|
371
|
+
RabbitMQConsumerManager, "_clients", {}).items():
|
|
372
|
+
if mgr_client is self:
|
|
373
|
+
RabbitMQConsumerManager._consumer_tags[name] = \
|
|
374
|
+
self._consumer_tag
|
|
375
|
+
break
|
|
376
|
+
except Exception as sync_err:
|
|
377
|
+
logger.debug(f"同步监控 consumer_tags 失败(忽略): {sync_err}")
|
|
344
378
|
else:
|
|
379
|
+
# 队列对象无效,置 None 让监控能检测到并兜底重启
|
|
380
|
+
self._consumer_tag = None
|
|
345
381
|
logger.warning("⚠️ 队列对象无效,暂缓恢复消费,等待监控器兜底")
|
|
346
382
|
|
|
347
383
|
async def set_message_handler(self, handler: Callable) -> None:
|
|
@@ -403,7 +439,7 @@ class RabbitMQClient:
|
|
|
403
439
|
except Exception as e:
|
|
404
440
|
logger.error(f"异步任务执行失败: {e}", exc_info=True)
|
|
405
441
|
|
|
406
|
-
async def start_consuming(self) -> Optional[ConsumerTag]:
|
|
442
|
+
async def start_consuming(self, consumer_tag: Optional[ConsumerTag] = None) -> Optional[ConsumerTag]:
|
|
407
443
|
if self._closed:
|
|
408
444
|
raise RuntimeError("客户端已关闭,无法启动消费")
|
|
409
445
|
|
|
@@ -425,7 +461,40 @@ class RabbitMQClient:
|
|
|
425
461
|
if not self._queue:
|
|
426
462
|
raise RuntimeError("未配置队列名或队列初始化失败")
|
|
427
463
|
|
|
428
|
-
|
|
464
|
+
# 防止重复注册消费:aio-pika RobustQueue._consumers 里若已有消费者,
|
|
465
|
+
# 再次 consume() 会在同一队列上挂多个回调(双消费/重复处理)。
|
|
466
|
+
# 注意:aiormq basic_consume 的 RPC 会占用 channel.lock 直到收到 Consume-Ok,
|
|
467
|
+
# 服务端收到 Basic.Consume 后可能立即开始投递,此时 RPC 锁未释放、
|
|
468
|
+
# _consumer_tag 尚未赋值,若已有消费者在跑则绝不能再来一次。
|
|
469
|
+
#
|
|
470
|
+
# 必须严格判断"非空 dict":getattr 拿到的是非 dict(如 MagicMock)或空 dict
|
|
471
|
+
# 时都不能进分支 —— 空 dict 会让 next(iter(...)) 抛 StopIteration,
|
|
472
|
+
# 且在 async 里被包成 RuntimeError,导致消费恢复假性失败、tag 被置 None。
|
|
473
|
+
#
|
|
474
|
+
# 两种幂等跳过:
|
|
475
|
+
# A. 未显式传 tag + 已有消费者 → 复用任意现有 tag(去重,防双消费)
|
|
476
|
+
# B. 显式传 tag X + _consumers 里已含 X → 该 tag 已在消费,直接复用,
|
|
477
|
+
# 避免对同一 tag 重复 basic_consume 触发 aiormq DuplicateConsumerTag
|
|
478
|
+
# (此情况发生在 connect() 恢复路径与 aio-pika Robust 自动 restore 撞车)。
|
|
479
|
+
# 若 _consumers 含的是别的 tag(理论上不应发生,Robust 用相同 tag restore),
|
|
480
|
+
# 则仍按显式 tag 真正 consume,交给服务端校验。
|
|
481
|
+
existing = getattr(self._queue, "_consumers", None)
|
|
482
|
+
if isinstance(existing, dict):
|
|
483
|
+
if existing and consumer_tag is None:
|
|
484
|
+
self._consumer_tag = next(iter(existing))
|
|
485
|
+
logger.warning(
|
|
486
|
+
f"队列 '{getattr(self._queue, 'name', '?')}' 已有 {len(existing)} 个消费者,"
|
|
487
|
+
f"跳过重复注册(复用现有 tag: {self._consumer_tag})")
|
|
488
|
+
return self._consumer_tag
|
|
489
|
+
if consumer_tag is not None and consumer_tag in existing:
|
|
490
|
+
self._consumer_tag = consumer_tag
|
|
491
|
+
logger.info(
|
|
492
|
+
f"队列 '{getattr(self._queue, 'name', '?')}' 的 tag {consumer_tag} "
|
|
493
|
+
f"已在消费,跳过重复注册(幂等)")
|
|
494
|
+
return self._consumer_tag
|
|
495
|
+
|
|
496
|
+
self._consumer_tag = await self._queue.consume(
|
|
497
|
+
self._process_message_callback, consumer_tag=consumer_tag)
|
|
429
498
|
logger.info(f"开始消费队列: {self._queue.name},tag: {self._consumer_tag}")
|
|
430
499
|
return self._consumer_tag
|
|
431
500
|
|
{sycommon_python_lib-0.2.7a47 → sycommon_python_lib-0.2.7a48}/src/sycommon/rabbitmq/rabbitmq_pool.py
RENAMED
|
@@ -293,9 +293,10 @@ class RabbitMQConnectionPool:
|
|
|
293
293
|
return channel, conn
|
|
294
294
|
except Exception as e:
|
|
295
295
|
logger.error(f"❌ [CHANNEL_FAIL] 创建独立通道失败: {e}")
|
|
296
|
-
#
|
|
297
|
-
#
|
|
298
|
-
|
|
296
|
+
# 通道级失败不应废掉整个连接池:连接本身可能仍健康,
|
|
297
|
+
# 置 _initialized=False 会导致 is_pool_initialized() 返回 False、
|
|
298
|
+
# 监控失明且 wait_for_pool_ready 超时。让调用方重试即可,
|
|
299
|
+
# 连接级问题由 _ensure_connection/is_alive 的心跳机制兜底。
|
|
299
300
|
raise
|
|
300
301
|
|
|
301
302
|
async def force_reconnect(self):
|