echotools 2.3.29__tar.gz → 2.3.30__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.29 → echotools-2.3.30}/PKG-INFO +1 -1
- {echotools-2.3.29 → echotools-2.3.30}/pyproject.toml +1 -1
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/prompt/history_format.py +6 -2
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/prompt/inject.py +10 -2
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/prompt/prompt_helpers.py +38 -6
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/protocols/entml_thinking_history.py +23 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools.egg-info/PKG-INFO +1 -1
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_entml_protocol.py +40 -0
- {echotools-2.3.29 → echotools-2.3.30}/README.md +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/docs/README.md +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/setup.cfg +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/cache/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/cache/list_cache.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/cache/memory_cache.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/config/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/config/base.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/config/center.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/config/center_notify.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/config/center_template.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/config/loader.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/config/merge.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/errors/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/errors/base.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/errors/classify.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/errors/common.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/errors/http.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/ids/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/ids/generator.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/io/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/io/io_utils.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/io/printstream.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/logger/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/logger/manager.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/retry/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/base/retry/retry.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/compat.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/dispatch/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/dispatch/candidate.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/dispatch/dispatcher.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/dispatch/proxy_selector.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/dispatch/race.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/dispatch/selector.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/dispatch/usage.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/parsers/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/parsers/stream.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/parsers/xml_params.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/parsers/xml_parser.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/prompt/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/prompt/history.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/prompt/templates.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/protocols/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/protocols/entml.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/protocols/entml_invoke.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/protocols/entml_patterns.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/protocols/entml_thinking.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/protocols/entml_thinking_parse.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/protocols/entml_tools.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/protocols/entml_values.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/registry.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/shared/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/shared/coercion.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/shared/loop_detect.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/shared/normalization.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/shared/schema_render.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/shared/xml_helpers.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/keys.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/lifecycle/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/lifecycle/manager.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/lifecycle/updater.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/lifecycle/updater_pull.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/process/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/process/port.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/protocol/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/protocol/base.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/terminal/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/terminal/conpty.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/terminal/local/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/terminal/local/core.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/terminal/local/proc.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/terminal/local/unix.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/terminal/local/win.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/terminal/sanitize.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/terminal/session/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/terminal/session/base.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/terminal/session/client.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/terminal/ssh.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/terminal/tmux.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/console/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/console/charmap.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/console/spinner.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/console/ui.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/events/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/events/bus.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/events/event.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/spinner/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/spinner/spinner.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/spinner/spinner_color.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/tracing/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/tracing/context.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/tracing/span.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/tracing/tracer.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/translate.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/watcher/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/watcher/file_watcher.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/application.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/broker.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/app.js +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/components/filezone.js +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/components/motionkit.js +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/components/sendbutton.js +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/components/sortablelist.css +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/components/sortablelist.js +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/components/textinput.js +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/components/voiceinput.js +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/fonts/inter-500.woff2 +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/fonts/inter-600.woff2 +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/fonts/inter400.woff2 +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/fonts/tailwind.css +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/inputbox.css +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/inputbox.js +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/style.css +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/voicegif.js +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/middleware.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/stats.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/utils.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/plat/files/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/plat/files/file_util.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/plat/network/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/plat/network/http_utils.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/plat/plugin/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/plat/plugin/base.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/plat/plugin/discovery.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/plat/plugin/registry.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/plat/plugin/registry_ops.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/plat/proxy/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/plat/proxy/manager.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/plat/runtime/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/plat/runtime/collector.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/plat/scheduler/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/plat/scheduler/scheduler.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/plat/sdk/__init__.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/plat/sdk/facade.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools/version.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools.egg-info/SOURCES.txt +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools.egg-info/dependency_links.txt +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools.egg-info/requires.txt +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/echotools.egg-info/top_level.txt +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/bench_import.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/conftest.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_cache_retry.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_completion.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_config.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_config_extended.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_console.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_coverage_core.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_dispatch.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_dispatch_extended.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_dispatch_race.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_entml_thinking_history.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_entml_thinking_parse.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_entml_tools.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_errors.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_errors_common.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_events.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_events_event.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_facade.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_fncall.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_ids.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_imports.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_io.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_keys.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_lifecycle.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_logger.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_merge.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_plugin.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_printstream.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_protocols.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_proxy.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_proxy_selector.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_runtime.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_scheduler.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_tracing.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_usage.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_web.py +0 -0
- {echotools-2.3.29 → echotools-2.3.30}/src/tests/test_web_broker.py +0 -0
|
@@ -18,6 +18,8 @@ from .prompt_helpers import (
|
|
|
18
18
|
def _format_conversation_history(
|
|
19
19
|
messages: List[Dict[str, Any]],
|
|
20
20
|
protocol: Optional[Any] = None,
|
|
21
|
+
*,
|
|
22
|
+
include_thinking_in_history: bool = False,
|
|
21
23
|
) -> str:
|
|
22
24
|
if not messages:
|
|
23
25
|
return ""
|
|
@@ -48,14 +50,16 @@ def _format_conversation_history(
|
|
|
48
50
|
tool_msgs.append(messages[j])
|
|
49
51
|
j += 1
|
|
50
52
|
block = format_assistant_block_with_results(
|
|
51
|
-
m, tool_msgs, protocol, call_id_to_name, seen_assistant_keys
|
|
53
|
+
m, tool_msgs, protocol, call_id_to_name, seen_assistant_keys,
|
|
54
|
+
include_thinking_in_history=include_thinking_in_history,
|
|
52
55
|
)
|
|
53
56
|
if block:
|
|
54
57
|
parts.append((block, False))
|
|
55
58
|
i = j
|
|
56
59
|
else:
|
|
57
60
|
block = format_assistant_block(
|
|
58
|
-
m, content_str, protocol, call_id_to_name, seen_assistant_keys
|
|
61
|
+
m, content_str, protocol, call_id_to_name, seen_assistant_keys,
|
|
62
|
+
include_thinking_in_history=include_thinking_in_history,
|
|
59
63
|
)
|
|
60
64
|
if block:
|
|
61
65
|
parts.append((block, False))
|
|
@@ -22,6 +22,10 @@ from echotools.exec.fncall.protocols.entml import (
|
|
|
22
22
|
format_entml_current_user_message,
|
|
23
23
|
)
|
|
24
24
|
from echotools.exec.fncall.protocols.entml_thinking import build_entml_thinking_section
|
|
25
|
+
from echotools.exec.fncall.protocols.entml_thinking_history import (
|
|
26
|
+
apply_thinking_history_policy,
|
|
27
|
+
parse_include_thinking_in_history,
|
|
28
|
+
)
|
|
25
29
|
from echotools.exec.fncall.shared.loop_detect import detect_tool_loop
|
|
26
30
|
from echotools.exec.fncall.shared.normalization import format_tool_descs
|
|
27
31
|
from echotools.exec.protocol.base import ToolProtocol
|
|
@@ -96,14 +100,18 @@ def inject_fncall(
|
|
|
96
100
|
protocol_options: Optional[Dict[str, Any]] = None,
|
|
97
101
|
) -> List[Dict[str, Any]]:
|
|
98
102
|
"""注入工具定义,返回单条 user 消息(含历史)。"""
|
|
99
|
-
|
|
103
|
+
include_history = parse_include_thinking_in_history(protocol_options)
|
|
104
|
+
prepared = apply_thinking_history_policy(list(messages), include_history)
|
|
105
|
+
normalized = _normalize_messages(prepared)
|
|
100
106
|
history_messages, current_user_message = split_last_user_message(normalized)
|
|
101
107
|
|
|
102
108
|
if hasattr(protocol, 'clean_tags'):
|
|
103
109
|
current_user_message = protocol.clean_tags(current_user_message)
|
|
104
110
|
|
|
105
111
|
history_text = _format_conversation_history(
|
|
106
|
-
history_messages,
|
|
112
|
+
history_messages,
|
|
113
|
+
protocol=protocol,
|
|
114
|
+
include_thinking_in_history=include_history,
|
|
107
115
|
).strip()
|
|
108
116
|
|
|
109
117
|
if not tools:
|
|
@@ -15,9 +15,37 @@ from .history import (
|
|
|
15
15
|
_try_convert_user_to_tool,
|
|
16
16
|
)
|
|
17
17
|
|
|
18
|
+
from echotools.exec.fncall.protocols.entml_thinking_history import (
|
|
19
|
+
extract_reasoning_text,
|
|
20
|
+
format_entml_thinking_history_block,
|
|
21
|
+
)
|
|
22
|
+
|
|
18
23
|
logger = get_logger(__name__)
|
|
19
24
|
|
|
20
25
|
|
|
26
|
+
def _assistant_history_content_blocks(
|
|
27
|
+
m: Dict[str, Any],
|
|
28
|
+
content_str: str,
|
|
29
|
+
protocol: Optional[Any],
|
|
30
|
+
include_thinking_in_history: bool,
|
|
31
|
+
) -> List[str]:
|
|
32
|
+
"""构建 assistant 历史块正文(可选前置 entml:thinking)。"""
|
|
33
|
+
blocks: List[str] = []
|
|
34
|
+
if (
|
|
35
|
+
include_thinking_in_history
|
|
36
|
+
and protocol is not None
|
|
37
|
+
and getattr(protocol, "id", None) == "entml"
|
|
38
|
+
):
|
|
39
|
+
reasoning = extract_reasoning_text(m)
|
|
40
|
+
if reasoning:
|
|
41
|
+
thinking_block = format_entml_thinking_history_block(reasoning)
|
|
42
|
+
if thinking_block:
|
|
43
|
+
blocks.append(thinking_block)
|
|
44
|
+
if content_str:
|
|
45
|
+
blocks.append(content_str)
|
|
46
|
+
return blocks
|
|
47
|
+
|
|
48
|
+
|
|
21
49
|
def split_last_user_message(
|
|
22
50
|
normalized: List[Dict[str, Any]],
|
|
23
51
|
) -> Tuple[List[Dict[str, Any]], str]:
|
|
@@ -52,11 +80,13 @@ def format_assistant_block(
|
|
|
52
80
|
protocol: Optional[Any],
|
|
53
81
|
call_id_to_name: Dict[str, str],
|
|
54
82
|
seen_assistant_keys: Set[Tuple[str, Tuple[Tuple[str, str], ...]]],
|
|
83
|
+
*,
|
|
84
|
+
include_thinking_in_history: bool = False,
|
|
55
85
|
) -> Optional[str]:
|
|
56
86
|
tcs: List[Dict[str, Any]] = m.get("tool_calls") or []
|
|
57
|
-
blocks
|
|
58
|
-
|
|
59
|
-
|
|
87
|
+
blocks = _assistant_history_content_blocks(
|
|
88
|
+
m, content_str, protocol, include_thinking_in_history
|
|
89
|
+
)
|
|
60
90
|
for tc in tcs:
|
|
61
91
|
cid = tc.get("id") or ""
|
|
62
92
|
fn_name = (tc.get("function") or {}).get("name") or ""
|
|
@@ -87,6 +117,8 @@ def format_assistant_block_with_results(
|
|
|
87
117
|
protocol: Optional[Any],
|
|
88
118
|
call_id_to_name: Dict[str, str],
|
|
89
119
|
seen_assistant_keys: Set[Tuple[str, Tuple[Tuple[str, str], ...]]],
|
|
120
|
+
*,
|
|
121
|
+
include_thinking_in_history: bool = False,
|
|
90
122
|
) -> Optional[str]:
|
|
91
123
|
tcs: List[Dict[str, Any]] = m.get("tool_calls") or []
|
|
92
124
|
content_str = normalize_content(m.get("content", ""))
|
|
@@ -102,9 +134,9 @@ def format_assistant_block_with_results(
|
|
|
102
134
|
for tmsg in tool_msgs
|
|
103
135
|
}
|
|
104
136
|
|
|
105
|
-
blocks
|
|
106
|
-
|
|
107
|
-
|
|
137
|
+
blocks = _assistant_history_content_blocks(
|
|
138
|
+
m, content_str, protocol, include_thinking_in_history
|
|
139
|
+
)
|
|
108
140
|
|
|
109
141
|
for tc in tcs:
|
|
110
142
|
if protocol is not None and hasattr(protocol, "format_assistant_tool_calls"):
|
{echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/protocols/entml_thinking_history.py
RENAMED
|
@@ -11,6 +11,29 @@ HISTORY_FLAG_KEYS = (
|
|
|
11
11
|
)
|
|
12
12
|
_THINKING_BLOCK_TYPES = frozenset({"thinking", "reasoning", "redacted_thinking"})
|
|
13
13
|
|
|
14
|
+
_THINKING_BLOCK_OPEN = "<entml:thinking>"
|
|
15
|
+
_THINKING_BLOCK_CLOSE = "</entml:thinking>"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def format_entml_thinking_history_block(text: str) -> str:
|
|
19
|
+
"""将历史 assistant 思考链格式化为 entml 块(供 conversation_history 使用)。"""
|
|
20
|
+
stripped = (text or "").strip()
|
|
21
|
+
if not stripped:
|
|
22
|
+
return ""
|
|
23
|
+
return f"{_THINKING_BLOCK_OPEN}\n{stripped}\n{_THINKING_BLOCK_CLOSE}"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def parse_include_thinking_in_history(
|
|
27
|
+
protocol_options: Optional[Mapping[str, Any]],
|
|
28
|
+
) -> bool:
|
|
29
|
+
"""从 protocol_options 解析是否在历史中渲染 assistant 思考链。"""
|
|
30
|
+
if not protocol_options:
|
|
31
|
+
return False
|
|
32
|
+
for key in HISTORY_FLAG_KEYS:
|
|
33
|
+
if key in protocol_options:
|
|
34
|
+
return bool(protocol_options[key])
|
|
35
|
+
return False
|
|
36
|
+
|
|
14
37
|
|
|
15
38
|
def parse_interleaved_history(
|
|
16
39
|
body: Mapping[str, Any],
|
|
@@ -426,3 +426,43 @@ def test_entml_parse_schema_coercion() -> None:
|
|
|
426
426
|
calls = parse_entml_tool_calls(sample, tools, schema_index)
|
|
427
427
|
args = json.loads(calls[0]["function"]["arguments"])
|
|
428
428
|
assert args == {"count": 7, "enabled": True, "tags": ["x", "y"]}
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
def test_inject_include_thinking_in_history() -> None:
|
|
432
|
+
"""protocol_options.include_thinking_in_history 应在历史中渲染 entml:thinking。"""
|
|
433
|
+
proto = get_protocol("entml")
|
|
434
|
+
tools = [
|
|
435
|
+
{
|
|
436
|
+
"type": "function",
|
|
437
|
+
"function": {
|
|
438
|
+
"name": "get_weather",
|
|
439
|
+
"description": "weather",
|
|
440
|
+
"parameters": {
|
|
441
|
+
"type": "object",
|
|
442
|
+
"properties": {"city": {"type": "string"}},
|
|
443
|
+
"required": ["city"],
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
}
|
|
447
|
+
]
|
|
448
|
+
msgs = [
|
|
449
|
+
{"role": "user", "content": "查北京天气"},
|
|
450
|
+
{
|
|
451
|
+
"role": "assistant",
|
|
452
|
+
"reasoning": "应先调用 get_weather 获取实时数据。",
|
|
453
|
+
"content": "我来查一下。",
|
|
454
|
+
},
|
|
455
|
+
{"role": "user", "content": "那上海呢?"},
|
|
456
|
+
]
|
|
457
|
+
plain = inject_fncall(msgs, tools, proto)[0]["content"]
|
|
458
|
+
assert "应先调用 get_weather" not in plain
|
|
459
|
+
|
|
460
|
+
with_history = inject_fncall(
|
|
461
|
+
msgs,
|
|
462
|
+
tools,
|
|
463
|
+
proto,
|
|
464
|
+
protocol_options={"include_thinking_in_history": True},
|
|
465
|
+
)[0]["content"]
|
|
466
|
+
assert "<entml:thinking>" in with_history
|
|
467
|
+
assert "应先调用 get_weather 获取实时数据。" in with_history
|
|
468
|
+
assert "那上海呢?" in with_history
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{echotools-2.3.29 → echotools-2.3.30}/src/echotools/exec/fncall/protocols/entml_thinking_parse.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/components/filezone.js
RENAMED
|
File without changes
|
{echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/components/motionkit.js
RENAMED
|
File without changes
|
{echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/components/sendbutton.js
RENAMED
|
File without changes
|
{echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/components/sortablelist.css
RENAMED
|
File without changes
|
{echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/components/sortablelist.js
RENAMED
|
File without changes
|
{echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/components/textinput.js
RENAMED
|
File without changes
|
{echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/components/voiceinput.js
RENAMED
|
File without changes
|
{echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/fonts/inter-500.woff2
RENAMED
|
File without changes
|
{echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/fonts/inter-600.woff2
RENAMED
|
File without changes
|
{echotools-2.3.29 → echotools-2.3.30}/src/echotools/media/web/input_box/fonts/inter400.woff2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|