Merge pull request #1531 from DaTweety/fix/mcp-edit-output-tail

qet MCP: keep the edit script's report lines when cutting long output
This commit is contained in:
ispyisail
2026-10-19 16:21:43 +13:00
committed by GitHub
2 changed files with 35 additions and 1 deletions
+18 -1
View File
@@ -1072,6 +1072,23 @@ def _user_collections() -> dict:
return found
def _keep_tail(text: str, tail: int) -> str:
"""The last `tail` characters of a run's output, but every line an edit
script reported through its marker kept whole, wherever it stands.
A large qet_edit logs far more than `tail` characters; cut from the
front, it lost the capability report the script makes first, and the
tool then said the binary had never run the script."""
if len(text) <= tail:
return text
marked = [ln for ln in text.splitlines() if "QETEDIT " in ln]
rest = text[-tail:]
if not marked:
return rest
kept = set(rest.splitlines())
return "\n".join([ln for ln in marked if ln not in kept] + [rest])
def _run_qet(binary: str, args: list[str], timeout: int = 180,
elements_dir: str | None = None,
script: str | None = None, tail: int = 4000,
@@ -1150,7 +1167,7 @@ def _run_qet(binary: str, args: list[str], timeout: int = 180,
"hint": "a modal dialog during load will hang a headless "
"run; check the project's format version"}
result = {"ok": p.returncode == 0, "exit_code": p.returncode,
"stdout": p.stdout[-tail:], "stderr": p.stderr[-tail:]}
"stdout": _keep_tail(p.stdout, tail), "stderr": _keep_tail(p.stderr, tail)}
# QElectroTech refuses --run when scripting is switched off, which
# it is by default. Its own message is clear but French, and it
# names a settings dialog that nobody driving this server is
+17
View File
@@ -6673,6 +6673,23 @@ class ZippedProjects(unittest.TestCase):
self.assertNotEqual(*rotated[0]["orientation"])
class TestKeepTail(unittest.TestCase):
"""A large edit logs more than the kept tail; the script's own report
lines must survive the cut, or qet_edit says the script never ran."""
def test_short_output_is_untouched(self):
self.assertEqual(m._keep_tail("a\nb", 100), "a\nb")
def test_marker_lines_survive_the_cut(self):
first = 'QETEDIT {"kind": "capabilities", "missing": []}'
text = first + "\n" + "x" * 1000 + "\n" + 'QETEDIT {"kind": "save", "result": true}'
kept = m._keep_tail(text, 100)
self.assertIn(first, kept)
self.assertIn('"kind": "save"', kept)
self.assertEqual(kept.count('"kind": "save"'), 1)
self.assertEqual(m._parse_script_output(kept).get("missing_methods"), [])
if __name__ == "__main__":
print(f"binary : {BINARY or '(none: integration tests skipped)'}")
print(f"elements : {ELEMENTS or '(none)'}")