echotools 2.3.7__tar.gz → 2.3.8__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.
- {echotools-2.3.7 → echotools-2.3.8}/PKG-INFO +1 -1
- echotools-2.3.8/README.md +3 -0
- {echotools-2.3.7 → echotools-2.3.8}/pyproject.toml +6 -6
- echotools-2.3.8/src/echotools/__init__.py +212 -0
- echotools-2.3.8/src/echotools/base/cache/__init__.py +8 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/cache/list_cache.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/config/__init__.py +4 -4
- echotools-2.3.8/src/echotools/base/config/base.py +146 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/config/center.py +17 -175
- echotools-2.3.8/src/echotools/base/config/center_notify.py +39 -0
- echotools-2.3.8/src/echotools/base/config/center_template.py +137 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/config/loader.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/errors/__init__.py +4 -4
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/errors/classify.py +3 -3
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/errors/common.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/errors/http.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/ids/__init__.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/io/__init__.py +2 -2
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/io/io_utils.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/io/printstream.py +17 -31
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/logger/__init__.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/retry/__init__.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/retry/retry.py +12 -26
- echotools-2.3.8/src/echotools/exec/dispatch/__init__.py +21 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/dispatch/dispatcher.py +56 -126
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/dispatch/proxy_selector.py +2 -2
- echotools-2.3.8/src/echotools/exec/dispatch/race.py +119 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/dispatch/selector.py +3 -3
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/fncall/__init__.py +7 -7
- echotools-2.3.8/src/echotools/exec/fncall/parsers/__init__.py +6 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/fncall/parsers/stream.py +1 -1
- echotools-2.3.8/src/echotools/exec/fncall/parsers/xml_params.py +41 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/fncall/parsers/xml_parser.py +48 -86
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/fncall/prompt/__init__.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/fncall/prompt/history.py +13 -145
- echotools-2.3.8/src/echotools/exec/fncall/prompt/history_format.py +56 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/fncall/prompt/inject.py +67 -70
- echotools-2.3.8/src/echotools/exec/fncall/prompt/prompt_helpers.py +153 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/fncall/protocols/__init__.py +2 -2
- echotools-2.3.8/src/echotools/exec/fncall/protocols/entml.py +159 -0
- echotools-2.3.8/src/echotools/exec/fncall/protocols/entml_invoke.py +109 -0
- echotools-2.3.8/src/echotools/exec/fncall/protocols/entml_patterns.py +42 -0
- echotools-2.3.8/src/echotools/exec/fncall/protocols/entml_thinking.py +42 -0
- echotools-2.3.8/src/echotools/exec/fncall/protocols/entml_values.py +74 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/fncall/registry.py +3 -3
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/fncall/shared/__init__.py +4 -4
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/fncall/shared/coercion.py +43 -54
- echotools-2.3.8/src/echotools/exec/fncall/shared/normalization.py +172 -0
- echotools-2.3.8/src/echotools/exec/fncall/shared/schema_render.py +127 -0
- echotools-2.3.8/src/echotools/exec/lifecycle/__init__.py +8 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/lifecycle/manager.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/lifecycle/updater.py +11 -38
- echotools-2.3.8/src/echotools/exec/lifecycle/updater_pull.py +33 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/process/__init__.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/process/port.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/protocol/__init__.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/protocol/base.py +2 -1
- echotools-2.3.8/src/echotools/exec/terminal/local/__init__.py +6 -0
- echotools-2.3.8/src/echotools/exec/terminal/local/core.py +319 -0
- echotools-2.3.8/src/echotools/exec/terminal/local/proc.py +330 -0
- echotools-2.3.8/src/echotools/exec/terminal/local/unix.py +201 -0
- echotools-2.3.8/src/echotools/exec/terminal/local/win.py +206 -0
- echotools-2.3.8/src/echotools/exec/terminal/session/__init__.py +7 -0
- echotools-2.3.7/src/echotools/terminal/session.py → echotools-2.3.8/src/echotools/exec/terminal/session/base.py +5 -145
- echotools-2.3.8/src/echotools/exec/terminal/session/client.py +155 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/terminal/ssh.py +40 -24
- echotools-2.3.8/src/echotools/fncall/__init__.py +1 -0
- echotools-2.3.8/src/echotools/fncall/parsers/__init__.py +1 -0
- echotools-2.3.8/src/echotools/fncall/parsers/stream.py +1 -0
- echotools-2.3.8/src/echotools/fncall/parsers/xml_parser.py +1 -0
- echotools-2.3.8/src/echotools/fncall/prompt/__init__.py +1 -0
- echotools-2.3.8/src/echotools/fncall/prompt/history.py +1 -0
- echotools-2.3.8/src/echotools/fncall/prompt/inject.py +1 -0
- echotools-2.3.8/src/echotools/fncall/prompt/templates.py +1 -0
- echotools-2.3.8/src/echotools/fncall/protocols/__init__.py +1 -0
- echotools-2.3.8/src/echotools/fncall/protocols/entml.py +1 -0
- echotools-2.3.8/src/echotools/fncall/registry.py +1 -0
- echotools-2.3.8/src/echotools/fncall/shared/__init__.py +1 -0
- echotools-2.3.8/src/echotools/fncall/shared/coercion.py +1 -0
- echotools-2.3.8/src/echotools/fncall/shared/loop_detect.py +1 -0
- echotools-2.3.8/src/echotools/fncall/shared/normalization.py +1 -0
- echotools-2.3.8/src/echotools/fncall/shared/xml_helpers.py +1 -0
- echotools-2.3.8/src/echotools/logger/__init__.py +1 -0
- echotools-2.3.8/src/echotools/logger/manager.py +1 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/events/__init__.py +2 -2
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/events/bus.py +2 -2
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/spinner/__init__.py +2 -2
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/spinner/spinner.py +9 -114
- echotools-2.3.8/src/echotools/media/spinner/spinner_color.py +101 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/tracing/__init__.py +3 -3
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/tracing/span.py +2 -2
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/tracing/tracer.py +2 -2
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/translate.py +24 -35
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/watcher/__init__.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/watcher/file_watcher.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/web/__init__.py +6 -6
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/web/application.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/web/input_box/app.js +8 -7
- echotools-2.3.8/src/echotools/media/web/input_box/components/filezone.js +277 -0
- echotools-2.3.8/src/echotools/media/web/input_box/components/motionkit.js +154 -0
- echotools-2.3.8/src/echotools/media/web/input_box/components/sendbutton.js +64 -0
- echotools-2.3.8/src/echotools/media/web/input_box/components/voiceinput.js +76 -0
- echotools-2.3.7/src/echotools/web/input_box/input-box.js → echotools-2.3.8/src/echotools/media/web/input_box/inputbox.js +7 -8
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/web/input_box/style.css +1 -1
- echotools-2.3.7/src/echotools/web/input_box/voice_input/voice-input.js → echotools-2.3.8/src/echotools/media/web/input_box/voicegif.js +2 -102
- echotools-2.3.8/src/echotools/media/web/middleware.py +126 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/web/stats.py +37 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/web/utils.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/plat}/files/__init__.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/plat}/files/file_util.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/plat}/network/__init__.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/plat}/network/http_utils.py +2 -2
- echotools-2.3.8/src/echotools/plat/plugin/__init__.py +9 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/plat}/plugin/discovery.py +2 -2
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/plat}/plugin/registry.py +23 -76
- echotools-2.3.8/src/echotools/plat/plugin/registry_ops.py +101 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/plat}/proxy/__init__.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/plat}/proxy/manager.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/plat}/runtime/__init__.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/plat}/runtime/collector.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/plat}/scheduler/__init__.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/plat}/scheduler/scheduler.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/plat}/sdk/__init__.py +1 -1
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/plat}/sdk/facade.py +12 -12
- echotools-2.3.8/src/echotools/protocol/__init__.py +1 -0
- echotools-2.3.8/src/echotools/protocol/base.py +1 -0
- {echotools-2.3.7 → echotools-2.3.8}/src/echotools.egg-info/PKG-INFO +1 -1
- echotools-2.3.8/src/echotools.egg-info/SOURCES.txt +195 -0
- echotools-2.3.8/src/echotools.egg-info/top_level.txt +3 -0
- echotools-2.3.8/src/tests/bench_import.py +14 -0
- echotools-2.3.8/src/tests/conftest.py +19 -0
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_cache_retry.py +2 -2
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_completion.py +2 -2
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_config.py +3 -3
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_config_extended.py +1 -1
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_coverage_core.py +23 -23
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_dispatch.py +2 -2
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_dispatch_extended.py +3 -3
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_dispatch_race.py +2 -2
- echotools-2.3.8/src/tests/test_entml_protocol.py +141 -0
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_errors.py +2 -2
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_errors_common.py +1 -1
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_events.py +1 -1
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_events_event.py +1 -1
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_facade.py +1 -1
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_fncall.py +2 -2
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_ids.py +1 -1
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_io.py +1 -1
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_keys.py +1 -1
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_lifecycle.py +1 -1
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_logger.py +1 -1
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_merge.py +2 -2
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_plugin.py +1 -1
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_printstream.py +1 -1
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_protocols.py +2 -2
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_proxy.py +1 -1
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_proxy_selector.py +1 -1
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_runtime.py +1 -1
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_scheduler.py +1 -1
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_tracing.py +1 -1
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_usage.py +1 -1
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_web.py +6 -6
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_web_broker.py +2 -2
- echotools-2.3.7/src/echotools/__init__.py +0 -212
- echotools-2.3.7/src/echotools/cache/__init__.py +0 -8
- echotools-2.3.7/src/echotools/config/base.py +0 -144
- echotools-2.3.7/src/echotools/dispatch/__init__.py +0 -21
- echotools-2.3.7/src/echotools/fncall/parsers/__init__.py +0 -6
- echotools-2.3.7/src/echotools/fncall/protocols/entml.py +0 -286
- echotools-2.3.7/src/echotools/fncall/shared/normalization.py +0 -257
- echotools-2.3.7/src/echotools/lifecycle/__init__.py +0 -8
- echotools-2.3.7/src/echotools/plugin/__init__.py +0 -9
- echotools-2.3.7/src/echotools/terminal/local.py +0 -964
- echotools-2.3.7/src/echotools/web/input_box/file_zone/file-zone.js +0 -268
- echotools-2.3.7/src/echotools/web/input_box/motion_kit/motion-kit.js +0 -139
- echotools-2.3.7/src/echotools/web/input_box/send_button/send-button.js +0 -64
- echotools-2.3.7/src/echotools/web/middleware.py +0 -161
- echotools-2.3.7/src/echotools.egg-info/SOURCES.txt +0 -150
- echotools-2.3.7/src/echotools.egg-info/top_level.txt +0 -1
- {echotools-2.3.7 → echotools-2.3.8/docs}/README.md +0 -0
- {echotools-2.3.7 → echotools-2.3.8}/setup.cfg +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/cache/memory_cache.py +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/config/merge.py +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/errors/base.py +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/ids/generator.py +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/base}/logger/manager.py +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/dispatch/candidate.py +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/dispatch/usage.py +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/fncall/prompt/templates.py +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/fncall/shared/loop_detect.py +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/fncall/shared/xml_helpers.py +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/keys.py +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/terminal/__init__.py +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/terminal/conpty.py +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/terminal/sanitize.py +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/exec}/terminal/tmux.py +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/events/event.py +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/tracing/context.py +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/web/broker.py +0 -0
- /echotools-2.3.7/src/echotools/web/input_box/sortable_list/sortable-list.css → /echotools-2.3.8/src/echotools/media/web/input_box/components/sortablelist.css +0 -0
- /echotools-2.3.7/src/echotools/web/input_box/sortable_list/sortable-list.js → /echotools-2.3.8/src/echotools/media/web/input_box/components/sortablelist.js +0 -0
- /echotools-2.3.7/src/echotools/web/input_box/text_input/text-input.js → /echotools-2.3.8/src/echotools/media/web/input_box/components/textinput.js +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/web/input_box/fonts/inter-500.woff2 +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/media}/web/input_box/fonts/inter-600.woff2 +0 -0
- /echotools-2.3.7/src/echotools/web/input_box/fonts/inter-400.woff2 → /echotools-2.3.8/src/echotools/media/web/input_box/fonts/inter400.woff2 +0 -0
- /echotools-2.3.7/src/echotools/web/input_box/fonts/tailwind.min.css → /echotools-2.3.8/src/echotools/media/web/input_box/fonts/tailwind.css +0 -0
- /echotools-2.3.7/src/echotools/web/input_box/input-box.css → /echotools-2.3.8/src/echotools/media/web/input_box/inputbox.css +0 -0
- {echotools-2.3.7/src/echotools → echotools-2.3.8/src/echotools/plat}/plugin/base.py +0 -0
- {echotools-2.3.7 → echotools-2.3.8}/src/echotools/py.typed +0 -0
- /echotools-2.3.7/src/echotools/_version.py → /echotools-2.3.8/src/echotools/version.py +0 -0
- {echotools-2.3.7 → echotools-2.3.8}/src/echotools.egg-info/dependency_links.txt +0 -0
- {echotools-2.3.7 → echotools-2.3.8}/src/echotools.egg-info/requires.txt +0 -0
- {echotools-2.3.7 → echotools-2.3.8/src}/tests/test_imports.py +0 -0
|
@@ -4,9 +4,9 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "echotools"
|
|
7
|
-
version = "2.3.
|
|
7
|
+
version = "2.3.8"
|
|
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,212 @@
|
|
|
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
|
+
|
|
14
|
+
__version__ = get_version()
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"__version__",
|
|
18
|
+
"EchoTools",
|
|
19
|
+
"ConfigBase",
|
|
20
|
+
"ConfigCenter",
|
|
21
|
+
"LoggerManager",
|
|
22
|
+
"get_logger",
|
|
23
|
+
"set_color",
|
|
24
|
+
"configure",
|
|
25
|
+
"Event",
|
|
26
|
+
"EventBus",
|
|
27
|
+
"Tracer",
|
|
28
|
+
"Trace",
|
|
29
|
+
"Span",
|
|
30
|
+
"get_current_trace_id",
|
|
31
|
+
"set_current_trace_id",
|
|
32
|
+
"get_current_span_id",
|
|
33
|
+
"set_current_span_id",
|
|
34
|
+
"get_request_id",
|
|
35
|
+
"set_request_id",
|
|
36
|
+
"ListCache",
|
|
37
|
+
"MemoryCache",
|
|
38
|
+
"TaskCandidate",
|
|
39
|
+
"make_id",
|
|
40
|
+
"AdaptiveSelector",
|
|
41
|
+
"TaskDispatcher",
|
|
42
|
+
"TaskScheduler",
|
|
43
|
+
"ProxySelector",
|
|
44
|
+
"ProxyRecord",
|
|
45
|
+
"Plugin",
|
|
46
|
+
"PluginRegistry",
|
|
47
|
+
"discover_plugins",
|
|
48
|
+
"ToolProtocol",
|
|
49
|
+
"register_protocol",
|
|
50
|
+
"get_protocol_by_id",
|
|
51
|
+
"get_protocol",
|
|
52
|
+
"list_protocols",
|
|
53
|
+
"LifecycleManager",
|
|
54
|
+
"AutoUpdater",
|
|
55
|
+
"ProxyManager",
|
|
56
|
+
"PortReleaseResult",
|
|
57
|
+
"ensure_port_available",
|
|
58
|
+
"RuntimeCollector",
|
|
59
|
+
"WebApplication",
|
|
60
|
+
"json_body",
|
|
61
|
+
"safe_flush",
|
|
62
|
+
"FileUtil",
|
|
63
|
+
"uuid7",
|
|
64
|
+
"short_id",
|
|
65
|
+
"trace_id",
|
|
66
|
+
"span_id",
|
|
67
|
+
"atomic_write_text",
|
|
68
|
+
"ensure_directory",
|
|
69
|
+
"read_text_if_exists",
|
|
70
|
+
"retry_with_backoff",
|
|
71
|
+
"retry_on_empty",
|
|
72
|
+
"retry_on_exception",
|
|
73
|
+
"retry_async_generator",
|
|
74
|
+
"KeyState",
|
|
75
|
+
"KeyPool",
|
|
76
|
+
"extract_text_from_messages",
|
|
77
|
+
"split_text_chunks",
|
|
78
|
+
"format_translation_response",
|
|
79
|
+
"TerminalSession",
|
|
80
|
+
"TerminalCallback",
|
|
81
|
+
"LocalTerminal",
|
|
82
|
+
"SSHTerminal",
|
|
83
|
+
"PrintStream",
|
|
84
|
+
"print_stream",
|
|
85
|
+
"start_print_stream",
|
|
86
|
+
"stop_print_stream",
|
|
87
|
+
"flush_print_stream",
|
|
88
|
+
"get_buffer_size",
|
|
89
|
+
"get_queue_length",
|
|
90
|
+
"is_print_stream_running",
|
|
91
|
+
"set_print_speed",
|
|
92
|
+
"configure_print_stream",
|
|
93
|
+
"inject_fncall",
|
|
94
|
+
"FncallStreamParser",
|
|
95
|
+
"detect_tool_loop",
|
|
96
|
+
"LoopDetectionResult",
|
|
97
|
+
"EchoError",
|
|
98
|
+
"ConfigError",
|
|
99
|
+
"ValidationError",
|
|
100
|
+
"NetworkError",
|
|
101
|
+
"TimeoutError",
|
|
102
|
+
"NotSupportedError",
|
|
103
|
+
"NoCandidateError",
|
|
104
|
+
"PluginError",
|
|
105
|
+
"ProtocolError",
|
|
106
|
+
"classify_http_error",
|
|
107
|
+
"Spinner",
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
_EXPORTS: dict[str, tuple[str, str]] = {
|
|
111
|
+
"ConfigBase": ("echotools.base.config", "ConfigBase"),
|
|
112
|
+
"ConfigCenter": ("echotools.base.config", "ConfigCenter"),
|
|
113
|
+
"LoggerManager": ("echotools.base.logger", "LoggerManager"),
|
|
114
|
+
"get_logger": ("echotools.base.logger", "get_logger"),
|
|
115
|
+
"set_color": ("echotools.base.logger", "set_color"),
|
|
116
|
+
"configure": ("echotools.base.logger", "configure"),
|
|
117
|
+
"Event": ("echotools.media.events", "Event"),
|
|
118
|
+
"EventBus": ("echotools.media.events", "EventBus"),
|
|
119
|
+
"Tracer": ("echotools.media.tracing", "Tracer"),
|
|
120
|
+
"Trace": ("echotools.media.tracing", "Trace"),
|
|
121
|
+
"Span": ("echotools.media.tracing", "Span"),
|
|
122
|
+
"get_current_trace_id": ("echotools.media.tracing", "get_current_trace_id"),
|
|
123
|
+
"set_current_trace_id": ("echotools.media.tracing", "set_current_trace_id"),
|
|
124
|
+
"get_current_span_id": ("echotools.media.tracing", "get_current_span_id"),
|
|
125
|
+
"set_current_span_id": ("echotools.media.tracing", "set_current_span_id"),
|
|
126
|
+
"get_request_id": ("echotools.media.tracing", "get_request_id"),
|
|
127
|
+
"set_request_id": ("echotools.media.tracing", "set_request_id"),
|
|
128
|
+
"ListCache": ("echotools.base.cache", "ListCache"),
|
|
129
|
+
"MemoryCache": ("echotools.base.cache", "MemoryCache"),
|
|
130
|
+
"TaskCandidate": ("echotools.exec.dispatch", "TaskCandidate"),
|
|
131
|
+
"make_id": ("echotools.exec.dispatch", "make_id"),
|
|
132
|
+
"AdaptiveSelector": ("echotools.exec.dispatch", "AdaptiveSelector"),
|
|
133
|
+
"TaskDispatcher": ("echotools.exec.dispatch", "TaskDispatcher"),
|
|
134
|
+
"TaskScheduler": ("echotools.plat.scheduler", "TaskScheduler"),
|
|
135
|
+
"ProxySelector": ("echotools.exec.dispatch", "ProxySelector"),
|
|
136
|
+
"ProxyRecord": ("echotools.exec.dispatch", "ProxyRecord"),
|
|
137
|
+
"Plugin": ("echotools.plat.plugin", "Plugin"),
|
|
138
|
+
"PluginRegistry": ("echotools.plat.plugin", "PluginRegistry"),
|
|
139
|
+
"discover_plugins": ("echotools.plat.plugin", "discover_plugins"),
|
|
140
|
+
"ToolProtocol": ("echotools.exec.protocol.base", "ToolProtocol"),
|
|
141
|
+
"register_protocol": ("echotools.exec.protocol.base", "register_protocol"),
|
|
142
|
+
"get_protocol_by_id": ("echotools.exec.protocol.base", "get_protocol_by_id"),
|
|
143
|
+
"get_protocol": ("echotools.exec.fncall.registry", "get_protocol"),
|
|
144
|
+
"list_protocols": ("echotools.exec.fncall.registry", "list_protocols"),
|
|
145
|
+
"LifecycleManager": ("echotools.exec.lifecycle", "LifecycleManager"),
|
|
146
|
+
"AutoUpdater": ("echotools.exec.lifecycle", "AutoUpdater"),
|
|
147
|
+
"ProxyManager": ("echotools.plat.proxy", "ProxyManager"),
|
|
148
|
+
"PortReleaseResult": ("echotools.exec.process", "PortReleaseResult"),
|
|
149
|
+
"ensure_port_available": ("echotools.exec.process", "ensure_port_available"),
|
|
150
|
+
"RuntimeCollector": ("echotools.plat.runtime", "RuntimeCollector"),
|
|
151
|
+
"WebApplication": ("echotools.media.web.application", "WebApplication"),
|
|
152
|
+
"json_body": ("echotools.media.web.utils", "json_body"),
|
|
153
|
+
"safe_flush": ("echotools.media.web.utils", "safe_flush"),
|
|
154
|
+
"FileUtil": ("echotools.plat.files", "FileUtil"),
|
|
155
|
+
"uuid7": ("echotools.base.ids", "uuid7"),
|
|
156
|
+
"short_id": ("echotools.base.ids", "short_id"),
|
|
157
|
+
"trace_id": ("echotools.base.ids", "trace_id"),
|
|
158
|
+
"span_id": ("echotools.base.ids", "span_id"),
|
|
159
|
+
"atomic_write_text": ("echotools.base.io", "atomic_write_text"),
|
|
160
|
+
"ensure_directory": ("echotools.base.io", "ensure_directory"),
|
|
161
|
+
"read_text_if_exists": ("echotools.base.io", "read_text_if_exists"),
|
|
162
|
+
"retry_with_backoff": ("echotools.base.retry", "retry_with_backoff"),
|
|
163
|
+
"retry_on_empty": ("echotools.base.retry", "retry_on_empty"),
|
|
164
|
+
"retry_on_exception": ("echotools.base.retry", "retry_on_exception"),
|
|
165
|
+
"retry_async_generator": ("echotools.base.retry", "retry_async_generator"),
|
|
166
|
+
"KeyState": ("echotools.exec.keys", "KeyState"),
|
|
167
|
+
"KeyPool": ("echotools.exec.keys", "KeyPool"),
|
|
168
|
+
"extract_text_from_messages": ("echotools.media.translate", "extract_text_from_messages"),
|
|
169
|
+
"split_text_chunks": ("echotools.media.translate", "split_text_chunks"),
|
|
170
|
+
"format_translation_response": ("echotools.media.translate", "format_translation_response"),
|
|
171
|
+
"TerminalSession": ("echotools.exec.terminal.session", "TerminalSession"),
|
|
172
|
+
"TerminalCallback": ("echotools.exec.terminal.session", "TerminalCallback"),
|
|
173
|
+
"LocalTerminal": ("echotools.exec.terminal.local", "LocalTerminal"),
|
|
174
|
+
"SSHTerminal": ("echotools.exec.terminal.ssh", "SSHTerminal"),
|
|
175
|
+
"PrintStream": ("echotools.base.io.printstream", "PrintStream"),
|
|
176
|
+
"print_stream": ("echotools.base.io.printstream", "print_stream"),
|
|
177
|
+
"start_print_stream": ("echotools.base.io.printstream", "start_print_stream"),
|
|
178
|
+
"stop_print_stream": ("echotools.base.io.printstream", "stop_print_stream"),
|
|
179
|
+
"flush_print_stream": ("echotools.base.io.printstream", "flush_print_stream"),
|
|
180
|
+
"get_buffer_size": ("echotools.base.io.printstream", "get_buffer_size"),
|
|
181
|
+
"get_queue_length": ("echotools.base.io.printstream", "get_queue_length"),
|
|
182
|
+
"is_print_stream_running": ("echotools.base.io.printstream", "is_print_stream_running"),
|
|
183
|
+
"set_print_speed": ("echotools.base.io.printstream", "set_print_speed"),
|
|
184
|
+
"configure_print_stream": ("echotools.base.io.printstream", "configure_print_stream"),
|
|
185
|
+
"inject_fncall": ("echotools.exec.fncall.prompt.inject", "inject_fncall"),
|
|
186
|
+
"FncallStreamParser": ("echotools.exec.fncall.parsers.stream", "FncallStreamParser"),
|
|
187
|
+
"detect_tool_loop": ("echotools.exec.fncall.shared.loop_detect", "detect_tool_loop"),
|
|
188
|
+
"LoopDetectionResult": ("echotools.exec.fncall.shared.loop_detect", "LoopDetectionResult"),
|
|
189
|
+
"EchoError": ("echotools.base.errors", "EchoError"),
|
|
190
|
+
"ConfigError": ("echotools.base.errors", "ConfigError"),
|
|
191
|
+
"ValidationError": ("echotools.base.errors", "ValidationError"),
|
|
192
|
+
"NetworkError": ("echotools.base.errors", "NetworkError"),
|
|
193
|
+
"TimeoutError": ("echotools.base.errors", "TimeoutError"),
|
|
194
|
+
"NotSupportedError": ("echotools.base.errors", "NotSupportedError"),
|
|
195
|
+
"NoCandidateError": ("echotools.base.errors", "NoCandidateError"),
|
|
196
|
+
"PluginError": ("echotools.base.errors", "PluginError"),
|
|
197
|
+
"ProtocolError": ("echotools.base.errors", "ProtocolError"),
|
|
198
|
+
"classify_http_error": ("echotools.base.errors", "classify_http_error"),
|
|
199
|
+
"Spinner": ("echotools.media.spinner", "Spinner"),
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def __getattr__(name: str) -> Any:
|
|
204
|
+
if name in _EXPORTS:
|
|
205
|
+
module_path, attr = _EXPORTS[name]
|
|
206
|
+
module = importlib.import_module(module_path)
|
|
207
|
+
return getattr(module, attr)
|
|
208
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def __dir__() -> list[str]:
|
|
212
|
+
return sorted(__all__)
|
|
@@ -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
|