Fix tool-call loop leaks, raise step cap, add message queueing - #6
Merged
Merged
Conversation
- core/workspace_tools.py: tolerate stray whitespace in <motion_tool> tags,
recognize the <| DSML | tool:NAME> channel leak from deepseek-v4-flash, and
add a general fallback guard so any unrecognized envelope wrapping
tool-call-shaped JSON is treated as malformed (and retried) instead of
leaking raw JSON to the user as a final answer.
- main.py: raise the per-turn tool-call cap (MAX_TOOL_STEPS) from a tight
limit to a generous safety ceiling (150) intended only to catch a truly
stuck model; report whatever progress was made instead of discarding it
when the cap is hit; stream progress for every tool op (not just writes)
so the UI can show live step-by-step activity for the whole loop.
- ui/tui.py:
- New asks start in read-only "plan" mode (discuss first); an explicit
build-trigger phrase or Tab switches to "build" mode.
- Plan-mode instructions no longer demand writes; the model is nudged to
produce a concrete plan instead of punting back to the user.
- Add StepsMessage: always-visible live tool-activity feed in chat (no
toggle required), separate from the opt-in "thinking" view.
- Messages submitted while the agent is busy are now queued instead of
cancelling the in-flight worker (@work(exclusive=True) would otherwise
kill it); the same worker drains the queue once its current turn ends.
- memory/db.py, memory/retriever.py: fix inverted cosine-distance ranking in
the sqlite-vec path, skip zero-norm embeddings instead of crashing, add a
minimum relevance threshold, and unconditional recall de-duplication.
- core/learning.py: SkillSynthesizer now computes a real (or hash-fallback)
embedding instead of a hardcoded zero vector.
- core/config.py, core/learning.py, core/orchestrator.py, install.sh: anchor
the harness's own persistent state (config, memory DB, skills) to the
install directory (REPO_DIR) instead of CWD, so `motion` can be invoked
from any workspace directory without losing track of its own state.
- docs/cli.md, docs/architecture.md, docs/roadmap.md: document the CLI/auth
flow and note which orchestration features aren't yet wired into the TUI.
Co-Authored-By: Warp <agent@warp.dev>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a recurring bug where malformed/unrecognized tool-call tags leaked raw JSON into the chat instead of executing, raises the agent loop's tool-call safety cap, and adds message queueing + live step visibility so long-running builds don't get silently cut off.
Changes
core/workspace_tools.py): tolerate stray whitespace in<motion_tool>tags, recognize the<| DSML | tool:NAME>channel leak observed from deepseek-v4-flash, and add a general fallback guard so any unrecognized envelope wrapping tool-call-shaped JSON is treated as malformed (triggering a retry) instead of being shown to the user as the final answer.main.py): raisedMAX_TOOL_STEPSfrom a tight limit to a generous safety ceiling (150), intended only to catch a truly stuck model rather than cap legitimate multi-file builds. If it's ever hit, completed work is reported instead of discarded. Every tool op (not just writes) now streams progress.ui/tui.py):StepsMessage: an always-visible live tool-activity feed in chat, separate from the opt-in "thinking" view.memory/db.py,memory/retriever.py,core/learning.py): fixed inverted cosine-distance ranking in the sqlite-vec path, skip zero-norm embeddings instead of crashing, added a minimum relevance threshold, unconditional recall de-duplication, andSkillSynthesizernow computes a real (or hash-fallback) embedding instead of a hardcoded zero vector.core/config.py,core/learning.py,core/orchestrator.py,install.sh): anchor the harness's own persistent state (config, memory DB, skills) to its install directory instead of CWD, somotioncan be invoked from any workspace directory without losing track of its own state.docs/cli.md, updateddocs/architecture.md/docs/roadmap.md.Testing
Full test suite passes locally:
PYTHONPATH=. .venv/bin/pytest tests/ -q→ 66 passed.Co-Authored-By: Warp agent@warp.dev