sycommon-python-lib 0.2.5a28__tar.gz → 0.2.5a29__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 (294) hide show
  1. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/PKG-INFO +1 -1
  2. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/pyproject.toml +1 -1
  3. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/agent/deep_agent.py +42 -1
  4. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/heartbeat_process/heartbeat_process_worker.py +0 -69
  5. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/llm/llm_with_token_tracking.py +8 -55
  6. sycommon_python_lib-0.2.5a29/src/sycommon/llm/token_utils.py +96 -0
  7. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/llm/usage_token.py +8 -46
  8. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/synacos/nacos_heartbeat_manager.py +0 -70
  9. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon_python_lib.egg-info/PKG-INFO +1 -1
  10. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon_python_lib.egg-info/SOURCES.txt +1 -1
  11. sycommon_python_lib-0.2.5a28/src/sycommon/synacos/dns_cache.py +0 -67
  12. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/README.md +0 -0
  13. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/setup.cfg +0 -0
  14. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/__init__.py +0 -0
  15. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/cli.py +0 -0
  16. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/core/__init__.py +0 -0
  17. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/core/console.py +0 -0
  18. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/core/models.py +0 -0
  19. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/core/project.py +0 -0
  20. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/core/utils.py +0 -0
  21. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/__init__.py +0 -0
  22. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/README.md.tpl +0 -0
  23. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/__init__.py +0 -0
  24. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/agent/__init__.py.tpl +0 -0
  25. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/agent/main_agent.py.tpl +0 -0
  26. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/agent/nodes/__init__.py.tpl +0 -0
  27. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/agent/nodes/example_node.py.tpl +0 -0
  28. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/agent/states/__init__.py.tpl +0 -0
  29. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/agent/states/agent_state.py.tpl +0 -0
  30. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/api/__init__.py.tpl +0 -0
  31. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/api/query.py.tpl +0 -0
  32. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/api/sse/__init__.py.tpl +0 -0
  33. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/api/sse/agent.py.tpl +0 -0
  34. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/app.py.tpl +0 -0
  35. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/client/__init__.py.tpl +0 -0
  36. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/db/__init__.py.tpl +0 -0
  37. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/db/model/__init__.py.tpl +0 -0
  38. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/db/model/entity.py.tpl +0 -0
  39. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/db/service.py.tpl +0 -0
  40. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/model/__init__.py.tpl +0 -0
  41. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/model/parse.py.tpl +0 -0
  42. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/tools/__init__.py.tpl +0 -0
  43. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/agent/tools/mq.py.tpl +0 -0
  44. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/base/.env.tpl +0 -0
  45. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/base/.gitignore.tpl +0 -0
  46. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/base/Dockerfile.tpl +0 -0
  47. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/base/README.md.tpl +0 -0
  48. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/base/__init__.py +0 -0
  49. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/base/app.py.tpl +0 -0
  50. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/base/app.yaml.tpl +0 -0
  51. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/base/client/FileServiceClient.py.tpl +0 -0
  52. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/base/client/__init__.py.tpl +0 -0
  53. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/base/model/__init__.py.tpl +0 -0
  54. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/base/model/file_info.py.tpl +0 -0
  55. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/base/requirements.txt.tpl +0 -0
  56. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/cli/README.md.tpl +0 -0
  57. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/cli/__init__.py +0 -0
  58. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/cli/app.py.tpl +0 -0
  59. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/cli/commands/__init__.py.tpl +0 -0
  60. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/cli/commands/hello.py.tpl +0 -0
  61. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/cli/pyproject.toml.tpl +0 -0
  62. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/cli/tools/__init__.py.tpl +0 -0
  63. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/web/README.md.tpl +0 -0
  64. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/web/__init__.py +0 -0
  65. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/web/api/__init__.py.tpl +0 -0
  66. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/web/api/echo.py.tpl +0 -0
  67. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/web/api/sse/__init__.py.tpl +0 -0
  68. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/web/api/sse/echo.py.tpl +0 -0
  69. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/web/app.py.tpl +0 -0
  70. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/web/client/__init__.py.tpl +0 -0
  71. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/web/model/__init__.py.tpl +0 -0
  72. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/web/tools/__init__.py.tpl +0 -0
  73. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/command/templates/web/tools/mq.py.tpl +0 -0
  74. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/nexus/__init__.py +0 -0
  75. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/__init__.py +0 -0
  76. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/__main__.py +0 -0
  77. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/agents/__init__.py +0 -0
  78. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/agents/factory.py +0 -0
  79. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/agents/prompts.py +0 -0
  80. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/cdp/__init__.py +0 -0
  81. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/cdp/browser.py +0 -0
  82. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/cdp/capabilities/__init__.py +0 -0
  83. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/cdp/capabilities/console.py +0 -0
  84. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/cdp/capabilities/dom.py +0 -0
  85. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/cdp/capabilities/network.py +0 -0
  86. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/cdp/capabilities/page_errors.py +0 -0
  87. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/cdp/capabilities/performance.py +0 -0
  88. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/cdp/capabilities/screenshot.py +0 -0
  89. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/cdp/client.py +0 -0
  90. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/cdp/protocol.py +0 -0
  91. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/cdp/repl.py +0 -0
  92. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/cli.py +0 -0
  93. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/commands/__init__.py +0 -0
  94. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/commands/cdp_cmd.py +0 -0
  95. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/commands/chat_cmd.py +0 -0
  96. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/commands/create_cmd.py +0 -0
  97. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/commands/evaluate_cmd.py +0 -0
  98. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/commands/init_cmd.py +0 -0
  99. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/commands/memory_cmd.py +0 -0
  100. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/commands/resume_cmd.py +0 -0
  101. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/commands/rollback_cmd.py +0 -0
  102. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/commands/run_cmd.py +0 -0
  103. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/core/__init__.py +0 -0
  104. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/core/backend.py +0 -0
  105. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/core/config.py +0 -0
  106. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/core/display.py +0 -0
  107. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/core/git_integration.py +0 -0
  108. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/core/llm.py +0 -0
  109. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/core/state.py +0 -0
  110. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/evaluate/__init__.py +0 -0
  111. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/evaluate/api_evaluator.py +0 -0
  112. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/memory/__init__.py +0 -0
  113. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/memory/compressor.py +0 -0
  114. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/memory/full.py +0 -0
  115. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/memory/hot.py +0 -0
  116. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/memory/manager.py +0 -0
  117. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/memory/warm.py +0 -0
  118. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/mode/__init__.py +0 -0
  119. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/mode/create.py +0 -0
  120. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/mode/optimize.py +0 -0
  121. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/models/__init__.py +0 -0
  122. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/models/config_models.py +0 -0
  123. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/rl/__init__.py +0 -0
  124. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/rl/baseline_tests.py +0 -0
  125. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/rl/checkpoint.py +0 -0
  126. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/rl/convergence.py +0 -0
  127. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/rl/diagnosis.py +0 -0
  128. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/rl/engine.py +0 -0
  129. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/rl/environment.py +0 -0
  130. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/rl/experience.py +0 -0
  131. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/rl/harness_prompts.py +0 -0
  132. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/rl/history.py +0 -0
  133. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/rl/optimization_logger.py +0 -0
  134. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/rl/pre_validation.py +0 -0
  135. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/rl/reward.py +0 -0
  136. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/rl/strategy_bandit.py +0 -0
  137. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/rl/strategy_generator.py +0 -0
  138. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/rl/strategy_prompts.py +0 -0
  139. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycli/skills/__init__.py +0 -0
  140. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/__init__.py +0 -0
  141. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/agent/__init__.py +0 -0
  142. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/agent/agent_manager.py +0 -0
  143. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/agent/chat_events.py +0 -0
  144. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/agent/mcp/__init__.py +0 -0
  145. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/agent/mcp/models.py +0 -0
  146. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/agent/mcp/tool_loader.py +0 -0
  147. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/agent/multi_agent_team.py +0 -0
  148. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/agent/sandbox/__init__.py +0 -0
  149. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/agent/sandbox/file_ops.py +0 -0
  150. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/agent/sandbox/http_sandbox_backend.py +0 -0
  151. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/agent/sandbox/minio_sync.py +0 -0
  152. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/agent/sandbox/sandbox_pool.py +0 -0
  153. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/agent/sandbox/sandbox_recovery.py +0 -0
  154. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/agent/sandbox/session.py +0 -0
  155. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/agent/summarization_utils.py +0 -0
  156. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/auth/__init__.py +0 -0
  157. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/auth/ldap_service.py +0 -0
  158. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/auth/oa_cache.py +0 -0
  159. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/auth/oa_crypto.py +0 -0
  160. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/auth/oa_service.py +0 -0
  161. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/auth/wecom_ldap_service.py +0 -0
  162. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/config/Config.py +0 -0
  163. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/config/DatabaseConfig.py +0 -0
  164. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/config/ElasticsearchConfig.py +0 -0
  165. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/config/EmbeddingConfig.py +0 -0
  166. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/config/LLMConfig.py +0 -0
  167. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/config/LangfuseConfig.py +0 -0
  168. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/config/MQConfig.py +0 -0
  169. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/config/PgConfig.py +0 -0
  170. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/config/RedisConfig.py +0 -0
  171. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/config/RerankerConfig.py +0 -0
  172. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/config/SentryConfig.py +0 -0
  173. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/config/XxlJobConfig.py +0 -0
  174. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/config/__init__.py +0 -0
  175. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/database/async_base_db_service.py +0 -0
  176. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/database/async_database_service.py +0 -0
  177. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/database/base_db_service.py +0 -0
  178. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/database/database_service.py +0 -0
  179. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/database/elasticsearch_service.py +0 -0
  180. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/database/pg_checkpoint_service.py +0 -0
  181. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/database/redis_service.py +0 -0
  182. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/database/token_usage_db_service.py +0 -0
  183. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/health/__init__.py +0 -0
  184. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/health/health_check.py +0 -0
  185. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/health/metrics.py +0 -0
  186. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/health/ping.py +0 -0
  187. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/heartbeat_process/__init__.py +0 -0
  188. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/heartbeat_process/heartbeat_config.py +0 -0
  189. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/heartbeat_process/heartbeat_process_manager.py +0 -0
  190. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/llm/__init__.py +0 -0
  191. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/llm/embedding.py +0 -0
  192. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/llm/get_llm.py +0 -0
  193. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/llm/llm_logger.py +0 -0
  194. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/llm/llm_tokens.py +0 -0
  195. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/llm/native_with_fallback_runnable.py +0 -0
  196. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/llm/output_fixing_runnable.py +0 -0
  197. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/llm/struct_token.py +0 -0
  198. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/llm/sy_langfuse.py +0 -0
  199. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/llm/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +0 -0
  200. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/llm/tiktoken_cache/fb374d419588a4632f3f557e76b4b70aebbca790 +0 -0
  201. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/llm/token_usage_es_service.py +0 -0
  202. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/llm/token_usage_mysql_service.py +0 -0
  203. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/logging/__init__.py +0 -0
  204. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/logging/async_sql_logger.py +0 -0
  205. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/logging/kafka_log.py +0 -0
  206. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/logging/logger_levels.py +0 -0
  207. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/logging/logger_wrapper.py +0 -0
  208. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/logging/process_logger.py +0 -0
  209. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/logging/sql_logger.py +0 -0
  210. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/mcp_server/__init__.py +0 -0
  211. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/mcp_server/server.py +0 -0
  212. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/middleware/__init__.py +0 -0
  213. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/middleware/context.py +0 -0
  214. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/middleware/cors.py +0 -0
  215. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/middleware/docs.py +0 -0
  216. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/middleware/exception.py +0 -0
  217. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/middleware/middleware.py +0 -0
  218. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/middleware/monitor_memory.py +0 -0
  219. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/middleware/mq.py +0 -0
  220. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/middleware/sandbox.py +0 -0
  221. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/middleware/timeout.py +0 -0
  222. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/middleware/token_tracking.py +0 -0
  223. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/middleware/tool_result_truncation.py +0 -0
  224. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/middleware/traceid.py +0 -0
  225. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/models/__init__.py +0 -0
  226. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/models/base_http.py +0 -0
  227. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/models/log.py +0 -0
  228. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/models/mcp_server_config.py +0 -0
  229. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/models/mqlistener_config.py +0 -0
  230. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/models/mqmsg_model.py +0 -0
  231. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/models/mqsend_config.py +0 -0
  232. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/models/sandbox.py +0 -0
  233. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/models/sso_user.py +0 -0
  234. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/models/token_usage.py +0 -0
  235. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/models/token_usage_mysql.py +0 -0
  236. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/models/xxljob_handler_config.py +0 -0
  237. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/notice/__init__.py +0 -0
  238. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/notice/uvicorn_monitor.py +0 -0
  239. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/notice/wecom_message.py +0 -0
  240. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/rabbitmq/process_pool_consumer.py +0 -0
  241. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/rabbitmq/rabbitmq_client.py +0 -0
  242. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/rabbitmq/rabbitmq_pool.py +0 -0
  243. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/rabbitmq/rabbitmq_service.py +0 -0
  244. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/rabbitmq/rabbitmq_service_client_manager.py +0 -0
  245. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/rabbitmq/rabbitmq_service_connection_monitor.py +0 -0
  246. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/rabbitmq/rabbitmq_service_consumer_manager.py +0 -0
  247. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/rabbitmq/rabbitmq_service_core.py +0 -0
  248. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/rabbitmq/rabbitmq_service_producer_manager.py +0 -0
  249. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/sentry/__init__.py +0 -0
  250. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/sentry/sy_sentry.py +0 -0
  251. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/services.py +0 -0
  252. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/sse/__init__.py +0 -0
  253. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/sse/event.py +0 -0
  254. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/sse/sse.py +0 -0
  255. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/synacos/__init__.py +0 -0
  256. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/synacos/example.py +0 -0
  257. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/synacos/example2.py +0 -0
  258. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/synacos/feign.py +0 -0
  259. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/synacos/feign_client.py +0 -0
  260. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/synacos/nacos_client_base.py +0 -0
  261. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/synacos/nacos_config_manager.py +0 -0
  262. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/synacos/nacos_service.py +0 -0
  263. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/synacos/nacos_service_discovery.py +0 -0
  264. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/synacos/nacos_service_registration.py +0 -0
  265. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/synacos/param.py +0 -0
  266. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tests/deep_agent_server.py +0 -0
  267. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tests/test_consumer_recovery.py +0 -0
  268. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tests/test_deep_agent.py +0 -0
  269. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tests/test_dynamic_max_tokens.py +0 -0
  270. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tests/test_email.py +0 -0
  271. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tests/test_encoding_cache.py +0 -0
  272. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tests/test_mcp_server.py +0 -0
  273. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tests/test_minimax_reasoning.py +0 -0
  274. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tests/test_mq.py +0 -0
  275. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tests/test_oa_login.py +0 -0
  276. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tests/test_real_summarization.py +0 -0
  277. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tests/test_summarization_config.py +0 -0
  278. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tests/test_summarization_real.py +0 -0
  279. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tools/__init__.py +0 -0
  280. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tools/async_utils.py +0 -0
  281. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tools/docs.py +0 -0
  282. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tools/env.py +0 -0
  283. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tools/merge_headers.py +0 -0
  284. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tools/snowflake.py +0 -0
  285. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tools/syemail.py +0 -0
  286. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/tools/timing.py +0 -0
  287. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/xxljob/__init__.py +0 -0
  288. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon/xxljob/xxljob_service.py +0 -0
  289. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon_python_lib.egg-info/dependency_links.txt +0 -0
  290. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon_python_lib.egg-info/entry_points.txt +0 -0
  291. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon_python_lib.egg-info/requires.txt +0 -0
  292. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/src/sycommon_python_lib.egg-info/top_level.txt +0 -0
  293. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/tests/test_asyncio_logging.py +0 -0
  294. {sycommon_python_lib-0.2.5a28 → sycommon_python_lib-0.2.5a29}/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.5a28
3
+ Version: 0.2.5a29
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.5a28"
3
+ version = "0.2.5a29"
4
4
  description = "Add your description here"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -153,6 +153,44 @@ def _patch_agent_streaming(agent):
153
153
  _handle_model_output = _hmo_cell.cell_contents
154
154
  _name = _name_cell.cell_contents if _name_cell is not None else None
155
155
 
156
+ def _clamp_max_tokens_for_model(model_, messages):
157
+ """在 raw_model 上执行 _clamp_max_tokens 逻辑。
158
+
159
+ 由于 create_deep_agent 提取了 raw_model(绕过了 LLMWithTokenTracking 包装),
160
+ 原本在 LLMWithTokenTracking._agenerate 中自动执行的 _clamp_max_tokens 被跳过,
161
+ 导致 max_tokens 不随 input tokens 动态调整,当 input + max_output > context_window
162
+ 时触发 400 错误。此函数补上这一逻辑。
163
+
164
+ 注意:_get_bound_model 返回的可能是 _ChatModelBinding(RunnableBindingBase 子类),
165
+ 需要通过 .bound 取到真正的 ChatOpenAI,否则 max_tokens 只设在 wrapper 上不生效。
166
+ """
167
+ from sycommon.config.LLMConfig import LLMConfig
168
+ from sycommon.config.Config import Config
169
+ from sycommon.llm.token_utils import clamp_max_tokens
170
+ try:
171
+ # 解包 binding wrapper,取到真正的 ChatModel
172
+ raw_model = getattr(model_, 'bound', model_)
173
+ llm_config = Config().get_llm_config(getattr(raw_model, 'model', None))
174
+ if not llm_config:
175
+ return
176
+ llm_cfg = LLMConfig(**llm_config)
177
+ max_tokens_limit = getattr(llm_cfg, 'maxTokens', None)
178
+ if not max_tokens_limit:
179
+ return
180
+ max_output = getattr(raw_model, 'max_tokens', None)
181
+ if not max_output:
182
+ return
183
+ dynamic_max = clamp_max_tokens(
184
+ raw_model, messages,
185
+ context_window=max_tokens_limit,
186
+ max_output_tokens=max_output,
187
+ )
188
+ SYLogger.debug(
189
+ f"[StreamingPatch] clamp max_tokens: "
190
+ f"context={max_tokens_limit}, max_output={max_output} → {dynamic_max}")
191
+ except Exception as e:
192
+ SYLogger.warning(f"[StreamingPatch] clamp max_tokens failed: {e}")
193
+
156
194
  async def _patched_execute_model_async(request):
157
195
  """替代 factory._execute_model_async: 用 astream + config 实现流式回调。"""
158
196
  from langchain.agents.middleware.types import ModelResponse
@@ -162,6 +200,9 @@ def _patch_agent_streaming(agent):
162
200
  if request.system_message:
163
201
  messages = [request.system_message, *messages]
164
202
 
203
+ # 动态调整 max_tokens,防止 input + max_output 超过上下文窗口
204
+ _clamp_max_tokens_for_model(model_, messages)
205
+
165
206
  # 从 ContextVar 读取 LangGraph 注入的 config(含 StreamMessagesHandler)
166
207
  config = var_child_runnable_config.get()
167
208
 
@@ -278,7 +319,7 @@ class AgentConfig(BaseModel):
278
319
  debug: bool = False
279
320
 
280
321
  # Rubric 评分配置
281
- rubric_max_iterations: int = 3 # rubric 评估最大迭代次数(0 = 不启用)
322
+ rubric_max_iterations: int = 0 # rubric 评估最大迭代次数(0 = 不启用,默认关闭)
282
323
 
283
324
  class Config:
284
325
  arbitrary_types_allowed = True
@@ -30,7 +30,6 @@ from sycommon.heartbeat_process.heartbeat_config import (
30
30
  RabbitMQMonitorConfig,
31
31
  LogConfig
32
32
  )
33
- from sycommon.synacos.dns_cache import NacosDnsCache
34
33
 
35
34
 
36
35
  def _init_process_logger(log_config: Optional[LogConfig] = None):
@@ -115,10 +114,6 @@ class HeartbeatProcessWorker:
115
114
  self._nacos_heartbeat_thread: Optional[threading.Thread] = None
116
115
  self._nacos_alert_sent = False
117
116
  self._nacos_disconnect_count = 0
118
- # DNS 缓存状态
119
- self._dns_cache = NacosDnsCache.get_instance()
120
- self._using_cached_ip: bool = False
121
- self._original_server_list = None
122
117
 
123
118
  # RabbitMQ 监控状态
124
119
  self._rabbitmq_alert_sent = False
@@ -226,10 +221,6 @@ class HeartbeatProcessWorker:
226
221
  f"Nacos 心跳成功,连续成功: {consecutive_success}次"
227
222
  )
228
223
 
229
- # DNS 缓存:连续成功 3 次后,解析域名并缓存 IP
230
- if consecutive_success >= 3 and not self._using_cached_ip:
231
- self._apply_dns_cache()
232
-
233
224
  # 恢复通知
234
225
  if self._nacos_alert_sent and consecutive_success >= 1:
235
226
  self._nacos_alert_sent = False
@@ -242,9 +233,6 @@ class HeartbeatProcessWorker:
242
233
  else:
243
234
  consecutive_success = 0
244
235
  consecutive_fail += 1
245
- # DNS 缓存:失败时清除缓存并恢复域名
246
- if self._using_cached_ip:
247
- self._revert_dns_cache()
248
236
  logger.warning(
249
237
  f"Nacos 心跳失败,连续失败: {consecutive_fail}次"
250
238
  )
@@ -253,9 +241,6 @@ class HeartbeatProcessWorker:
253
241
  except Exception as e:
254
242
  consecutive_success = 0
255
243
  consecutive_fail += 1
256
- # DNS 缓存:异常时清除缓存并恢复域名
257
- if self._using_cached_ip:
258
- self._revert_dns_cache()
259
244
  logger.error(f"Nacos 心跳异常: {e}")
260
245
  self._handle_nacos_failure(consecutive_fail)
261
246
 
@@ -355,60 +340,6 @@ class HeartbeatProcessWorker:
355
340
  except Exception as e:
356
341
  logger.error(f"发送 Nacos 告警失败: {e}")
357
342
 
358
- # ── DNS 缓存方法 ─────────────────────────────────────
359
-
360
- def _apply_dns_cache(self):
361
- """连续成功 3 次后,将 Nacos 服务端域名解析为 IP 并替换 server_list。"""
362
- if self.nacos_client is None:
363
- return
364
-
365
- # 备份原始 server_list
366
- self._original_server_list = list(self.nacos_client.server_list)
367
-
368
- new_server_list = []
369
- changed = False
370
- for host, port in self.nacos_client.server_list:
371
- if NacosDnsCache.is_ip(host):
372
- new_server_list.append((host, port))
373
- continue
374
- ip = self._dns_cache.resolve(host)
375
- if ip:
376
- self._dns_cache.cache_ip(host, ip)
377
- new_server_list.append((ip, port))
378
- changed = True
379
- logger.info(f"DNS 缓存 - {host} -> {ip}")
380
- else:
381
- logger.warning(f"DNS 解析失败,保持域名: {host}")
382
- new_server_list.append((host, port))
383
-
384
- if changed:
385
- with self.nacos_client.server_list_lock:
386
- self.nacos_client.server_list = new_server_list
387
- self.nacos_client.current_server = new_server_list[0]
388
- self.nacos_client.server_offset = 0
389
- self._using_cached_ip = True
390
- logger.info(f"DNS 缓存已生效, server_list={new_server_list}")
391
-
392
- def _revert_dns_cache(self):
393
- """心跳失败时,恢复原始域名地址,清除 DNS 缓存。"""
394
- if self._original_server_list is None:
395
- return
396
-
397
- if self.nacos_client is None:
398
- return
399
-
400
- # 清除 DNS 缓存条目
401
- for host, _ in self._original_server_list:
402
- self._dns_cache.invalidate(host)
403
-
404
- # 恢复原始 server_list
405
- with self.nacos_client.server_list_lock:
406
- self.nacos_client.server_list = list(self._original_server_list)
407
- self.nacos_client.current_server = self._original_server_list[0]
408
- self.nacos_client.server_offset = 0
409
- self._using_cached_ip = False
410
- logger.info(f"DNS 缓存已清除, 恢复域名: {self._original_server_list}")
411
-
412
343
  def _run_rabbitmq_monitor(self):
413
344
  """运行 RabbitMQ 连接监控(asyncio 事件循环)
414
345
 
@@ -11,6 +11,7 @@ from langchain_core.language_models import BaseChatModel
11
11
  from pydantic import BaseModel, Field
12
12
 
13
13
  from sycommon.config.LLMConfig import LLMConfig
14
+ from sycommon.llm.token_utils import clamp_max_tokens, count_messages_tokens
14
15
  from sycommon.llm.token_usage_mysql_service import TokenUsageMySQLService
15
16
  from sycommon.tools.merge_headers import get_header_value
16
17
 
@@ -109,64 +110,16 @@ class LLMWithTokenTracking(BaseChatModel):
109
110
  return
110
111
 
111
112
  try:
112
- input_est = self._count_tokens(messages)
113
+ clamp_max_tokens(
114
+ self.llm, messages,
115
+ context_window=self.llmConfig.maxTokens,
116
+ max_output_tokens=max_output,
117
+ )
113
118
  except Exception:
114
119
  return
115
120
 
116
- buffer = 8192
117
- available = self.llmConfig.maxTokens - input_est - buffer
118
- dynamic_max = min(max_output, max(available, 1024))
119
- self.llm.max_tokens = dynamic_max
120
-
121
- @staticmethod
122
- def _count_tokens(messages) -> int:
123
- """精确计算 messages 的 token 数
124
-
125
- 优先使用 tiktoken(OpenAI 兼容模型),否则回退到字符估算。
126
- 中文等非 ASCII 文本 chars_per_token 约 1.0-1.5,比英文 2.0-4.0 更密集。
127
- """
128
- total_chars = 0
129
- for msg in messages:
130
- content = getattr(msg, 'content', '')
131
- if isinstance(content, str):
132
- total_chars += len(content)
133
- elif isinstance(content, list):
134
- for part in content:
135
- if isinstance(part, str):
136
- total_chars += len(part)
137
- elif isinstance(part, dict):
138
- total_chars += len(str(part))
139
-
140
- # 检查是否有高比例非 ASCII(中文/日文等)
141
- sample = str(total_chars)
142
- non_ascii = sum(1 for c in sample if ord(c) > 127)
143
- ratio = non_ascii / max(len(sample), 1)
144
-
145
- # 中文等语言 chars_per_token 约 1.5,英文约 4.0
146
- chars_per_token = 1.5 if ratio > 0.3 else 3.5
147
-
148
- # 尝试 tiktoken 精确计数
149
- try:
150
- import tiktoken
151
- enc = tiktoken.get_encoding("cl100k_base")
152
- token_count = 0
153
- for msg in messages:
154
- content = getattr(msg, 'content', '')
155
- if isinstance(content, str):
156
- token_count += len(enc.encode(content))
157
- elif isinstance(content, list):
158
- for part in content:
159
- if isinstance(part, str):
160
- token_count += len(enc.encode(part))
161
- elif isinstance(part, dict):
162
- token_count += len(enc.encode(str(part)))
163
- # 加上消息格式开销(role、separator 等)
164
- return token_count + len(messages) * 4
165
- except Exception:
166
- pass
167
-
168
- # 回退:字符估算 + 每条消息 4 token 格式开销
169
- return int(total_chars / chars_per_token) + len(messages) * 4
121
+ # 统一使用 token_utils.count_messages_tokens,保留静态方法作为兼容别名
122
+ _count_tokens = staticmethod(count_messages_tokens)
170
123
 
171
124
  def _generate(self, messages, stop=None, run_manager=None, **kwargs):
172
125
  """
@@ -0,0 +1,96 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Token 计数与 max_tokens 动态调整工具函数
4
+
5
+ 统一供 LLMWithTokenTracking、LLMWithAutoTokenUsage、DeepAgent 等模块使用,
6
+ 避免同一逻辑分散在多处。
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from typing import List, Optional
12
+
13
+ from langchain_core.messages import BaseMessage
14
+
15
+
16
+ def count_messages_tokens(messages: List[BaseMessage]) -> int:
17
+ """精确计算 messages 的 token 数。
18
+
19
+ 优先使用 tiktoken(cl100k_base 编码),否则回退到字符估算。
20
+ 中文等非 ASCII 文本 chars_per_token 约 1.0-1.5,比英文 2.0-4.0 更密集。
21
+
22
+ Args:
23
+ messages: LangChain 消息列表。
24
+
25
+ Returns:
26
+ 估算的 token 总数(含每条消息 4 token 格式开销)。
27
+ """
28
+ total_chars = 0
29
+ for msg in messages:
30
+ content = getattr(msg, 'content', '')
31
+ if isinstance(content, str):
32
+ total_chars += len(content)
33
+ elif isinstance(content, list):
34
+ for part in content:
35
+ if isinstance(part, str):
36
+ total_chars += len(part)
37
+ elif isinstance(part, dict):
38
+ total_chars += len(str(part))
39
+
40
+ # 尝试 tiktoken 精确计数
41
+ try:
42
+ import tiktoken
43
+ enc = tiktoken.get_encoding("cl100k_base")
44
+ token_count = 0
45
+ for msg in messages:
46
+ content = getattr(msg, 'content', '')
47
+ if isinstance(content, str):
48
+ token_count += len(enc.encode(content))
49
+ elif isinstance(content, list):
50
+ for part in content:
51
+ if isinstance(part, str):
52
+ token_count += len(enc.encode(part))
53
+ elif isinstance(part, dict):
54
+ token_count += len(enc.encode(str(part)))
55
+ return token_count + len(messages) * 4
56
+ except Exception:
57
+ pass
58
+
59
+ # 回退:字符估算(中文 1.5 chars/token,英文 3.5 chars/token)
60
+ non_ascii = sum(1 for c in str(total_chars) if ord(c) > 127)
61
+ ratio = non_ascii / max(len(str(total_chars)), 1)
62
+ chars_per_token = 1.5 if ratio > 0.3 else 3.5
63
+ return int(total_chars / chars_per_token) + len(messages) * 4
64
+
65
+
66
+ def clamp_max_tokens(
67
+ model,
68
+ messages: List[BaseMessage],
69
+ *,
70
+ context_window: int,
71
+ max_output_tokens: int,
72
+ buffer: int = 8192,
73
+ min_output: int = 1024,
74
+ ) -> int:
75
+ """动态调整模型的 max_tokens,确保 input + max_output 不超过上下文窗口。
76
+
77
+ 每次调用前根据当前 input tokens 精确计算可用空间,
78
+ 将 model.max_tokens = min(max_output_tokens, context_window - input - buffer),
79
+ 最低保底 min_output。
80
+
81
+ Args:
82
+ model: 拥有 ``max_tokens`` 属性的 ChatModel 实例。
83
+ messages: 即将发送给模型的消息列表。
84
+ context_window: 模型上下文窗口大小(来自 LLMConfig.maxTokens)。
85
+ max_output_tokens: 配置的最大输出 token 数(来自 LLMConfig.maxOutputTokens)。
86
+ buffer: 保留的余量 token 数,默认 8192。
87
+ min_output: 最小输出 token 数保底值,默认 1024。
88
+
89
+ Returns:
90
+ 调整后的 max_tokens 值。
91
+ """
92
+ input_est = count_messages_tokens(messages)
93
+ available = context_window - input_est - buffer
94
+ dynamic_max = min(max_output_tokens, max(available, min_output))
95
+ model.max_tokens = dynamic_max
96
+ return dynamic_max
@@ -21,6 +21,7 @@ from sycommon.config.LLMConfig import LLMConfig
21
21
  from sycommon.llm.struct_token import StructuredRunnableWithToken
22
22
  from sycommon.llm.output_fixing_runnable import OutputFixingRunnable
23
23
  from sycommon.llm.native_with_fallback_runnable import NativeWithFallbackRunnable
24
+ from sycommon.llm.token_utils import clamp_max_tokens, count_messages_tokens
24
25
 
25
26
 
26
27
  class LLMWithAutoTokenUsage(BaseChatModel):
@@ -175,55 +176,16 @@ class LLMWithAutoTokenUsage(BaseChatModel):
175
176
  return
176
177
 
177
178
  try:
178
- input_est = self._count_tokens(messages)
179
+ clamp_max_tokens(
180
+ self.llm, messages,
181
+ context_window=self.llmConfig.maxTokens,
182
+ max_output_tokens=max_output,
183
+ )
179
184
  except Exception:
180
185
  return
181
186
 
182
- buffer = 8192
183
- available = self.llmConfig.maxTokens - input_est - buffer
184
- dynamic_max = min(max_output, max(available, 1024))
185
- self.llm.max_tokens = dynamic_max
186
-
187
- @staticmethod
188
- def _count_tokens(messages) -> int:
189
- """精确计算 messages 的 token 数"""
190
- total_chars = 0
191
- for msg in messages:
192
- content = getattr(msg, 'content', '')
193
- if isinstance(content, str):
194
- total_chars += len(content)
195
- elif isinstance(content, list):
196
- for part in content:
197
- if isinstance(part, str):
198
- total_chars += len(part)
199
- elif isinstance(part, dict):
200
- total_chars += len(str(part))
201
-
202
- # 尝试 tiktoken 精确计数
203
- try:
204
- import tiktoken
205
- enc = tiktoken.get_encoding("cl100k_base")
206
- token_count = 0
207
- for msg in messages:
208
- content = getattr(msg, 'content', '')
209
- if isinstance(content, str):
210
- token_count += len(enc.encode(content))
211
- elif isinstance(content, list):
212
- for part in content:
213
- if isinstance(part, str):
214
- token_count += len(enc.encode(part))
215
- elif isinstance(part, dict):
216
- token_count += len(enc.encode(str(part)))
217
- return token_count + len(messages) * 4
218
- except Exception:
219
- pass
220
-
221
- # 回退:字符估算(中文 1.5,英文 3.5)
222
- sample = str(total_chars)
223
- non_ascii = sum(1 for c in sample if ord(c) > 127)
224
- ratio = non_ascii / max(len(sample), 1)
225
- chars_per_token = 1.5 if ratio > 0.3 else 3.5
226
- return int(total_chars / chars_per_token) + len(messages) * 4
187
+ # 统一使用 token_utils.count_messages_tokens,保留静态方法作为兼容别名
188
+ _count_tokens = staticmethod(count_messages_tokens)
227
189
 
228
190
  # ========== 实现BaseChatModel抽象方法 ==========
229
191
  def _generate(self, messages, stop=None, run_manager=None, **kwargs):
@@ -2,7 +2,6 @@ import asyncio
2
2
  import threading
3
3
  import time
4
4
  from sycommon.logging.kafka_log import SYLogger
5
- from sycommon.synacos.dns_cache import NacosDnsCache
6
5
  from sycommon.synacos.nacos_client_base import NacosClientBase
7
6
  from sycommon.synacos.nacos_service_registration import NacosServiceRegistration
8
7
 
@@ -63,10 +62,6 @@ class NacosHeartbeatManager:
63
62
  self._alert_sent: bool = False
64
63
  self._disconnect_count: int = 0
65
64
  self._alert_fail_count: int = 0
66
- # DNS 缓存状态
67
- self._dns_cache = NacosDnsCache.get_instance()
68
- self._using_cached_ip: bool = False
69
- self._original_server_list = None # 备份原始 (domain, port) 列表
70
65
 
71
66
  def start_heartbeat(self):
72
67
  """启动心跳线程(确保单例)"""
@@ -122,9 +117,6 @@ class NacosHeartbeatManager:
122
117
  SYLogger.info(
123
118
  f"nacos:心跳发送成功 - 间隔: {self.heartbeat_interval}秒, 连续成功: {consecutive_success}次"
124
119
  )
125
- # DNS 缓存:连续成功 3 次后,解析域名并缓存 IP
126
- if consecutive_success >= 3 and not self._using_cached_ip:
127
- self._apply_dns_cache()
128
120
  # 恢复后发送通知(心跳成功一次即恢复)
129
121
  if self._alert_sent and consecutive_success >= 1:
130
122
  SYLogger.info(f"nacos:检测恢复状态 - _alert_sent={self._alert_sent}, consecutive_success={consecutive_success}")
@@ -142,9 +134,6 @@ class NacosHeartbeatManager:
142
134
  consecutive_success = 0 # 失败时重置连续成功计数
143
135
  consecutive_fail += 1
144
136
  self._heartbeat_fail_count += 1
145
- # DNS 缓存:失败时清除缓存并恢复域名
146
- if self._using_cached_ip:
147
- self._revert_dns_cache()
148
137
  SYLogger.warning(
149
138
  f"nacos:心跳发送失败 - 连续失败: {consecutive_fail}次"
150
139
  )
@@ -175,9 +164,6 @@ class NacosHeartbeatManager:
175
164
  consecutive_fail += 1
176
165
  consecutive_success = 0 # 异常时重置连续成功计数
177
166
  self._heartbeat_fail_count += 1
178
- # DNS 缓存:异常时清除缓存并恢复域名
179
- if self._using_cached_ip:
180
- self._revert_dns_cache()
181
167
  SYLogger.error(
182
168
  f"nacos:心跳异常: {str(e)}, 连续失败: {consecutive_fail}次")
183
169
 
@@ -257,59 +243,3 @@ class NacosHeartbeatManager:
257
243
  else:
258
244
  SYLogger.warning(f"nacos:心跳发送失败,Nacos返回: {result}")
259
245
  return False
260
-
261
- # ── DNS 缓存方法 ─────────────────────────────────────
262
-
263
- def _apply_dns_cache(self):
264
- """连续成功 3 次后,将 Nacos 服务端域名解析为 IP 并替换 server_list。"""
265
- nacos_client = self.client_base.nacos_client
266
- if nacos_client is None:
267
- return
268
-
269
- # 备份原始 server_list
270
- self._original_server_list = list(nacos_client.server_list)
271
-
272
- new_server_list = []
273
- changed = False
274
- for host, port in nacos_client.server_list:
275
- if NacosDnsCache.is_ip(host):
276
- new_server_list.append((host, port))
277
- continue
278
- ip = self._dns_cache.resolve(host)
279
- if ip:
280
- self._dns_cache.cache_ip(host, ip)
281
- new_server_list.append((ip, port))
282
- changed = True
283
- SYLogger.info(f"nacos:DNS 缓存 - {host} -> {ip}")
284
- else:
285
- SYLogger.warning(f"nacos:DNS 解析失败,保持域名: {host}")
286
- new_server_list.append((host, port))
287
-
288
- if changed:
289
- with nacos_client.server_list_lock:
290
- nacos_client.server_list = new_server_list
291
- nacos_client.current_server = new_server_list[0]
292
- nacos_client.server_offset = 0
293
- self._using_cached_ip = True
294
- SYLogger.info(f"nacos:DNS 缓存已生效, server_list={new_server_list}")
295
-
296
- def _revert_dns_cache(self):
297
- """心跳失败时,恢复原始域名地址,清除 DNS 缓存。"""
298
- if self._original_server_list is None:
299
- return
300
-
301
- nacos_client = self.client_base.nacos_client
302
- if nacos_client is None:
303
- return
304
-
305
- # 清除 DNS 缓存条目
306
- for host, _ in self._original_server_list:
307
- self._dns_cache.invalidate(host)
308
-
309
- # 恢复原始 server_list
310
- with nacos_client.server_list_lock:
311
- nacos_client.server_list = list(self._original_server_list)
312
- nacos_client.current_server = self._original_server_list[0]
313
- nacos_client.server_offset = 0
314
- self._using_cached_ip = False
315
- SYLogger.info(f"nacos:DNS 缓存已清除, 恢复域名: {self._original_server_list}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sycommon-python-lib
3
- Version: 0.2.5a28
3
+ Version: 0.2.5a29
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -191,6 +191,7 @@ src/sycommon/llm/struct_token.py
191
191
  src/sycommon/llm/sy_langfuse.py
192
192
  src/sycommon/llm/token_usage_es_service.py
193
193
  src/sycommon/llm/token_usage_mysql_service.py
194
+ src/sycommon/llm/token_utils.py
194
195
  src/sycommon/llm/usage_token.py
195
196
  src/sycommon/llm/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4
196
197
  src/sycommon/llm/tiktoken_cache/fb374d419588a4632f3f557e76b4b70aebbca790
@@ -246,7 +247,6 @@ src/sycommon/sse/__init__.py
246
247
  src/sycommon/sse/event.py
247
248
  src/sycommon/sse/sse.py
248
249
  src/sycommon/synacos/__init__.py
249
- src/sycommon/synacos/dns_cache.py
250
250
  src/sycommon/synacos/example.py
251
251
  src/sycommon/synacos/example2.py
252
252
  src/sycommon/synacos/feign.py
@@ -1,67 +0,0 @@
1
- """Nacos 服务端地址 DNS 缓存模块。
2
-
3
- 心跳连续成功 3 次后缓存域名解析结果,避免后续每次心跳都做 DNS 解析。
4
- 心跳失败时清除缓存,重新走域名解析,再次连续成功 3 次后重新缓存。
5
- """
6
- import socket
7
- import threading
8
- from typing import Dict, Optional
9
-
10
-
11
- class NacosDnsCache:
12
- """线程安全的 Nacos 服务端地址 DNS 缓存(单例)。"""
13
-
14
- _instance = None
15
- _init_lock = threading.Lock()
16
-
17
- def __init__(self):
18
- self._cache: Dict[str, str] = {} # domain -> resolved IP
19
- self._lock = threading.Lock()
20
-
21
- @classmethod
22
- def get_instance(cls) -> "NacosDnsCache":
23
- if cls._instance is None:
24
- with cls._init_lock:
25
- if cls._instance is None:
26
- cls._instance = cls()
27
- return cls._instance
28
-
29
- # ── 公共方法 ──────────────────────────────────────────
30
-
31
- def resolve(self, hostname: str) -> Optional[str]:
32
- """将域名解析为 IP 地址,失败返回 None。已为 IP 的直接返回。"""
33
- if self.is_ip(hostname):
34
- return hostname
35
- try:
36
- return socket.gethostbyname(hostname)
37
- except (socket.gaierror, socket.herror, OSError):
38
- return None
39
-
40
- def cache_ip(self, domain: str, ip: str):
41
- """显式缓存 domain -> IP 映射。"""
42
- with self._lock:
43
- self._cache[domain] = ip
44
-
45
- def get_cached(self, domain: str) -> Optional[str]:
46
- """返回缓存的 IP,无缓存返回 None。"""
47
- with self._lock:
48
- return self._cache.get(domain)
49
-
50
- def invalidate(self, domain: str):
51
- """删除指定域名的缓存条目。"""
52
- with self._lock:
53
- self._cache.pop(domain, None)
54
-
55
- def clear(self):
56
- """清空所有缓存。"""
57
- with self._lock:
58
- self._cache.clear()
59
-
60
- @staticmethod
61
- def is_ip(addr: str) -> bool:
62
- """判断 addr 是否已是 IP 地址(IPv4),跳过解析。"""
63
- try:
64
- socket.inet_aton(addr)
65
- return True
66
- except (socket.error, OSError):
67
- return False