echotools 2.3.7__tar.gz → 2.3.10__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 (194) hide show
  1. {echotools-2.3.7 → echotools-2.3.10}/PKG-INFO +1 -1
  2. echotools-2.3.10/README.md +3 -0
  3. {echotools-2.3.7 → echotools-2.3.10}/pyproject.toml +6 -6
  4. echotools-2.3.10/src/echotools/__init__.py +215 -0
  5. echotools-2.3.10/src/echotools/base/cache/__init__.py +8 -0
  6. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/cache/list_cache.py +1 -1
  7. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/config/__init__.py +4 -4
  8. echotools-2.3.10/src/echotools/base/config/base.py +146 -0
  9. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/config/center.py +17 -175
  10. echotools-2.3.10/src/echotools/base/config/center_notify.py +39 -0
  11. echotools-2.3.10/src/echotools/base/config/center_template.py +137 -0
  12. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/config/loader.py +1 -1
  13. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/errors/__init__.py +4 -4
  14. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/errors/classify.py +3 -3
  15. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/errors/common.py +1 -1
  16. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/errors/http.py +1 -1
  17. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/ids/__init__.py +1 -1
  18. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/io/__init__.py +2 -2
  19. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/io/io_utils.py +1 -1
  20. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/io/printstream.py +17 -31
  21. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/logger/__init__.py +1 -1
  22. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/retry/__init__.py +1 -1
  23. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/retry/retry.py +12 -26
  24. echotools-2.3.10/src/echotools/compat.py +83 -0
  25. echotools-2.3.10/src/echotools/exec/dispatch/__init__.py +21 -0
  26. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/dispatch/dispatcher.py +56 -126
  27. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/dispatch/proxy_selector.py +2 -2
  28. echotools-2.3.10/src/echotools/exec/dispatch/race.py +119 -0
  29. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/dispatch/selector.py +6 -4
  30. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/fncall/__init__.py +7 -7
  31. echotools-2.3.10/src/echotools/exec/fncall/parsers/__init__.py +6 -0
  32. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/fncall/parsers/stream.py +1 -1
  33. echotools-2.3.10/src/echotools/exec/fncall/parsers/xml_params.py +41 -0
  34. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/fncall/parsers/xml_parser.py +48 -86
  35. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/fncall/prompt/__init__.py +1 -1
  36. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/fncall/prompt/history.py +13 -145
  37. echotools-2.3.10/src/echotools/exec/fncall/prompt/history_format.py +56 -0
  38. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/fncall/prompt/inject.py +67 -70
  39. echotools-2.3.10/src/echotools/exec/fncall/prompt/prompt_helpers.py +153 -0
  40. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/fncall/protocols/__init__.py +2 -2
  41. echotools-2.3.10/src/echotools/exec/fncall/protocols/entml.py +159 -0
  42. echotools-2.3.10/src/echotools/exec/fncall/protocols/entml_invoke.py +109 -0
  43. echotools-2.3.10/src/echotools/exec/fncall/protocols/entml_patterns.py +42 -0
  44. echotools-2.3.10/src/echotools/exec/fncall/protocols/entml_thinking.py +42 -0
  45. echotools-2.3.10/src/echotools/exec/fncall/protocols/entml_values.py +74 -0
  46. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/fncall/registry.py +3 -3
  47. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/fncall/shared/__init__.py +4 -4
  48. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/fncall/shared/coercion.py +43 -54
  49. echotools-2.3.10/src/echotools/exec/fncall/shared/normalization.py +172 -0
  50. echotools-2.3.10/src/echotools/exec/fncall/shared/schema_render.py +127 -0
  51. echotools-2.3.10/src/echotools/exec/lifecycle/__init__.py +8 -0
  52. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/lifecycle/manager.py +1 -1
  53. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/lifecycle/updater.py +11 -38
  54. echotools-2.3.10/src/echotools/exec/lifecycle/updater_pull.py +33 -0
  55. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/process/__init__.py +1 -1
  56. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/process/port.py +1 -1
  57. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/protocol/__init__.py +1 -1
  58. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/protocol/base.py +2 -1
  59. echotools-2.3.10/src/echotools/exec/terminal/local/__init__.py +6 -0
  60. echotools-2.3.10/src/echotools/exec/terminal/local/core.py +319 -0
  61. echotools-2.3.10/src/echotools/exec/terminal/local/proc.py +330 -0
  62. echotools-2.3.10/src/echotools/exec/terminal/local/unix.py +201 -0
  63. echotools-2.3.10/src/echotools/exec/terminal/local/win.py +206 -0
  64. echotools-2.3.10/src/echotools/exec/terminal/session/__init__.py +20 -0
  65. echotools-2.3.7/src/echotools/terminal/session.py → echotools-2.3.10/src/echotools/exec/terminal/session/base.py +5 -145
  66. echotools-2.3.10/src/echotools/exec/terminal/session/client.py +155 -0
  67. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/terminal/ssh.py +40 -24
  68. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/events/__init__.py +2 -2
  69. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/events/bus.py +2 -2
  70. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/spinner/__init__.py +2 -2
  71. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/spinner/spinner.py +9 -114
  72. echotools-2.3.10/src/echotools/media/spinner/spinner_color.py +101 -0
  73. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/tracing/__init__.py +3 -3
  74. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/tracing/span.py +2 -2
  75. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/tracing/tracer.py +2 -2
  76. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/translate.py +24 -35
  77. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/watcher/__init__.py +1 -1
  78. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/watcher/file_watcher.py +1 -1
  79. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/web/__init__.py +6 -6
  80. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/web/application.py +1 -1
  81. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/web/input_box/app.js +8 -7
  82. echotools-2.3.10/src/echotools/media/web/input_box/components/filezone.js +277 -0
  83. echotools-2.3.10/src/echotools/media/web/input_box/components/motionkit.js +154 -0
  84. echotools-2.3.10/src/echotools/media/web/input_box/components/sendbutton.js +64 -0
  85. echotools-2.3.10/src/echotools/media/web/input_box/components/voiceinput.js +76 -0
  86. echotools-2.3.7/src/echotools/web/input_box/input-box.js → echotools-2.3.10/src/echotools/media/web/input_box/inputbox.js +7 -8
  87. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/web/input_box/style.css +1 -1
  88. echotools-2.3.7/src/echotools/web/input_box/voice_input/voice-input.js → echotools-2.3.10/src/echotools/media/web/input_box/voicegif.js +2 -102
  89. echotools-2.3.10/src/echotools/media/web/middleware.py +126 -0
  90. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/web/stats.py +37 -0
  91. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/web/utils.py +1 -1
  92. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/plat}/files/__init__.py +1 -1
  93. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/plat}/files/file_util.py +1 -1
  94. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/plat}/network/__init__.py +1 -1
  95. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/plat}/network/http_utils.py +2 -2
  96. echotools-2.3.10/src/echotools/plat/plugin/__init__.py +9 -0
  97. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/plat}/plugin/discovery.py +2 -2
  98. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/plat}/plugin/registry.py +23 -76
  99. echotools-2.3.10/src/echotools/plat/plugin/registry_ops.py +101 -0
  100. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/plat}/proxy/__init__.py +1 -1
  101. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/plat}/proxy/manager.py +1 -1
  102. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/plat}/runtime/__init__.py +1 -1
  103. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/plat}/runtime/collector.py +1 -1
  104. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/plat}/scheduler/__init__.py +1 -1
  105. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/plat}/scheduler/scheduler.py +1 -1
  106. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/plat}/sdk/__init__.py +1 -1
  107. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/plat}/sdk/facade.py +12 -12
  108. {echotools-2.3.7 → echotools-2.3.10}/src/echotools.egg-info/PKG-INFO +1 -1
  109. echotools-2.3.10/src/echotools.egg-info/SOURCES.txt +175 -0
  110. echotools-2.3.10/src/echotools.egg-info/top_level.txt +3 -0
  111. echotools-2.3.10/src/tests/bench_import.py +14 -0
  112. echotools-2.3.10/src/tests/conftest.py +19 -0
  113. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_cache_retry.py +2 -2
  114. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_completion.py +2 -2
  115. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_config.py +3 -3
  116. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_config_extended.py +1 -1
  117. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_coverage_core.py +23 -23
  118. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_dispatch.py +2 -2
  119. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_dispatch_extended.py +3 -3
  120. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_dispatch_race.py +2 -2
  121. echotools-2.3.10/src/tests/test_entml_protocol.py +209 -0
  122. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_errors.py +2 -2
  123. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_errors_common.py +1 -1
  124. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_events.py +1 -1
  125. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_events_event.py +1 -1
  126. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_facade.py +1 -1
  127. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_fncall.py +2 -2
  128. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_ids.py +1 -1
  129. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_io.py +1 -1
  130. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_keys.py +1 -1
  131. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_lifecycle.py +1 -1
  132. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_logger.py +1 -1
  133. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_merge.py +2 -2
  134. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_plugin.py +1 -1
  135. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_printstream.py +1 -1
  136. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_protocols.py +2 -2
  137. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_proxy.py +1 -1
  138. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_proxy_selector.py +1 -1
  139. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_runtime.py +1 -1
  140. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_scheduler.py +1 -1
  141. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_tracing.py +1 -1
  142. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_usage.py +1 -1
  143. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_web.py +6 -6
  144. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_web_broker.py +2 -2
  145. echotools-2.3.7/src/echotools/__init__.py +0 -212
  146. echotools-2.3.7/src/echotools/cache/__init__.py +0 -8
  147. echotools-2.3.7/src/echotools/config/base.py +0 -144
  148. echotools-2.3.7/src/echotools/dispatch/__init__.py +0 -21
  149. echotools-2.3.7/src/echotools/fncall/parsers/__init__.py +0 -6
  150. echotools-2.3.7/src/echotools/fncall/protocols/entml.py +0 -286
  151. echotools-2.3.7/src/echotools/fncall/shared/normalization.py +0 -257
  152. echotools-2.3.7/src/echotools/lifecycle/__init__.py +0 -8
  153. echotools-2.3.7/src/echotools/plugin/__init__.py +0 -9
  154. echotools-2.3.7/src/echotools/py.typed +0 -0
  155. echotools-2.3.7/src/echotools/terminal/local.py +0 -964
  156. echotools-2.3.7/src/echotools/web/input_box/file_zone/file-zone.js +0 -268
  157. echotools-2.3.7/src/echotools/web/input_box/motion_kit/motion-kit.js +0 -139
  158. echotools-2.3.7/src/echotools/web/input_box/send_button/send-button.js +0 -64
  159. echotools-2.3.7/src/echotools/web/middleware.py +0 -161
  160. echotools-2.3.7/src/echotools.egg-info/SOURCES.txt +0 -150
  161. echotools-2.3.7/src/echotools.egg-info/top_level.txt +0 -1
  162. {echotools-2.3.7 → echotools-2.3.10/docs}/README.md +0 -0
  163. {echotools-2.3.7 → echotools-2.3.10}/setup.cfg +0 -0
  164. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/cache/memory_cache.py +0 -0
  165. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/config/merge.py +0 -0
  166. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/errors/base.py +0 -0
  167. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/ids/generator.py +0 -0
  168. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/base}/logger/manager.py +0 -0
  169. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/dispatch/candidate.py +0 -0
  170. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/dispatch/usage.py +0 -0
  171. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/fncall/prompt/templates.py +0 -0
  172. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/fncall/shared/loop_detect.py +0 -0
  173. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/fncall/shared/xml_helpers.py +0 -0
  174. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/keys.py +0 -0
  175. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/terminal/__init__.py +0 -0
  176. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/terminal/conpty.py +0 -0
  177. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/terminal/sanitize.py +0 -0
  178. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/exec}/terminal/tmux.py +0 -0
  179. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/events/event.py +0 -0
  180. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/tracing/context.py +0 -0
  181. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/web/broker.py +0 -0
  182. /echotools-2.3.7/src/echotools/web/input_box/sortable_list/sortable-list.css → /echotools-2.3.10/src/echotools/media/web/input_box/components/sortablelist.css +0 -0
  183. /echotools-2.3.7/src/echotools/web/input_box/sortable_list/sortable-list.js → /echotools-2.3.10/src/echotools/media/web/input_box/components/sortablelist.js +0 -0
  184. /echotools-2.3.7/src/echotools/web/input_box/text_input/text-input.js → /echotools-2.3.10/src/echotools/media/web/input_box/components/textinput.js +0 -0
  185. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/web/input_box/fonts/inter-500.woff2 +0 -0
  186. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/media}/web/input_box/fonts/inter-600.woff2 +0 -0
  187. /echotools-2.3.7/src/echotools/web/input_box/fonts/inter-400.woff2 → /echotools-2.3.10/src/echotools/media/web/input_box/fonts/inter400.woff2 +0 -0
  188. /echotools-2.3.7/src/echotools/web/input_box/fonts/tailwind.min.css → /echotools-2.3.10/src/echotools/media/web/input_box/fonts/tailwind.css +0 -0
  189. /echotools-2.3.7/src/echotools/web/input_box/input-box.css → /echotools-2.3.10/src/echotools/media/web/input_box/inputbox.css +0 -0
  190. {echotools-2.3.7/src/echotools → echotools-2.3.10/src/echotools/plat}/plugin/base.py +0 -0
  191. /echotools-2.3.7/src/echotools/_version.py → /echotools-2.3.10/src/echotools/version.py +0 -0
  192. {echotools-2.3.7 → echotools-2.3.10}/src/echotools.egg-info/dependency_links.txt +0 -0
  193. {echotools-2.3.7 → echotools-2.3.10}/src/echotools.egg-info/requires.txt +0 -0
  194. {echotools-2.3.7 → echotools-2.3.10/src}/tests/test_imports.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: echotools
3
- Version: 2.3.7
3
+ Version: 2.3.10
4
4
  Summary: 通用基础设施 SDK:配置、日志、事件、调度、插件、协议、调用链
5
5
  Author: nichengfuben
6
6
  License: MIT
@@ -0,0 +1,3 @@
1
+ # echotools
2
+
3
+ Documentation: [docs/README.md](docs/README.md)
@@ -4,9 +4,9 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "echotools"
7
- version = "2.3.7"
7
+ version = "2.3.10"
8
8
  description = "通用基础设施 SDK:配置、日志、事件、调度、插件、协议、调用链"
9
- readme = "README.md"
9
+ readme = "docs/README.md"
10
10
  requires-python = ">=3.8"
11
11
  license = { text = "MIT" }
12
12
  authors = [{ name = "nichengfuben" }]
@@ -59,7 +59,7 @@ Issues = "https://github.com/nichengfuben/echotools/issues"
59
59
  where = ["src"]
60
60
 
61
61
  [tool.setuptools.package-data]
62
- echotools = ["py.typed", "web/input_box/**/*"]
62
+ echotools = ["py.typed", "media/web/input_box/**/*"]
63
63
 
64
64
  [tool.ruff]
65
65
  line-length = 88
@@ -91,11 +91,11 @@ disable_error_code = [
91
91
  ]
92
92
 
93
93
  [[tool.mypy.overrides]]
94
- module = "echotools.terminal.*"
94
+ module = "echotools.exec.terminal.*"
95
95
  ignore_errors = true
96
96
 
97
97
  [tool.pytest.ini_options]
98
- testpaths = ["tests"]
98
+ testpaths = ["src/tests"]
99
99
  asyncio_mode = "auto"
100
100
  addopts = ["--strict-markers", "--tb=short"]
101
101
  markers = [
@@ -112,7 +112,7 @@ omit = [
112
112
  "*/__init__.py",
113
113
  "*/terminal/*",
114
114
  "*/spinner/*",
115
- "*/web/input_box/*",
115
+ "*/media/web/input_box/*",
116
116
  "*/lifecycle/updater.py",
117
117
  "*/watcher/*",
118
118
  "*/process/*",
@@ -0,0 +1,215 @@
1
+ from __future__ import annotations
2
+
3
+ """echotools:通用基础设施 SDK。
4
+
5
+ 完全项目无关,支持调用链,覆盖 Python 3.8-3.14。
6
+ """
7
+
8
+ import importlib
9
+ from typing import Any
10
+
11
+ from echotools.version import get_version
12
+ from echotools.plat.sdk import EchoTools
13
+ from echotools.compat import install_compat_aliases
14
+
15
+ install_compat_aliases()
16
+
17
+ __version__ = get_version()
18
+
19
+ __all__ = [
20
+ "__version__",
21
+ "EchoTools",
22
+ "ConfigBase",
23
+ "ConfigCenter",
24
+ "LoggerManager",
25
+ "get_logger",
26
+ "set_color",
27
+ "configure",
28
+ "Event",
29
+ "EventBus",
30
+ "Tracer",
31
+ "Trace",
32
+ "Span",
33
+ "get_current_trace_id",
34
+ "set_current_trace_id",
35
+ "get_current_span_id",
36
+ "set_current_span_id",
37
+ "get_request_id",
38
+ "set_request_id",
39
+ "ListCache",
40
+ "MemoryCache",
41
+ "TaskCandidate",
42
+ "make_id",
43
+ "AdaptiveSelector",
44
+ "TaskDispatcher",
45
+ "TaskScheduler",
46
+ "ProxySelector",
47
+ "ProxyRecord",
48
+ "Plugin",
49
+ "PluginRegistry",
50
+ "discover_plugins",
51
+ "ToolProtocol",
52
+ "register_protocol",
53
+ "get_protocol_by_id",
54
+ "get_protocol",
55
+ "list_protocols",
56
+ "LifecycleManager",
57
+ "AutoUpdater",
58
+ "ProxyManager",
59
+ "PortReleaseResult",
60
+ "ensure_port_available",
61
+ "RuntimeCollector",
62
+ "WebApplication",
63
+ "json_body",
64
+ "safe_flush",
65
+ "FileUtil",
66
+ "uuid7",
67
+ "short_id",
68
+ "trace_id",
69
+ "span_id",
70
+ "atomic_write_text",
71
+ "ensure_directory",
72
+ "read_text_if_exists",
73
+ "retry_with_backoff",
74
+ "retry_on_empty",
75
+ "retry_on_exception",
76
+ "retry_async_generator",
77
+ "KeyState",
78
+ "KeyPool",
79
+ "extract_text_from_messages",
80
+ "split_text_chunks",
81
+ "format_translation_response",
82
+ "TerminalSession",
83
+ "TerminalCallback",
84
+ "LocalTerminal",
85
+ "SSHTerminal",
86
+ "PrintStream",
87
+ "print_stream",
88
+ "start_print_stream",
89
+ "stop_print_stream",
90
+ "flush_print_stream",
91
+ "get_buffer_size",
92
+ "get_queue_length",
93
+ "is_print_stream_running",
94
+ "set_print_speed",
95
+ "configure_print_stream",
96
+ "inject_fncall",
97
+ "FncallStreamParser",
98
+ "detect_tool_loop",
99
+ "LoopDetectionResult",
100
+ "EchoError",
101
+ "ConfigError",
102
+ "ValidationError",
103
+ "NetworkError",
104
+ "TimeoutError",
105
+ "NotSupportedError",
106
+ "NoCandidateError",
107
+ "PluginError",
108
+ "ProtocolError",
109
+ "classify_http_error",
110
+ "Spinner",
111
+ ]
112
+
113
+ _EXPORTS: dict[str, tuple[str, str]] = {
114
+ "ConfigBase": ("echotools.base.config", "ConfigBase"),
115
+ "ConfigCenter": ("echotools.base.config", "ConfigCenter"),
116
+ "LoggerManager": ("echotools.base.logger", "LoggerManager"),
117
+ "get_logger": ("echotools.base.logger", "get_logger"),
118
+ "set_color": ("echotools.base.logger", "set_color"),
119
+ "configure": ("echotools.base.logger", "configure"),
120
+ "Event": ("echotools.media.events", "Event"),
121
+ "EventBus": ("echotools.media.events", "EventBus"),
122
+ "Tracer": ("echotools.media.tracing", "Tracer"),
123
+ "Trace": ("echotools.media.tracing", "Trace"),
124
+ "Span": ("echotools.media.tracing", "Span"),
125
+ "get_current_trace_id": ("echotools.media.tracing", "get_current_trace_id"),
126
+ "set_current_trace_id": ("echotools.media.tracing", "set_current_trace_id"),
127
+ "get_current_span_id": ("echotools.media.tracing", "get_current_span_id"),
128
+ "set_current_span_id": ("echotools.media.tracing", "set_current_span_id"),
129
+ "get_request_id": ("echotools.media.tracing", "get_request_id"),
130
+ "set_request_id": ("echotools.media.tracing", "set_request_id"),
131
+ "ListCache": ("echotools.base.cache", "ListCache"),
132
+ "MemoryCache": ("echotools.base.cache", "MemoryCache"),
133
+ "TaskCandidate": ("echotools.exec.dispatch", "TaskCandidate"),
134
+ "make_id": ("echotools.exec.dispatch", "make_id"),
135
+ "AdaptiveSelector": ("echotools.exec.dispatch", "AdaptiveSelector"),
136
+ "TaskDispatcher": ("echotools.exec.dispatch", "TaskDispatcher"),
137
+ "TaskScheduler": ("echotools.plat.scheduler", "TaskScheduler"),
138
+ "ProxySelector": ("echotools.exec.dispatch", "ProxySelector"),
139
+ "ProxyRecord": ("echotools.exec.dispatch", "ProxyRecord"),
140
+ "Plugin": ("echotools.plat.plugin", "Plugin"),
141
+ "PluginRegistry": ("echotools.plat.plugin", "PluginRegistry"),
142
+ "discover_plugins": ("echotools.plat.plugin", "discover_plugins"),
143
+ "ToolProtocol": ("echotools.exec.protocol.base", "ToolProtocol"),
144
+ "register_protocol": ("echotools.exec.protocol.base", "register_protocol"),
145
+ "get_protocol_by_id": ("echotools.exec.protocol.base", "get_protocol_by_id"),
146
+ "get_protocol": ("echotools.exec.fncall.registry", "get_protocol"),
147
+ "list_protocols": ("echotools.exec.fncall.registry", "list_protocols"),
148
+ "LifecycleManager": ("echotools.exec.lifecycle", "LifecycleManager"),
149
+ "AutoUpdater": ("echotools.exec.lifecycle", "AutoUpdater"),
150
+ "ProxyManager": ("echotools.plat.proxy", "ProxyManager"),
151
+ "PortReleaseResult": ("echotools.exec.process", "PortReleaseResult"),
152
+ "ensure_port_available": ("echotools.exec.process", "ensure_port_available"),
153
+ "RuntimeCollector": ("echotools.plat.runtime", "RuntimeCollector"),
154
+ "WebApplication": ("echotools.media.web.application", "WebApplication"),
155
+ "json_body": ("echotools.media.web.utils", "json_body"),
156
+ "safe_flush": ("echotools.media.web.utils", "safe_flush"),
157
+ "FileUtil": ("echotools.plat.files", "FileUtil"),
158
+ "uuid7": ("echotools.base.ids", "uuid7"),
159
+ "short_id": ("echotools.base.ids", "short_id"),
160
+ "trace_id": ("echotools.base.ids", "trace_id"),
161
+ "span_id": ("echotools.base.ids", "span_id"),
162
+ "atomic_write_text": ("echotools.base.io", "atomic_write_text"),
163
+ "ensure_directory": ("echotools.base.io", "ensure_directory"),
164
+ "read_text_if_exists": ("echotools.base.io", "read_text_if_exists"),
165
+ "retry_with_backoff": ("echotools.base.retry", "retry_with_backoff"),
166
+ "retry_on_empty": ("echotools.base.retry", "retry_on_empty"),
167
+ "retry_on_exception": ("echotools.base.retry", "retry_on_exception"),
168
+ "retry_async_generator": ("echotools.base.retry", "retry_async_generator"),
169
+ "KeyState": ("echotools.exec.keys", "KeyState"),
170
+ "KeyPool": ("echotools.exec.keys", "KeyPool"),
171
+ "extract_text_from_messages": ("echotools.media.translate", "extract_text_from_messages"),
172
+ "split_text_chunks": ("echotools.media.translate", "split_text_chunks"),
173
+ "format_translation_response": ("echotools.media.translate", "format_translation_response"),
174
+ "TerminalSession": ("echotools.exec.terminal.session", "TerminalSession"),
175
+ "TerminalCallback": ("echotools.exec.terminal.session", "TerminalCallback"),
176
+ "LocalTerminal": ("echotools.exec.terminal.local", "LocalTerminal"),
177
+ "SSHTerminal": ("echotools.exec.terminal.ssh", "SSHTerminal"),
178
+ "PrintStream": ("echotools.base.io.printstream", "PrintStream"),
179
+ "print_stream": ("echotools.base.io.printstream", "print_stream"),
180
+ "start_print_stream": ("echotools.base.io.printstream", "start_print_stream"),
181
+ "stop_print_stream": ("echotools.base.io.printstream", "stop_print_stream"),
182
+ "flush_print_stream": ("echotools.base.io.printstream", "flush_print_stream"),
183
+ "get_buffer_size": ("echotools.base.io.printstream", "get_buffer_size"),
184
+ "get_queue_length": ("echotools.base.io.printstream", "get_queue_length"),
185
+ "is_print_stream_running": ("echotools.base.io.printstream", "is_print_stream_running"),
186
+ "set_print_speed": ("echotools.base.io.printstream", "set_print_speed"),
187
+ "configure_print_stream": ("echotools.base.io.printstream", "configure_print_stream"),
188
+ "inject_fncall": ("echotools.exec.fncall.prompt.inject", "inject_fncall"),
189
+ "FncallStreamParser": ("echotools.exec.fncall.parsers.stream", "FncallStreamParser"),
190
+ "detect_tool_loop": ("echotools.exec.fncall.shared.loop_detect", "detect_tool_loop"),
191
+ "LoopDetectionResult": ("echotools.exec.fncall.shared.loop_detect", "LoopDetectionResult"),
192
+ "EchoError": ("echotools.base.errors", "EchoError"),
193
+ "ConfigError": ("echotools.base.errors", "ConfigError"),
194
+ "ValidationError": ("echotools.base.errors", "ValidationError"),
195
+ "NetworkError": ("echotools.base.errors", "NetworkError"),
196
+ "TimeoutError": ("echotools.base.errors", "TimeoutError"),
197
+ "NotSupportedError": ("echotools.base.errors", "NotSupportedError"),
198
+ "NoCandidateError": ("echotools.base.errors", "NoCandidateError"),
199
+ "PluginError": ("echotools.base.errors", "PluginError"),
200
+ "ProtocolError": ("echotools.base.errors", "ProtocolError"),
201
+ "classify_http_error": ("echotools.base.errors", "classify_http_error"),
202
+ "Spinner": ("echotools.media.spinner", "Spinner"),
203
+ }
204
+
205
+
206
+ def __getattr__(name: str) -> Any:
207
+ if name in _EXPORTS:
208
+ module_path, attr = _EXPORTS[name]
209
+ module = importlib.import_module(module_path)
210
+ return getattr(module, attr)
211
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
212
+
213
+
214
+ def __dir__() -> list[str]:
215
+ return sorted(__all__)
@@ -0,0 +1,8 @@
1
+ from __future__ import annotations
2
+
3
+ """cache 模块导出。"""
4
+
5
+ from echotools.base.cache.list_cache import ListCache
6
+ from echotools.base.cache.memory_cache import MemoryCache
7
+
8
+ __all__ = ["ListCache", "MemoryCache"]
@@ -11,7 +11,7 @@ import time
11
11
  from pathlib import Path
12
12
  from typing import Awaitable, Callable, List, Optional
13
13
 
14
- from echotools.logger.manager import get_logger
14
+ from echotools.base.logger.manager import get_logger
15
15
 
16
16
  __all__ = ["ListCache"]
17
17
 
@@ -2,15 +2,15 @@ from __future__ import annotations
2
2
 
3
3
  """config 模块导出。"""
4
4
 
5
- from echotools.config.base import ConfigBase
6
- from echotools.config.center import ConfigCenter
7
- from echotools.config.loader import (
5
+ from echotools.base.config.base import ConfigBase
6
+ from echotools.base.config.center import ConfigCenter
7
+ from echotools.base.config.loader import (
8
8
  find_config,
9
9
  find_template,
10
10
  load_file,
11
11
  write_toml,
12
12
  )
13
- from echotools.config.merge import merge_dicts
13
+ from echotools.base.config.merge import merge_dicts
14
14
 
15
15
  __all__ = [
16
16
  "ConfigBase",
@@ -0,0 +1,146 @@
1
+ from __future__ import annotations
2
+
3
+ """配置数据类基类,提供自动 from_dict 反序列化。"""
4
+
5
+ from dataclasses import MISSING, fields, is_dataclass
6
+ from typing import Any, Literal, Type, TypeVar, Union, get_args, get_origin, get_type_hints
7
+
8
+ __all__ = ["ConfigBase"]
9
+
10
+ T = TypeVar("T", bound="ConfigBase")
11
+
12
+ _type_hints_cache: dict[type, dict[str, Any]] = {}
13
+
14
+
15
+ class ConfigBase:
16
+ """配置类基类,提供 from_dict 自动反序列化。"""
17
+
18
+ @classmethod
19
+ def from_dict(cls: Type[T], data: dict[str, Any]) -> T:
20
+ """从字典构造实例。"""
21
+ if not isinstance(data, dict):
22
+ raise TypeError(
23
+ "Expected a dict, got {}".format(type(data).__name__)
24
+ )
25
+ init_args: dict[str, Any] = {}
26
+ type_hints = _get_type_hints(cls)
27
+ for f in fields(cls): # type: ignore[arg-type]
28
+ field_name = f.name
29
+ field_type = type_hints.get(field_name, f.type)
30
+ if field_name.startswith("_"):
31
+ continue
32
+ if not f.init:
33
+ continue
34
+ if field_name not in data:
35
+ if f.default is not MISSING:
36
+ init_args[field_name] = f.default
37
+ continue
38
+ if f.default_factory is not MISSING: # type: ignore[misc]
39
+ init_args[field_name] = f.default_factory() # type: ignore[misc]
40
+ continue
41
+ raise ValueError(
42
+ "Missing required field: '{}'".format(field_name)
43
+ )
44
+ value = data[field_name]
45
+ init_args[field_name] = cls._convert_field(value, field_type)
46
+ return cls(**init_args)
47
+
48
+ @classmethod
49
+ def _convert_field(cls, value: Any, field_type: Any) -> Any:
50
+ """转换单个字段。"""
51
+ if isinstance(field_type, type) and is_dataclass(field_type):
52
+ return field_type.from_dict(value) # type: ignore[attr-defined]
53
+ origin = get_origin(field_type)
54
+ args = get_args(field_type)
55
+ if origin is list:
56
+ item_type = args[0] if args else Any
57
+ return _convert_list_field(cls, value, item_type)
58
+ if origin is set:
59
+ item_type = args[0] if args else Any
60
+ return _convert_set_field(cls, value, item_type)
61
+ if origin is tuple:
62
+ return _convert_tuple_field(cls, value, args)
63
+ if origin is dict:
64
+ key_type, val_type = args if len(args) == 2 else (Any, Any)
65
+ return _convert_dict_field(cls, value, key_type, val_type)
66
+ if origin is Union:
67
+ return _convert_union_field(cls, value, args)
68
+ if origin is Literal:
69
+ return _convert_literal_field(value, field_type)
70
+ if isinstance(field_type, type):
71
+ return _convert_scalar_field(value, field_type)
72
+ return value
73
+
74
+ def __str__(self) -> str:
75
+ field_strs = [
76
+ "{}={!r}".format(f.name, getattr(self, f.name))
77
+ for f in fields(self) # type: ignore[arg-type]
78
+ ]
79
+ return "{}({})".format(
80
+ self.__class__.__name__, ", ".join(field_strs)
81
+ )
82
+
83
+
84
+ def _get_type_hints(cls: type) -> dict[str, Any]:
85
+ """带缓存的 get_type_hints。"""
86
+ if cls not in _type_hints_cache:
87
+ try:
88
+ _type_hints_cache[cls] = get_type_hints(cls)
89
+ except Exception:
90
+ _type_hints_cache[cls] = {}
91
+ return _type_hints_cache[cls]
92
+
93
+
94
+ def _convert_list_field(cls: type, value: Any, item_type: Any) -> list:
95
+ if not isinstance(value, list):
96
+ raise TypeError("Expected list, got {}".format(type(value).__name__))
97
+ return [cls._convert_field(i, item_type) for i in value]
98
+
99
+
100
+ def _convert_set_field(cls: type, value: Any, item_type: Any) -> set:
101
+ if not isinstance(value, list):
102
+ raise TypeError("Expected list, got {}".format(type(value).__name__))
103
+ return {cls._convert_field(i, item_type) for i in value}
104
+
105
+
106
+ def _convert_tuple_field(cls: type, value: Any, args: tuple) -> tuple:
107
+ return tuple(cls._convert_field(i, a) for i, a in zip(value, args))
108
+
109
+
110
+ def _convert_dict_field(cls: type, value: Any, key_type: Any, val_type: Any) -> dict:
111
+ if not isinstance(value, dict):
112
+ raise TypeError("Expected dict, got {}".format(type(value).__name__))
113
+ result = {}
114
+ for k, v in value.items():
115
+ ck = cls._convert_field(k, key_type)
116
+ try:
117
+ cv = cls._convert_field(v, val_type)
118
+ except (TypeError, ValueError):
119
+ cv = v
120
+ result[ck] = cv
121
+ return result
122
+
123
+
124
+ def _convert_union_field(cls: type, value: Any, args: tuple) -> Any:
125
+ if value is None:
126
+ return None
127
+ real_type = next((a for a in args if a is not type(None)), Any)
128
+ return cls._convert_field(value, real_type)
129
+
130
+
131
+ def _convert_literal_field(value: Any, field_type: Any) -> Any:
132
+ allowed = get_args(field_type)
133
+ if value not in allowed:
134
+ raise TypeError("Value '{}' not in allowed values {}".format(value, allowed))
135
+ return value
136
+
137
+
138
+ def _convert_scalar_field(value: Any, field_type: type) -> Any:
139
+ if isinstance(value, field_type):
140
+ return value
141
+ try:
142
+ return field_type(value)
143
+ except (ValueError, TypeError) as e:
144
+ raise TypeError(
145
+ "Cannot convert {} to {}".format(type(value).__name__, field_type.__name__)
146
+ ) from e