fix(tools): drop a materialized foreground terminal heartbeat - #119203
liuhao1024 wants to merge 1 commit into
Conversation
Providers that materialize every advertised property send heartbeat=60 (the schema minimum) on ordinary foreground terminal calls; the handler refused them, looping the model on a validation error (or baiting it into background=true for short commands). Heartbeat only rides a tracked background process, so a foreground value has no meaning — normalize it away and keep the teaching rejection for notify/watch_patterns. Fixes NousResearch#119196
|
Withdrawing this PR in favor of #119201, which was opened ~6 minutes earlier and implements the same mechanism: dropping Two small deltas from my verification pass that #119201 may want to absorb:
For the maintainers: #119202 (schema |
|
Closing in favor of #119201 (earlier, same mechanism). Notes for the maintainers are in my comment above. |
What does this PR do?
Providers that materialize every advertised tool-schema property send
heartbeat=60(the schemaminimum) on ordinary foregroundterminalcalls. The dispatch wrapper refused those calls before execution ("notify/heartbeat only apply to background commands..."), so the model looped on the same rejected call — or followed the error'sbackground=truesuggestion and flooded short commands with completion notifications (#119196).heartbeatonly rides a tracked background process's completion delivery path; a foreground value has no execution meaning. This PR normalizes it away on foreground calls instead of rejecting: the materialized full-schema shape (background=false, notify=false, heartbeat=60, pty=false) now executes once in the foreground with no tracked process and no notification arming. The teaching rejection fornotify/watch_patterns/notify_on_completeon foreground calls is preserved (those are opt-in notification intent, not mechanically materialized values), and background heartbeat behavior is untouched.Related Issue
Fixes #119196
Type of Change
Changes Made
tools/terminal_tool.py: in_handle_terminal, dropheartbeatto0whenbackgroundis false instead of including it in the foreground rejection condition; update the rejection message (now "notify only applies...") and the surrounding comment to match.tests/tools/test_process_heartbeat.py: rework the dispatch invariant test — the full materialized foreground shape now must execute once withheartbeat=0/notify_on_complete=False/nowatch_patterns, while the backgroundheartbeat→notify_on_complete=Truemapping is unchanged.How to Test
Before:
d["error"]is the "notify/heartbeat only apply to background commands" validation error. After:d["error"]isNone,d["exit_code"] == 0— the command executes once in the foreground (observed result:exit_code=0,output=/private/tmp/...).2. Foreground
notify=Trueis still refused with the corrected-call teaching error (observed:"notify only applies to background commands (foreground results return directly). Either drop it, or run as terminal(command=..., background=true, notify=...).").3. Background heartbeat is unchanged:
{"command": "sleep 1", "background": True, "heartbeat": 120}spawns a tracked process (observed:session_id=proc_...) and the dispatch test assertsheartbeat=120+notify_on_complete=True.4.
pytest tests/tools/test_process_heartbeat.py tests/tools/test_notify_on_complete.py tests/tools/test_watch_patterns.py tests/tools/test_terminal_tool.py -q→ 60 passed, 1 skipped (linux-only case).5.
pytest tests/tools/ -k terminal tests/tools/test_code_execution.py -q→ 395 passed, 2 skipped;pytest tests/tools/test_code_execution.py -q→ 44 passed.ruff checkon both changed files passes.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests pass (full terminal/process/code-execution surfaces intests/tools/as listed under How to Test)Documentation & Housekeeping
docs/, docstrings) — N/A (comment updated in place)cli-config.yaml.exampleif I added/changed config keys — N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — N/A