sycommon-python-lib 0.2.1a27__tar.gz → 0.2.1a29__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 (167) hide show
  1. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/PKG-INFO +1 -1
  2. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/pyproject.toml +1 -1
  3. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/sandbox/http_sandbox_backend.py +130 -9
  4. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/middleware/sandbox.py +269 -146
  5. sycommon_python_lib-0.2.1a29/src/sycommon/models/sandbox.py +201 -0
  6. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon_python_lib.egg-info/PKG-INFO +1 -1
  7. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon_python_lib.egg-info/SOURCES.txt +1 -0
  8. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/README.md +0 -0
  9. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/setup.cfg +0 -0
  10. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/command/__init__.py +0 -0
  11. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/command/cli.py +0 -0
  12. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/command/core/__init__.py +0 -0
  13. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/command/core/console.py +0 -0
  14. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/command/core/models.py +0 -0
  15. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/command/core/project.py +0 -0
  16. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/command/core/utils.py +0 -0
  17. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/command/templates/__init__.py +0 -0
  18. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/command/templates/agent/__init__.py +0 -0
  19. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/command/templates/base/__init__.py +0 -0
  20. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/command/templates/web/__init__.py +0 -0
  21. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/__init__.py +0 -0
  22. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/__init__.py +0 -0
  23. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/01_basic_agent.py +0 -0
  24. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/02_tool_agent.py +0 -0
  25. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/03_structured_output.py +0 -0
  26. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/04_memory_agent.py +0 -0
  27. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/05_streaming.py +0 -0
  28. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/06_multi_agent.py +0 -0
  29. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/07_skills_agent.py +0 -0
  30. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/08_middleware.py +0 -0
  31. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/09_interrupt.py +0 -0
  32. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/10_custom_llm.py +0 -0
  33. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/11_complex_workflow.py +0 -0
  34. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/12_batch_processing.py +0 -0
  35. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/__init__.py +0 -0
  36. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/middleware/01_basic_monitoring.py +0 -0
  37. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/middleware/02_permission_control.py +0 -0
  38. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/middleware/03_tool_skill_filter.py +0 -0
  39. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/middleware/04_caching_retry.py +0 -0
  40. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/middleware/05_sanitization.py +0 -0
  41. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/middleware/06_tracking.py +0 -0
  42. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/middleware/07_advanced.py +0 -0
  43. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/middleware/08_progressive_skills.py +0 -0
  44. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/middleware/__init__.py +0 -0
  45. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/middleware/override_examples.py +0 -0
  46. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/examples/virtual_employee_demo.py +0 -0
  47. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/exports.py +0 -0
  48. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/get_agent.py +0 -0
  49. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/sandbox/__init__.py +0 -0
  50. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/sandbox/file_ops.py +0 -0
  51. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/sandbox/sandbox_pool.py +0 -0
  52. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/sandbox/sandbox_recovery.py +0 -0
  53. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/sandbox/session.py +0 -0
  54. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/skills/__init__.py +0 -0
  55. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/skills/examples/faq_handler/scripts/search.py +0 -0
  56. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/skills/exports.py +0 -0
  57. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/agent/virtual_employee.py +0 -0
  58. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/config/Config.py +0 -0
  59. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/config/DatabaseConfig.py +0 -0
  60. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/config/ElasticsearchConfig.py +0 -0
  61. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/config/EmbeddingConfig.py +0 -0
  62. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/config/LLMConfig.py +0 -0
  63. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/config/LangfuseConfig.py +0 -0
  64. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/config/MQConfig.py +0 -0
  65. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/config/RedisConfig.py +0 -0
  66. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/config/RerankerConfig.py +0 -0
  67. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/config/SentryConfig.py +0 -0
  68. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/config/__init__.py +0 -0
  69. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/database/async_base_db_service.py +0 -0
  70. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/database/async_database_service.py +0 -0
  71. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/database/base_db_service.py +0 -0
  72. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/database/database_service.py +0 -0
  73. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/database/elasticsearch_service.py +0 -0
  74. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/database/redis_service.py +0 -0
  75. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/database/token_usage_db_service.py +0 -0
  76. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/health/__init__.py +0 -0
  77. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/health/health_check.py +0 -0
  78. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/health/metrics.py +0 -0
  79. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/health/ping.py +0 -0
  80. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/heartbeat_process/__init__.py +0 -0
  81. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/heartbeat_process/heartbeat_config.py +0 -0
  82. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/heartbeat_process/heartbeat_process_manager.py +0 -0
  83. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/heartbeat_process/heartbeat_process_worker.py +0 -0
  84. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/llm/__init__.py +0 -0
  85. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/llm/embedding.py +0 -0
  86. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/llm/get_llm.py +0 -0
  87. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/llm/llm_logger.py +0 -0
  88. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/llm/llm_tokens.py +0 -0
  89. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/llm/llm_with_token_tracking.py +0 -0
  90. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/llm/native_with_fallback_runnable.py +0 -0
  91. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/llm/output_fixing_runnable.py +0 -0
  92. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/llm/struct_token.py +0 -0
  93. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/llm/sy_langfuse.py +0 -0
  94. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/llm/token_usage_es_service.py +0 -0
  95. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/llm/token_usage_mysql_service.py +0 -0
  96. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/llm/usage_token.py +0 -0
  97. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/logging/__init__.py +0 -0
  98. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/logging/async_sql_logger.py +0 -0
  99. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/logging/kafka_log.py +0 -0
  100. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/logging/logger_levels.py +0 -0
  101. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/logging/logger_wrapper.py +0 -0
  102. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/logging/process_logger.py +0 -0
  103. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/logging/sql_logger.py +0 -0
  104. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/middleware/__init__.py +0 -0
  105. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/middleware/context.py +0 -0
  106. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/middleware/cors.py +0 -0
  107. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/middleware/docs.py +0 -0
  108. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/middleware/exception.py +0 -0
  109. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/middleware/middleware.py +0 -0
  110. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/middleware/monitor_memory.py +0 -0
  111. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/middleware/mq.py +0 -0
  112. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/middleware/timeout.py +0 -0
  113. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/middleware/traceid.py +0 -0
  114. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/models/__init__.py +0 -0
  115. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/models/base_http.py +0 -0
  116. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/models/log.py +0 -0
  117. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/models/mqlistener_config.py +0 -0
  118. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/models/mqmsg_model.py +0 -0
  119. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/models/mqsend_config.py +0 -0
  120. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/models/sso_user.py +0 -0
  121. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/models/token_usage.py +0 -0
  122. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/models/token_usage_mysql.py +0 -0
  123. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/notice/__init__.py +0 -0
  124. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/notice/uvicorn_monitor.py +0 -0
  125. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/rabbitmq/process_pool_consumer.py +0 -0
  126. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/rabbitmq/rabbitmq_client.py +0 -0
  127. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/rabbitmq/rabbitmq_pool.py +0 -0
  128. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/rabbitmq/rabbitmq_service.py +0 -0
  129. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/rabbitmq/rabbitmq_service_client_manager.py +0 -0
  130. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/rabbitmq/rabbitmq_service_connection_monitor.py +0 -0
  131. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/rabbitmq/rabbitmq_service_consumer_manager.py +0 -0
  132. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/rabbitmq/rabbitmq_service_core.py +0 -0
  133. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/rabbitmq/rabbitmq_service_producer_manager.py +0 -0
  134. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/sentry/__init__.py +0 -0
  135. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/sentry/sy_sentry.py +0 -0
  136. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/services.py +0 -0
  137. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/sse/__init__.py +0 -0
  138. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/sse/event.py +0 -0
  139. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/sse/sse.py +0 -0
  140. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/synacos/__init__.py +0 -0
  141. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/synacos/example.py +0 -0
  142. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/synacos/example2.py +0 -0
  143. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/synacos/feign.py +0 -0
  144. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/synacos/feign_client.py +0 -0
  145. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/synacos/nacos_client_base.py +0 -0
  146. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/synacos/nacos_config_manager.py +0 -0
  147. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/synacos/nacos_heartbeat_manager.py +0 -0
  148. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/synacos/nacos_service.py +0 -0
  149. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/synacos/nacos_service_discovery.py +0 -0
  150. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/synacos/nacos_service_registration.py +0 -0
  151. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/synacos/param.py +0 -0
  152. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/tests/deep_agent_server.py +0 -0
  153. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/tests/test_deep_agent.py +0 -0
  154. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/tests/test_email.py +0 -0
  155. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/tests/test_mq.py +0 -0
  156. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/tools/__init__.py +0 -0
  157. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/tools/async_utils.py +0 -0
  158. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/tools/docs.py +0 -0
  159. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/tools/env.py +0 -0
  160. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/tools/merge_headers.py +0 -0
  161. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/tools/snowflake.py +0 -0
  162. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/tools/syemail.py +0 -0
  163. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon/tools/timing.py +0 -0
  164. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon_python_lib.egg-info/dependency_links.txt +0 -0
  165. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon_python_lib.egg-info/entry_points.txt +0 -0
  166. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon_python_lib.egg-info/requires.txt +0 -0
  167. {sycommon_python_lib-0.2.1a27 → sycommon_python_lib-0.2.1a29}/src/sycommon_python_lib.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sycommon-python-lib
3
- Version: 0.2.1a27
3
+ Version: 0.2.1a29
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sycommon-python-lib"
3
- version = "0.2.1a27"
3
+ version = "0.2.1a29"
4
4
  description = "Add your description here"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -342,6 +342,110 @@ class HTTPSandboxBackend(FileOperationsMixin, SandboxBackendProtocol):
342
342
  """异步执行 shell 命令"""
343
343
  return await asyncio.to_thread(self.execute, command, timeout=timeout)
344
344
 
345
+ # ============== 后台进程执行 ==============
346
+
347
+ def execute_background(self, command: str, *, timeout: int = 600) -> dict:
348
+ """后台执行 shell 命令(不阻塞,立即返回 process_id)
349
+
350
+ 适用于长时间运行的服务(如 uvicorn、FastAPI 等)
351
+
352
+ Args:
353
+ command: 要执行的命令
354
+ timeout: 命令超时时间(秒),默认 600 秒
355
+
356
+ Returns:
357
+ dict: {"process_id": str, "status": "started"}
358
+
359
+ Example:
360
+ # 启动后台服务
361
+ result = backend.execute_background("uvicorn main:app --host 0.0.0.0 --port 8000")
362
+ process_id = result["process_id"]
363
+
364
+ # 稍后检查状态
365
+ status = backend.check_process(process_id)
366
+ if status["status"] == "running":
367
+ print("服务正在运行...")
368
+
369
+ # 需要时终止进程
370
+ backend.kill_process(process_id)
371
+ """
372
+ self._ensure_synced_sync()
373
+ SYLogger.info(f"[Sandbox] 后台执行: {command}")
374
+ try:
375
+ result = self._post_sync(f"{SANDBOX_API_PREFIX}/execute_background", {
376
+ "command": command,
377
+ "user_id": self._user_id,
378
+ "timeout": timeout
379
+ })
380
+ SYLogger.info(f"[Sandbox] 后台进程已启动: process_id={result['process_id']}")
381
+ return result
382
+ except Exception as e:
383
+ SYLogger.error(f"[Sandbox] 后台执行失败: {e}")
384
+ return {"process_id": None, "status": "error", "error": str(e)}
385
+
386
+ async def aexecute_background(self, command: str, *, timeout: int = 600) -> dict:
387
+ """异步后台执行 shell 命令"""
388
+ return await asyncio.to_thread(self.execute_background, command, timeout=timeout)
389
+
390
+ def check_process(self, process_id: str) -> dict:
391
+ """检查后台进程状态
392
+
393
+ Args:
394
+ process_id: execute_background 返回的进程 ID
395
+
396
+ Returns:
397
+ dict: {
398
+ "process_id": str,
399
+ "status": "running" | "completed" | "timeout" | "error" | "not_found",
400
+ "exit_code": int | None,
401
+ "output": str | None, # 仅在进程结束时返回
402
+ "truncated": bool,
403
+ "command": str | None,
404
+ "started_at": str | None
405
+ }
406
+ """
407
+ try:
408
+ result = self._post_sync(f"{SANDBOX_API_PREFIX}/process_status", {
409
+ "process_id": process_id,
410
+ "user_id": self._user_id
411
+ })
412
+ return result
413
+ except Exception as e:
414
+ SYLogger.error(f"[Sandbox] 检查进程失败: {e}")
415
+ return {"process_id": process_id, "status": "error", "error": str(e)}
416
+
417
+ async def acheck_process(self, process_id: str) -> dict:
418
+ """异步检查后台进程状态"""
419
+ return await asyncio.to_thread(self.check_process, process_id)
420
+
421
+ def kill_process(self, process_id: str) -> dict:
422
+ """终止后台进程
423
+
424
+ Args:
425
+ process_id: execute_background 返回的进程 ID
426
+
427
+ Returns:
428
+ dict: {
429
+ "process_id": str,
430
+ "status": "killed" | "not_found" | "already_completed",
431
+ "output": str | None # 进程截止到被杀死时的输出
432
+ }
433
+ """
434
+ try:
435
+ result = self._post_sync(f"{SANDBOX_API_PREFIX}/kill_process", {
436
+ "process_id": process_id,
437
+ "user_id": self._user_id
438
+ })
439
+ SYLogger.info(f"[Sandbox] 进程终止: {process_id}, status={result['status']}")
440
+ return result
441
+ except Exception as e:
442
+ SYLogger.error(f"[Sandbox] 终止进程失败: {e}")
443
+ return {"process_id": process_id, "status": "error", "error": str(e)}
444
+
445
+ async def akill_process(self, process_id: str) -> dict:
446
+ """异步终止后台进程"""
447
+ return await asyncio.to_thread(self.kill_process, process_id)
448
+
345
449
  # ============== 批量操作 ==============
346
450
 
347
451
  def upload_files(self, files: List[tuple[str, bytes]]) -> List[FileUploadResponse]:
@@ -596,21 +700,38 @@ class HTTPSandboxBackend(FileOperationsMixin, SandboxBackendProtocol):
596
700
  """异步重置沙箱环境"""
597
701
  return await asyncio.to_thread(self.reset)
598
702
 
599
- def health_check(self) -> dict:
600
- """健康检查"""
703
+ def health_check(self, timeout: int = 10) -> dict:
704
+ """健康检查(快速检查,默认10秒超时)"""
601
705
  trace_id = SYLogger.get_trace_id()
602
706
  headers = {}
603
707
  if trace_id:
604
708
  headers["x-traceid-header"] = str(trace_id)
605
709
 
606
- resp = requests.get(
607
- f"{self._base_url}{SANDBOX_API_PREFIX}/health",
608
- headers=headers if headers else None,
609
- timeout=30
610
- )
611
- resp.raise_for_status()
612
- return resp.json()
710
+ url = f"{self._base_url}{SANDBOX_API_PREFIX}/health"
711
+ SYLogger.info(f"[Sandbox] 健康检查: {url}, timeout={timeout}s")
712
+ try:
713
+ resp = requests.get(
714
+ url,
715
+ headers=headers if headers else None,
716
+ timeout=timeout
717
+ )
718
+ resp.raise_for_status()
719
+ result = resp.json()
720
+ SYLogger.info(f"[Sandbox] 健康检查成功: {result}")
721
+ return result
722
+ except Exception as e:
723
+ SYLogger.error(f"[Sandbox] 健康检查失败: {e}")
724
+ raise
613
725
 
614
726
  async def ahealth_check(self) -> dict:
615
727
  """异步健康检查"""
616
728
  return await asyncio.to_thread(self.health_check)
729
+
730
+ def check_available(self, timeout: int = 5) -> bool:
731
+ """快速检查沙箱是否可用(5秒超时)"""
732
+ try:
733
+ self.health_check(timeout=timeout)
734
+ return True
735
+ except Exception as e:
736
+ SYLogger.warning(f"[Sandbox] 沙箱不可用: {e}")
737
+ return False
@@ -26,12 +26,34 @@ import base64
26
26
  import shutil
27
27
  import tempfile
28
28
  import platform
29
+ import uuid
30
+ import threading
29
31
  from datetime import datetime
30
32
  from fastapi import FastAPI, APIRouter, Request, Header
31
- from typing import Optional
33
+ from typing import Dict
32
34
 
33
- from pydantic import BaseModel
34
35
  from sycommon.logging.kafka_log import SYLogger
36
+ from sycommon.models.sandbox import (
37
+ ExecuteRequest, ExecuteResponse,
38
+ UploadRequest, UploadResponse,
39
+ DownloadRequest, DownloadResponse,
40
+ FileInfo, LsRequest, LsResponse,
41
+ GlobRequest, GrepRequest, GrepMatch,
42
+ ReadRequest, ReadResponse,
43
+ WriteRequest, WriteResponse,
44
+ EditRequest, EditResponse,
45
+ HealthResponse, ResetRequest, ResetResponse,
46
+ ExecuteBackgroundRequest, ExecuteBackgroundResponse,
47
+ ProcessStatusRequest, ProcessStatusResponse,
48
+ KillProcessRequest, KillProcessResponse,
49
+ )
50
+
51
+
52
+ # ============== 后台进程管理 ==============
53
+
54
+ # 进程存储: process_id -> {process: Popen, command: str, user_id: str, started_at: datetime, workspace: str}
55
+ _background_processes: Dict[str, dict] = {}
56
+ _process_lock = threading.Lock()
35
57
 
36
58
 
37
59
  # ============== 常量配置 ==============
@@ -100,150 +122,6 @@ def resolve_sandbox_path(path: str, workspace: str) -> str:
100
122
  return resolved
101
123
 
102
124
 
103
- # ============== 请求/响应模型 ==============
104
-
105
- class ExecuteRequest(BaseModel):
106
- """执行命令请求"""
107
- command: str
108
- user_id: str # 用户ID,用于隔离工作目录
109
- timeout: Optional[int] = 120 # 默认超时 120 秒
110
-
111
-
112
- class ExecuteResponse(BaseModel):
113
- """执行命令响应"""
114
- output: str
115
- exit_code: int
116
- truncated: bool = False
117
-
118
-
119
- class UploadRequest(BaseModel):
120
- """上传文件请求"""
121
- path: str
122
- content: str # base64 encoded
123
- user_id: str
124
-
125
-
126
- class UploadResponse(BaseModel):
127
- """上传文件响应"""
128
- path: str
129
- error: Optional[str] = None
130
-
131
-
132
- class DownloadRequest(BaseModel):
133
- """下载文件请求"""
134
- path: str
135
- user_id: str
136
-
137
-
138
- class DownloadResponse(BaseModel):
139
- """下载文件响应"""
140
- path: str
141
- content: Optional[str] = None # base64 encoded
142
- error: Optional[str] = None
143
-
144
-
145
- class FileInfo(BaseModel):
146
- """文件信息"""
147
- path: str
148
- is_dir: Optional[bool] = None
149
- size: Optional[int] = None
150
- modified_at: Optional[str] = None
151
-
152
-
153
- class LsRequest(BaseModel):
154
- """列出目录请求"""
155
- path: str
156
- user_id: str
157
-
158
-
159
- class LsResponse(BaseModel):
160
- """列出目录响应"""
161
- files: list[FileInfo] = []
162
- error: Optional[str] = None
163
-
164
-
165
- class GlobRequest(BaseModel):
166
- """glob 搜索请求"""
167
- pattern: str
168
- path: str = "/"
169
- user_id: str
170
-
171
-
172
- class GrepRequest(BaseModel):
173
- """grep 搜索请求"""
174
- pattern: str
175
- user_id: str
176
- path: Optional[str] = None
177
- glob: Optional[str] = None
178
-
179
-
180
- class GrepMatch(BaseModel):
181
- """grep 匹配结果"""
182
- path: str
183
- line: int
184
- text: str
185
-
186
-
187
- class ReadRequest(BaseModel):
188
- """读取文件请求"""
189
- file_path: str
190
- user_id: str
191
- offset: int = 0
192
- limit: int = 2000
193
-
194
-
195
- class ReadResponse(BaseModel):
196
- """读取文件响应"""
197
- content: Optional[str] = None
198
- error: Optional[str] = None
199
-
200
-
201
- class WriteRequest(BaseModel):
202
- """写入文件请求"""
203
- file_path: str
204
- content: str # base64 encoded
205
- user_id: str
206
-
207
-
208
- class WriteResponse(BaseModel):
209
- """写入文件响应"""
210
- error: Optional[str] = None
211
- path: Optional[str] = None
212
-
213
-
214
- class EditRequest(BaseModel):
215
- """编辑文件请求"""
216
- file_path: str
217
- old_string: str # base64 encoded
218
- new_string: str # base64 encoded
219
- user_id: str
220
- replace_all: bool = False
221
-
222
-
223
- class EditResponse(BaseModel):
224
- """编辑文件响应"""
225
- error: Optional[str] = None
226
- path: Optional[str] = None
227
- occurrences: Optional[int] = None
228
-
229
-
230
- class HealthResponse(BaseModel):
231
- """健康检查响应"""
232
- status: str
233
- workspace: str
234
-
235
-
236
- class ResetRequest(BaseModel):
237
- """重置请求"""
238
- user_id: str
239
-
240
-
241
- class ResetResponse(BaseModel):
242
- """重置响应"""
243
- status: str
244
- path: str
245
-
246
-
247
125
  def setup_sandbox_handler(app: FastAPI, config: dict = None):
248
126
  """
249
127
  沙箱服务初始化
@@ -448,6 +326,251 @@ COMMAND_EOF
448
326
  truncated=False
449
327
  )
450
328
 
329
+ @sandbox_router.post("/execute_background", response_model=ExecuteBackgroundResponse)
330
+ async def execute_background(req: ExecuteBackgroundRequest):
331
+ """后台执行 shell 命令(不阻塞,立即返回 process_id)"""
332
+ workspace = get_user_workspace(req.user_id)
333
+
334
+ if not req.command:
335
+ raise ValueError("Command must be a non-empty string.")
336
+
337
+ process_id = str(uuid.uuid4())[:8]
338
+ SYLogger.info(f"[Sandbox Server] 后台执行命令: {req.command} (user={req.user_id}, process_id={process_id})")
339
+
340
+ # 创建常用目录
341
+ for subdir in ["tmp", "output", "skills", "memory", "data"]:
342
+ os.makedirs(os.path.join(workspace, subdir), exist_ok=True)
343
+
344
+ # 使用与 execute 相同的 shell 初始化脚本
345
+ init_script = f'''
346
+ # 沙箱环境初始化
347
+ export SANDBOX_ROOT="{workspace}"
348
+ export _SANDBOX_WORKSPACE="{workspace}"
349
+
350
+ sandbox_path() {{
351
+ local path="$1"
352
+ if [[ "$path" == "$_SANDBOX_WORKSPACE"* ]]; then
353
+ echo "$path"
354
+ return
355
+ fi
356
+ if [[ "$path" == /* ]]; then
357
+ path="${{path#/}}"
358
+ echo "$_SANDBOX_WORKSPACE/$path"
359
+ else
360
+ echo "$path"
361
+ fi
362
+ }}
363
+
364
+ cd() {{
365
+ local target="$1"
366
+ if [[ -z "$target" ]]; then
367
+ command cd "$_SANDBOX_WORKSPACE"
368
+ elif [[ "$target" == "$_SANDBOX_WORKSPACE"* ]]; then
369
+ command cd "$target"
370
+ elif [[ "$target" == /* ]]; then
371
+ local mapped="$_SANDBOX_WORKSPACE/${{target#/}}"
372
+ command cd "$mapped"
373
+ else
374
+ command cd "$target"
375
+ fi
376
+ }}
377
+
378
+ mkdir() {{
379
+ local args=("$@")
380
+ local new_args=()
381
+ for arg in "${{args[@]}}"; do
382
+ if [[ "$arg" == "$_SANDBOX_WORKSPACE"* ]]; then
383
+ new_args+=("$arg")
384
+ elif [[ "$arg" == /* ]]; then
385
+ new_args+=("$_SANDBOX_WORKSPACE/${{arg#/}}")
386
+ else
387
+ new_args+=("$arg")
388
+ fi
389
+ done
390
+ command mkdir "${{new_args[@]}}"
391
+ }}
392
+
393
+ cd "$_SANDBOX_WORKSPACE"
394
+ '''
395
+
396
+ full_command = f'''bash <<'COMMAND_EOF'
397
+ {init_script}
398
+ {req.command}
399
+ COMMAND_EOF
400
+ '''
401
+
402
+ env = os.environ.copy()
403
+ env["TMPDIR"] = os.path.join(workspace, "tmp")
404
+ env["TEMP"] = os.path.join(workspace, "tmp")
405
+ env["TMP"] = os.path.join(workspace, "tmp")
406
+ env["SANDBOX_ROOT"] = workspace
407
+
408
+ try:
409
+ process = subprocess.Popen(
410
+ full_command,
411
+ shell=True,
412
+ stdout=subprocess.PIPE,
413
+ stderr=subprocess.PIPE,
414
+ text=True,
415
+ cwd=workspace,
416
+ env=env
417
+ )
418
+
419
+ with _process_lock:
420
+ _background_processes[process_id] = {
421
+ "process": process,
422
+ "command": req.command,
423
+ "user_id": req.user_id,
424
+ "started_at": datetime.now(),
425
+ "workspace": workspace,
426
+ "timeout": req.timeout,
427
+ "output_buffer": "",
428
+ "completed": False,
429
+ "killed": False
430
+ }
431
+
432
+ # 启动后台线程监控进程
433
+ def monitor_process():
434
+ try:
435
+ stdout, stderr = process.communicate(timeout=req.timeout)
436
+ except subprocess.TimeoutExpired:
437
+ process.kill()
438
+ stdout, stderr = process.communicate()
439
+ with _process_lock:
440
+ if process_id in _background_processes:
441
+ _background_processes[process_id]["killed"] = True
442
+ _background_processes[process_id]["output_buffer"] = f"Error: Command timed out after {req.timeout} seconds.\nPartial output:\n{stdout}"
443
+ except Exception as e:
444
+ with _process_lock:
445
+ if process_id in _background_processes:
446
+ _background_processes[process_id]["output_buffer"] = f"Error: {type(e).__name__}: {e}"
447
+ return
448
+
449
+ output_parts = []
450
+ if stdout:
451
+ output_parts.append(stdout)
452
+ if stderr:
453
+ stderr_lines = stderr.strip().split("\n")
454
+ output_parts.extend(f"[stderr] {line}" for line in stderr_lines)
455
+
456
+ output = "\n".join(output_parts) if output_parts else "<no output>"
457
+
458
+ if len(output) > MAX_OUTPUT_BYTES:
459
+ output = output[:MAX_OUTPUT_BYTES] + f"\n\n... Output truncated at {MAX_OUTPUT_BYTES} bytes."
460
+
461
+ exit_code = process.returncode
462
+ if exit_code != 0:
463
+ output = f"{output.rstrip()}\n\nExit code: {exit_code}"
464
+
465
+ with _process_lock:
466
+ if process_id in _background_processes:
467
+ _background_processes[process_id]["output_buffer"] = output
468
+ _background_processes[process_id]["exit_code"] = exit_code
469
+ _background_processes[process_id]["completed"] = True
470
+
471
+ monitor_thread = threading.Thread(target=monitor_process, daemon=True)
472
+ monitor_thread.start()
473
+
474
+ return ExecuteBackgroundResponse(process_id=process_id, status="started")
475
+
476
+ except Exception as e:
477
+ SYLogger.error(f"[Sandbox Server] 后台执行异常: {e}")
478
+ raise RuntimeError(f"Failed to start background process: {e}")
479
+
480
+ @sandbox_router.post("/process_status", response_model=ProcessStatusResponse)
481
+ async def get_process_status(req: ProcessStatusRequest):
482
+ """查询后台进程状态"""
483
+ with _process_lock:
484
+ proc_info = _background_processes.get(req.process_id)
485
+
486
+ if not proc_info:
487
+ return ProcessStatusResponse(
488
+ process_id=req.process_id,
489
+ status="not_found"
490
+ )
491
+
492
+ # 检查用户权限
493
+ if proc_info["user_id"] != req.user_id:
494
+ return ProcessStatusResponse(
495
+ process_id=req.process_id,
496
+ status="not_found"
497
+ )
498
+
499
+ process = proc_info["process"]
500
+
501
+ # 判断进程状态
502
+ if proc_info["killed"]:
503
+ status = "timeout"
504
+ elif proc_info["completed"]:
505
+ status = "completed"
506
+ elif process.poll() is not None:
507
+ # 进程已结束但还没被监控线程处理(极少情况)
508
+ status = "completed"
509
+ else:
510
+ status = "running"
511
+
512
+ return ProcessStatusResponse(
513
+ process_id=req.process_id,
514
+ status=status,
515
+ exit_code=proc_info.get("exit_code"),
516
+ output=proc_info.get("output_buffer") if proc_info["completed"] or proc_info["killed"] else None,
517
+ truncated=len(proc_info.get("output_buffer", "")) >= MAX_OUTPUT_BYTES if proc_info.get("output_buffer") else False,
518
+ command=proc_info["command"],
519
+ started_at=proc_info["started_at"].isoformat()
520
+ )
521
+
522
+ @sandbox_router.post("/kill_process", response_model=KillProcessResponse)
523
+ async def kill_process(req: KillProcessRequest):
524
+ """终止后台进程"""
525
+ with _process_lock:
526
+ proc_info = _background_processes.get(req.process_id)
527
+
528
+ if not proc_info:
529
+ return KillProcessResponse(
530
+ process_id=req.process_id,
531
+ status="not_found"
532
+ )
533
+
534
+ # 检查用户权限
535
+ if proc_info["user_id"] != req.user_id:
536
+ return KillProcessResponse(
537
+ process_id=req.process_id,
538
+ status="not_found"
539
+ )
540
+
541
+ if proc_info["completed"] or proc_info["killed"]:
542
+ return KillProcessResponse(
543
+ process_id=req.process_id,
544
+ status="already_completed",
545
+ output=proc_info.get("output_buffer")
546
+ )
547
+
548
+ process = proc_info["process"]
549
+ try:
550
+ process.kill()
551
+ # 等待进程结束
552
+ process.wait(timeout=5)
553
+ except Exception as e:
554
+ SYLogger.warning(f"[Sandbox Server] 终止进程时出错: {e}")
555
+
556
+ # 获取当前输出(如果有)
557
+ current_output = proc_info.get("output_buffer", "")
558
+ proc_info["killed"] = True
559
+ proc_info["completed"] = True
560
+ proc_info["exit_code"] = process.returncode if process.returncode is not None else -9
561
+
562
+ if not current_output:
563
+ current_output = f"Process killed by user request. Exit code: {proc_info['exit_code']}"
564
+ proc_info["output_buffer"] = current_output
565
+
566
+ SYLogger.info(f"[Sandbox Server] 进程已终止: {req.process_id}")
567
+
568
+ return KillProcessResponse(
569
+ process_id=req.process_id,
570
+ status="killed",
571
+ output=current_output
572
+ )
573
+
451
574
  @sandbox_router.post("/ls", response_model=list[FileInfo])
452
575
  async def ls_info(req: LsRequest):
453
576
  """列出目录内容"""