sycommon-python-lib 0.2.5a37__tar.gz → 0.2.5a39__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.5a37 → sycommon_python_lib-0.2.5a39}/PKG-INFO +1 -1
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/pyproject.toml +1 -1
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/agent/deep_agent.py +33 -17
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/agent/multi_agent_team.py +13 -8
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/agent/sandbox/file_ops.py +21 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/agent/sandbox/http_sandbox_backend.py +128 -25
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/agent/sandbox/minio_sync.py +45 -3
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/auth/wecom_ldap_service.py +87 -3
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon_python_lib.egg-info/PKG-INFO +1 -1
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/README.md +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/setup.cfg +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/cli.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/core/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/core/console.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/core/models.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/core/project.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/core/utils.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/agent/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/agent/main_agent.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/agent/nodes/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/agent/nodes/example_node.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/agent/states/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/agent/states/agent_state.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/api/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/api/query.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/api/sse/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/api/sse/agent.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/client/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/db/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/db/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/db/model/entity.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/db/service.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/model/parse.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/tools/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/agent/tools/mq.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/base/.env.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/base/.gitignore.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/base/Dockerfile.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/base/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/base/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/base/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/base/app.yaml.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/base/client/FileServiceClient.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/base/client/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/base/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/base/model/file_info.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/base/requirements.txt.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/cli/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/cli/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/cli/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/cli/commands/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/cli/commands/hello.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/cli/pyproject.toml.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/cli/tools/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/web/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/web/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/web/api/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/web/api/echo.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/web/api/sse/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/web/api/sse/echo.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/web/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/web/client/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/web/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/web/tools/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/command/templates/web/tools/mq.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/nexus/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/__main__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/agents/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/agents/factory.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/agents/prompts.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/cdp/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/cdp/browser.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/cdp/capabilities/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/cdp/capabilities/console.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/cdp/capabilities/dom.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/cdp/capabilities/network.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/cdp/capabilities/page_errors.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/cdp/capabilities/performance.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/cdp/capabilities/screenshot.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/cdp/client.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/cdp/protocol.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/cdp/repl.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/cli.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/commands/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/commands/cdp_cmd.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/commands/chat_cmd.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/commands/create_cmd.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/commands/evaluate_cmd.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/commands/init_cmd.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/commands/memory_cmd.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/commands/resume_cmd.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/commands/rollback_cmd.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/commands/run_cmd.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/core/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/core/backend.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/core/config.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/core/display.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/core/git_integration.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/core/llm.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/core/state.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/evaluate/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/evaluate/api_evaluator.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/memory/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/memory/compressor.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/memory/full.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/memory/hot.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/memory/manager.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/memory/warm.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/mode/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/mode/create.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/mode/optimize.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/models/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/models/config_models.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/rl/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/rl/baseline_tests.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/rl/checkpoint.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/rl/convergence.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/rl/diagnosis.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/rl/engine.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/rl/environment.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/rl/experience.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/rl/harness_prompts.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/rl/history.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/rl/optimization_logger.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/rl/pre_validation.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/rl/reward.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/rl/strategy_bandit.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/rl/strategy_generator.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/rl/strategy_prompts.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycli/skills/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/agent/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/agent/agent_manager.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/agent/chat_events.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/agent/mcp/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/agent/mcp/models.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/agent/mcp/tool_loader.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/agent/sandbox/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/agent/sandbox/sandbox_pool.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/agent/sandbox/sandbox_recovery.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/agent/sandbox/session.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/agent/summarization_utils.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/auth/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/auth/ldap_service.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/auth/oa_cache.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/auth/oa_crypto.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/auth/oa_service.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/config/Config.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/config/DatabaseConfig.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/config/ElasticsearchConfig.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/config/EmbeddingConfig.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/config/LLMConfig.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/config/LangfuseConfig.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/config/MQConfig.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/config/PgConfig.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/config/RedisConfig.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/config/RerankerConfig.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/config/SentryConfig.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/config/XxlJobConfig.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/config/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/database/async_base_db_service.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/database/async_database_service.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/database/base_db_service.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/database/database_service.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/database/elasticsearch_service.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/database/pg_checkpoint_service.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/database/redis_service.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/database/token_usage_db_service.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/health/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/health/health_check.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/health/metrics.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/health/ping.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/heartbeat_process/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/heartbeat_process/heartbeat_config.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/heartbeat_process/heartbeat_process_manager.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/heartbeat_process/heartbeat_process_worker.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/llm/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/llm/embedding.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/llm/get_llm.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/llm/llm_logger.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/llm/llm_tokens.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/llm/llm_with_token_tracking.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/llm/native_with_fallback_runnable.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/llm/output_fixing_runnable.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/llm/struct_token.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/llm/sy_langfuse.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/llm/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/llm/tiktoken_cache/fb374d419588a4632f3f557e76b4b70aebbca790 +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/llm/token_usage_es_service.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/llm/token_usage_mysql_service.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/llm/token_utils.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/llm/usage_token.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/logging/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/logging/async_sql_logger.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/logging/kafka_log.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/logging/logger_levels.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/logging/logger_wrapper.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/logging/process_logger.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/logging/sql_logger.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/mcp_server/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/mcp_server/server.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/middleware/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/middleware/context.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/middleware/cors.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/middleware/docs.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/middleware/exception.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/middleware/middleware.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/middleware/monitor_memory.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/middleware/mq.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/middleware/sandbox.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/middleware/timeout.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/middleware/token_tracking.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/middleware/tool_result_truncation.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/middleware/traceid.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/models/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/models/base_http.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/models/log.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/models/mcp_server_config.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/models/mqlistener_config.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/models/mqmsg_model.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/models/mqsend_config.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/models/sandbox.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/models/sso_user.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/models/token_usage.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/models/token_usage_mysql.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/models/xxljob_handler_config.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/notice/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/notice/uvicorn_monitor.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/notice/wecom_message.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/rabbitmq/process_pool_consumer.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/rabbitmq/rabbitmq_client.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/rabbitmq/rabbitmq_pool.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/rabbitmq/rabbitmq_service.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/rabbitmq/rabbitmq_service_client_manager.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/rabbitmq/rabbitmq_service_connection_monitor.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/rabbitmq/rabbitmq_service_consumer_manager.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/rabbitmq/rabbitmq_service_core.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/rabbitmq/rabbitmq_service_producer_manager.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/sentry/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/sentry/sy_sentry.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/services.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/sse/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/sse/event.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/sse/sse.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/synacos/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/synacos/example.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/synacos/example2.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/synacos/feign.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/synacos/feign_client.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/synacos/nacos_client_base.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/synacos/nacos_config_manager.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/synacos/nacos_heartbeat_manager.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/synacos/nacos_service.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/synacos/nacos_service_discovery.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/synacos/nacos_service_registration.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/synacos/param.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tests/deep_agent_server.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tests/test_consumer_loss_rootcause.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tests/test_consumer_recovery.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tests/test_deep_agent.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tests/test_dynamic_max_tokens.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tests/test_email.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tests/test_encoding_cache.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tests/test_fix_verification.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tests/test_mcp_server.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tests/test_minimax_reasoning.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tests/test_mq.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tests/test_oa_login.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tests/test_real_summarization.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tests/test_summarization_config.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tests/test_summarization_real.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tests/test_summary_leak_e2e.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tools/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tools/async_utils.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tools/docs.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tools/env.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tools/merge_headers.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tools/snowflake.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tools/syemail.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/tools/timing.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/xxljob/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/xxljob/xxljob_service.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon_python_lib.egg-info/SOURCES.txt +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon_python_lib.egg-info/dependency_links.txt +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon_python_lib.egg-info/entry_points.txt +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon_python_lib.egg-info/requires.txt +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon_python_lib.egg-info/top_level.txt +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/tests/test_asyncio_logging.py +0 -0
- {sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/tests/test_sycli.py +0 -0
{sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/agent/deep_agent.py
RENAMED
|
@@ -762,13 +762,10 @@ class DeepAgent:
|
|
|
762
762
|
|
|
763
763
|
# 发送 tool_call 事件,前端根据 tool_call_id 更新
|
|
764
764
|
tc_id = existing_tc["id"]
|
|
765
|
-
if tc_id:
|
|
765
|
+
if tc_id and tc_id not in seen_tool_call_ids:
|
|
766
766
|
current_args = existing_tc["args"]
|
|
767
|
-
# 只有以下情况才发送:
|
|
768
|
-
# 1. 首次出现(args 为空,先发一个占位)
|
|
769
|
-
# 2. args 解析成功(有实质更新)
|
|
770
767
|
is_first = not existing_tc.get("_sent")
|
|
771
|
-
if is_first
|
|
768
|
+
if is_first:
|
|
772
769
|
event = ChatEventBuilder.tool_call(
|
|
773
770
|
name=existing_tc["name"],
|
|
774
771
|
args=current_args,
|
|
@@ -777,6 +774,7 @@ class DeepAgent:
|
|
|
777
774
|
agent=DEFAULT_AGENT_NAME,
|
|
778
775
|
)
|
|
779
776
|
existing_tc["_sent"] = True
|
|
777
|
+
seen_tool_call_ids.add(tc_id)
|
|
780
778
|
if on_event:
|
|
781
779
|
await on_event(event)
|
|
782
780
|
yield event
|
|
@@ -788,6 +786,9 @@ class DeepAgent:
|
|
|
788
786
|
tc_id = tc.get("id", "")
|
|
789
787
|
if not tc_id:
|
|
790
788
|
continue
|
|
789
|
+
if tc_id in seen_tool_call_ids:
|
|
790
|
+
continue
|
|
791
|
+
seen_tool_call_ids.add(tc_id)
|
|
791
792
|
|
|
792
793
|
tc_name = tc.get("name", "unknown")
|
|
793
794
|
tc_args = tc.get("args", {})
|
|
@@ -1237,7 +1238,11 @@ async def _sync_skills_to_sandbox(
|
|
|
1237
1238
|
skills_dir: str,
|
|
1238
1239
|
backend: HTTPSandboxBackend,
|
|
1239
1240
|
) -> None:
|
|
1240
|
-
"""同步 skills 到沙箱(按版本检查,版本不一致则覆盖)
|
|
1241
|
+
"""同步 skills SKILL.md 到沙箱(按版本检查,版本不一致则覆盖)
|
|
1242
|
+
|
|
1243
|
+
只同步 SKILL.md 文件,不同步 scripts/ 等大目录。
|
|
1244
|
+
scripts/ 在 agent 实际调用时由 HTTPSandboxBackend._lazy_sync_skill_from_path 按需同步。
|
|
1245
|
+
"""
|
|
1241
1246
|
if not os.path.isdir(skills_dir):
|
|
1242
1247
|
return
|
|
1243
1248
|
|
|
@@ -1291,9 +1296,15 @@ async def _sync_skills_to_sandbox(
|
|
|
1291
1296
|
f"[DeepAgent] 删除旧版技能失败: {skill_name}, {e}")
|
|
1292
1297
|
continue
|
|
1293
1298
|
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1299
|
+
# 只同步 SKILL.md(不再同步整个目录)
|
|
1300
|
+
if os.path.isfile(local_skill_md):
|
|
1301
|
+
with open(local_skill_md, "rb") as f:
|
|
1302
|
+
content = f.read()
|
|
1303
|
+
await backend.aupload_files([
|
|
1304
|
+
(f"/skills/{skill_name}/SKILL.md", content)
|
|
1305
|
+
])
|
|
1306
|
+
SYLogger.info(
|
|
1307
|
+
f"[DeepAgent] 同步技能元数据到沙箱: {skill_name} v{local_version} (仅 SKILL.md)")
|
|
1297
1308
|
except Exception as e:
|
|
1298
1309
|
SYLogger.warning(f"[DeepAgent] 技能同步失败: {e}")
|
|
1299
1310
|
|
|
@@ -1303,16 +1314,14 @@ async def _create_sandbox_backend(
|
|
|
1303
1314
|
config: AgentConfig,
|
|
1304
1315
|
project_root: Path,
|
|
1305
1316
|
) -> HTTPSandboxBackend:
|
|
1306
|
-
"""创建并同步沙箱后端
|
|
1307
|
-
sync_dirs = []
|
|
1317
|
+
"""创建并同步沙箱后端
|
|
1308
1318
|
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
skills_dir.mkdir(parents=True, exist_ok=True)
|
|
1314
|
-
sync_dirs.append((str(skills_dir), "/skills"))
|
|
1319
|
+
注意:skills 目录不再通过 sync_dirs 全量同步,
|
|
1320
|
+
而是由 _sync_skills_to_sandbox() 做版本感知的增量同步。
|
|
1321
|
+
"""
|
|
1322
|
+
sync_dirs = []
|
|
1315
1323
|
|
|
1324
|
+
# skills 不再通过 sync_dirs 全量同步,改由 _sync_skills_to_sandbox() 按版本增量同步
|
|
1316
1325
|
if config.memory_dir:
|
|
1317
1326
|
memory_dir = Path(config.memory_dir)
|
|
1318
1327
|
else:
|
|
@@ -1320,12 +1329,19 @@ async def _create_sandbox_backend(
|
|
|
1320
1329
|
memory_dir.mkdir(parents=True, exist_ok=True)
|
|
1321
1330
|
sync_dirs.append((str(memory_dir), "/memory"))
|
|
1322
1331
|
|
|
1332
|
+
# 确定 skills_dir,传递给沙箱后端用于懒同步
|
|
1333
|
+
if config.skills_dir:
|
|
1334
|
+
skills_dir_for_backend = str(Path(config.skills_dir))
|
|
1335
|
+
else:
|
|
1336
|
+
skills_dir_for_backend = str(project_root / "skills")
|
|
1337
|
+
|
|
1323
1338
|
sandbox_backend = HTTPSandboxBackend.from_nacos(
|
|
1324
1339
|
service_name=config.sandbox_service_name,
|
|
1325
1340
|
user_id=user_id,
|
|
1326
1341
|
timeout=config.sandbox_timeout,
|
|
1327
1342
|
sync_dirs=sync_dirs,
|
|
1328
1343
|
auto_sync=True,
|
|
1344
|
+
skills_dir=skills_dir_for_backend,
|
|
1329
1345
|
)
|
|
1330
1346
|
|
|
1331
1347
|
try:
|
{sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/agent/multi_agent_team.py
RENAMED
|
@@ -655,16 +655,14 @@ async def _create_sandbox_backend_for_team(
|
|
|
655
655
|
config: TeamConfig,
|
|
656
656
|
project_root: Path,
|
|
657
657
|
) -> HTTPSandboxBackend:
|
|
658
|
-
"""创建并同步沙箱后端(团队版本)
|
|
659
|
-
sync_dirs = []
|
|
658
|
+
"""创建并同步沙箱后端(团队版本)
|
|
660
659
|
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
skills_dir.mkdir(parents=True, exist_ok=True)
|
|
666
|
-
sync_dirs.append((str(skills_dir), "/skills"))
|
|
660
|
+
注意:skills 目录不再通过 sync_dirs 全量同步,
|
|
661
|
+
而是由 _sync_skills_to_sandbox() 做版本感知的增量同步。
|
|
662
|
+
"""
|
|
663
|
+
sync_dirs = []
|
|
667
664
|
|
|
665
|
+
# skills 不再通过 sync_dirs 全量同步,改由 _sync_skills_to_sandbox() 按版本增量同步
|
|
668
666
|
if config.memory_dir:
|
|
669
667
|
memory_dir = Path(config.memory_dir)
|
|
670
668
|
else:
|
|
@@ -672,6 +670,12 @@ async def _create_sandbox_backend_for_team(
|
|
|
672
670
|
memory_dir.mkdir(parents=True, exist_ok=True)
|
|
673
671
|
sync_dirs.append((str(memory_dir), "/memory"))
|
|
674
672
|
|
|
673
|
+
# 确定 skills_dir,传递给沙箱后端用于懒同步
|
|
674
|
+
if config.skills_dir:
|
|
675
|
+
skills_dir_for_backend = str(Path(config.skills_dir))
|
|
676
|
+
else:
|
|
677
|
+
skills_dir_for_backend = str(project_root / "skills")
|
|
678
|
+
|
|
675
679
|
sandbox_backend = HTTPSandboxBackend.from_nacos(
|
|
676
680
|
service_name=config.sandbox_service_name,
|
|
677
681
|
user_id=user_id,
|
|
@@ -679,6 +683,7 @@ async def _create_sandbox_backend_for_team(
|
|
|
679
683
|
sync_dirs=sync_dirs,
|
|
680
684
|
auto_sync=True,
|
|
681
685
|
version=get_env_var('VERSION') or None,
|
|
686
|
+
skills_dir=skills_dir_for_backend,
|
|
682
687
|
)
|
|
683
688
|
|
|
684
689
|
# 健康检查
|
{sycommon_python_lib-0.2.5a37 → sycommon_python_lib-0.2.5a39}/src/sycommon/agent/sandbox/file_ops.py
RENAMED
|
@@ -182,6 +182,7 @@ class FileOperationsMixin:
|
|
|
182
182
|
def ls(self: "HTTPSandboxBackend", path: str) -> LsResult:
|
|
183
183
|
"""列出目录内容"""
|
|
184
184
|
try:
|
|
185
|
+
self._lazy_sync_skill_from_path_sync(path)
|
|
185
186
|
self._ensure_synced_sync()
|
|
186
187
|
SYLogger.info(f"[Sandbox] 列出目录: {path}")
|
|
187
188
|
result = self._post_sync(f"{SANDBOX_API_PREFIX}/ls", {
|
|
@@ -198,6 +199,7 @@ class FileOperationsMixin:
|
|
|
198
199
|
async def als(self: "HTTPSandboxBackend", path: str, *, timeout: int = None) -> LsResult:
|
|
199
200
|
"""异步列出目录内容"""
|
|
200
201
|
try:
|
|
202
|
+
await self._lazy_sync_skill_from_path(path)
|
|
201
203
|
await self._ensure_synced_async()
|
|
202
204
|
SYLogger.info(f"[Sandbox] 异步列出目录: {path}")
|
|
203
205
|
result = await self._post_async_with_failover(f"{SANDBOX_API_PREFIX}/ls", {
|
|
@@ -221,6 +223,9 @@ class FileOperationsMixin:
|
|
|
221
223
|
) -> ReadResult:
|
|
222
224
|
"""读取文件内容"""
|
|
223
225
|
try:
|
|
226
|
+
# 按需懒同步:检测是否读取 skill 资源
|
|
227
|
+
self._lazy_sync_skill_from_path_sync(file_path)
|
|
228
|
+
|
|
224
229
|
self._ensure_synced_sync()
|
|
225
230
|
SYLogger.info(
|
|
226
231
|
f"[Sandbox] 读取文件: {file_path} (offset={offset}, limit={limit})")
|
|
@@ -256,6 +261,9 @@ class FileOperationsMixin:
|
|
|
256
261
|
) -> ReadResult:
|
|
257
262
|
"""异步读取文件内容"""
|
|
258
263
|
try:
|
|
264
|
+
# 按需懒同步:检测是否读取 skill 资源
|
|
265
|
+
await self._lazy_sync_skill_from_path(file_path)
|
|
266
|
+
|
|
259
267
|
await self._ensure_synced_async()
|
|
260
268
|
SYLogger.info(
|
|
261
269
|
f"[Sandbox] 异步读取文件: {file_path} (offset={offset}, limit={limit})")
|
|
@@ -302,6 +310,7 @@ class FileOperationsMixin:
|
|
|
302
310
|
/conversation_history/ 路径)。设为 False 时,文件已存在返回错误。
|
|
303
311
|
"""
|
|
304
312
|
try:
|
|
313
|
+
self._lazy_sync_skill_from_path_sync(file_path)
|
|
305
314
|
self._ensure_synced_sync()
|
|
306
315
|
SYLogger.info(f"[Sandbox] 写入文件: {file_path} ({len(content)} 字符)")
|
|
307
316
|
result = self._post_sync(f"{SANDBOX_API_PREFIX}/write", {
|
|
@@ -340,6 +349,7 @@ class FileOperationsMixin:
|
|
|
340
349
|
timeout: 请求超时时间。
|
|
341
350
|
"""
|
|
342
351
|
try:
|
|
352
|
+
await self._lazy_sync_skill_from_path(file_path)
|
|
343
353
|
await self._ensure_synced_async()
|
|
344
354
|
SYLogger.info(f"[Sandbox] 异步写入文件: {file_path} ({len(content)} 字符)")
|
|
345
355
|
result = await self._post_async_with_failover(f"{SANDBOX_API_PREFIX}/write", {
|
|
@@ -374,6 +384,7 @@ class FileOperationsMixin:
|
|
|
374
384
|
) -> EditResult:
|
|
375
385
|
"""编辑文件"""
|
|
376
386
|
try:
|
|
387
|
+
self._lazy_sync_skill_from_path_sync(file_path)
|
|
377
388
|
self._ensure_synced_sync()
|
|
378
389
|
result = self._post_sync(f"{SANDBOX_API_PREFIX}/edit", {
|
|
379
390
|
"file_path": file_path,
|
|
@@ -402,6 +413,7 @@ class FileOperationsMixin:
|
|
|
402
413
|
) -> EditResult:
|
|
403
414
|
"""异步编辑文件"""
|
|
404
415
|
try:
|
|
416
|
+
await self._lazy_sync_skill_from_path(file_path)
|
|
405
417
|
await self._ensure_synced_async()
|
|
406
418
|
result = await self._post_async_with_failover(f"{SANDBOX_API_PREFIX}/edit", {
|
|
407
419
|
"file_path": file_path,
|
|
@@ -424,6 +436,7 @@ class FileOperationsMixin:
|
|
|
424
436
|
def glob(self: "HTTPSandboxBackend", pattern: str, path: str | None = None) -> GlobResult:
|
|
425
437
|
"""glob 搜索文件"""
|
|
426
438
|
try:
|
|
439
|
+
self._lazy_sync_skill_from_path_sync(path or "/")
|
|
427
440
|
self._ensure_synced_sync()
|
|
428
441
|
result = self._post_sync(f"{SANDBOX_API_PREFIX}/glob", {
|
|
429
442
|
"pattern": pattern,
|
|
@@ -439,6 +452,7 @@ class FileOperationsMixin:
|
|
|
439
452
|
async def aglob(self: "HTTPSandboxBackend", pattern: str, path: str | None = None, *, timeout: int = None) -> GlobResult:
|
|
440
453
|
"""异步 glob 搜索文件"""
|
|
441
454
|
try:
|
|
455
|
+
await self._lazy_sync_skill_from_path(path or "/")
|
|
442
456
|
await self._ensure_synced_async()
|
|
443
457
|
result = await self._post_async_with_failover(f"{SANDBOX_API_PREFIX}/glob", {
|
|
444
458
|
"pattern": pattern,
|
|
@@ -456,6 +470,7 @@ class FileOperationsMixin:
|
|
|
456
470
|
def tree(self: "HTTPSandboxBackend", path: str = "/", max_depth: int = 30, max_files: int = 0) -> TreeResult:
|
|
457
471
|
"""以树形结构展示目录"""
|
|
458
472
|
try:
|
|
473
|
+
self._lazy_sync_skill_from_path_sync(path)
|
|
459
474
|
self._ensure_synced_sync()
|
|
460
475
|
SYLogger.info(f"[Sandbox] tree: {path}")
|
|
461
476
|
result = self._post_sync(f"{SANDBOX_API_PREFIX}/tree", {
|
|
@@ -476,6 +491,7 @@ class FileOperationsMixin:
|
|
|
476
491
|
async def atree(self: "HTTPSandboxBackend", path: str = "/", max_depth: int = 30, max_files: int = 0, *, timeout: int = None) -> TreeResult:
|
|
477
492
|
"""异步以树形结构展示目录"""
|
|
478
493
|
try:
|
|
494
|
+
await self._lazy_sync_skill_from_path(path)
|
|
479
495
|
await self._ensure_synced_async()
|
|
480
496
|
SYLogger.info(f"[Sandbox] 异步 tree: {path}")
|
|
481
497
|
result = await self._post_async_with_failover(f"{SANDBOX_API_PREFIX}/tree", {
|
|
@@ -501,6 +517,7 @@ class FileOperationsMixin:
|
|
|
501
517
|
) -> GrepResult:
|
|
502
518
|
"""搜索文件内容"""
|
|
503
519
|
try:
|
|
520
|
+
self._lazy_sync_skill_from_path_sync(path or "/")
|
|
504
521
|
self._ensure_synced_sync()
|
|
505
522
|
result = self._post_sync(f"{SANDBOX_API_PREFIX}/grep", {
|
|
506
523
|
"pattern": pattern,
|
|
@@ -534,6 +551,7 @@ class FileOperationsMixin:
|
|
|
534
551
|
) -> GrepResult:
|
|
535
552
|
"""异步搜索文件内容"""
|
|
536
553
|
try:
|
|
554
|
+
await self._lazy_sync_skill_from_path(path or "/")
|
|
537
555
|
await self._ensure_synced_async()
|
|
538
556
|
result = await self._post_async_with_failover(f"{SANDBOX_API_PREFIX}/grep", {
|
|
539
557
|
"pattern": pattern,
|
|
@@ -564,6 +582,7 @@ class FileOperationsMixin:
|
|
|
564
582
|
) -> DeleteResult:
|
|
565
583
|
"""删除文件或文件夹"""
|
|
566
584
|
try:
|
|
585
|
+
self._lazy_sync_skill_from_path_sync(path)
|
|
567
586
|
self._ensure_synced_sync()
|
|
568
587
|
SYLogger.info(f"[Sandbox] 删除: {path} (recursive={recursive})")
|
|
569
588
|
result = self._post_sync(f"{SANDBOX_API_PREFIX}/delete", {
|
|
@@ -593,6 +612,7 @@ class FileOperationsMixin:
|
|
|
593
612
|
) -> DeleteResult:
|
|
594
613
|
"""异步删除文件或文件夹"""
|
|
595
614
|
try:
|
|
615
|
+
await self._lazy_sync_skill_from_path(path)
|
|
596
616
|
await self._ensure_synced_async()
|
|
597
617
|
SYLogger.info(f"[Sandbox] 异步删除: {path} (recursive={recursive})")
|
|
598
618
|
result = await self._post_async_with_failover(f"{SANDBOX_API_PREFIX}/delete", {
|
|
@@ -618,6 +638,7 @@ class FileOperationsMixin:
|
|
|
618
638
|
async def astat(self: "HTTPSandboxBackend", path: str, *, timeout: int = None) -> "StatResult":
|
|
619
639
|
"""异步检查文件或目录状态"""
|
|
620
640
|
try:
|
|
641
|
+
await self._lazy_sync_skill_from_path(path)
|
|
621
642
|
await self._ensure_synced_async()
|
|
622
643
|
SYLogger.info(f"[Sandbox] 异步查询文件状态: {path}")
|
|
623
644
|
result = await self._post_async_with_failover(f"{SANDBOX_API_PREFIX}/stat", {
|
|
@@ -14,7 +14,7 @@ import sys
|
|
|
14
14
|
import tempfile
|
|
15
15
|
import threading
|
|
16
16
|
import requests
|
|
17
|
-
from pathlib import Path
|
|
17
|
+
from pathlib import Path, PurePosixPath
|
|
18
18
|
from typing import Optional, List
|
|
19
19
|
|
|
20
20
|
import aiohttp
|
|
@@ -126,6 +126,7 @@ class HTTPSandboxBackend(FileOperationsMixin, SandboxBackendProtocol):
|
|
|
126
126
|
nacos_group: str = "DEFAULT_GROUP",
|
|
127
127
|
token: str = None,
|
|
128
128
|
env: dict[str, str] = None,
|
|
129
|
+
skills_dir: str = None,
|
|
129
130
|
):
|
|
130
131
|
"""
|
|
131
132
|
初始化 HTTP 沙箱后端
|
|
@@ -139,6 +140,7 @@ class HTTPSandboxBackend(FileOperationsMixin, SandboxBackendProtocol):
|
|
|
139
140
|
nacos_service_name: Nacos 服务名(用于故障转移时重新发现服务)
|
|
140
141
|
nacos_group: Nacos 服务分组
|
|
141
142
|
env: 注入到沙箱的环境变量字典,每次执行命令时自动前置 export
|
|
143
|
+
skills_dir: 本地 skills 目录路径,用于 execute 时按需懒同步 scripts/
|
|
142
144
|
"""
|
|
143
145
|
self._base_url = base_url.rstrip("/")
|
|
144
146
|
self._user_id = user_id.lower().replace(" ", "") if user_id else user_id
|
|
@@ -149,6 +151,10 @@ class HTTPSandboxBackend(FileOperationsMixin, SandboxBackendProtocol):
|
|
|
149
151
|
self._workspace_verified = False
|
|
150
152
|
self._local_mode: Optional[bool] = None
|
|
151
153
|
|
|
154
|
+
# Skills 懒同步:记录本地 skills 目录,访问时按需同步整个 skill 子目录
|
|
155
|
+
self._skills_dir = skills_dir
|
|
156
|
+
self._synced_skills: set[str] = set() # 已完整同步的 skill 名称
|
|
157
|
+
|
|
152
158
|
# Token authentication: instance-level > env var
|
|
153
159
|
self._token = token if token is not None else os.environ.get(
|
|
154
160
|
"SANDBOX_TOKEN", "")
|
|
@@ -244,6 +250,7 @@ class HTTPSandboxBackend(FileOperationsMixin, SandboxBackendProtocol):
|
|
|
244
250
|
auto_sync: bool = False,
|
|
245
251
|
load_balance: bool = True,
|
|
246
252
|
env: dict[str, str] = None,
|
|
253
|
+
skills_dir: str = None,
|
|
247
254
|
) -> "HTTPSandboxBackend":
|
|
248
255
|
"""
|
|
249
256
|
从 Nacos 服务发现创建后端实例
|
|
@@ -257,6 +264,7 @@ class HTTPSandboxBackend(FileOperationsMixin, SandboxBackendProtocol):
|
|
|
257
264
|
sync_dirs: 要同步的目录列表 [(本地路径, 沙箱路径), ...]
|
|
258
265
|
auto_sync: 是否在首次文件操作时自动同步
|
|
259
266
|
load_balance: 是否基于 user_id 进行负载均衡(默认 True)
|
|
267
|
+
skills_dir: 本地 skills 目录路径,用于 execute 时按需懒同步 scripts/
|
|
260
268
|
|
|
261
269
|
Returns:
|
|
262
270
|
HTTPSandboxBackend 实例
|
|
@@ -279,6 +287,7 @@ class HTTPSandboxBackend(FileOperationsMixin, SandboxBackendProtocol):
|
|
|
279
287
|
sync_dirs=sync_dirs,
|
|
280
288
|
auto_sync=auto_sync,
|
|
281
289
|
env=env,
|
|
290
|
+
skills_dir=skills_dir,
|
|
282
291
|
)
|
|
283
292
|
|
|
284
293
|
from sycommon.synacos.nacos_service import NacosService
|
|
@@ -330,6 +339,7 @@ class HTTPSandboxBackend(FileOperationsMixin, SandboxBackendProtocol):
|
|
|
330
339
|
nacos_service_name=service_name,
|
|
331
340
|
nacos_group=group,
|
|
332
341
|
env=env,
|
|
342
|
+
skills_dir=skills_dir,
|
|
333
343
|
)
|
|
334
344
|
|
|
335
345
|
@classmethod
|
|
@@ -344,17 +354,22 @@ class HTTPSandboxBackend(FileOperationsMixin, SandboxBackendProtocol):
|
|
|
344
354
|
auto_sync: bool = False,
|
|
345
355
|
load_balance: bool = True,
|
|
346
356
|
env: dict[str, str] = None,
|
|
357
|
+
skills_dir: str = None,
|
|
347
358
|
) -> "HTTPSandboxBackend":
|
|
348
359
|
"""异步从 Nacos 服务发现创建后端实例"""
|
|
349
360
|
return await asyncio.to_thread(
|
|
350
361
|
cls.from_nacos,
|
|
351
|
-
service_name, user_id, group, version, timeout, sync_dirs, auto_sync, load_balance, env,
|
|
362
|
+
service_name, user_id, group, version, timeout, sync_dirs, auto_sync, load_balance, env, skills_dir,
|
|
352
363
|
)
|
|
353
364
|
|
|
354
365
|
# ============== 内部方法 - 同步版本 ==============
|
|
355
366
|
|
|
356
367
|
def _refresh_from_nacos_and_switch_sync(self) -> bool:
|
|
357
|
-
"""从 Nacos 重新获取服务实例并切换(同步版本)
|
|
368
|
+
"""从 Nacos 重新获取服务实例并切换(同步版本)
|
|
369
|
+
|
|
370
|
+
优先从 MinIO 恢复用户文件到新沙箱,避免沙箱间互相迁移脏数据。
|
|
371
|
+
只有 MinIO 不可用时才尝试从旧沙箱拉取。
|
|
372
|
+
"""
|
|
358
373
|
# 防止递归:如果在故障转移过程中再次调用,直接返回 False
|
|
359
374
|
if getattr(self, '_in_failover', False):
|
|
360
375
|
SYLogger.warning("[Sandbox] 已在故障转移过程中,跳过重复调用")
|
|
@@ -399,33 +414,40 @@ class HTTPSandboxBackend(FileOperationsMixin, SandboxBackendProtocol):
|
|
|
399
414
|
old_url = self._base_url
|
|
400
415
|
SYLogger.info(f"[Sandbox] 准备切换服务: {old_url} -> {new_url}")
|
|
401
416
|
|
|
402
|
-
# 1.
|
|
403
|
-
workspace_files = []
|
|
404
|
-
try:
|
|
405
|
-
sync_result = self._sync_workspace_sync()
|
|
406
|
-
workspace_files = sync_result.get("files", [])
|
|
407
|
-
SYLogger.info(
|
|
408
|
-
f"[Sandbox] 从旧服务获取 {len(workspace_files)} 个工作空间文件")
|
|
409
|
-
except Exception as e:
|
|
410
|
-
SYLogger.warning(f"[Sandbox] 获取工作空间文件失败: {e}")
|
|
411
|
-
|
|
412
|
-
# 2. 切换到新服务
|
|
417
|
+
# 1. 切换到新服务
|
|
413
418
|
self._base_url = new_url
|
|
414
419
|
self._synced = False
|
|
415
420
|
|
|
416
|
-
#
|
|
421
|
+
# 2. 同步配置的目录到新服务(skills, memory 等本地文件)
|
|
417
422
|
if self._sync_dirs:
|
|
418
423
|
SYLogger.info(f"[Sandbox] 重新同步配置目录到新服务...")
|
|
419
424
|
self._sync_sync()
|
|
420
425
|
|
|
421
|
-
#
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
426
|
+
# 3. 优先从 MinIO 恢复用户工作空间文件
|
|
427
|
+
workspace_restored = False
|
|
428
|
+
try:
|
|
429
|
+
from sycommon.agent.sandbox.minio_sync import MinioSyncService
|
|
430
|
+
minio = MinioSyncService()
|
|
431
|
+
if minio.is_available():
|
|
432
|
+
SYLogger.info(
|
|
433
|
+
f"[Sandbox] 从 MinIO 恢复用户文件到新沙箱...")
|
|
434
|
+
import asyncio
|
|
435
|
+
loop = asyncio.new_event_loop()
|
|
436
|
+
try:
|
|
437
|
+
restored = loop.run_until_complete(
|
|
438
|
+
minio.restore_from_minio(self, self._user_id))
|
|
439
|
+
workspace_restored = restored > 0
|
|
440
|
+
SYLogger.info(
|
|
441
|
+
f"[Sandbox] MinIO 恢复完成: {restored} 个文件")
|
|
442
|
+
finally:
|
|
443
|
+
loop.close()
|
|
444
|
+
except Exception as e:
|
|
445
|
+
SYLogger.warning(
|
|
446
|
+
f"[Sandbox] MinIO 恢复失败: {e}")
|
|
447
|
+
|
|
448
|
+
if not workspace_restored:
|
|
427
449
|
SYLogger.info(
|
|
428
|
-
f"[Sandbox]
|
|
450
|
+
f"[Sandbox] MinIO 无可用数据,新沙箱将从空工作空间开始")
|
|
429
451
|
|
|
430
452
|
SYLogger.info(f"[Sandbox] 服务切换完成: {old_url} -> {new_url}")
|
|
431
453
|
return True
|
|
@@ -702,9 +724,17 @@ class HTTPSandboxBackend(FileOperationsMixin, SandboxBackendProtocol):
|
|
|
702
724
|
)
|
|
703
725
|
|
|
704
726
|
async def aexecute(self, command: str, *, timeout: int = None) -> ExecuteResponse:
|
|
705
|
-
"""异步执行 shell 命令(服务端负责路径隔离和目录初始化)
|
|
727
|
+
"""异步执行 shell 命令(服务端负责路径隔离和目录初始化)
|
|
728
|
+
|
|
729
|
+
如果命令引用了 /skills/<name>/ 下的资源,
|
|
730
|
+
会自动按需同步该 skill 的整个目录到沙箱。
|
|
731
|
+
"""
|
|
706
732
|
command = self._inject_env(command)
|
|
707
733
|
SYLogger.info(f"[Sandbox] aexecute 开始: command={command}")
|
|
734
|
+
|
|
735
|
+
# 按需懒同步:检测命令中是否引用了 skill 资源
|
|
736
|
+
await self._lazy_sync_skill_from_path(command)
|
|
737
|
+
|
|
708
738
|
await self._ensure_synced_async()
|
|
709
739
|
SYLogger.info(f"[Sandbox] _ensure_synced_async 完成,开始执行命令: {command}")
|
|
710
740
|
try:
|
|
@@ -728,6 +758,79 @@ class HTTPSandboxBackend(FileOperationsMixin, SandboxBackendProtocol):
|
|
|
728
758
|
truncated=False
|
|
729
759
|
)
|
|
730
760
|
|
|
761
|
+
async def _lazy_sync_skill_from_path(self, path: str) -> None:
|
|
762
|
+
"""从文件路径中检测是否访问了 skill 资源,按需同步整个 skill 目录
|
|
763
|
+
|
|
764
|
+
检测路径中是否包含 /skills/<name>/ 模式(不限 scripts/,覆盖
|
|
765
|
+
assets/、references/ 及任意自定义子目录)。
|
|
766
|
+
如果该 skill 尚未同步,则上传整个 skill 目录到沙箱。
|
|
767
|
+
"""
|
|
768
|
+
if not self._skills_dir:
|
|
769
|
+
return
|
|
770
|
+
|
|
771
|
+
import re
|
|
772
|
+
# 匹配 /skills/<skill_name>/ 或 skills/<skill_name>/
|
|
773
|
+
match = re.search(r'/skills/([a-zA-Z0-9_\-]+)/', path)
|
|
774
|
+
if not match:
|
|
775
|
+
match = re.search(r'(?:^|\s|")skills/([a-zA-Z0-9_\-]+)/', path)
|
|
776
|
+
if not match:
|
|
777
|
+
return
|
|
778
|
+
|
|
779
|
+
skill_name = match.group(1)
|
|
780
|
+
if skill_name in self._synced_skills:
|
|
781
|
+
return
|
|
782
|
+
|
|
783
|
+
skill_dir = os.path.join(self._skills_dir, skill_name)
|
|
784
|
+
if not os.path.isdir(skill_dir):
|
|
785
|
+
self._synced_skills.add(skill_name)
|
|
786
|
+
return
|
|
787
|
+
|
|
788
|
+
try:
|
|
789
|
+
await self.async_sync_dirs([
|
|
790
|
+
(skill_dir, f"/skills/{skill_name}")
|
|
791
|
+
])
|
|
792
|
+
self._synced_skills.add(skill_name)
|
|
793
|
+
SYLogger.info(
|
|
794
|
+
f"[Sandbox] 懒同步技能目录: {skill_name}/")
|
|
795
|
+
except Exception as e:
|
|
796
|
+
SYLogger.warning(
|
|
797
|
+
f"[Sandbox] 懒同步技能目录失败: {skill_name}, {e}")
|
|
798
|
+
|
|
799
|
+
def _lazy_sync_skill_from_path_sync(self, path: str) -> None:
|
|
800
|
+
"""同步版本的懒同步(在同步文件操作中调用)
|
|
801
|
+
|
|
802
|
+
内部使用 asyncio.run_coroutine_threadsafe 或回退到同步上传。
|
|
803
|
+
"""
|
|
804
|
+
if not self._skills_dir:
|
|
805
|
+
return
|
|
806
|
+
|
|
807
|
+
import re
|
|
808
|
+
match = re.search(r'/skills/([a-zA-Z0-9_\-]+)/', path)
|
|
809
|
+
if not match:
|
|
810
|
+
match = re.search(r'(?:^|\s|")skills/([a-zA-Z0-9_\-]+)/', path)
|
|
811
|
+
if not match:
|
|
812
|
+
return
|
|
813
|
+
|
|
814
|
+
skill_name = match.group(1)
|
|
815
|
+
if skill_name in self._synced_skills:
|
|
816
|
+
return
|
|
817
|
+
|
|
818
|
+
skill_dir = os.path.join(self._skills_dir, skill_name)
|
|
819
|
+
if not os.path.isdir(skill_dir):
|
|
820
|
+
self._synced_skills.add(skill_name)
|
|
821
|
+
return
|
|
822
|
+
|
|
823
|
+
try:
|
|
824
|
+
# 同步版本直接调用同步上传方法
|
|
825
|
+
self._upload_directory_sync(
|
|
826
|
+
skill_dir, f"/skills/{skill_name}", mode="full")
|
|
827
|
+
self._synced_skills.add(skill_name)
|
|
828
|
+
SYLogger.info(
|
|
829
|
+
f"[Sandbox] 懒同步技能目录(sync): {skill_name}/")
|
|
830
|
+
except Exception as e:
|
|
831
|
+
SYLogger.warning(
|
|
832
|
+
f"[Sandbox] 懒同步技能目录失败(sync): {skill_name}, {e}")
|
|
833
|
+
|
|
731
834
|
async def _sync_async(self, *, timeout: int = None) -> dict:
|
|
732
835
|
"""同步目录(异步版本)
|
|
733
836
|
|
|
@@ -855,7 +958,7 @@ class HTTPSandboxBackend(FileOperationsMixin, SandboxBackendProtocol):
|
|
|
855
958
|
|
|
856
959
|
local_file = Path(root) / file
|
|
857
960
|
relative_path = local_file.relative_to(local_path)
|
|
858
|
-
sandbox_path = str(
|
|
961
|
+
sandbox_path = str(PurePosixPath(remote_path) / relative_path.as_posix())
|
|
859
962
|
result.append((sandbox_path, local_file))
|
|
860
963
|
return result
|
|
861
964
|
|
|
@@ -1236,7 +1339,7 @@ class HTTPSandboxBackend(FileOperationsMixin, SandboxBackendProtocol):
|
|
|
1236
1339
|
|
|
1237
1340
|
local_file = Path(root) / file
|
|
1238
1341
|
relative_path = local_file.relative_to(local_path)
|
|
1239
|
-
sandbox_path = str(
|
|
1342
|
+
sandbox_path = str(PurePosixPath(remote_path) / relative_path.as_posix())
|
|
1240
1343
|
files_to_upload.append((sandbox_path, local_file))
|
|
1241
1344
|
|
|
1242
1345
|
SYLogger.info(f"[Sandbox] 准备上传 {len(files_to_upload)} 个文件到沙箱")
|
|
@@ -218,6 +218,19 @@ class MinioSyncService(metaclass=SingletonMeta):
|
|
|
218
218
|
"""异步删除 MinIO 中指定前缀下的所有对象"""
|
|
219
219
|
return await asyncio.to_thread(self.remove_prefix, prefix)
|
|
220
220
|
|
|
221
|
+
async def cleanup_user_history(self, user_id: str) -> None:
|
|
222
|
+
"""清理用户沙箱对话历史和工具缓存(沙箱 + MinIO 双删)
|
|
223
|
+
|
|
224
|
+
用于新建会话/重置对话时,确保沙箱和 MinIO 中的
|
|
225
|
+
conversation_history 和 large_tool_results 都被清除,
|
|
226
|
+
避免 restore_from_minio 把旧文件同步回来。
|
|
227
|
+
"""
|
|
228
|
+
uid = user_id.lower().replace(" ", "")
|
|
229
|
+
await asyncio.gather(
|
|
230
|
+
self.aremove_prefix(f"{uid}/current/conversation_history/"),
|
|
231
|
+
self.aremove_prefix(f"{uid}/current/large_tool_results/"),
|
|
232
|
+
)
|
|
233
|
+
|
|
221
234
|
# ============== 查找最近副本 ==============
|
|
222
235
|
|
|
223
236
|
def find_latest_object_key(self, user_id: str, file_path: str) -> Optional[str]:
|
|
@@ -303,7 +316,10 @@ class MinioSyncService(metaclass=SingletonMeta):
|
|
|
303
316
|
async def sync_sandbox_to_minio(self, sandbox_backend, user_id: str) -> int:
|
|
304
317
|
"""扫描沙箱目录,增量同步文件到 MinIO
|
|
305
318
|
|
|
306
|
-
存储到 {user_id}/current/
|
|
319
|
+
存储到 {user_id}/current/ 目录:
|
|
320
|
+
- 上传新增或修改的文件
|
|
321
|
+
- 删除 MinIO 中存在但沙箱中已不存在的文件(双向同步)
|
|
322
|
+
|
|
307
323
|
max_files=0 表示不限制,tree 返回全部文件。
|
|
308
324
|
下载/上传采用并发(每批 CONCURRENT_BATCH 个),避免串行太慢。
|
|
309
325
|
|
|
@@ -329,6 +345,13 @@ class MinioSyncService(metaclass=SingletonMeta):
|
|
|
329
345
|
|
|
330
346
|
sandbox_files = self.collect_sandbox_files(tree_result)
|
|
331
347
|
if not sandbox_files:
|
|
348
|
+
# 沙箱为空,清理 MinIO 中该用户的所有文件
|
|
349
|
+
try:
|
|
350
|
+
removed = await self.aremove_prefix(f"{user_id.lower()}/current/")
|
|
351
|
+
if removed > 0:
|
|
352
|
+
SYLogger.info(f"[MinIO] 沙箱为空,清理 MinIO: user={user_id}, removed={removed}")
|
|
353
|
+
except Exception as e:
|
|
354
|
+
SYLogger.warning(f"[MinIO] 沙箱为空时清理 MinIO 失败: {e}")
|
|
332
355
|
return 0
|
|
333
356
|
|
|
334
357
|
# 2. 确定存储目录
|
|
@@ -353,17 +376,36 @@ class MinioSyncService(metaclass=SingletonMeta):
|
|
|
353
376
|
SYLogger.warning(f"[MinIO] 列出已有副本失败,将全量上传: {e}")
|
|
354
377
|
|
|
355
378
|
# 4. 找出需要同步的文件(新增的不在 MinIO 中)
|
|
379
|
+
sandbox_file_set = set(sandbox_files)
|
|
356
380
|
changed_files = [
|
|
357
381
|
fp for fp in sandbox_files if fp not in existing_objects]
|
|
358
382
|
|
|
383
|
+
# 5. 找出需要删除的文件(MinIO 中存在但沙箱中已不存在)
|
|
384
|
+
deleted_files = [
|
|
385
|
+
fp for fp in existing_objects if fp not in sandbox_file_set]
|
|
386
|
+
|
|
387
|
+
# 删除 MinIO 中的孤立文件
|
|
388
|
+
if deleted_files:
|
|
389
|
+
removed_count = 0
|
|
390
|
+
for fp in deleted_files:
|
|
391
|
+
try:
|
|
392
|
+
object_key = f"{prefix}{fp}"
|
|
393
|
+
await self.aremove_object(object_key)
|
|
394
|
+
removed_count += 1
|
|
395
|
+
except Exception as e:
|
|
396
|
+
SYLogger.warning(f"[MinIO] 删除孤立文件失败: {fp}, {e}")
|
|
397
|
+
if removed_count > 0:
|
|
398
|
+
SYLogger.info(
|
|
399
|
+
f"[MinIO] 清理孤立文件: user={user_id}, removed={removed_count}")
|
|
400
|
+
|
|
359
401
|
if not changed_files:
|
|
360
|
-
SYLogger.info(f"[MinIO]
|
|
402
|
+
SYLogger.info(f"[MinIO] 所有文件均无变化: user={user_id}")
|
|
361
403
|
return 0
|
|
362
404
|
|
|
363
405
|
SYLogger.info(
|
|
364
406
|
f"[MinIO] 检测到 {len(changed_files)} 个文件有变化: user={user_id}")
|
|
365
407
|
|
|
366
|
-
#
|
|
408
|
+
# 6. 并发下载并上传变化文件
|
|
367
409
|
synced = await self._sync_batch(sandbox_backend, changed_files, existing_objects, prefix)
|
|
368
410
|
|
|
369
411
|
SYLogger.info(
|