echotools 2.3.22__tar.gz → 2.3.25__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 (188) hide show
  1. {echotools-2.3.22 → echotools-2.3.25}/PKG-INFO +6 -1
  2. {echotools-2.3.22 → echotools-2.3.25}/pyproject.toml +5 -1
  3. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/compat.py +1 -0
  4. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/parsers/stream.py +18 -5
  5. echotools-2.3.25/src/echotools/media/console/__init__.py +38 -0
  6. echotools-2.3.25/src/echotools/media/console/charmap.py +148 -0
  7. echotools-2.3.25/src/echotools/media/console/spinner.py +342 -0
  8. echotools-2.3.25/src/echotools/media/console/ui.py +4243 -0
  9. {echotools-2.3.22 → echotools-2.3.25}/src/echotools.egg-info/PKG-INFO +6 -1
  10. {echotools-2.3.22 → echotools-2.3.25}/src/echotools.egg-info/SOURCES.txt +5 -0
  11. {echotools-2.3.22 → echotools-2.3.25}/src/echotools.egg-info/requires.txt +6 -0
  12. echotools-2.3.25/src/tests/test_console.py +28 -0
  13. {echotools-2.3.22 → echotools-2.3.25}/README.md +0 -0
  14. {echotools-2.3.22 → echotools-2.3.25}/docs/README.md +0 -0
  15. {echotools-2.3.22 → echotools-2.3.25}/setup.cfg +0 -0
  16. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/__init__.py +0 -0
  17. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/cache/__init__.py +0 -0
  18. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/cache/list_cache.py +0 -0
  19. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/cache/memory_cache.py +0 -0
  20. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/config/__init__.py +0 -0
  21. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/config/base.py +0 -0
  22. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/config/center.py +0 -0
  23. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/config/center_notify.py +0 -0
  24. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/config/center_template.py +0 -0
  25. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/config/loader.py +0 -0
  26. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/config/merge.py +0 -0
  27. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/errors/__init__.py +0 -0
  28. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/errors/base.py +0 -0
  29. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/errors/classify.py +0 -0
  30. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/errors/common.py +0 -0
  31. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/errors/http.py +0 -0
  32. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/ids/__init__.py +0 -0
  33. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/ids/generator.py +0 -0
  34. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/io/__init__.py +0 -0
  35. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/io/io_utils.py +0 -0
  36. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/io/printstream.py +0 -0
  37. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/logger/__init__.py +0 -0
  38. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/logger/manager.py +0 -0
  39. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/retry/__init__.py +0 -0
  40. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/base/retry/retry.py +0 -0
  41. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/dispatch/__init__.py +0 -0
  42. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/dispatch/candidate.py +0 -0
  43. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/dispatch/dispatcher.py +0 -0
  44. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/dispatch/proxy_selector.py +0 -0
  45. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/dispatch/race.py +0 -0
  46. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/dispatch/selector.py +0 -0
  47. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/dispatch/usage.py +0 -0
  48. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/__init__.py +0 -0
  49. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/parsers/__init__.py +0 -0
  50. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/parsers/xml_params.py +0 -0
  51. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/parsers/xml_parser.py +0 -0
  52. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/prompt/__init__.py +0 -0
  53. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/prompt/history.py +0 -0
  54. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/prompt/history_format.py +0 -0
  55. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/prompt/inject.py +0 -0
  56. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/prompt/prompt_helpers.py +0 -0
  57. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/prompt/templates.py +0 -0
  58. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/protocols/__init__.py +0 -0
  59. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/protocols/entml.py +0 -0
  60. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/protocols/entml_invoke.py +0 -0
  61. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/protocols/entml_patterns.py +0 -0
  62. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/protocols/entml_thinking.py +0 -0
  63. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/protocols/entml_thinking_history.py +0 -0
  64. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/protocols/entml_thinking_parse.py +0 -0
  65. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/protocols/entml_tools.py +0 -0
  66. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/protocols/entml_values.py +0 -0
  67. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/registry.py +0 -0
  68. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/shared/__init__.py +0 -0
  69. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/shared/coercion.py +0 -0
  70. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/shared/loop_detect.py +0 -0
  71. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/shared/normalization.py +0 -0
  72. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/shared/schema_render.py +0 -0
  73. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/fncall/shared/xml_helpers.py +0 -0
  74. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/keys.py +0 -0
  75. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/lifecycle/__init__.py +0 -0
  76. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/lifecycle/manager.py +0 -0
  77. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/lifecycle/updater.py +0 -0
  78. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/lifecycle/updater_pull.py +0 -0
  79. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/process/__init__.py +0 -0
  80. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/process/port.py +0 -0
  81. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/protocol/__init__.py +0 -0
  82. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/protocol/base.py +0 -0
  83. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/terminal/__init__.py +0 -0
  84. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/terminal/conpty.py +0 -0
  85. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/terminal/local/__init__.py +0 -0
  86. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/terminal/local/core.py +0 -0
  87. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/terminal/local/proc.py +0 -0
  88. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/terminal/local/unix.py +0 -0
  89. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/terminal/local/win.py +0 -0
  90. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/terminal/sanitize.py +0 -0
  91. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/terminal/session/__init__.py +0 -0
  92. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/terminal/session/base.py +0 -0
  93. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/terminal/session/client.py +0 -0
  94. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/terminal/ssh.py +0 -0
  95. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/exec/terminal/tmux.py +0 -0
  96. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/events/__init__.py +0 -0
  97. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/events/bus.py +0 -0
  98. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/events/event.py +0 -0
  99. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/spinner/__init__.py +0 -0
  100. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/spinner/spinner.py +0 -0
  101. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/spinner/spinner_color.py +0 -0
  102. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/tracing/__init__.py +0 -0
  103. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/tracing/context.py +0 -0
  104. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/tracing/span.py +0 -0
  105. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/tracing/tracer.py +0 -0
  106. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/translate.py +0 -0
  107. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/watcher/__init__.py +0 -0
  108. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/watcher/file_watcher.py +0 -0
  109. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/__init__.py +0 -0
  110. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/application.py +0 -0
  111. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/broker.py +0 -0
  112. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/input_box/app.js +0 -0
  113. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/input_box/components/filezone.js +0 -0
  114. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/input_box/components/motionkit.js +0 -0
  115. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/input_box/components/sendbutton.js +0 -0
  116. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/input_box/components/sortablelist.css +0 -0
  117. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/input_box/components/sortablelist.js +0 -0
  118. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/input_box/components/textinput.js +0 -0
  119. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/input_box/components/voiceinput.js +0 -0
  120. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/input_box/fonts/inter-500.woff2 +0 -0
  121. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/input_box/fonts/inter-600.woff2 +0 -0
  122. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/input_box/fonts/inter400.woff2 +0 -0
  123. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/input_box/fonts/tailwind.css +0 -0
  124. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/input_box/inputbox.css +0 -0
  125. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/input_box/inputbox.js +0 -0
  126. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/input_box/style.css +0 -0
  127. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/input_box/voicegif.js +0 -0
  128. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/middleware.py +0 -0
  129. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/stats.py +0 -0
  130. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/media/web/utils.py +0 -0
  131. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/plat/files/__init__.py +0 -0
  132. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/plat/files/file_util.py +0 -0
  133. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/plat/network/__init__.py +0 -0
  134. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/plat/network/http_utils.py +0 -0
  135. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/plat/plugin/__init__.py +0 -0
  136. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/plat/plugin/base.py +0 -0
  137. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/plat/plugin/discovery.py +0 -0
  138. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/plat/plugin/registry.py +0 -0
  139. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/plat/plugin/registry_ops.py +0 -0
  140. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/plat/proxy/__init__.py +0 -0
  141. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/plat/proxy/manager.py +0 -0
  142. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/plat/runtime/__init__.py +0 -0
  143. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/plat/runtime/collector.py +0 -0
  144. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/plat/scheduler/__init__.py +0 -0
  145. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/plat/scheduler/scheduler.py +0 -0
  146. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/plat/sdk/__init__.py +0 -0
  147. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/plat/sdk/facade.py +0 -0
  148. {echotools-2.3.22 → echotools-2.3.25}/src/echotools/version.py +0 -0
  149. {echotools-2.3.22 → echotools-2.3.25}/src/echotools.egg-info/dependency_links.txt +0 -0
  150. {echotools-2.3.22 → echotools-2.3.25}/src/echotools.egg-info/top_level.txt +0 -0
  151. {echotools-2.3.22 → echotools-2.3.25}/src/tests/bench_import.py +0 -0
  152. {echotools-2.3.22 → echotools-2.3.25}/src/tests/conftest.py +0 -0
  153. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_cache_retry.py +0 -0
  154. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_completion.py +0 -0
  155. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_config.py +0 -0
  156. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_config_extended.py +0 -0
  157. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_coverage_core.py +0 -0
  158. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_dispatch.py +0 -0
  159. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_dispatch_extended.py +0 -0
  160. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_dispatch_race.py +0 -0
  161. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_entml_protocol.py +0 -0
  162. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_entml_thinking_history.py +0 -0
  163. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_entml_thinking_parse.py +0 -0
  164. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_entml_tools.py +0 -0
  165. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_errors.py +0 -0
  166. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_errors_common.py +0 -0
  167. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_events.py +0 -0
  168. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_events_event.py +0 -0
  169. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_facade.py +0 -0
  170. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_fncall.py +0 -0
  171. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_ids.py +0 -0
  172. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_imports.py +0 -0
  173. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_io.py +0 -0
  174. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_keys.py +0 -0
  175. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_lifecycle.py +0 -0
  176. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_logger.py +0 -0
  177. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_merge.py +0 -0
  178. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_plugin.py +0 -0
  179. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_printstream.py +0 -0
  180. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_protocols.py +0 -0
  181. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_proxy.py +0 -0
  182. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_proxy_selector.py +0 -0
  183. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_runtime.py +0 -0
  184. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_scheduler.py +0 -0
  185. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_tracing.py +0 -0
  186. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_usage.py +0 -0
  187. {echotools-2.3.22 → echotools-2.3.25}/src/tests/test_web.py +0 -0
  188. {echotools-2.3.22 → echotools-2.3.25}/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.3.22
3
+ Version: 2.3.25
4
4
  Summary: 通用基础设施 SDK:配置、日志、事件、调度、插件、协议、调用链
5
5
  Author: nichengfuben
6
6
  License: MIT
@@ -33,6 +33,9 @@ Provides-Extra: ssh
33
33
  Requires-Dist: paramiko>=3.0.0; extra == "ssh"
34
34
  Provides-Extra: terminal
35
35
  Requires-Dist: pywinpty>=2.0.0; sys_platform == "win32" and extra == "terminal"
36
+ Provides-Extra: console
37
+ Requires-Dist: rich>=13.0; extra == "console"
38
+ Requires-Dist: wcwidth>=0.2; extra == "console"
36
39
  Provides-Extra: all
37
40
  Requires-Dist: tomlkit>=0.11.0; extra == "all"
38
41
  Requires-Dist: tomli>=2.0.0; python_version < "3.11" and extra == "all"
@@ -41,6 +44,8 @@ Requires-Dist: aiohttp>=3.8.0; extra == "all"
41
44
  Requires-Dist: aiohttp-socks>=0.8.0; extra == "all"
42
45
  Requires-Dist: paramiko>=3.0.0; extra == "all"
43
46
  Requires-Dist: pywinpty>=2.0.0; sys_platform == "win32" and extra == "all"
47
+ Requires-Dist: rich>=13.0; extra == "all"
48
+ Requires-Dist: wcwidth>=0.2; extra == "all"
44
49
  Provides-Extra: dev
45
50
  Requires-Dist: pytest>=7.4.0; extra == "dev"
46
51
  Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "echotools"
7
- version = "2.3.22"
7
+ version = "2.3.25"
8
8
  description = "通用基础设施 SDK:配置、日志、事件、调度、插件、协议、调用链"
9
9
  readme = "docs/README.md"
10
10
  requires-python = ">=3.8"
@@ -33,6 +33,7 @@ http = ["aiohttp>=3.8.0"]
33
33
  socks = ["aiohttp-socks>=0.8.0"]
34
34
  ssh = ["paramiko>=3.0.0"]
35
35
  terminal = ["pywinpty>=2.0.0; sys_platform == 'win32'"]
36
+ console = ["rich>=13.0", "wcwidth>=0.2"]
36
37
  all = [
37
38
  "tomlkit>=0.11.0",
38
39
  "tomli>=2.0.0; python_version < '3.11'",
@@ -41,6 +42,8 @@ all = [
41
42
  "aiohttp-socks>=0.8.0",
42
43
  "paramiko>=3.0.0",
43
44
  "pywinpty>=2.0.0; sys_platform == 'win32'",
45
+ "rich>=13.0",
46
+ "wcwidth>=0.2",
44
47
  ]
45
48
  dev = [
46
49
  "pytest>=7.4.0",
@@ -113,6 +116,7 @@ omit = [
113
116
  "*/compat.py",
114
117
  "*/terminal/*",
115
118
  "*/spinner/*",
119
+ "*/console/*",
116
120
  "*/media/web/input_box/*",
117
121
  "*/lifecycle/updater.py",
118
122
  "*/watcher/*",
@@ -29,6 +29,7 @@ _MODULE_ALIASES: Dict[str, str] = {
29
29
  "echotools.web": "echotools.media.web",
30
30
  "echotools.events": "echotools.media.events",
31
31
  "echotools.spinner": "echotools.media.spinner",
32
+ "echotools.console": "echotools.media.console",
32
33
  "echotools.tracing": "echotools.media.tracing",
33
34
  "echotools.translate": "echotools.media.translate",
34
35
  "echotools.watcher": "echotools.media.watcher",
@@ -40,12 +40,26 @@ class FncallStreamParser:
40
40
  self._state: str = self.WAITING_FOR_TAG
41
41
  self._finalized_result: Optional[Tuple[str, List[Dict[str, Any]]]] = None
42
42
 
43
- # Precompute end tags from trigger tags (avoids per-chunk string parsing)
43
+ # 三种情况:
44
+ # 1. 协议实现了 get_stream_end_tags() 且返回非空列表 → 用声明的结束标记
45
+ # 2. 协议实现了 get_stream_end_tags() 且返回空列表 → 禁止自动关闭,等 finalize()
46
+ # 3. 协议未实现 get_stream_end_tags() → 从 trigger tags 推断(旧协议兼容)
44
47
  self._end_tags: List[str] = []
48
+ self._no_auto_close: bool = False
49
+ if hasattr(protocol, "get_stream_end_tags"):
50
+ declared = list(protocol.get_stream_end_tags())
51
+ if declared:
52
+ self._end_tags = declared
53
+ else:
54
+ self._no_auto_close = True
55
+ return
56
+ # 旧协议兼容:从 trigger tags 推断结束标记
45
57
  for tag in protocol.get_trigger_tags():
46
58
  if tag.startswith("<") and not tag.startswith("</"):
47
59
  tag_name = tag.lstrip("<").split(">")[0].split()[0]
48
- self._end_tags.append(f"</{tag_name}>")
60
+ end = f"</{tag_name}>"
61
+ if end != tag.replace("<", "</"):
62
+ self._end_tags.append(end)
49
63
  elif tag.startswith("[") and not tag.startswith("[/"):
50
64
  inner = tag.lstrip("[").split("]")[0]
51
65
  self._end_tags.append(f"[/{inner}]")
@@ -97,13 +111,12 @@ class FncallStreamParser:
97
111
 
98
112
  def _is_call_closed(self) -> bool:
99
113
  """检测 fncall 缓冲区中是否包含结束标记。"""
114
+ if self._no_auto_close:
115
+ return False
100
116
  buf = self._fncall_buf
101
117
  for end_tag in self._end_tags:
102
118
  if end_tag in buf:
103
119
  return True
104
- # Fallback only for protocols without recognizable end tags
105
- if not self._end_tags:
106
- return "</" in buf or "]" in buf or "}" in buf
107
120
  return False
108
121
 
109
122
  def feed(self, chunk: str) -> None:
@@ -0,0 +1,38 @@
1
+ from __future__ import annotations
2
+
3
+ """echotools.media.console:终端 ConsoleUI 框架。
4
+
5
+ 渐变文本、圆角边框、ASCII 艺术字、表格/面板、异步输入与 Spinner。
6
+ 依赖:rich、wcwidth(``pip install echotools[console]``)。
7
+ """
8
+
9
+ from echotools.media.console.charmap import char_map
10
+ from echotools.media.console.spinner import Clock, Spinner
11
+ from echotools.media.console.ui import (
12
+ Alignment,
13
+ BorderStyle,
14
+ ConsoleUI,
15
+ FileLogWriter,
16
+ FontStyle,
17
+ GradientTheme,
18
+ TextUtils,
19
+ create_ui,
20
+ _get_backend,
21
+ _normalize_key_event,
22
+ )
23
+
24
+ __all__ = [
25
+ "Alignment",
26
+ "BorderStyle",
27
+ "Clock",
28
+ "ConsoleUI",
29
+ "FileLogWriter",
30
+ "FontStyle",
31
+ "GradientTheme",
32
+ "Spinner",
33
+ "TextUtils",
34
+ "char_map",
35
+ "create_ui",
36
+ "_get_backend",
37
+ "_normalize_key_event",
38
+ ]
@@ -0,0 +1,148 @@
1
+ char_map = {
2
+ '!': [' ██╗ ', ' ██║ ', ' ██║ ', ' ╚═╝ ', ' ██╗ ', ' ╚═╝ '],
3
+ '"': [' ██╗ ██╗', ' ██║ ██║', ' ╚═╝ ╚═╝', ' ', ' ', ' '],
4
+ '#': [' ██╗ ██╗ ', '████████╗', '╚██╔═██╔╝', '████████╗', '╚██╔═██╔╝', ' ╚═╝ ╚═╝ '],
5
+ '$': [' ▄███╗ ', '██╔═██╗ ', '███████║', '╚═█████║', ' ╚═══██║', ' ▀███╔╝ '],
6
+ '%': ['██╗ ██╗ ', '╚═╝ ██╔╝ ', ' ██╔╝ ', ' ██╔╝ ', ' ██╔╝ ██╗', '██╔╝ ╚═╝'],
7
+ "'": [' ██╗ ', ' ██║ ', ' ╚═╝ ', ' ', ' ', ' '],
8
+ '(': [' ██╗ ', '██╔╝ ', '██║ ', '██║ ', '╚██╗ ', ' ╚═╝ '],
9
+ ')': ['██╗ ', '╚██╗ ', ' ██║ ', ' ██║ ', '██╔╝ ', '╚═╝ '],
10
+ '+': [' ', ' ██╗ ', '████████╗', '╚══██╔══╝', ' ██║ ', ' ╚═╝ '],
11
+ ',': [' ', ' ', ' ', ' ', ' ██╗ ', '██╔╝ '],
12
+ '.': [' ', ' ', ' ', ' ', ' ██╗ ', ' ╚═╝ '],
13
+ '/': [' ██╗', ' ██╔╝', ' ██╔╝ ', ' ██╔╝ ', ' ██╔╝ ', '██╔╝ '],
14
+ '0': [' ██████╗ ', '██╔═████╗', '██║██╔██║', '████╔╝██║', '╚██████╔╝', ' ╚═════╝ '],
15
+ '1': [' ██╗ ', '███║ ', '╚██║ ', ' ██║ ', ' ██║ ', ' ╚═╝ '],
16
+ '2': ['██████╗ ', '╚════██╗', ' █████╔╝', '██╔═══╝ ', '███████╗', '╚══════╝'],
17
+ '3': ['██████╗ ', '╚════██╗', ' █████╔╝', ' ╚═══██╗', '██████╔╝', '╚═════╝ '],
18
+ '4': ['██╗ ██╗', '██║ ██║', '███████║', '╚════██║', ' ██║', ' ╚═╝'],
19
+ '5': ['███████╗', '██╔════╝', '███████╗', '╚════██║', '███████║', '╚══════╝'],
20
+ '6': [' ██████╗ ', '██╔════╝ ', '███████╗ ', '██╔═══██╗', '╚██████╔╝', ' ╚═════╝ '],
21
+ '7': ['███████╗', '╚════██║', ' ██╔╝', ' ██╔╝ ', ' ██║ ', ' ╚═╝ '],
22
+ '8': [' █████╗ ', '██╔══██╗', '╚█████╔╝', '██╔══██╗', '╚█████╔╝', ' ╚════╝ '],
23
+ '9': [' █████╗ ', '██╔══██╗', '╚██████║', ' ╚═══██║', ' █████╔╝', ' ╚════╝ '],
24
+ ':': [' ', ' ██╗ ', ' ╚═╝ ', ' ', ' ██╗ ', ' ╚═╝ '],
25
+ ';': [' ', ' ██╗ ', ' ╚═╝ ', ' ', ' ██╗ ', '██╔╝ '],
26
+ '=': [' ', '█████████╗', '╚════════╝', '█████████╗', '╚════════╝', ' '],
27
+ '?': [' █████╗ ', '██╔══██╗', ' ███╔╝', ' ██╔╝ ', ' ╚═╝ ', ' ██╗ '],
28
+ '@': [' ██████╗ ', '██╔██╗██╗ ', '██║██║██║ ', '██║╚█████║', '╚██████╔╝ ', ' ╚═════╝ '],
29
+ 'A': [' █████╗ ', '██╔══██╗', '███████║', '██╔══██║', '██║ ██║', '╚═╝ ╚═╝'],
30
+ 'B': ['██████╗ ', '██╔══██╗', '██████╔╝', '██╔══██╗', '██████╔╝', '╚═════╝ '],
31
+ 'C': [' ██████╗', '██╔════╝', '██║ ', '██║ ', '╚██████╗', ' ╚═════╝'],
32
+ 'D': ['██████╗ ', '██╔══██╗', '██║ ██║', '██║ ██║', '██████╔╝', '╚═════╝ '],
33
+ 'E': ['███████╗', '██╔════╝', '█████╗ ', '██╔══╝ ', '███████╗', '╚══════╝'],
34
+ 'F': ['███████╗', '██╔════╝', '█████╗ ', '██╔══╝ ', '██║ ', '╚═╝ '],
35
+ 'G': [' ██████╗ ', '██╔════╝ ', '██║ ███╗', '██║ ██║', '╚██████╔╝', ' ╚═════╝ '],
36
+ 'H': ['██╗ ██╗', '██║ ██║', '███████║', '██╔══██║', '██║ ██║', '╚═╝ ╚═╝'],
37
+ 'I': ['██╗ ', '██║ ', '██║ ', '██║ ', '██║ ', '╚═╝ '],
38
+ 'J': [' ██╗', ' ██║', ' ██║', '██ ██║', '╚█████╔╝', ' ╚════╝ '],
39
+ 'K': ['██╗ ██╗', '██║ ██╔╝', '█████╔╝ ', '██╔═██╗ ', '██║ ██╗', '╚═╝ ╚═╝'],
40
+ 'L': ['██╗ ', '██║ ', '██║ ', '██║ ', '███████╗', '╚══════╝'],
41
+ 'M': ['███╗ ███╗', '████╗ ████║', '██╔████╔██║', '██║╚██╔╝██║', '██║ ╚═╝ ██║', '╚═╝ ╚═╝'],
42
+ 'N': ['███╗ ██╗', '████╗ ██║', '██╔██╗ ██║', '██║╚██╗██║', '██║ ╚████║', '╚═╝ ╚═══╝'],
43
+ 'O': [' ██████╗ ', '██╔═══██╗', '██║ ██║', '██║ ██║', '╚██████╔╝', ' ╚═════╝ '],
44
+ 'P': ['██████╗ ', '██╔══██╗', '██████╔╝', '██╔═══╝ ', '██║ ', '╚═╝ '],
45
+ 'Q': [' ██████╗ ', '██╔═══██╗', '██║ ██║', '██║▄▄ ██║', '╚██████╔╝', ' ╚══▀▀═╝ '],
46
+ 'R': ['██████╗ ', '██╔══██╗', '██████╔╝', '██╔══██╗', '██║ ██║', '╚═╝ ╚═╝'],
47
+ 'S': ['███████╗', '██╔════╝', '███████╗', '╚════██║', '███████║', '╚══════╝'],
48
+ 'T': ['████████╗', '╚══██╔══╝', ' ██║ ', ' ██║ ', ' ██║ ', ' ╚═╝ '],
49
+ 'U': ['██╗ ██╗', '██║ ██║', '██║ ██║', '██║ ██║', '╚██████╔╝', ' ╚═════╝ '],
50
+ 'V': ['██╗ ██╗', '██║ ██║', '██║ ██║', '╚██╗ ██╔╝', ' ╚████╔╝ ', ' ╚═══╝ '],
51
+ 'W': ['██╗ ██╗', '██║ ██║', '██║ █╗ ██║', '██║███╗██║', '╚███╔███╔╝', ' ╚══╝╚══╝ '],
52
+ 'X': ['██╗ ██╗', '╚██╗██╔╝', ' ╚███╔╝ ', ' ██╔██╗ ', '██╔╝ ██╗', '╚═╝ ╚═╝'],
53
+ 'Y': ['██╗ ██╗', '╚██╗ ██╔╝', ' ╚████╔╝ ', ' ╚██╔╝ ', ' ██║ ', ' ╚═╝ '],
54
+ 'Z': ['███████╗', '╚══███╔╝', ' ███╔╝ ', ' ███╔╝ ', '███████╗', '╚══════╝'],
55
+ '_': [' ', ' ', ' ', ' ', ' ', '████████'],
56
+ 'a': [' ', ' ', ' ██████╗ ', '██╔══██║ ', '╚███████╗', ' ╚══════╝'],
57
+ 'b': ['██╗ ', '██║ ', '██████╗ ', '██╔══██╗', '██████╔╝', '╚═════╝ '],
58
+ 'c': [' ', ' ', ' ██████╗', '██╔════╝', '╚██████╗', ' ╚═════╝'],
59
+ 'd': [' ██╗', ' ██║', ' ██████║', '██╔══██║', '╚██████║', ' ╚═════╝'],
60
+ 'e': [' ', ' ', ' █████╗ ', '██╔══╝ ', '███████╗', '╚══════╝'],
61
+ 'f': [' ████╗ ', '██╔══╝ ', '█████╗ ', '██╔══╝ ', '██║ ', '╚═╝ '],
62
+ 'g': [' ', ' ██████╗', '██╔══██║', '╚██████║', ' ╚═══██║', '██████╔╝'],
63
+ 'h': ['██╗ ', '██║ ', '██████╗ ', '██╔══██╗', '██║ ██║', '╚═╝ ╚═╝'],
64
+ 'i': ['██╗ ', '╚═╝ ', '██╗ ', '██║ ', '██║ ', '╚═╝ '],
65
+ 'j': [' ██╗ ', ' ╚═╝ ', ' ██╗ ', ' ██║ ', ' ██║ ', '████╔╝ '],
66
+ 'k': ['██╗ ', '██║ ', '██║ ██╗ ', '████╔╝ ', '██╔═██╗ ', '╚═╝ ╚═╝ '],
67
+ 'l': ['██╗ ', '██║ ', '██║ ', '██║ ', '██║ ', '╚═╝ '],
68
+ 'm': [' ', ' ', '██████████╗', '██╔═██╔═██║', '██║ ██║ ██║', '╚═╝ ╚═╝ ╚═╝'],
69
+ 'n': [' ', ' ', '██████╗ ', '██╔══██╗', '██║ ██║', '╚═╝ ╚═╝'],
70
+ 'o': [' ', ' ', ' ██████╗ ', '██╔═══██║', '╚██████╔╝', ' ╚═════╝ '],
71
+ 'p': [' ', '██████╗ ', '██╔══██╗', '██████╔╝', '██╔═══╝ ', '╚═╝ '],
72
+ 'q': [' ', ' ██████╗', '██╔══██║', '╚██████║', ' ╚═══██║', ' ╚═╝'],
73
+ 'r': [' ', ' ', '██████╗ ', '██╔══██╗', '██║ ╚═╝', '╚═╝ '],
74
+ 's': [' ', ' ████╗ ', '████ ╝ ', '╚══█ ╗ ', '█████║ ', '╚════╝ '],
75
+ 't': [' ██╗ ', ' ██║ ', '███████╗ ', '╚══██╔═╝ ', ' ████║ ', ' ╚═══╝ '],
76
+ 'u': [' ', ' ', '██╗ ██╗', '██║ ██║', '╚██████║', ' ╚═════╝'],
77
+ 'v': [' ', ' ', '██╗ ██╗', '╚██╗██╔╝', ' ╚███╔╝ ', ' ╚══╝ '],
78
+ 'w': [' ', ' ', '██╗ ██╗ ██╗', '╚██╗████╗██╔╝', ' ╚██╔══██╔╝ ', ' ╚═╝ ╚═╝ '],
79
+ 'x': [' ', ' ', '██╗ ██╗', '╚████╔╝ ', '██╔═██╗ ', '╚═╝ ╚═╝ '],
80
+ 'y': [' ', '██╗ ██╗', '╚██╗██╔╝', ' ╚███╔╝ ', '███╔═╝ ', '╚═╝ '],
81
+ 'z': [' ', ' ', '███████╗', '╚══███╔╝', '███████║', '╚══════╝'],
82
+ 'ı': ['██╗ ', '██║ ', '██║ ', '██║ ', '██║ ', '╚═╝ '],
83
+ 'ſ': ['███████╗', '██╔════╝', '███████╗', '╚════██║', '███████║', '╚══════╝'],
84
+ ' ': [' ', ' ', ' ', ' ', ' ', ' '],
85
+ '-': [' ', ' ', '███████╗', '╚══════╝', ' ', ' '],
86
+ '[': ['███╗ ', '██╔╝ ', '██║ ', '██║ ', '███╗ ', '╚══╝ '],
87
+ ']': ['███╗ ', '╚██║ ', ' ██║ ', ' ██║ ', '███║ ', '╚══╝ '],
88
+ '{': [' ██╗ ', '██╔╝ ', '█╔╝ ', '╚██╗ ', ' ╚██╗ ', ' ╚═╝ '],
89
+ '}': ['██╗ ', '╚██╗ ', ' ╚█╗ ', '██╔╝ ', '██╔╝ ', '╚═╝ '],
90
+ '\\': ['██╗ ', '╚██╗ ', ' ╚██╗ ', ' ╚██╗ ', ' ╚██╗ ', ' ╚██╗'],
91
+ '|': ['██╗ ', '██║ ', '██║ ', '██║ ', '██║ ', '╚═╝ '],
92
+ '^': [' ██╗ ', '████╗ ', '╚═██║ ', ' ╚═╝ ', ' ', ' '],
93
+ '&': [' █████╗ ', '██╔══██╗', '╚█████╔╝', '██╔═██╗ ', '╚██████║', ' ╚═════╝'],
94
+ '*': [' ', ' ▄ █ ▄ ', '██████╗ ', ' ▀ █ ▀ ', ' ', ' '],
95
+ '<': [' ██╗ ', ' ██╔╝ ', ' ██╔╝ ', ' ╚██╗ ', ' ╚██╗ ', ' ╚═╝ '],
96
+ '>': ['██╗ ', '╚██╗ ', ' ╚██╗ ', ' ██╔╝ ', '██╔╝ ', '╚═╝ '],
97
+ '~': [' ', '███╗ ██╗ ', '╚██████╔╝', ' ╚═══██║ ', ' ', ' '],
98
+ '`': ['██╗ ', '╚█╗ ', ' ╚╝ ', ' ', ' ', ' '],
99
+ '±': [' ', ' ██╗ ', '████████╗', '╚══██╔══╝', '████████╗', '╚═══════╝'],
100
+ '×': [' ', '██╗ ██╗ ', '╚████╔██╗', '██╔███╔╝ ', '██╔╝╚██╗ ', '╚═╝ ╚═╝ '],
101
+ '÷': [' ', ' ██╗ ', '████████╗', '╚══██╔══╝', ' ██║ ', ' ╚═╝ '],
102
+ '°': ['██████╗ ', '██╔══██║', '╚██████║', ' ╚═════╝', ' ', ' '],
103
+ '€': [' █████╗ ', '██╔═══╝ ', '█████╗ ', '██╔══╝ ', '╚██████╗', ' ╚═════╝'],
104
+ '£': [' █████╗ ', '██╔══██╗', '█████╔═╝', '██╔══╝ ', '███████╗', '╚══════╝'],
105
+ '¥': ['██╗ ██╗', '╚██╗ ██╔╝', '████████╗', '╚══██╔══╝', ' ██║ ', ' ╚═╝ '],
106
+ '¢': [' ██╗ ', ' ██████╗ ', '██╔════╝ ', '██║ ', '╚██████╗ ', ' ╚══╝ '],
107
+ '§': [' █████╗ ', '██╔═══╝ ', '███████╗', '╚════██║', '███████║', '╚══════╝'],
108
+ '©': [' ██████╗ ', '██╔═══██╗ ', '██║ ▄▄██║ ', '██║ ╚═╝██║', '╚██████╔╝ ', ' ╚═════╝ '],
109
+ '®': [' ██████╗ ', '██╔══██╗ ', '██████╔╔╝', '██╔══██╗ ', '██║ ██║ ', '╚═╝ ╚═╝ '],
110
+ '™': ['████████╗███╗████ ', '╚══██╔══╝████║█ ', ' ██║ ██╔═█═█║█', ' ██║ ██║ █ █║█', ' ██║ ██║ █ ║ ', ' ╚═╝ ╚═╝ █ ╝█ '],
111
+ '¿': [' ██╗ ', ' ██╔╝ ', ' ███╔╝ ', '██╔══██╗ ', '╚█████╔╝ ', ' ╚════╝ '],
112
+ '¡': [' ██╗ ', ' ╚═╝ ', ' ██╗ ', ' ██║ ', ' ██║ ', ' ╚═╝ '],
113
+ '→': [' ', ' ██╗ ', ' ████╗', '██████╔═╝', '╚═════╝ ', ' '],
114
+ '←': [' ', ' ██╗ ', '████╗ ', '╚═██████╗', ' ', ' '],
115
+ '↑': [' ██╗ ', ' ███╗ ', '████████║', '╚═══██║ ', ' ██║ ', ' ╚═╝ '],
116
+ '↓': [' ██╗ ', ' ██║ ', ' ██║ ', '██████║ ', '╚═███╔╝ ', ' ╚═╝ '],
117
+ '☺': [' ██████╗ ', '██╔██╗██╗ ', '██║ ╚═██║', '██║ ╔══██║', '╚██████╔╝ ', ' ╚═════╝ '],
118
+ '☹': [' ██████╗ ', '██╔██╗██╗ ', '██║ ██║', '██║ ╔══██║', '╚██████╔╝ ', ' ╚═════╝ '],
119
+ '♥': [' ', ' ██╗ ██╗ ', '███████╗ ', '╚██████╔╝', ' ╚████╔╝ ', ' ╚══╝ '],
120
+ '♦': [' ██╗ ', ' ████╗ ', ' ██████╗ ', '╚██████╔╝', ' ╚██╔╝ ', ' ╚═╝ '],
121
+ '♠': [' ██╗ ', ' ████╗ ', ' ██████╗ ', '╚██████╔╝', ' ██║ ', ' ████╗ '],
122
+ '♣': [' ████╗ ', ' ██████╗ ', '╚██████╔╝', ' ██║ ', ' ████╗ ', ' ╚════╝ '],
123
+ 'α': [' ', ' █ ', ' ██████╗ ', '██╔══██╗ ', '╚██████║ ', ' ╚════█═╝'],
124
+ 'β': ['██████╗ ', '██╔══██╗', '██████╔╝', '██╔══██╗', '██████╔╝', '█═════╝ '],
125
+ 'γ': ['█ █ ', ' █ █ ', '███████╗ ', '╚══██╔══╝ ', '███╔╝ ', '╚══╝ '],
126
+ 'δ': [' ████╗ ', '██╔══██╗ ', '███║ ██║ ', '██║ ██║ ', '╚██████╔╝', ' ╚═════╝ '],
127
+ 'π': [' ', '█████████╗ ', '╚══██╔═█═╝ ', ' ██║ █ ', ' ██║ ██ ', ' ╚═╝ ╚═╝ '],
128
+ 'Σ': ['███████╗', '██╔════╝', '█████╗ ', '██╔══╝ ', '███████╗', '╚══════╝'],
129
+ 'Ω': [' ██████╗ ', '██╔═══██╗', '██║ ██║', '╚██╗ ██╔╝', ' ╚═══╝ ', ' '],
130
+ '∞': [' ', '███╗ ███╗ ', '██████████║', '╚██╔═██╔══╝', ' ╚═╝ ╚═╝ ', ' '],
131
+ '∑': ['███████╗', '██╔════╝', ' █████╗ ', '██╔══╝ ', '███████╗', '╚══════╝'],
132
+ '∆': [' ██╗ ', ' ████╗ ', ' ██╔═██╗ ', '██╔╝ ██╗', '████████╗', '╚═══════╝'],
133
+ '√': [' ██╗', ' ██╔╝', ' ██╔╝ ', '██ ██╔╝ ', '████╔╝ ', '╚══╝ '],
134
+ '≤': [' ██╗ ', ' ██╔╝ ', ' ██╔╝ ', '████╗ ', '╚██████╗', ' ╚═════╝'],
135
+ '≥': ['██╗ ', '╚██╗ ', ' ╚██╗ ', ' ██████╗', '██████╔╝', '╚═════╝ '],
136
+ '≠': [' ██╗ ', '███████╗ ', '╚══██╔══╝', '███████╗ ', '██╔════╝ ', '╚═╝ '],
137
+ '≈': [' ', '███╗ ██╗ ', '╚██████╔╝', '███╗ ██╗ ', '╚██████╔╝', ' ╚═════╝ '],
138
+ '∴': [' ', ' ██╗ ', '████████╗', '╚══██╔══╝', '███╗██╗ ', '╚══╝╚═╝ '],
139
+ '∵': ['███╗██╗ ', '╚══╝╚═╝ ', '████████╗', '╚══██╔══╝', ' ██╗ ', ' ╚═╝ '],
140
+ '∈': [' ', '██████╗ ', '██╔═══██╗', '██║ ████║', '╚██████╔╝', ' ╚═════╝ '],
141
+ '∉': [' ██╗ ', '██████╔╝ ', '██╔═█████╗ ', '██║██╔══██║', '╚██████╔╝ ', ' ╚═════╝ '],
142
+ '⊂': [' ', ' ██████╗ ', '██╔════╝ ', '██║ ', '╚██████╗ ', ' ╚═════╝ '],
143
+ '⊃': [' ', ' ██████╗ ', ' ╚═════██║', ' ██║', ' ██████╔╝ ', ' ╚═════╝ '],
144
+ '∪': [' ', '██╗ ██╗', '██║ ██║', '██║ ██║', '╚██████╔╝', ' ╚═════╝ '],
145
+ '∩': [' ', ' ██████╗ ', '██╔════██╗', '██║ ██║', '██║ ██║', '╚═╝ ╚═╝'],
146
+ '\n': [' ', ' ', ' ', ' ', ' ', ' '],
147
+ '\t': [' ', ' ', ' ', ' ', ' ', ' '],
148
+ }