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.
Files changed (267) hide show
  1. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/PKG-INFO +2 -1
  2. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/pyproject.toml +2 -1
  3. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/sandbox/__init__.py +4 -0
  4. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/sandbox/file_ops.py +6 -13
  5. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/sandbox/http_sandbox_backend.py +2 -2
  6. sycommon_python_lib-0.2.2a14/src/sycommon/agent/sandbox/minio_sync.py +479 -0
  7. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/database/async_database_service.py +4 -2
  8. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/database/token_usage_db_service.py +3 -2
  9. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/sandbox.py +5 -3
  10. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/traceid.py +13 -2
  11. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon_python_lib.egg-info/PKG-INFO +2 -1
  12. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon_python_lib.egg-info/SOURCES.txt +1 -0
  13. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon_python_lib.egg-info/requires.txt +1 -0
  14. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/README.md +0 -0
  15. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/setup.cfg +0 -0
  16. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/__init__.py +0 -0
  17. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/cli.py +0 -0
  18. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/core/__init__.py +0 -0
  19. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/core/console.py +0 -0
  20. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/core/models.py +0 -0
  21. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/core/project.py +0 -0
  22. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/core/utils.py +0 -0
  23. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/__init__.py +0 -0
  24. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/README.md.tpl +0 -0
  25. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/__init__.py +0 -0
  26. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/agent/__init__.py.tpl +0 -0
  27. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/agent/main_agent.py.tpl +0 -0
  28. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/agent/nodes/__init__.py.tpl +0 -0
  29. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/agent/nodes/example_node.py.tpl +0 -0
  30. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/agent/states/__init__.py.tpl +0 -0
  31. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/agent/states/agent_state.py.tpl +0 -0
  32. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/api/__init__.py.tpl +0 -0
  33. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/api/query.py.tpl +0 -0
  34. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/api/sse/__init__.py.tpl +0 -0
  35. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/api/sse/agent.py.tpl +0 -0
  36. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/app.py.tpl +0 -0
  37. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/client/__init__.py.tpl +0 -0
  38. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/db/__init__.py.tpl +0 -0
  39. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/db/model/__init__.py.tpl +0 -0
  40. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/db/model/entity.py.tpl +0 -0
  41. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/db/service.py.tpl +0 -0
  42. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/model/__init__.py.tpl +0 -0
  43. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/model/parse.py.tpl +0 -0
  44. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/tools/__init__.py.tpl +0 -0
  45. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/agent/tools/mq.py.tpl +0 -0
  46. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/.env.tpl +0 -0
  47. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/.gitignore.tpl +0 -0
  48. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/Dockerfile.tpl +0 -0
  49. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/README.md.tpl +0 -0
  50. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/__init__.py +0 -0
  51. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/app.py.tpl +0 -0
  52. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/app.yaml.tpl +0 -0
  53. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/client/FileServiceClient.py.tpl +0 -0
  54. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/client/__init__.py.tpl +0 -0
  55. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/model/__init__.py.tpl +0 -0
  56. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/model/file_info.py.tpl +0 -0
  57. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/base/requirements.txt.tpl +0 -0
  58. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/cli/README.md.tpl +0 -0
  59. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/cli/__init__.py +0 -0
  60. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/cli/app.py.tpl +0 -0
  61. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/cli/commands/__init__.py.tpl +0 -0
  62. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/cli/commands/hello.py.tpl +0 -0
  63. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/cli/pyproject.toml.tpl +0 -0
  64. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/cli/tools/__init__.py.tpl +0 -0
  65. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/README.md.tpl +0 -0
  66. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/__init__.py +0 -0
  67. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/api/__init__.py.tpl +0 -0
  68. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/api/echo.py.tpl +0 -0
  69. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/api/sse/__init__.py.tpl +0 -0
  70. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/api/sse/echo.py.tpl +0 -0
  71. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/app.py.tpl +0 -0
  72. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/client/__init__.py.tpl +0 -0
  73. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/model/__init__.py.tpl +0 -0
  74. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/tools/__init__.py.tpl +0 -0
  75. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/command/templates/web/tools/mq.py.tpl +0 -0
  76. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/nexus/__init__.py +0 -0
  77. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/__init__.py +0 -0
  78. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/__main__.py +0 -0
  79. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/agents/__init__.py +0 -0
  80. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/agents/factory.py +0 -0
  81. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/agents/prompts.py +0 -0
  82. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/__init__.py +0 -0
  83. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/browser.py +0 -0
  84. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/capabilities/__init__.py +0 -0
  85. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/capabilities/console.py +0 -0
  86. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/capabilities/dom.py +0 -0
  87. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/capabilities/network.py +0 -0
  88. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/capabilities/page_errors.py +0 -0
  89. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/capabilities/performance.py +0 -0
  90. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/capabilities/screenshot.py +0 -0
  91. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/client.py +0 -0
  92. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/protocol.py +0 -0
  93. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cdp/repl.py +0 -0
  94. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/cli.py +0 -0
  95. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/__init__.py +0 -0
  96. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/cdp_cmd.py +0 -0
  97. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/chat_cmd.py +0 -0
  98. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/create_cmd.py +0 -0
  99. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/evaluate_cmd.py +0 -0
  100. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/init_cmd.py +0 -0
  101. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/memory_cmd.py +0 -0
  102. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/resume_cmd.py +0 -0
  103. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/rollback_cmd.py +0 -0
  104. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/commands/run_cmd.py +0 -0
  105. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/core/__init__.py +0 -0
  106. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/core/backend.py +0 -0
  107. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/core/config.py +0 -0
  108. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/core/display.py +0 -0
  109. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/core/git_integration.py +0 -0
  110. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/core/llm.py +0 -0
  111. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/core/state.py +0 -0
  112. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/evaluate/__init__.py +0 -0
  113. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/evaluate/api_evaluator.py +0 -0
  114. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/memory/__init__.py +0 -0
  115. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/memory/compressor.py +0 -0
  116. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/memory/full.py +0 -0
  117. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/memory/hot.py +0 -0
  118. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/memory/manager.py +0 -0
  119. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/memory/warm.py +0 -0
  120. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/mode/__init__.py +0 -0
  121. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/mode/create.py +0 -0
  122. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/mode/optimize.py +0 -0
  123. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/models/__init__.py +0 -0
  124. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/models/config_models.py +0 -0
  125. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/__init__.py +0 -0
  126. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/baseline_tests.py +0 -0
  127. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/checkpoint.py +0 -0
  128. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/convergence.py +0 -0
  129. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/diagnosis.py +0 -0
  130. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/engine.py +0 -0
  131. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/environment.py +0 -0
  132. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/experience.py +0 -0
  133. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/harness_prompts.py +0 -0
  134. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/history.py +0 -0
  135. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/optimization_logger.py +0 -0
  136. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/pre_validation.py +0 -0
  137. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/reward.py +0 -0
  138. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/strategy_bandit.py +0 -0
  139. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/strategy_generator.py +0 -0
  140. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/rl/strategy_prompts.py +0 -0
  141. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycli/skills/__init__.py +0 -0
  142. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/__init__.py +0 -0
  143. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/__init__.py +0 -0
  144. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/agent_manager.py +0 -0
  145. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/chat_events.py +0 -0
  146. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/deep_agent.py +0 -0
  147. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/multi_agent_team.py +0 -0
  148. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/sandbox/sandbox_pool.py +0 -0
  149. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/sandbox/sandbox_recovery.py +0 -0
  150. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/agent/sandbox/session.py +0 -0
  151. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/auth/__init__.py +0 -0
  152. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/auth/ldap_service.py +0 -0
  153. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/auth/wecom_ldap_service.py +0 -0
  154. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/Config.py +0 -0
  155. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/DatabaseConfig.py +0 -0
  156. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/ElasticsearchConfig.py +0 -0
  157. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/EmbeddingConfig.py +0 -0
  158. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/LLMConfig.py +0 -0
  159. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/LangfuseConfig.py +0 -0
  160. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/MQConfig.py +0 -0
  161. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/RedisConfig.py +0 -0
  162. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/RerankerConfig.py +0 -0
  163. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/SentryConfig.py +0 -0
  164. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/XxlJobConfig.py +0 -0
  165. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/config/__init__.py +0 -0
  166. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/database/async_base_db_service.py +0 -0
  167. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/database/base_db_service.py +0 -0
  168. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/database/database_service.py +0 -0
  169. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/database/elasticsearch_service.py +0 -0
  170. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/database/redis_service.py +0 -0
  171. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/health/__init__.py +0 -0
  172. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/health/health_check.py +0 -0
  173. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/health/metrics.py +0 -0
  174. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/health/ping.py +0 -0
  175. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/heartbeat_process/__init__.py +0 -0
  176. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/heartbeat_process/heartbeat_config.py +0 -0
  177. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/heartbeat_process/heartbeat_process_manager.py +0 -0
  178. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/heartbeat_process/heartbeat_process_worker.py +0 -0
  179. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/__init__.py +0 -0
  180. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/embedding.py +0 -0
  181. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/get_llm.py +0 -0
  182. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/llm_logger.py +0 -0
  183. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/llm_tokens.py +0 -0
  184. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/llm_with_token_tracking.py +0 -0
  185. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/native_with_fallback_runnable.py +0 -0
  186. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/output_fixing_runnable.py +0 -0
  187. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/struct_token.py +0 -0
  188. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/sy_langfuse.py +0 -0
  189. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/token_usage_es_service.py +0 -0
  190. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/token_usage_mysql_service.py +0 -0
  191. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/llm/usage_token.py +0 -0
  192. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/logging/__init__.py +0 -0
  193. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/logging/async_sql_logger.py +0 -0
  194. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/logging/kafka_log.py +0 -0
  195. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/logging/logger_levels.py +0 -0
  196. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/logging/logger_wrapper.py +0 -0
  197. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/logging/process_logger.py +0 -0
  198. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/logging/sql_logger.py +0 -0
  199. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/__init__.py +0 -0
  200. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/background_execution.py +0 -0
  201. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/context.py +0 -0
  202. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/cors.py +0 -0
  203. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/docs.py +0 -0
  204. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/exception.py +0 -0
  205. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/middleware.py +0 -0
  206. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/monitor_memory.py +0 -0
  207. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/mq.py +0 -0
  208. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/timeout.py +0 -0
  209. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/middleware/token_tracking.py +0 -0
  210. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/__init__.py +0 -0
  211. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/base_http.py +0 -0
  212. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/log.py +0 -0
  213. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/mqlistener_config.py +0 -0
  214. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/mqmsg_model.py +0 -0
  215. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/mqsend_config.py +0 -0
  216. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/sandbox.py +0 -0
  217. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/sso_user.py +0 -0
  218. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/token_usage.py +0 -0
  219. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/token_usage_mysql.py +0 -0
  220. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/models/xxljob_handler_config.py +0 -0
  221. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/notice/__init__.py +0 -0
  222. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/notice/uvicorn_monitor.py +0 -0
  223. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/rabbitmq/process_pool_consumer.py +0 -0
  224. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/rabbitmq/rabbitmq_client.py +0 -0
  225. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/rabbitmq/rabbitmq_pool.py +0 -0
  226. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/rabbitmq/rabbitmq_service.py +0 -0
  227. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/rabbitmq/rabbitmq_service_client_manager.py +0 -0
  228. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/rabbitmq/rabbitmq_service_connection_monitor.py +0 -0
  229. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/rabbitmq/rabbitmq_service_consumer_manager.py +0 -0
  230. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/rabbitmq/rabbitmq_service_core.py +0 -0
  231. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/rabbitmq/rabbitmq_service_producer_manager.py +0 -0
  232. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/sentry/__init__.py +0 -0
  233. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/sentry/sy_sentry.py +0 -0
  234. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/services.py +0 -0
  235. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/sse/__init__.py +0 -0
  236. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/sse/event.py +0 -0
  237. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/sse/sse.py +0 -0
  238. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/__init__.py +0 -0
  239. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/example.py +0 -0
  240. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/example2.py +0 -0
  241. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/feign.py +0 -0
  242. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/feign_client.py +0 -0
  243. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/nacos_client_base.py +0 -0
  244. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/nacos_config_manager.py +0 -0
  245. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/nacos_heartbeat_manager.py +0 -0
  246. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/nacos_service.py +0 -0
  247. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/nacos_service_discovery.py +0 -0
  248. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/nacos_service_registration.py +0 -0
  249. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/synacos/param.py +0 -0
  250. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tests/deep_agent_server.py +0 -0
  251. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tests/test_deep_agent.py +0 -0
  252. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tests/test_email.py +0 -0
  253. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tests/test_mq.py +0 -0
  254. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tools/__init__.py +0 -0
  255. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tools/async_utils.py +0 -0
  256. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tools/docs.py +0 -0
  257. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tools/env.py +0 -0
  258. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tools/merge_headers.py +0 -0
  259. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tools/snowflake.py +0 -0
  260. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tools/syemail.py +0 -0
  261. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/tools/timing.py +0 -0
  262. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/xxljob/__init__.py +0 -0
  263. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon/xxljob/xxljob_service.py +0 -0
  264. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon_python_lib.egg-info/dependency_links.txt +0 -0
  265. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon_python_lib.egg-info/entry_points.txt +0 -0
  266. {sycommon_python_lib-0.2.2a13 → sycommon_python_lib-0.2.2a14}/src/sycommon_python_lib.egg-info/top_level.txt +0 -0
  267. {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.2a13
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.2a13"
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]
@@ -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",
@@ -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, field
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(f"[Sandbox] 读取完成: {len(content)} 字符, encoding={encoding}")
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(f"[Sandbox] 异步读取完成: {len(content)} 字符, encoding={encoding}")
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 = 120,
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 = 120,
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=10, # 连接池大小
78
- max_overflow=20, # 最大溢出连接数
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=2,
161
- max_overflow=3,
161
+ pool_size=1,
162
+ max_overflow=2,
162
163
  pool_timeout=5,
163
164
  pool_recycle=3600,
164
165
  pool_pre_ping=True,
@@ -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 or 5
1125
- max_files = req.max_files or 500
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
  ))
@@ -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
- if len(response_log_body) > 10000:
254
- response_log_body = response_log_body[:10000] + f"... (truncated, total {len(response_body)} bytes)"
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,