sycommon-python-lib 0.2.2a13__tar.gz → 0.2.2a14__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.2a13 → sycommon_python_lib-0.2.2a14}/PKG-INFO +2 -1
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/pyproject.toml +2 -1
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/sandbox/__init__.py +4 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/sandbox/file_ops.py +6 -13
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/sandbox/http_sandbox_backend.py +2 -2
- sycommon_python_lib-0.2.2a14/src/sycommon/agent/sandbox/minio_sync.py +479 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/database/async_database_service.py +4 -2
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/database/token_usage_db_service.py +3 -2
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/sandbox.py +5 -3
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/traceid.py +13 -2
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon_python_lib.egg-info/PKG-INFO +2 -1
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon_python_lib.egg-info/SOURCES.txt +1 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon_python_lib.egg-info/requires.txt +1 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/README.md +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/setup.cfg +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/cli.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/core/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/core/console.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/core/models.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/core/project.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/core/utils.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/agent/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/agent/main_agent.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/agent/nodes/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/agent/nodes/example_node.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/agent/states/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/agent/states/agent_state.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/api/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/api/query.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/api/sse/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/api/sse/agent.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/client/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/db/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/db/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/db/model/entity.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/db/service.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/model/parse.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/tools/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/tools/mq.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/.env.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/.gitignore.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/Dockerfile.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/app.yaml.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/client/FileServiceClient.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/client/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/model/file_info.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/requirements.txt.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/cli/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/cli/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/cli/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/cli/commands/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/cli/commands/hello.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/cli/pyproject.toml.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/cli/tools/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/api/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/api/echo.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/api/sse/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/api/sse/echo.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/client/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/tools/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/tools/mq.py.tpl +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/nexus/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/__main__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/agents/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/agents/factory.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/agents/prompts.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/browser.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/capabilities/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/capabilities/console.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/capabilities/dom.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/capabilities/network.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/capabilities/page_errors.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/capabilities/performance.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/capabilities/screenshot.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/client.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/protocol.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/repl.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cli.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/cdp_cmd.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/chat_cmd.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/create_cmd.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/evaluate_cmd.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/init_cmd.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/memory_cmd.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/resume_cmd.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/rollback_cmd.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/run_cmd.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/core/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/core/backend.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/core/config.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/core/display.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/core/git_integration.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/core/llm.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/core/state.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/evaluate/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/evaluate/api_evaluator.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/memory/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/memory/compressor.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/memory/full.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/memory/hot.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/memory/manager.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/memory/warm.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/mode/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/mode/create.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/mode/optimize.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/models/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/models/config_models.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/baseline_tests.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/checkpoint.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/convergence.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/diagnosis.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/engine.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/environment.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/experience.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/harness_prompts.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/history.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/optimization_logger.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/pre_validation.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/reward.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/strategy_bandit.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/strategy_generator.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/strategy_prompts.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/skills/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/agent_manager.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/chat_events.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/deep_agent.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/multi_agent_team.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/sandbox/sandbox_pool.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/sandbox/sandbox_recovery.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/sandbox/session.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/auth/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/auth/ldap_service.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/auth/wecom_ldap_service.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/Config.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/DatabaseConfig.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/ElasticsearchConfig.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/EmbeddingConfig.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/LLMConfig.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/LangfuseConfig.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/MQConfig.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/RedisConfig.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/RerankerConfig.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/SentryConfig.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/XxlJobConfig.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/database/async_base_db_service.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/database/base_db_service.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/database/database_service.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/database/elasticsearch_service.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/database/redis_service.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/health/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/health/health_check.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/health/metrics.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/health/ping.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/heartbeat_process/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/heartbeat_process/heartbeat_config.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/heartbeat_process/heartbeat_process_manager.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/heartbeat_process/heartbeat_process_worker.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/embedding.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/get_llm.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/llm_logger.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/llm_tokens.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/llm_with_token_tracking.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/native_with_fallback_runnable.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/output_fixing_runnable.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/struct_token.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/sy_langfuse.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/token_usage_es_service.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/token_usage_mysql_service.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/usage_token.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/logging/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/logging/async_sql_logger.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/logging/kafka_log.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/logging/logger_levels.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/logging/logger_wrapper.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/logging/process_logger.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/logging/sql_logger.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/background_execution.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/context.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/cors.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/docs.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/exception.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/middleware.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/monitor_memory.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/mq.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/timeout.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/token_tracking.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/base_http.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/log.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/mqlistener_config.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/mqmsg_model.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/mqsend_config.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/sandbox.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/sso_user.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/token_usage.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/token_usage_mysql.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/xxljob_handler_config.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/notice/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/notice/uvicorn_monitor.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/rabbitmq/process_pool_consumer.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/rabbitmq/rabbitmq_client.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/rabbitmq/rabbitmq_pool.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/rabbitmq/rabbitmq_service.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/rabbitmq/rabbitmq_service_client_manager.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/rabbitmq/rabbitmq_service_connection_monitor.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/rabbitmq/rabbitmq_service_consumer_manager.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/rabbitmq/rabbitmq_service_core.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/rabbitmq/rabbitmq_service_producer_manager.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/sentry/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/sentry/sy_sentry.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/services.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/sse/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/sse/event.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/sse/sse.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/example.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/example2.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/feign.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/feign_client.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/nacos_client_base.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/nacos_config_manager.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/nacos_heartbeat_manager.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/nacos_service.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/nacos_service_discovery.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/nacos_service_registration.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/param.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tests/deep_agent_server.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tests/test_deep_agent.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tests/test_email.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tests/test_mq.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tools/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tools/async_utils.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tools/docs.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tools/env.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tools/merge_headers.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tools/snowflake.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tools/syemail.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tools/timing.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/xxljob/__init__.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/xxljob/xxljob_service.py +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon_python_lib.egg-info/dependency_links.txt +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon_python_lib.egg-info/entry_points.txt +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon_python_lib.egg-info/top_level.txt +0 -0
- {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/tests/test_sycli.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sycommon-python-lib
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2a14
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -38,6 +38,7 @@ Requires-Dist: tiktoken>=0.12.0
|
|
|
38
38
|
Requires-Dist: uvicorn>=0.46.0
|
|
39
39
|
Requires-Dist: wecom-aibot-python-sdk>=1.0.2
|
|
40
40
|
Requires-Dist: twine>=6.2.0
|
|
41
|
+
Requires-Dist: minio>=7.2.20
|
|
41
42
|
|
|
42
43
|
# sycommon-python-lib
|
|
43
44
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "sycommon-python-lib"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.2a14"
|
|
4
4
|
description = "Add your description here"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -39,6 +39,7 @@ dependencies = [
|
|
|
39
39
|
"uvicorn>=0.46.0",
|
|
40
40
|
"wecom-aibot-python-sdk>=1.0.2",
|
|
41
41
|
"twine>=6.2.0",
|
|
42
|
+
"minio>=7.2.20",
|
|
42
43
|
]
|
|
43
44
|
|
|
44
45
|
[tool.setuptools]
|
{sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/sandbox/__init__.py
RENAMED
|
@@ -78,6 +78,7 @@ from sycommon.agent.sandbox.sandbox_pool import (
|
|
|
78
78
|
aget_sandbox_status,
|
|
79
79
|
)
|
|
80
80
|
from sycommon.agent.sandbox.sandbox_recovery import SandboxRecoveryManager
|
|
81
|
+
from sycommon.agent.sandbox.minio_sync import MinioSyncService
|
|
81
82
|
|
|
82
83
|
__all__ = [
|
|
83
84
|
# 后端
|
|
@@ -93,6 +94,9 @@ __all__ = [
|
|
|
93
94
|
# 恢复管理
|
|
94
95
|
"SandboxRecoveryManager",
|
|
95
96
|
|
|
97
|
+
# MinIO 同步
|
|
98
|
+
"MinioSyncService",
|
|
99
|
+
|
|
96
100
|
# 便捷函数
|
|
97
101
|
"areset_all_sandboxes",
|
|
98
102
|
"aget_sandbox_status",
|
{sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/sandbox/file_ops.py
RENAMED
|
@@ -5,9 +5,8 @@
|
|
|
5
5
|
适配 deepagents 0.5.0a2 协议
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
import asyncio
|
|
9
8
|
import base64
|
|
10
|
-
from dataclasses import dataclass
|
|
9
|
+
from dataclasses import dataclass
|
|
11
10
|
from typing import Optional, TYPE_CHECKING
|
|
12
11
|
|
|
13
12
|
from sycommon.logging.kafka_log import SYLogger
|
|
@@ -236,7 +235,8 @@ class FileOperationsMixin:
|
|
|
236
235
|
return ReadResult(error=result["error"])
|
|
237
236
|
content = result.get("content", "")
|
|
238
237
|
encoding = result.get("encoding", "utf-8")
|
|
239
|
-
SYLogger.info(
|
|
238
|
+
SYLogger.info(
|
|
239
|
+
f"[Sandbox] 读取完成: {len(content)} 字符, encoding={encoding}")
|
|
240
240
|
file_data = FileData(
|
|
241
241
|
content=content,
|
|
242
242
|
encoding=encoding,
|
|
@@ -270,7 +270,8 @@ class FileOperationsMixin:
|
|
|
270
270
|
return ReadResult(error=result["error"])
|
|
271
271
|
content = result.get("content", "")
|
|
272
272
|
encoding = result.get("encoding", "utf-8")
|
|
273
|
-
SYLogger.info(
|
|
273
|
+
SYLogger.info(
|
|
274
|
+
f"[Sandbox] 异步读取完成: {len(content)} 字符, encoding={encoding}")
|
|
274
275
|
file_data = FileData(
|
|
275
276
|
content=content,
|
|
276
277
|
encoding=encoding,
|
|
@@ -519,15 +520,7 @@ class FileOperationsMixin:
|
|
|
519
520
|
path: str,
|
|
520
521
|
recursive: bool = False,
|
|
521
522
|
) -> DeleteResult:
|
|
522
|
-
"""删除文件或文件夹
|
|
523
|
-
|
|
524
|
-
Args:
|
|
525
|
-
path: 要删除的文件或文件夹路径
|
|
526
|
-
recursive: 是否递归删除(删除文件夹时需要设为 True)
|
|
527
|
-
|
|
528
|
-
Returns:
|
|
529
|
-
DeleteResult
|
|
530
|
-
"""
|
|
523
|
+
"""删除文件或文件夹"""
|
|
531
524
|
try:
|
|
532
525
|
self._ensure_synced_sync()
|
|
533
526
|
SYLogger.info(f"[Sandbox] 删除: {path} (recursive={recursive})")
|
|
@@ -80,7 +80,7 @@ class HTTPSandboxBackend(FileOperationsMixin, SandboxBackendProtocol):
|
|
|
80
80
|
self,
|
|
81
81
|
base_url: str,
|
|
82
82
|
user_id: str,
|
|
83
|
-
timeout: int =
|
|
83
|
+
timeout: int = 180,
|
|
84
84
|
sync_dirs: List[tuple[str, str]] = None,
|
|
85
85
|
auto_sync: bool = False,
|
|
86
86
|
nacos_service_name: str = None,
|
|
@@ -128,7 +128,7 @@ class HTTPSandboxBackend(FileOperationsMixin, SandboxBackendProtocol):
|
|
|
128
128
|
user_id: str,
|
|
129
129
|
group: str = "DEFAULT_GROUP",
|
|
130
130
|
version: str = None,
|
|
131
|
-
timeout: int =
|
|
131
|
+
timeout: int = 180,
|
|
132
132
|
sync_dirs: List[tuple[str, str]] = None,
|
|
133
133
|
auto_sync: bool = False,
|
|
134
134
|
load_balance: bool = True,
|
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
"""MinIO 文件同步服务
|
|
2
|
+
|
|
3
|
+
将沙箱中的文件自动同步到 MinIO 对象存储。
|
|
4
|
+
存储结构:{user_id}/current/{file_path}
|
|
5
|
+
- current 目录保存沙箱全量文件的最新状态
|
|
6
|
+
- 增量同步:只上传新增或修改的文件
|
|
7
|
+
- 下载时直接从 current 目录查找
|
|
8
|
+
|
|
9
|
+
配置来源(优先 Nacos,其次环境变量):
|
|
10
|
+
Nacos: minio.endpoint, minio.accessKey, minio.secretKey, minio.bucket, minio.secure
|
|
11
|
+
环境变量: MINIO_ENDPOINT, MINIO_ACCESS_KEY, MINIO_SECRET_KEY, MINIO_BUCKET, MINIO_SECURE
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import asyncio
|
|
15
|
+
import mimetypes
|
|
16
|
+
import os
|
|
17
|
+
from datetime import datetime, timedelta, timezone
|
|
18
|
+
from io import BytesIO
|
|
19
|
+
from typing import Optional
|
|
20
|
+
|
|
21
|
+
from sycommon.config.Config import SingletonMeta
|
|
22
|
+
from sycommon.logging.kafka_log import SYLogger
|
|
23
|
+
|
|
24
|
+
# 日期快照功能预留,当前暂不启用
|
|
25
|
+
_SNAPSHOT_ENABLED = False
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class MinioSyncService(metaclass=SingletonMeta):
|
|
29
|
+
"""MinIO 文件同步服务(单例)"""
|
|
30
|
+
|
|
31
|
+
def __init__(self):
|
|
32
|
+
self._client = None
|
|
33
|
+
self._bucket = None
|
|
34
|
+
# None=未初始化, True=已成功, False=配置缺失/初始化失败(不重试)
|
|
35
|
+
self._initialized = None
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def setup(cls, config: dict = None):
|
|
39
|
+
"""初始化 MinIO 客户端(可多次调用,仅首次生效)"""
|
|
40
|
+
instance = cls()
|
|
41
|
+
if instance._initialized is not None:
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
cfg = instance._load_config(config)
|
|
45
|
+
if not cfg.get("endpoint"):
|
|
46
|
+
instance._initialized = False
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
from minio import Minio
|
|
51
|
+
instance._client = Minio(
|
|
52
|
+
endpoint=cfg["endpoint"],
|
|
53
|
+
access_key=cfg["access_key"],
|
|
54
|
+
secret_key=cfg["secret_key"],
|
|
55
|
+
secure=cfg["secure"],
|
|
56
|
+
)
|
|
57
|
+
instance._bucket = cfg["bucket"]
|
|
58
|
+
|
|
59
|
+
if not instance._client.bucket_exists(instance._bucket):
|
|
60
|
+
instance._client.make_bucket(instance._bucket)
|
|
61
|
+
SYLogger.info(f"[MinIO] Created bucket: {instance._bucket}")
|
|
62
|
+
|
|
63
|
+
instance._initialized = True
|
|
64
|
+
SYLogger.info(
|
|
65
|
+
f"[MinIO] Client initialized: {cfg['endpoint']}, bucket={instance._bucket}")
|
|
66
|
+
except Exception as e:
|
|
67
|
+
SYLogger.error(f"[MinIO] Client initialization failed: {e}")
|
|
68
|
+
instance._initialized = False
|
|
69
|
+
|
|
70
|
+
def _load_config(self, config: dict = None) -> dict:
|
|
71
|
+
"""从 Nacos 配置或环境变量加载 MinIO 配置"""
|
|
72
|
+
if config:
|
|
73
|
+
minio_cfg = config.get("Minio", {})
|
|
74
|
+
if minio_cfg.get("endpoint"):
|
|
75
|
+
return {
|
|
76
|
+
"endpoint": minio_cfg.get("endpoint", ""),
|
|
77
|
+
"access_key": minio_cfg.get("accessKey", ""),
|
|
78
|
+
"secret_key": minio_cfg.get("secretKey", ""),
|
|
79
|
+
"bucket": minio_cfg.get("bucket", "digital-work-files"),
|
|
80
|
+
"secure": str(minio_cfg.get("secure", False)).lower() == "true",
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
try:
|
|
84
|
+
from sycommon.config.Config import Config
|
|
85
|
+
nacos_cfg = Config().config
|
|
86
|
+
minio_cfg = nacos_cfg.get("Minio", {})
|
|
87
|
+
if minio_cfg.get("endpoint"):
|
|
88
|
+
return {
|
|
89
|
+
"endpoint": minio_cfg.get("endpoint", ""),
|
|
90
|
+
"access_key": minio_cfg.get("accessKey", ""),
|
|
91
|
+
"secret_key": minio_cfg.get("secretKey", ""),
|
|
92
|
+
"bucket": minio_cfg.get("bucket", "digital-work-files"),
|
|
93
|
+
"secure": str(minio_cfg.get("secure", False)).lower() == "true",
|
|
94
|
+
}
|
|
95
|
+
except Exception:
|
|
96
|
+
pass
|
|
97
|
+
|
|
98
|
+
# 兜底:尝试从 .env 文件加载(项目未显式 load_dotenv 时)
|
|
99
|
+
if not os.environ.get("MINIO_ENDPOINT"):
|
|
100
|
+
try:
|
|
101
|
+
from dotenv import load_dotenv
|
|
102
|
+
load_dotenv()
|
|
103
|
+
except ImportError:
|
|
104
|
+
pass
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
"endpoint": os.environ.get("MINIO_ENDPOINT", ""),
|
|
108
|
+
"access_key": os.environ.get("MINIO_ACCESS_KEY", ""),
|
|
109
|
+
"secret_key": os.environ.get("MINIO_SECRET_KEY", ""),
|
|
110
|
+
"bucket": os.environ.get("MINIO_BUCKET", "digital-work-files"),
|
|
111
|
+
"secure": os.environ.get("MINIO_SECURE", "false").lower() == "true",
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@classmethod
|
|
115
|
+
def is_available(cls) -> bool:
|
|
116
|
+
"""检查 MinIO 是否可用"""
|
|
117
|
+
instance = cls()
|
|
118
|
+
if instance._initialized is None:
|
|
119
|
+
cls.setup()
|
|
120
|
+
return instance._client is not None
|
|
121
|
+
|
|
122
|
+
@staticmethod
|
|
123
|
+
def make_object_key(user_id: str, date_str: str, file_path: str) -> str:
|
|
124
|
+
"""生成 object key: {user_id}/{date_str}/{file_path}"""
|
|
125
|
+
clean_path = file_path.replace("\\", "/").lstrip("./").lstrip("/")
|
|
126
|
+
return f"{user_id.lower()}/{date_str}/{clean_path}"
|
|
127
|
+
|
|
128
|
+
def upload_bytes(self, object_key: str, content: bytes,
|
|
129
|
+
content_type: str = "application/octet-stream") -> bool:
|
|
130
|
+
"""同步上传文件到 MinIO"""
|
|
131
|
+
if not self._client:
|
|
132
|
+
return False
|
|
133
|
+
try:
|
|
134
|
+
self._client.put_object(
|
|
135
|
+
bucket_name=self._bucket,
|
|
136
|
+
object_name=object_key,
|
|
137
|
+
data=BytesIO(content),
|
|
138
|
+
length=len(content),
|
|
139
|
+
content_type=content_type,
|
|
140
|
+
)
|
|
141
|
+
SYLogger.info(
|
|
142
|
+
f"[MinIO] Upload success: {object_key}, size={len(content)}")
|
|
143
|
+
return True
|
|
144
|
+
except Exception as e:
|
|
145
|
+
SYLogger.error(f"[MinIO] Upload failed: {object_key}, error={e}")
|
|
146
|
+
return False
|
|
147
|
+
|
|
148
|
+
async def aupload_bytes(self, object_key: str, content: bytes,
|
|
149
|
+
content_type: str = "application/octet-stream") -> bool:
|
|
150
|
+
"""异步上传文件到 MinIO"""
|
|
151
|
+
return await asyncio.to_thread(
|
|
152
|
+
self.upload_bytes, object_key, content, content_type
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
def stat_object(self, object_key: str):
|
|
156
|
+
"""获取 MinIO 对象元信息(含 last_modified),不存在返回 None"""
|
|
157
|
+
if not self._client:
|
|
158
|
+
return None
|
|
159
|
+
try:
|
|
160
|
+
return self._client.stat_object(self._bucket, object_key)
|
|
161
|
+
except Exception:
|
|
162
|
+
return None
|
|
163
|
+
|
|
164
|
+
def get_presigned_url(self, object_key: str, expires_days: int = 7) -> Optional[str]:
|
|
165
|
+
"""生成预签名下载 URL"""
|
|
166
|
+
if not self._client:
|
|
167
|
+
return None
|
|
168
|
+
try:
|
|
169
|
+
url = self._client.presigned_get_object(
|
|
170
|
+
bucket_name=self._bucket,
|
|
171
|
+
object_name=object_key,
|
|
172
|
+
expires=timedelta(days=expires_days),
|
|
173
|
+
)
|
|
174
|
+
return url
|
|
175
|
+
except Exception as e:
|
|
176
|
+
SYLogger.error(
|
|
177
|
+
f"[MinIO] Presigned URL failed: {object_key}, error={e}")
|
|
178
|
+
return None
|
|
179
|
+
|
|
180
|
+
def remove_object(self, object_key: str) -> bool:
|
|
181
|
+
"""从 MinIO 删除文件"""
|
|
182
|
+
if not self._client:
|
|
183
|
+
return False
|
|
184
|
+
try:
|
|
185
|
+
self._client.remove_object(self._bucket, object_key)
|
|
186
|
+
SYLogger.info(f"[MinIO] Delete success: {object_key}")
|
|
187
|
+
return True
|
|
188
|
+
except Exception as e:
|
|
189
|
+
SYLogger.warning(f"[MinIO] Delete failed: {object_key}, error={e}")
|
|
190
|
+
return False
|
|
191
|
+
|
|
192
|
+
# ============== 查找最近副本 ==============
|
|
193
|
+
|
|
194
|
+
def find_latest_object_key(self, user_id: str, file_path: str) -> Optional[str]:
|
|
195
|
+
"""查找某个文件在 MinIO 中的 object key
|
|
196
|
+
|
|
197
|
+
当前存储在 current 目录,直接构造 key。
|
|
198
|
+
启用日期快照后改为按日期倒序查找。
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
object_key 或 None
|
|
202
|
+
"""
|
|
203
|
+
if not self._client:
|
|
204
|
+
return None
|
|
205
|
+
|
|
206
|
+
clean_path = file_path.replace("\\", "/").lstrip("./").lstrip("/")
|
|
207
|
+
key = f"{user_id.lower()}/current/{clean_path}"
|
|
208
|
+
|
|
209
|
+
if self.stat_object(key):
|
|
210
|
+
return key
|
|
211
|
+
|
|
212
|
+
# 回溯旧日期格式目录(兼容已有数据)
|
|
213
|
+
if _SNAPSHOT_ENABLED:
|
|
214
|
+
return self._find_in_date_dirs(user_id, clean_path)
|
|
215
|
+
return None
|
|
216
|
+
|
|
217
|
+
def _find_in_date_dirs(self, user_id: str, clean_path: str) -> Optional[str]:
|
|
218
|
+
"""按日期倒序查找文件(启用日期快照后使用)"""
|
|
219
|
+
prefix = f"{user_id.lower()}/"
|
|
220
|
+
try:
|
|
221
|
+
objects = list(self._client.list_objects(
|
|
222
|
+
self._bucket, prefix=prefix, recursive=True))
|
|
223
|
+
candidates = [
|
|
224
|
+
obj.object_name for obj in objects
|
|
225
|
+
if obj.object_name.endswith(f"/{clean_path}")
|
|
226
|
+
]
|
|
227
|
+
if candidates:
|
|
228
|
+
candidates.sort(reverse=True)
|
|
229
|
+
return candidates[0]
|
|
230
|
+
except Exception as e:
|
|
231
|
+
SYLogger.warning(f"[MinIO] find_latest failed: {e}")
|
|
232
|
+
return None
|
|
233
|
+
|
|
234
|
+
async def afinf_latest_object_key(self, user_id: str, file_path: str) -> Optional[str]:
|
|
235
|
+
"""异步查找某个文件最近一天的 object key"""
|
|
236
|
+
return await asyncio.to_thread(self.find_latest_object_key, user_id, file_path)
|
|
237
|
+
|
|
238
|
+
# ============== 批量扫描同步 ==============
|
|
239
|
+
|
|
240
|
+
def collect_sandbox_files(self, tree_result) -> list[str]:
|
|
241
|
+
"""从沙箱 tree 结果中收集所有文件路径
|
|
242
|
+
|
|
243
|
+
tree 根节点 name 通常是 user_id(如 "osulcode.xiao"),
|
|
244
|
+
收集时跳过根节点,从其 children 开始递归,这样路径不含 user_id 前缀,
|
|
245
|
+
与 astat/adownload_files 的路径语义一致。
|
|
246
|
+
"""
|
|
247
|
+
if tree_result.error or not tree_result.tree:
|
|
248
|
+
return []
|
|
249
|
+
|
|
250
|
+
root = tree_result.tree
|
|
251
|
+
files = []
|
|
252
|
+
if root.is_dir and root.children:
|
|
253
|
+
for child in root.children:
|
|
254
|
+
self._collect_files_from_node(child, "", files)
|
|
255
|
+
|
|
256
|
+
# tree 在文件过多时会插入 "... (truncated, max N files)" 虚拟节点,过滤掉
|
|
257
|
+
files = [f for f in files if "truncated" not in f]
|
|
258
|
+
return files
|
|
259
|
+
|
|
260
|
+
def _collect_files_from_node(self, node, prefix: str, files: list):
|
|
261
|
+
"""递归收集文件节点"""
|
|
262
|
+
if not node:
|
|
263
|
+
return
|
|
264
|
+
|
|
265
|
+
path = f"{prefix}/{node.name}" if prefix else node.name
|
|
266
|
+
|
|
267
|
+
if node.is_dir:
|
|
268
|
+
if node.children:
|
|
269
|
+
for child in node.children:
|
|
270
|
+
self._collect_files_from_node(child, path, files)
|
|
271
|
+
else:
|
|
272
|
+
files.append(path)
|
|
273
|
+
|
|
274
|
+
async def sync_sandbox_to_minio(self, sandbox_backend, user_id: str) -> int:
|
|
275
|
+
"""扫描沙箱目录,增量同步文件到 MinIO
|
|
276
|
+
|
|
277
|
+
存储到 {user_id}/current/ 目录,只上传新增或修改的文件。
|
|
278
|
+
max_files=0 表示不限制,tree 返回全部文件。
|
|
279
|
+
下载/上传采用并发(每批 CONCURRENT_BATCH 个),避免串行太慢。
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
sandbox_backend: 沙箱后端实例
|
|
283
|
+
user_id: 用户ID
|
|
284
|
+
|
|
285
|
+
Returns:
|
|
286
|
+
同步的文件数量
|
|
287
|
+
"""
|
|
288
|
+
if not self.is_available():
|
|
289
|
+
return 0
|
|
290
|
+
|
|
291
|
+
# 1. 获取沙箱目录树(max_files=0 不限制数量,max_depth=0 不限制深度)
|
|
292
|
+
try:
|
|
293
|
+
tree_result = await sandbox_backend.atree(path="/", max_depth=0, max_files=0)
|
|
294
|
+
# 兼容旧版 sandbox:max_depth=0 或 max_files=0 可能返回空树,改用大数值
|
|
295
|
+
if tree_result.tree and tree_result.tree.is_dir and not tree_result.tree.children:
|
|
296
|
+
tree_result = await sandbox_backend.atree(path="/", max_depth=30, max_files=10000)
|
|
297
|
+
except Exception as e:
|
|
298
|
+
SYLogger.error(f"[MinIO] 获取沙箱目录树失败: {e}")
|
|
299
|
+
return 0
|
|
300
|
+
|
|
301
|
+
sandbox_files = self.collect_sandbox_files(tree_result)
|
|
302
|
+
if not sandbox_files:
|
|
303
|
+
return 0
|
|
304
|
+
|
|
305
|
+
# 2. 确定存储目录
|
|
306
|
+
if _SNAPSHOT_ENABLED:
|
|
307
|
+
dir_name = datetime.now(timezone.utc).strftime("%Y-%m-%d")
|
|
308
|
+
else:
|
|
309
|
+
dir_name = "current"
|
|
310
|
+
|
|
311
|
+
prefix = f"{user_id.lower()}/{dir_name}/"
|
|
312
|
+
|
|
313
|
+
# 3. 获取 MinIO 已有副本
|
|
314
|
+
existing_objects = {}
|
|
315
|
+
try:
|
|
316
|
+
objects = await asyncio.to_thread(
|
|
317
|
+
lambda: list(self._client.list_objects(
|
|
318
|
+
self._bucket, prefix=prefix, recursive=True))
|
|
319
|
+
)
|
|
320
|
+
for obj in objects:
|
|
321
|
+
rel_path = obj.object_name[len(prefix):]
|
|
322
|
+
existing_objects[rel_path] = obj
|
|
323
|
+
except Exception as e:
|
|
324
|
+
SYLogger.warning(f"[MinIO] 列出已有副本失败,将全量上传: {e}")
|
|
325
|
+
|
|
326
|
+
# 4. 找出需要同步的文件(新增的不在 MinIO 中)
|
|
327
|
+
changed_files = [
|
|
328
|
+
fp for fp in sandbox_files if fp not in existing_objects]
|
|
329
|
+
|
|
330
|
+
if not changed_files:
|
|
331
|
+
SYLogger.info(f"[MinIO] 所有文件均无变化,跳过同步: user={user_id}")
|
|
332
|
+
return 0
|
|
333
|
+
|
|
334
|
+
SYLogger.info(
|
|
335
|
+
f"[MinIO] 检测到 {len(changed_files)} 个文件有变化: user={user_id}")
|
|
336
|
+
|
|
337
|
+
# 5. 并发下载并上传变化文件
|
|
338
|
+
synced = await self._sync_batch(sandbox_backend, changed_files, existing_objects, prefix)
|
|
339
|
+
|
|
340
|
+
SYLogger.info(
|
|
341
|
+
f"[MinIO] 同步完成: user={user_id}, dir={dir_name}, synced={synced}/{len(changed_files)}")
|
|
342
|
+
return synced
|
|
343
|
+
|
|
344
|
+
async def _sync_batch(self, sandbox_backend, file_paths: list[str],
|
|
345
|
+
existing_objects: dict, prefix: str,
|
|
346
|
+
batch_size: int = 5) -> int:
|
|
347
|
+
"""并发下载并上传文件,每批 batch_size 个并发"""
|
|
348
|
+
synced = 0
|
|
349
|
+
|
|
350
|
+
for i in range(0, len(file_paths), batch_size):
|
|
351
|
+
batch = file_paths[i:i + batch_size]
|
|
352
|
+
tasks = [
|
|
353
|
+
self._sync_one(sandbox_backend, fp, existing_objects, prefix)
|
|
354
|
+
for fp in batch
|
|
355
|
+
]
|
|
356
|
+
results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
357
|
+
for r in results:
|
|
358
|
+
if r is True:
|
|
359
|
+
synced += 1
|
|
360
|
+
|
|
361
|
+
return synced
|
|
362
|
+
|
|
363
|
+
async def _sync_one(self, sandbox_backend, fp: str,
|
|
364
|
+
existing_objects: dict, prefix: str) -> bool:
|
|
365
|
+
"""同步单个文件:下载 + 上传,成功返回 True"""
|
|
366
|
+
try:
|
|
367
|
+
results = await sandbox_backend.adownload_files([f"/{fp}"])
|
|
368
|
+
if not results or results[0].error or not results[0].content:
|
|
369
|
+
error = results[0].error if results else "unknown"
|
|
370
|
+
SYLogger.warning(f"[MinIO] 下载沙箱文件失败: {fp}, error={error}")
|
|
371
|
+
return False
|
|
372
|
+
|
|
373
|
+
content = results[0].content
|
|
374
|
+
|
|
375
|
+
# 如果 MinIO 已有且 size 相同,跳过
|
|
376
|
+
if fp in existing_objects and existing_objects[fp].size == len(content):
|
|
377
|
+
return False
|
|
378
|
+
|
|
379
|
+
mime_type, _ = mimetypes.guess_type(fp)
|
|
380
|
+
object_key = f"{prefix}{fp}"
|
|
381
|
+
|
|
382
|
+
return await self.aupload_bytes(
|
|
383
|
+
object_key, content,
|
|
384
|
+
content_type=mime_type or "application/octet-stream",
|
|
385
|
+
)
|
|
386
|
+
except Exception as e:
|
|
387
|
+
SYLogger.warning(f"[MinIO] 同步文件异常: {fp}, error={e}")
|
|
388
|
+
return False
|
|
389
|
+
|
|
390
|
+
# ============== 反向同步(MinIO → 沙箱) ==============
|
|
391
|
+
|
|
392
|
+
async def restore_from_minio(self, sandbox_backend, user_id: str) -> int:
|
|
393
|
+
"""将 MinIO 中的文件恢复到沙箱
|
|
394
|
+
|
|
395
|
+
场景:沙箱重启后文件丢失,从 MinIO current 目录恢复。
|
|
396
|
+
只上传沙箱中不存在的文件,不覆盖已有文件。
|
|
397
|
+
|
|
398
|
+
Args:
|
|
399
|
+
sandbox_backend: 沙箱后端实例
|
|
400
|
+
user_id: 用户ID
|
|
401
|
+
|
|
402
|
+
Returns:
|
|
403
|
+
恢复的文件数量
|
|
404
|
+
"""
|
|
405
|
+
if not self._client:
|
|
406
|
+
return 0
|
|
407
|
+
|
|
408
|
+
prefix = f"{user_id.lower()}/current/"
|
|
409
|
+
|
|
410
|
+
# 1. 列出 MinIO 中所有文件
|
|
411
|
+
try:
|
|
412
|
+
objects = await asyncio.to_thread(
|
|
413
|
+
lambda: list(self._client.list_objects(
|
|
414
|
+
self._bucket, prefix=prefix, recursive=True))
|
|
415
|
+
)
|
|
416
|
+
except Exception as e:
|
|
417
|
+
SYLogger.error(f"[MinIO] 恢复时列出文件失败: {e}")
|
|
418
|
+
return 0
|
|
419
|
+
|
|
420
|
+
if not objects:
|
|
421
|
+
return 0
|
|
422
|
+
|
|
423
|
+
# 2. 获取沙箱已有文件
|
|
424
|
+
try:
|
|
425
|
+
tree_result = await sandbox_backend.atree(path="/", max_depth=0, max_files=0)
|
|
426
|
+
if tree_result.tree and tree_result.tree.is_dir and not tree_result.tree.children:
|
|
427
|
+
tree_result = await sandbox_backend.atree(path="/", max_depth=30, max_files=10000)
|
|
428
|
+
except Exception:
|
|
429
|
+
tree_result = None
|
|
430
|
+
|
|
431
|
+
existing_files = set()
|
|
432
|
+
if tree_result:
|
|
433
|
+
existing_files = set(self.collect_sandbox_files(tree_result))
|
|
434
|
+
|
|
435
|
+
# 3. 找出沙箱中没有的文件
|
|
436
|
+
to_restore = []
|
|
437
|
+
for obj in objects:
|
|
438
|
+
rel_path = obj.object_name[len(prefix):]
|
|
439
|
+
if rel_path and rel_path not in existing_files:
|
|
440
|
+
to_restore.append(rel_path)
|
|
441
|
+
|
|
442
|
+
if not to_restore:
|
|
443
|
+
SYLogger.info(f"[MinIO] 沙箱文件完整,无需恢复: user={user_id}")
|
|
444
|
+
return 0
|
|
445
|
+
|
|
446
|
+
SYLogger.info(f"[MinIO] 需恢复 {len(to_restore)} 个文件到沙箱: user={user_id}")
|
|
447
|
+
|
|
448
|
+
# 4. 批量恢复
|
|
449
|
+
restored = 0
|
|
450
|
+
for i in range(0, len(to_restore), 5):
|
|
451
|
+
batch = to_restore[i:i + 5]
|
|
452
|
+
files_to_upload = []
|
|
453
|
+
for rel_path in batch:
|
|
454
|
+
try:
|
|
455
|
+
response = await asyncio.to_thread(
|
|
456
|
+
self._client.get_object, self._bucket, f"{prefix}{rel_path}"
|
|
457
|
+
)
|
|
458
|
+
content = response.read()
|
|
459
|
+
response.close()
|
|
460
|
+
response.release_conn()
|
|
461
|
+
files_to_upload.append((f"/{rel_path}", content))
|
|
462
|
+
except Exception as e:
|
|
463
|
+
SYLogger.warning(f"[MinIO] 下载文件失败: {rel_path}, error={e}")
|
|
464
|
+
|
|
465
|
+
if files_to_upload:
|
|
466
|
+
try:
|
|
467
|
+
results = await sandbox_backend.aupload_files(files_to_upload)
|
|
468
|
+
for r in results:
|
|
469
|
+
if not r.error:
|
|
470
|
+
restored += 1
|
|
471
|
+
else:
|
|
472
|
+
SYLogger.warning(
|
|
473
|
+
f"[MinIO] 上传到沙箱失败: {r.path}, error={r.error}")
|
|
474
|
+
except Exception as e:
|
|
475
|
+
SYLogger.warning(f"[MinIO] 批量上传到沙箱失败: {e}")
|
|
476
|
+
|
|
477
|
+
SYLogger.info(
|
|
478
|
+
f"[MinIO] 恢复完成: user={user_id}, restored={restored}/{len(to_restore)}")
|
|
479
|
+
return restored
|
|
@@ -71,11 +71,13 @@ class AsyncDatabaseConnector(metaclass=SingletonMeta):
|
|
|
71
71
|
|
|
72
72
|
# 优化连接池配置
|
|
73
73
|
# 使用 create_async_engine 替代 create_engine
|
|
74
|
+
# 注意:多 Worker 模式下每个进程各自创建独立连接池,需控制总量不超 MySQL max_connections
|
|
75
|
+
# 4 workers × (pool_size=5 + max_overflow=5) = 40,留余量给其他服务
|
|
74
76
|
self.engine = create_async_engine(
|
|
75
77
|
self.db_url,
|
|
76
78
|
connect_args=params,
|
|
77
|
-
pool_size=
|
|
78
|
-
max_overflow=
|
|
79
|
+
pool_size=5, # 连接池大小
|
|
80
|
+
max_overflow=5, # 最大溢出连接数
|
|
79
81
|
pool_timeout=30, # 连接超时时间(秒)
|
|
80
82
|
pool_recycle=3600, # 连接回收时间(秒)
|
|
81
83
|
pool_pre_ping=True, # 每次获取连接前检查连接是否有效
|
|
@@ -154,11 +154,12 @@ class TokenUsageDBConnector(metaclass=SingletonMeta):
|
|
|
154
154
|
SYLogger.info(f"TokenUsageDBService Database URL: {safe_url}")
|
|
155
155
|
|
|
156
156
|
# 创建异步引擎(Token 记录连接池较小,增加连接超时防止慢 MySQL 拖垮主服务)
|
|
157
|
+
# 4 workers × (pool_size=1 + max_overflow=2) = 12
|
|
157
158
|
self.engine = create_async_engine(
|
|
158
159
|
self.db_url,
|
|
159
160
|
connect_args={**params, "connect_timeout": 3},
|
|
160
|
-
pool_size=
|
|
161
|
-
max_overflow=
|
|
161
|
+
pool_size=1,
|
|
162
|
+
max_overflow=2,
|
|
162
163
|
pool_timeout=5,
|
|
163
164
|
pool_recycle=3600,
|
|
164
165
|
pool_pre_ping=True,
|
{sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/sandbox.py
RENAMED
|
@@ -1121,8 +1121,10 @@ COMMAND_EOF
|
|
|
1121
1121
|
SYLogger.error(f"[Sandbox Server] tree 失败: {e}")
|
|
1122
1122
|
return TreeResponse(error=str(e))
|
|
1123
1123
|
|
|
1124
|
-
max_depth = req.max_depth
|
|
1125
|
-
max_files = req.max_files
|
|
1124
|
+
max_depth = req.max_depth if req.max_depth is not None else 5
|
|
1125
|
+
max_files = req.max_files if req.max_files is not None else 500
|
|
1126
|
+
if max_depth == 0:
|
|
1127
|
+
max_depth = 100
|
|
1126
1128
|
|
|
1127
1129
|
def _tree():
|
|
1128
1130
|
if not os.path.isdir(target_path):
|
|
@@ -1145,7 +1147,7 @@ COMMAND_EOF
|
|
|
1145
1147
|
return node
|
|
1146
1148
|
|
|
1147
1149
|
for entry in entries:
|
|
1148
|
-
if file_count >= max_files:
|
|
1150
|
+
if max_files > 0 and file_count >= max_files:
|
|
1149
1151
|
node.children.append(TreeNode(
|
|
1150
1152
|
path="...", name=f"... (truncated, max {max_files} files)", is_dir=False
|
|
1151
1153
|
))
|
{sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/traceid.py
RENAMED
|
@@ -250,8 +250,19 @@ def setup_trace_id_handler(app):
|
|
|
250
250
|
|
|
251
251
|
# 构建响应日志
|
|
252
252
|
response_log_body = response_body.decode('utf-8', errors='ignore')
|
|
253
|
-
|
|
254
|
-
|
|
253
|
+
total_len = len(response_log_body)
|
|
254
|
+
# 检测是否包含 base64 二进制内容(如 PDF、图片等)
|
|
255
|
+
is_binary_response = False
|
|
256
|
+
try:
|
|
257
|
+
resp_json = json.loads(response_log_body)
|
|
258
|
+
if isinstance(resp_json, dict) and resp_json.get("content") and len(str(resp_json["content"])) > 1000:
|
|
259
|
+
resp_json["content"] = f"... (base64/binary content omitted, {len(str(resp_json['content']))} chars)"
|
|
260
|
+
response_log_body = json.dumps(resp_json, ensure_ascii=False)
|
|
261
|
+
is_binary_response = True
|
|
262
|
+
except (json.JSONDecodeError, ValueError):
|
|
263
|
+
pass
|
|
264
|
+
if not is_binary_response and total_len > 10000:
|
|
265
|
+
response_log_body = response_log_body[:10000] + f"... (truncated, total {total_len} bytes)"
|
|
255
266
|
response_message = {
|
|
256
267
|
"traceId": trace_id,
|
|
257
268
|
"status_code": response.status_code,
|