echotools 2.4.7__tar.gz → 2.4.9__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 (291) hide show
  1. {echotools-2.4.7 → echotools-2.4.9}/PKG-INFO +2 -2
  2. {echotools-2.4.7 → echotools-2.4.9}/README.md +1 -1
  3. {echotools-2.4.7 → echotools-2.4.9}/pyproject.toml +18 -1
  4. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/cache/__init__.py +0 -2
  5. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/cache/list_cache.py +1 -35
  6. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/cache/memory_cache.py +1 -11
  7. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/config/__init__.py +0 -2
  8. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/config/center.py +8 -68
  9. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/errors/__init__.py +0 -2
  10. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/errors/base.py +0 -7
  11. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/ids/__init__.py +0 -2
  12. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/ids/generator.py +2 -24
  13. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/io/__init__.py +0 -2
  14. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/io/printstream.py +8 -103
  15. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/logger/__init__.py +0 -2
  16. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/retry/__init__.py +0 -2
  17. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/retry/retry.py +4 -42
  18. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/dispatch/__init__.py +0 -2
  19. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/__init__.py +0 -2
  20. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/shared/__init__.py +0 -2
  21. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/lifecycle/__init__.py +0 -2
  22. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/lifecycle/manager.py +1 -11
  23. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/lifecycle/updater.py +0 -12
  24. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/process/__init__.py +0 -2
  25. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/protocol/__init__.py +0 -2
  26. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/terminal/local/core.py +0 -2
  27. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/terminal/ssh.py +1 -22
  28. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uicore/mixins/__init__.py +0 -2
  29. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uicore/mixins/uibase.py +0 -12
  30. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/events/__init__.py +0 -2
  31. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/events/bus.py +2 -24
  32. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/tracing/__init__.py +0 -2
  33. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/tracing/span.py +0 -12
  34. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/tracing/tracer.py +2 -22
  35. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/watcher/__init__.py +0 -2
  36. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/watcher/file_watcher.py +1 -12
  37. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/__init__.py +0 -2
  38. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/application.py +0 -11
  39. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/audio_monitor/types.py +0 -4
  40. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/shared/__init__.py +11 -12
  41. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/shared/win_com.py +6 -3
  42. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/files/__init__.py +0 -2
  43. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/plugin/__init__.py +0 -2
  44. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/plugin/registry.py +5 -60
  45. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/proxy/__init__.py +0 -2
  46. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/proxy/manager.py +2 -18
  47. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/sdk/__init__.py +0 -2
  48. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/sdk/facade.py +0 -20
  49. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/sdk/runtime.py +1 -22
  50. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/sdk/scheduler.py +1 -26
  51. {echotools-2.4.7 → echotools-2.4.9}/src/echotools.egg-info/PKG-INFO +2 -2
  52. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_plat_capture.py +95 -2
  53. {echotools-2.4.7 → echotools-2.4.9}/setup.cfg +0 -0
  54. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/__init__.py +0 -0
  55. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/config/base.py +0 -0
  56. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/config/center_notify.py +0 -0
  57. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/config/center_template.py +0 -0
  58. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/config/loader.py +0 -0
  59. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/config/merge.py +0 -0
  60. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/errors/classify.py +0 -0
  61. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/errors/common.py +0 -0
  62. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/errors/http.py +0 -0
  63. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/io/io_utils.py +0 -0
  64. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/base/logger/manager.py +0 -0
  65. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/dispatch/candidate.py +0 -0
  66. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/dispatch/dispatcher.py +0 -0
  67. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/dispatch/proxy_selector.py +0 -0
  68. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/dispatch/race.py +0 -0
  69. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/dispatch/selector.py +0 -0
  70. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/dispatch/usage.py +0 -0
  71. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/parsers/__init__.py +0 -0
  72. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/parsers/stream.py +0 -0
  73. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/parsers/stream_delta.py +0 -0
  74. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/parsers/stream_feed.py +0 -0
  75. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/parsers/stream_final.py +0 -0
  76. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/prompt/__init__.py +0 -0
  77. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/prompt/behavior_blocks.py +0 -0
  78. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/prompt/history.py +0 -0
  79. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/prompt/history_format.py +0 -0
  80. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/prompt/inject.py +0 -0
  81. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/prompt/prompt_helpers.py +0 -0
  82. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/__init__.py +0 -0
  83. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml.py +0 -0
  84. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_patterns/__init__.py +0 -0
  85. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_patterns/invoke.py +0 -0
  86. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_patterns/params.py +0 -0
  87. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_patterns/regex.py +0 -0
  88. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_patterns/strip.py +0 -0
  89. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_schema/__init__.py +0 -0
  90. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_schema/mangled.py +0 -0
  91. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_schema/validate.py +0 -0
  92. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_stream/__init__.py +0 -0
  93. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_stream/body.py +0 -0
  94. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_stream/snap.py +0 -0
  95. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_think/__init__.py +0 -0
  96. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_think/core.py +0 -0
  97. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_think/filter.py +0 -0
  98. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_think/hist.py +0 -0
  99. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_think/hold.py +0 -0
  100. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_think/parse.py +0 -0
  101. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_tool/__init__.py +0 -0
  102. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_tool/comment.py +0 -0
  103. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_tool/fakemarkup.py +0 -0
  104. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_tool/invoke.py +0 -0
  105. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_tool/tools.py +0 -0
  106. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/protocols/entml_tool/values.py +0 -0
  107. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/registry.py +0 -0
  108. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/shared/coercion.py +0 -0
  109. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/shared/entml_format.py +0 -0
  110. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/shared/history_markup.py +0 -0
  111. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/shared/loop_detect.py +0 -0
  112. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/shared/normalization.py +0 -0
  113. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/shared/schema_render.py +0 -0
  114. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/fncall/tool_id.py +0 -0
  115. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/keys.py +0 -0
  116. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/lifecycle/updater_pull.py +0 -0
  117. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/process/port.py +0 -0
  118. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/protocol/base.py +0 -0
  119. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/terminal/__init__.py +0 -0
  120. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/terminal/conpty.py +0 -0
  121. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/terminal/local/__init__.py +0 -0
  122. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/terminal/local/proc.py +0 -0
  123. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/terminal/local/unix.py +0 -0
  124. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/terminal/local/win.py +0 -0
  125. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/terminal/sanitize.py +0 -0
  126. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/terminal/session/__init__.py +0 -0
  127. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/terminal/session/base.py +0 -0
  128. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/terminal/session/client.py +0 -0
  129. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/exec/terminal/tmux.py +0 -0
  130. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/__init__.py +0 -0
  131. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/charmap.py +0 -0
  132. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/spinner.py +0 -0
  133. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/ui.py +0 -0
  134. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uicore/mixins/uicmds.py +0 -0
  135. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uicore/mixins/uiinteract.py +0 -0
  136. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uicore/mixins/uioutput.py +0 -0
  137. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uicore/mixins/uistream.py +0 -0
  138. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uicore/ui_console.py +0 -0
  139. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uicore/ui_io.py +0 -0
  140. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uicore/ui_log.py +0 -0
  141. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uicore/ui_platform.py +0 -0
  142. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uicore/ui_text.py +0 -0
  143. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uicore/ui_types.py +0 -0
  144. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uilayout/ui_bridge.py +0 -0
  145. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uilayout/ui_countdown.py +0 -0
  146. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uilayout/ui_layout.py +0 -0
  147. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uilayout/ui_misc.py +0 -0
  148. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uilayout/ui_panel.py +0 -0
  149. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uilayout/ui_table.py +0 -0
  150. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uilayout/ui_tree.py +0 -0
  151. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uiwidgets/ui_box.py +0 -0
  152. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uiwidgets/ui_editor.py +0 -0
  153. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uiwidgets/ui_progress.py +0 -0
  154. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uiwidgets/ui_richcli.py +0 -0
  155. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uiwidgets/ui_select.py +0 -0
  156. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uiwidgets/ui_stream.py +0 -0
  157. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/console/uiwidgets/ui_themes.py +0 -0
  158. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/events/event.py +0 -0
  159. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/spinner/__init__.py +0 -0
  160. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/spinner/spinner.py +0 -0
  161. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/spinner/spinner_color.py +0 -0
  162. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/tracing/context.py +0 -0
  163. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/translate.py +0 -0
  164. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/broker.py +0 -0
  165. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/input_box/app.js +0 -0
  166. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/input_box/components/filezone.js +0 -0
  167. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/input_box/components/motionkit.js +0 -0
  168. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/input_box/components/sendbutton.js +0 -0
  169. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/input_box/components/sortablelist.css +0 -0
  170. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/input_box/components/sortablelist.js +0 -0
  171. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/input_box/components/textinput.js +0 -0
  172. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/input_box/components/voiceinput.js +0 -0
  173. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/input_box/fonts/inter-500.woff2 +0 -0
  174. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/input_box/fonts/inter-600.woff2 +0 -0
  175. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/input_box/fonts/inter400.woff2 +0 -0
  176. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/input_box/inputbox.css +0 -0
  177. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/input_box/inputbox.js +0 -0
  178. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/input_box/style.css +0 -0
  179. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/input_box/voicegif.js +0 -0
  180. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/middleware.py +0 -0
  181. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/stats.py +0 -0
  182. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/media/web/utils.py +0 -0
  183. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/__init__.py +0 -0
  184. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/audio_monitor/api.py +0 -0
  185. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/audio_monitor/config.py +0 -0
  186. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/audio_monitor/linux.py +0 -0
  187. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/audio_monitor/mac.py +0 -0
  188. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/audio_monitor/win.py +0 -0
  189. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/audio_record/api.py +0 -0
  190. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/audio_record/config.py +0 -0
  191. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/audio_record/linux.py +0 -0
  192. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/audio_record/mac.py +0 -0
  193. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/audio_record/win.py +0 -0
  194. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/audio_record/win_wasapi.py +0 -0
  195. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/audio_record/win_winmm.py +0 -0
  196. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/screenshot/api.py +0 -0
  197. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/screenshot/config.py +0 -0
  198. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/screenshot/linux.py +0 -0
  199. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/screenshot/mac.py +0 -0
  200. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/screenshot/win.py +0 -0
  201. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/screenshot/win_dxgi.py +0 -0
  202. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/screenshot/win_gdi.py +0 -0
  203. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/shared/bmp.py +0 -0
  204. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/shared/pcm.py +0 -0
  205. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/shared/platform.py +0 -0
  206. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/capture/shared/wav.py +0 -0
  207. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/files/file_util.py +0 -0
  208. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/network/__init__.py +0 -0
  209. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/network/http_utils.py +0 -0
  210. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/plugin/base.py +0 -0
  211. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/plugin/discovery.py +0 -0
  212. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/plat/plugin/registry_ops.py +0 -0
  213. {echotools-2.4.7 → echotools-2.4.9}/src/echotools/version.py +0 -0
  214. {echotools-2.4.7 → echotools-2.4.9}/src/echotools.egg-info/SOURCES.txt +0 -0
  215. {echotools-2.4.7 → echotools-2.4.9}/src/echotools.egg-info/dependency_links.txt +0 -0
  216. {echotools-2.4.7 → echotools-2.4.9}/src/echotools.egg-info/requires.txt +0 -0
  217. {echotools-2.4.7 → echotools-2.4.9}/src/echotools.egg-info/top_level.txt +0 -0
  218. {echotools-2.4.7 → echotools-2.4.9}/src/tests/_check_parity.py +0 -0
  219. {echotools-2.4.7 → echotools-2.4.9}/src/tests/bench_import.py +0 -0
  220. {echotools-2.4.7 → echotools-2.4.9}/src/tests/conftest.py +0 -0
  221. {echotools-2.4.7 → echotools-2.4.9}/src/tests/fixtures/__init__.py +0 -0
  222. {echotools-2.4.7 → echotools-2.4.9}/src/tests/fixtures/entml_golden.py +0 -0
  223. {echotools-2.4.7 → echotools-2.4.9}/src/tests/fixtures/entml_golden_update.py +0 -0
  224. {echotools-2.4.7 → echotools-2.4.9}/src/tests/fixtures/simulated_fake_history_markup_responses.py +0 -0
  225. {echotools-2.4.7 → echotools-2.4.9}/src/tests/fixtures/simulated_fault_thinking_responses.py +0 -0
  226. {echotools-2.4.7 → echotools-2.4.9}/src/tests/fixtures/simulated_llm_tool_responses.py +0 -0
  227. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_adversarial_stream_splits.py +0 -0
  228. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_cache_retry.py +0 -0
  229. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_completion.py +0 -0
  230. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_config.py +0 -0
  231. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_config_extended.py +0 -0
  232. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_console.py +0 -0
  233. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_coverage_core.py +0 -0
  234. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_dispatch.py +0 -0
  235. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_dispatch_extended.py +0 -0
  236. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_dispatch_race.py +0 -0
  237. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_entml_agent_output_formats.py +0 -0
  238. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_entml_bare_invoke_format.py +0 -0
  239. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_entml_batch_stream_comprehensive.py +0 -0
  240. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_entml_fake_structure_markup.py +0 -0
  241. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_entml_golden.py +0 -0
  242. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_entml_invoke_known_tool_gate.py +0 -0
  243. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_entml_parser_comprehensive.py +0 -0
  244. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_entml_protocol.py +0 -0
  245. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_entml_stream_json.py +0 -0
  246. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_entml_stream_json_exhaustive.py +0 -0
  247. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_entml_thinking_history.py +0 -0
  248. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_entml_thinking_parse.py +0 -0
  249. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_entml_tool_parse_leak.py +0 -0
  250. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_entml_tool_pipeline.py +0 -0
  251. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_entml_tools.py +0 -0
  252. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_errors.py +0 -0
  253. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_errors_common.py +0 -0
  254. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_events.py +0 -0
  255. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_events_event.py +0 -0
  256. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_facade.py +0 -0
  257. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_fake_history_markup_batch.py +0 -0
  258. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_fake_history_markup_invoke_preserve.py +0 -0
  259. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_fake_history_markup_reply_protect.py +0 -0
  260. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_fake_history_markup_stream.py +0 -0
  261. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_fault_thinking_close_batch.py +0 -0
  262. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_fault_thinking_close_stream.py +0 -0
  263. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_fncall.py +0 -0
  264. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_fncall_stream_thinking.py +0 -0
  265. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_history_markup_filter.py +0 -0
  266. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_ids.py +0 -0
  267. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_imports.py +0 -0
  268. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_io.py +0 -0
  269. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_keys.py +0 -0
  270. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_lifecycle.py +0 -0
  271. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_logger.py +0 -0
  272. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_merge.py +0 -0
  273. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_model_branch_matrix.py +0 -0
  274. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_multiline_parameter_comprehensive.py +0 -0
  275. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_plugin.py +0 -0
  276. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_printstream.py +0 -0
  277. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_protocols.py +0 -0
  278. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_proxy.py +0 -0
  279. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_proxy_selector.py +0 -0
  280. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_runtime.py +0 -0
  281. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_scheduler.py +0 -0
  282. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_schema_validate.py +0 -0
  283. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_simulated_llm_tool_parse.py +0 -0
  284. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_stream_partial_json_parity.py +0 -0
  285. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_stream_realtime_parse.py +0 -0
  286. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_tool_id.py +0 -0
  287. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_tracing.py +0 -0
  288. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_ui_bridge.py +0 -0
  289. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_usage.py +0 -0
  290. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_web.py +0 -0
  291. {echotools-2.4.7 → echotools-2.4.9}/src/tests/test_web_broker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: echotools
3
- Version: 2.4.7
3
+ Version: 2.4.9
4
4
  Summary: 通用基础设施 SDK:配置、日志、事件、调度、插件、协议、调用链
5
5
  Home-page: https://github.com/nichengfuben/echotools
6
6
  Author: nichengfuben
@@ -58,7 +58,7 @@ Requires-Dist: ruff>=0.4.0; extra == "dev"
58
58
 
59
59
  通用基础设施 SDK:配置、日志、事件、调度、插件、调用链,以及 **entml** LLM 工具调用协议与终端 Console UI。
60
60
 
61
- 完全项目无关,兼容 Python 3.8–3.14。当前版本:**2.4.7**(详见 [CHANGELOG](docs/CHANGELOG.md))。
61
+ 完全项目无关,兼容 Python 3.8–3.14。当前版本:**2.4.9**(详见 [CHANGELOG](docs/CHANGELOG.md))。
62
62
 
63
63
  ## 安装
64
64
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  通用基础设施 SDK:配置、日志、事件、调度、插件、调用链,以及 **entml** LLM 工具调用协议与终端 Console UI。
4
4
 
5
- 完全项目无关,兼容 Python 3.8–3.14。当前版本:**2.4.7**(详见 [CHANGELOG](docs/CHANGELOG.md))。
5
+ 完全项目无关,兼容 Python 3.8–3.14。当前版本:**2.4.9**(详见 [CHANGELOG](docs/CHANGELOG.md))。
6
6
 
7
7
  ## 安装
8
8
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "echotools"
7
- version = "2.4.7"
7
+ version = "2.4.9"
8
8
  description = "通用基础设施 SDK:配置、日志、事件、调度、插件、协议、调用链"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -142,6 +142,23 @@ omit = [
142
142
  "*/web/application.py",
143
143
  "*/web/middleware.py",
144
144
  "*/web/utils.py",
145
+ "*/plat/capture/shared/win_com.py",
146
+ "*/plat/capture/audio_monitor/api.py",
147
+ "*/plat/capture/audio_record/api.py",
148
+ "*/plat/capture/screenshot/api.py",
149
+ "*/plat/capture/audio_monitor/win.py",
150
+ "*/plat/capture/audio_monitor/mac.py",
151
+ "*/plat/capture/audio_monitor/linux.py",
152
+ "*/plat/capture/audio_record/win.py",
153
+ "*/plat/capture/audio_record/win_wasapi.py",
154
+ "*/plat/capture/audio_record/win_winmm.py",
155
+ "*/plat/capture/audio_record/mac.py",
156
+ "*/plat/capture/audio_record/linux.py",
157
+ "*/plat/capture/screenshot/win.py",
158
+ "*/plat/capture/screenshot/win_dxgi.py",
159
+ "*/plat/capture/screenshot/win_gdi.py",
160
+ "*/plat/capture/screenshot/mac.py",
161
+ "*/plat/capture/screenshot/linux.py",
145
162
  ]
146
163
 
147
164
  [tool.coverage.report]
@@ -1,7 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- """cache 模块导出。"""
4
-
5
3
  from echotools.base.cache.list_cache import ListCache
6
4
  from echotools.base.cache.memory_cache import MemoryCache
7
5
 
@@ -19,14 +19,7 @@ logger = get_logger(__name__)
19
19
 
20
20
 
21
21
  class ListCache:
22
- """通用字符串列表缓存管理器。
23
-
24
- 职责:
25
- 1. 从持久化文件读取缓存
26
- 2. 定时调用 fetch_fn 刷新远程列表
27
- 3. 根据 overwrite 决定覆盖或追加
28
- 4. 更新后触发 on_update 回调
29
- """
22
+ """持久化字符串列表;定时 fetch 刷新,overwrite 控制覆盖或只增不减。"""
30
23
 
31
24
  def __init__(
32
25
  self,
@@ -36,15 +29,6 @@ class ListCache:
36
29
  overwrite: bool = True,
37
30
  data_key: str = "items",
38
31
  ) -> None:
39
- """初始化列表缓存。
40
-
41
- Args:
42
- name: 缓存标识名(仅用于日志)。
43
- fallback: 兜底列表。
44
- cache_path: 持久化文件路径。
45
- overwrite: True=覆盖,False=只增不减。
46
- data_key: JSON 中存储列表的键名,默认 "items"。
47
- """
48
32
  self._name = name
49
33
  self._fallback = list(fallback)
50
34
  self._overwrite = overwrite
@@ -54,11 +38,6 @@ class ListCache:
54
38
  self._data_key = data_key
55
39
 
56
40
  async def load(self) -> List[str]:
57
- """从缓存文件加载列表。
58
-
59
- Returns:
60
- 缓存列表,无缓存则返回兜底列表。
61
- """
62
41
  try:
63
42
  if self._cache_path.is_file():
64
43
  text = self._cache_path.read_text(encoding="utf-8")
@@ -76,11 +55,6 @@ class ListCache:
76
55
  return list(self._items)
77
56
 
78
57
  async def save(self, items: List[str]) -> None:
79
- """保存列表到缓存文件。
80
-
81
- Args:
82
- items: 要保存的列表。
83
- """
84
58
  try:
85
59
  self._cache_path.parent.mkdir(parents=True, exist_ok=True)
86
60
  data = {self._data_key: items, "updated_at": int(time.time())}
@@ -92,7 +66,6 @@ class ListCache:
92
66
  logger.warning("[%s] 缓存保存失败: %s", self._name, e)
93
67
 
94
68
  def _merge(self, remote: List[str]) -> List[str]:
95
- """根据策略合并列表。"""
96
69
  if self._overwrite:
97
70
  return list(remote) if remote else list(self._items)
98
71
  existing = set(self._items)
@@ -111,13 +84,6 @@ class ListCache:
111
84
  Callable[[List[str]], Awaitable[None]]
112
85
  ] = None,
113
86
  ) -> None:
114
- """启动定时刷新循环(永久运行)。
115
-
116
- Args:
117
- fetch_fn: 返回远程列表的异步函数。
118
- interval: 刷新间隔(秒)。
119
- on_update: 更新回调。
120
- """
121
87
  while True:
122
88
  await self._do_refresh(fetch_fn, on_update)
123
89
  await asyncio.sleep(interval)
@@ -14,19 +14,12 @@ class MemoryCache:
14
14
  """Thread-safe TTL memory cache with optional LRU eviction."""
15
15
 
16
16
  def __init__(self, default_ttl: float = 0.0, max_size: int = 0) -> None:
17
- """初始化缓存。
18
-
19
- Args:
20
- default_ttl: 默认存活秒数,0 表示永不过期。
21
- max_size: 最大条目数,0 表示不限制。
22
- """
23
17
  self._store: "OrderedDict[str, Tuple[Any, float]]" = OrderedDict()
24
18
  self._default_ttl = default_ttl
25
19
  self._max_size = max_size
26
20
  self._lock = threading.RLock()
27
21
 
28
22
  def set(self, key: str, value: Any, ttl: Optional[float] = None) -> None:
29
- """写入缓存。"""
30
23
  effective = self._default_ttl if ttl is None else ttl
31
24
  expire = 0.0 if effective <= 0 else time.time() + effective
32
25
  with self._lock:
@@ -36,7 +29,6 @@ class MemoryCache:
36
29
  self._evict_if_needed()
37
30
 
38
31
  def get(self, key: str, default: Any = None) -> Any:
39
- """读取缓存。"""
40
32
  with self._lock:
41
33
  item = self._store.get(key)
42
34
  if item is None:
@@ -49,17 +41,15 @@ class MemoryCache:
49
41
  return value
50
42
 
51
43
  def delete(self, key: str) -> None:
52
- """删除键。"""
53
44
  with self._lock:
54
45
  self._store.pop(key, None)
55
46
 
56
47
  def clear(self) -> None:
57
- """清空缓存。"""
58
48
  with self._lock:
59
49
  self._store.clear()
60
50
 
61
51
  def cleanup(self) -> int:
62
- """清理过期项,返回清理数量。"""
52
+ """返回被剔除的过期条目数。"""
63
53
  now = time.time()
64
54
  with self._lock:
65
55
  expired = [k for k, (_, exp) in self._store.items() if exp and now > exp]
@@ -1,7 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- """config 模块导出。"""
4
-
5
3
  from echotools.base.config.base import ConfigBase
6
4
  from echotools.base.config.center import ConfigCenter
7
5
  from echotools.base.config.loader import (
@@ -52,7 +52,6 @@ class ConfigCenter:
52
52
  """
53
53
 
54
54
  def __init__(self) -> None:
55
- """初始化配置中心。"""
56
55
  self._raw: Dict[str, Any] = {}
57
56
  self._path: Optional[Path] = None
58
57
  self._callbacks: Dict[str, List[Callable[[Any, Any], Any]]] = {}
@@ -77,19 +76,7 @@ class ConfigCenter:
77
76
  filename: str = "config.toml",
78
77
  data: Optional[Dict[str, Any]] = None,
79
78
  ) -> Dict[str, Any]:
80
- """加载配置。
81
-
82
- Args:
83
- path: 配置文件路径。
84
- filename: 自动查找时的文件名。
85
- data: 直接提供字典(最高优先,跳过文件)。
86
-
87
- Returns:
88
- 原始配置字典。
89
-
90
- Raises:
91
- ConfigError: 无法定位或解析配置。
92
- """
79
+ """加载配置;data 非空时跳过文件读取。"""
93
80
  if data is not None:
94
81
  self._raw = copy.deepcopy(data)
95
82
  return dict(self._raw)
@@ -104,15 +91,7 @@ class ConfigCenter:
104
91
  return dict(self._raw)
105
92
 
106
93
  def get(self, path: str, default: Any = None) -> Any:
107
- """按点路径获取配置值。
108
-
109
- Args:
110
- path: 形如 "server.port" 的点路径。
111
- default: 缺省值。
112
-
113
- Returns:
114
- 配置值或默认值。
115
- """
94
+ """按点路径获取配置值。"""
116
95
  node: Any = self._raw
117
96
  for part in path.split("."):
118
97
  if isinstance(node, dict) and part in node:
@@ -122,12 +101,7 @@ class ConfigCenter:
122
101
  return node
123
102
 
124
103
  def set(self, path: str, value: Any) -> None:
125
- """按点路径设置配置值(内存中)。
126
-
127
- Args:
128
- path: 点路径。
129
- value: 新值。
130
- """
104
+ """按点路径设置配置值(仅内存,不写文件)。"""
131
105
  parts = path.split(".")
132
106
  node = self._raw
133
107
  for part in parts[:-1]:
@@ -137,15 +111,7 @@ class ConfigCenter:
137
111
  node[parts[-1]] = value
138
112
 
139
113
  def bind(self, schema: Type[C], section: str = "") -> C:
140
- """将配置绑定到类型化 ConfigBase 子类。
141
-
142
- Args:
143
- schema: ConfigBase 子类。
144
- section: 子段点路径,空表示根。
145
-
146
- Returns:
147
- 类型化配置实例。
148
- """
114
+ """将配置绑定到类型化 ConfigBase 子类。"""
149
115
  data = self.get(section, {}) if section else self._raw
150
116
  if not isinstance(data, dict):
151
117
  raise ConfigError(
@@ -155,31 +121,20 @@ class ConfigCenter:
155
121
 
156
122
  @property
157
123
  def raw(self) -> Dict[str, Any]:
158
- """原始配置字典副本。"""
159
124
  return copy.deepcopy(self._raw)
160
125
 
161
126
  @property
162
127
  def path(self) -> Optional[Path]:
163
- """配置文件路径。"""
164
128
  return self._path
165
129
 
166
130
  def on_change(
167
131
  self, path: str, callback: Callable[[Any, Any], Any]
168
132
  ) -> None:
169
- """注册配置变更回调。
170
-
171
- Args:
172
- path: 监听的点路径。
173
- callback: 回调(old, new),支持同步/异步。
174
- """
133
+ """注册配置变更回调;callback(old, new) 支持同步或异步。"""
175
134
  self._callbacks.setdefault(path, []).append(callback)
176
135
 
177
136
  async def reload(self) -> bool:
178
- """热重载配置文件并触发变更回调。
179
-
180
- Returns:
181
- 是否成功。
182
- """
137
+ """热重载配置文件并触发已注册的变更回调。"""
183
138
  if self._path is None or not self._path.exists():
184
139
  return False
185
140
  async with self._get_lock():
@@ -214,11 +169,7 @@ class ConfigCenter:
214
169
  return init_from_template(self, **kwargs)
215
170
 
216
171
  def write(self, data: Optional[Dict[str, Any]] = None) -> None:
217
- """将配置写回文件(tomlkit 保留注释)。
218
-
219
- Args:
220
- data: 要写入的字典,None 则写入当前 _raw。
221
- """
172
+ """将配置写回文件(tomlkit 保留注释)。"""
222
173
  if self._path is None:
223
174
  raise ConfigError("配置路径未设置")
224
175
  write_toml(self._path, data if data is not None else self._raw)
@@ -226,14 +177,7 @@ class ConfigCenter:
226
177
  self._raw = copy.deepcopy(data)
227
178
 
228
179
  def backup(self, backup_dir: Optional[str] = None) -> Optional[Path]:
229
- """创建配置文件的带时间戳备份。
230
-
231
- Args:
232
- backup_dir: 备份目录,默认 <config_dir>/template/old。
233
-
234
- Returns:
235
- 备份文件路径,无配置路径时返回 None。
236
- """
180
+ """创建配置文件的带时间戳备份;默认目录为 <config_dir>/template/old。"""
237
181
  if self._path is None or not self._path.exists():
238
182
  return None
239
183
  if backup_dir is None:
@@ -247,10 +191,6 @@ class ConfigCenter:
247
191
  logger.debug("已备份: %s", backup_path)
248
192
  return backup_path
249
193
 
250
- # ------------------------------------------------------------------
251
- # __getattr__ 代理
252
- # ------------------------------------------------------------------
253
-
254
194
  def bind_proxy(self, schema: Type[C], section: str = "") -> C:
255
195
  """绑定 schema 并启用 __getattr__ 代理。
256
196
 
@@ -1,7 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- """错误模块统一导出。"""
4
-
5
3
  from echotools.base.errors.base import EchoError
6
4
  from echotools.base.errors.classify import classify_http_error
7
5
  from echotools.base.errors.common import (
@@ -19,13 +19,6 @@ class EchoError(Exception):
19
19
  original: Optional[Exception] = None,
20
20
  status_code: int = 500,
21
21
  ) -> None:
22
- """初始化异常。
23
-
24
- Args:
25
- message: 错误信息。
26
- original: 原始异常。
27
- status_code: 关联状态码。
28
- """
29
22
  super().__init__(message)
30
23
  self.message = message
31
24
  self.original = original
@@ -1,7 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- """ids 模块导出。"""
4
-
5
3
  from echotools.base.ids.generator import gen_tool_id, short_id, span_id, trace_id, uuid7
6
4
 
7
5
  __all__ = ["uuid7", "short_id", "trace_id", "span_id", "gen_tool_id"]
@@ -11,11 +11,7 @@ __all__ = ["uuid7", "short_id", "trace_id", "span_id", "gen_tool_id"]
11
11
 
12
12
 
13
13
  def uuid7() -> str:
14
- """生成时间有序的 UUIDv7 字符串。
15
-
16
- Returns:
17
- 符合 UUIDv7 位布局的字符串。
18
- """
14
+ """时间有序的 UUIDv7。"""
19
15
  ts_ms = int(time.time() * 1000) & 0xFFFFFFFFFFFF
20
16
  rand_bytes = secrets.token_bytes(10)
21
17
  rand_a = struct.unpack(">H", rand_bytes[:2])[0] & 0x0FFF
@@ -31,37 +27,19 @@ def uuid7() -> str:
31
27
 
32
28
 
33
29
  def short_id(length: int = 12) -> str:
34
- """生成短随机 ID。
35
-
36
- Args:
37
- length: 长度,默认为 12。
38
-
39
- Returns:
40
- 十六进制随机字符串。
41
- """
42
30
  if length <= 0:
43
31
  raise ValueError("length 必须为正整数")
44
32
  return uuid.uuid4().hex[:length]
45
33
 
46
34
 
47
35
  def trace_id() -> str:
48
- """生成 trace_id(32 位十六进制)。
49
-
50
- Returns:
51
- trace_id 字符串。
52
- """
53
36
  return secrets.token_hex(16)
54
37
 
55
38
 
56
39
  def span_id() -> str:
57
- """生成 span_id(16 位十六进制)。
58
-
59
- Returns:
60
- span_id 字符串。
61
- """
62
40
  return secrets.token_hex(8)
63
41
 
64
42
 
65
43
  def gen_tool_id() -> str:
66
- """生成 Anthropic 兼容的 tool_use id(``toolu_`` + 24 位十六进制)。"""
44
+ """Anthropic 兼容 tool_use id(``toolu_`` + 24 hex)。"""
67
45
  return f"toolu_{uuid.uuid4().hex[:24]}"
@@ -1,7 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- """io 模块导出。"""
4
-
5
3
  from echotools.base.io.io_utils import (
6
4
  atomic_write_text,
7
5
  ensure_directory,
@@ -1,9 +1,4 @@
1
- """Dynamic speed print stream system for controlled console output.
2
-
3
- This module provides a PrintStream class that implements dynamic speed
4
- printing with ordered queue management, suitable for controlled output
5
- of large text blocks with adaptive speed based on queue depth.
6
- """
1
+ """动态速率打印流:按队列深度自适应输出速度。"""
7
2
 
8
3
  from __future__ import annotations
9
4
 
@@ -17,21 +12,7 @@ from typing import Any, Optional
17
12
 
18
13
 
19
14
  class PrintStream:
20
- """Dynamic speed print stream system with ordered queue.
21
-
22
- This class manages a queue of text blocks and outputs them with
23
- adaptive speed based on the current queue depth. The output speed
24
- increases as more text is pending, providing smooth, controlled output.
25
-
26
- Attributes:
27
- min_speed: Minimum output speed in characters per second.
28
- max_speed: Maximum output speed in characters per second.
29
- decay_factor: Controls how quickly speed adapts to queue depth.
30
- smoothing_factor: Controls speed change smoothing (0.0-1.0).
31
- current_speed: Current output speed in characters per second.
32
- accumulated_chars: Fractional characters pending output.
33
- total_pending_chars: Total characters waiting to be output.
34
- """
15
+ """按队列深度自适应输出速度的打印流。"""
35
16
 
36
17
  def __init__(
37
18
  self,
@@ -40,14 +21,6 @@ class PrintStream:
40
21
  decay_factor: float = 20.0,
41
22
  smoothing_factor: float = 0.8,
42
23
  ) -> None:
43
- """Initialize the print stream.
44
-
45
- Args:
46
- min_speed: Minimum output speed (characters/second).
47
- max_speed: Maximum output speed (characters/second).
48
- decay_factor: Controls speed adaptation curve.
49
- smoothing_factor: Controls speed change smoothing.
50
- """
51
24
  # Queue management
52
25
  self._text_queue: deque[str] = deque()
53
26
  self._current_text: str = ""
@@ -80,10 +53,7 @@ class PrintStream:
80
53
  self._output_thread.start()
81
54
 
82
55
  def stop(self) -> None:
83
- """Stop the print stream system.
84
-
85
- Waits for all pending output to complete before stopping.
86
- """
56
+ """停止输出;会等待队列中待输出内容排空。"""
87
57
  if self._running:
88
58
  self._running = False
89
59
  # Wait for all content to be output
@@ -98,11 +68,7 @@ class PrintStream:
98
68
  self._output_thread.join(timeout=1)
99
69
 
100
70
  def add_to_buffer(self, text: str) -> None:
101
- """Add text to the output queue.
102
-
103
- Args:
104
- text: Text to add to the queue.
105
- """
71
+ """将文本加入输出队列。"""
106
72
  if not self._running:
107
73
  self.start()
108
74
 
@@ -129,14 +95,7 @@ class PrintStream:
129
95
  self.accumulated_chars = 0.0
130
96
 
131
97
  def _calculate_dynamic_speed(self, buffer_length: int) -> float:
132
- """Calculate dynamic output speed based on buffer length.
133
-
134
- Args:
135
- buffer_length: Number of pending characters.
136
-
137
- Returns:
138
- Calculated speed in characters per second.
139
- """
98
+ """根据待输出字符数计算当前输出速率。"""
140
99
  if buffer_length <= 0:
141
100
  return self.min_speed
142
101
 
@@ -201,31 +160,16 @@ class PrintStream:
201
160
 
202
161
  @property
203
162
  def buffer_size(self) -> int:
204
- """Get total characters waiting to be output.
205
-
206
- Returns:
207
- Number of pending characters.
208
- """
209
163
  with self._lock:
210
164
  queue_chars = sum(len(text) for text in self._text_queue)
211
165
  return len(self._current_text) + queue_chars
212
166
 
213
167
  @property
214
168
  def is_running(self) -> bool:
215
- """Check if the system is running.
216
-
217
- Returns:
218
- True if running, False otherwise.
219
- """
220
169
  return self._running
221
170
 
222
171
  @property
223
172
  def queue_length(self) -> int:
224
- """Get number of text blocks in queue.
225
-
226
- Returns:
227
- Number of queued text blocks.
228
- """
229
173
  with self._lock:
230
174
  return len(self._text_queue)
231
175
 
@@ -240,17 +184,7 @@ def print_stream(
240
184
  end: str = "\n",
241
185
  flush: bool = False,
242
186
  ) -> None:
243
- """Dynamic speed print function.
244
-
245
- This function provides a drop-in replacement for the built-in print()
246
- function with dynamic speed output based on queue depth.
247
-
248
- Args:
249
- *args: Content to print.
250
- sep: Separator between arguments (default: space).
251
- end: End character (default: newline).
252
- flush: If True, output immediately without queuing.
253
- """
187
+ """动态速率 print 替代;flush=True 时立即输出不入队。"""
254
188
  try:
255
189
  # Ensure system is started
256
190
  if not _global_print_stream.is_running:
@@ -288,39 +222,19 @@ def flush_print_stream() -> None:
288
222
 
289
223
 
290
224
  def get_buffer_size() -> int:
291
- """Get current buffer size.
292
-
293
- Returns:
294
- Number of pending characters.
295
- """
296
225
  return _global_print_stream.buffer_size
297
226
 
298
227
 
299
228
  def get_queue_length() -> int:
300
- """Get number of text blocks in queue.
301
-
302
- Returns:
303
- Number of queued text blocks.
304
- """
305
229
  return _global_print_stream.queue_length
306
230
 
307
231
 
308
232
  def is_print_stream_running() -> bool:
309
- """Check if the print stream system is running.
310
-
311
- Returns:
312
- True if running, False otherwise.
313
- """
314
233
  return _global_print_stream.is_running
315
234
 
316
235
 
317
236
  def set_print_speed(min_speed: float = 5.0, max_speed: float = 50.0) -> None:
318
- """Set print speed range.
319
-
320
- Args:
321
- min_speed: Minimum print speed (characters/second).
322
- max_speed: Maximum print speed (characters/second).
323
- """
237
+ """设置输出速率上下限。"""
324
238
  _global_print_stream.min_speed = max(1.0, min_speed)
325
239
  _global_print_stream.max_speed = max(_global_print_stream.min_speed, max_speed)
326
240
 
@@ -331,14 +245,7 @@ def configure_print_stream(
331
245
  decay_factor: float = 20.0,
332
246
  smoothing_factor: float = 0.8,
333
247
  ) -> None:
334
- """Configure print stream system parameters.
335
-
336
- Args:
337
- min_speed: Minimum print speed.
338
- max_speed: Maximum print speed.
339
- decay_factor: Decay factor for speed adaptation.
340
- smoothing_factor: Smoothing factor for speed changes.
341
- """
248
+ """配置输出速率与平滑参数。"""
342
249
  _global_print_stream.min_speed = max(1.0, min_speed)
343
250
  _global_print_stream.max_speed = max(_global_print_stream.min_speed, max_speed)
344
251
  _global_print_stream.decay_factor = max(1.0, decay_factor)
@@ -357,8 +264,6 @@ def _cleanup() -> None:
357
264
  # Register cleanup function
358
265
  atexit.register(_cleanup)
359
266
 
360
-
361
- # Module exports
362
267
  __all__ = [
363
268
  "PrintStream",
364
269
  "print_stream",
@@ -1,7 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- """logger 模块导出。"""
4
-
5
3
  from echotools.base.logger.manager import (
6
4
  LoggerManager,
7
5
  configure,
@@ -1,7 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- """retry 模块导出。"""
4
-
5
3
  from echotools.base.retry.retry import (
6
4
  retry_async_generator,
7
5
  retry_on_empty,