code exec reset polish, history and scroller fix

frdel committed Feb 5, 2026 at 16:47 UTC 153f0a50230ccb026485e61726ccce9d68c99c4c
4 files changed +43 -27
prompts/agent.system.tool.code_exe.md
+31 -22
@@ -2,10 +2,11 @@
2
3 execute terminal commands python nodejs code for computation or software tasks
4 place code in "code" arg; escape carefully and indent properly
5 -select "runtime" arg: "terminal" "python" "nodejs" "output" "reset"
5 +select "runtime" arg: "terminal" "python" "nodejs" "output"
6 select "session" number, 0 default, others for multitasking
7 -if code runs long, use "output" to wait, "reset" to kill process
8 -use "pip" "npm" "apt-get" in "terminal" to install packages
7 +if code runs long, use runtime "output" to wait
8 +use reset true on next call to kill previous process when stuck default false
9 +use "pip" "npm" "apt-get" in "terminal" to install package
10 to output, use print() or console.log()
11 if tool outputs error, adjust code before retrying;
12 important: check code for placeholders or demo data; replace with real variables; don't reuse snippets
@@ -14,67 +15,75 @@ check dependencies before running code
15 output may end with [SYSTEM: ...] information comming from framework, not terminal
16 usage:
17
17 -1 execute python code
18
19 +1 execute terminal command
20 ~~~json
21 {
22 "thoughts": [
23 "Need to do...",
23 - "I can use...",
24 - "Then I can...",
24 + "Need to install...",
25 ],
26 - "headline": "Executing Python code to check current directory",
26 + "headline": "Installing zip package via terminal",
27 "tool_name": "code_execution_tool",
28 "tool_args": {
29 - "runtime": "python",
29 + "runtime": "terminal",
30 "session": 0,
31 - "code": "import os\nprint(os.getcwd())",
31 + "reset": false,
32 + "code": "apt-get install zip",
33 }
34 }
35 ~~~
36
36 -2 execute terminal command
37 +2 execute python code
38 +
39 ~~~json
40 {
41 "thoughts": [
42 "Need to do...",
41 - "Need to install...",
43 + "I can use...",
44 + "Then I can...",
45 ],
43 - "headline": "Installing zip package via terminal",
46 + "headline": "Executing Python code to check current directory",
47 "tool_name": "code_execution_tool",
48 "tool_args": {
46 - "runtime": "terminal",
49 + "runtime": "python",
50 "session": 0,
48 - "code": "apt-get install zip",
51 + "reset": false,
52 + "code": "import os\nprint(os.getcwd())",
53 }
54 }
55 ~~~
56
53 -2.1 wait for output with long-running scripts
57 +3 execute nodejs code
58 +
59 ~~~json
60 {
61 "thoughts": [
57 - "Waiting for program to finish...",
62 + "Need to do...",
63 + "I can use...",
64 + "Then I can...",
65 ],
59 - "headline": "Waiting for long-running program to complete",
66 + "headline": "Executing Javascript code to check current directory",
67 "tool_name": "code_execution_tool",
68 "tool_args": {
62 - "runtime": "output",
69 + "runtime": "nodejs",
70 "session": 0,
71 + "reset": false,
72 + "code": "console.log(process.cwd());",
73 }
74 }
75 ~~~
76
68 -2.2 reset terminal
77 +4 wait for output with long-running scripts
78 ~~~json
79 {
80 "thoughts": [
72 - "code_execution_tool not responding...",
81 + "Waiting for program to finish...",
82 ],
74 - "headline": "Resetting unresponsive terminal session",
83 + "headline": "Waiting for long-running program to complete",
84 "tool_name": "code_execution_tool",
85 "tool_args": {
77 - "runtime": "reset",
86 + "runtime": "output",
87 "session": 0,
88 }
89 }
python/helpers/history.py
+1 -1
@@ -521,7 +521,7 @@ def output_langchain(messages: list[OutputMessage]):
521 for m in messages:
522 content = _output_content_langchain(content=m["content"])
523 if not content or (isinstance(content, str) and not content.strip()):
524 - continue
524 + continue # skip empty messages, models
525 if m["ai"]:
526 result.append(AIMessage(content)) # type: ignore
527 else:
python/tools/code_execution_tool.py
+4 -3
@@ -64,18 +64,19 @@ class CodeExecution(Tool):
64 runtime = self.args.get("runtime", "").lower().strip()
65 session = int(self.args.get("session", 0))
66 self.allow_running = bool(self.args.get("allow_running", False))
67 + reset = bool(self.args.get("reset", False) or runtime == "reset")
68
69 if runtime == "python":
70 response = await self.execute_python_code(
70 - code=self.args["code"], session=session
71 + code=self.args["code"], session=session, reset=reset
72 )
73 elif runtime == "nodejs":
74 response = await self.execute_nodejs_code(
74 - code=self.args["code"], session=session
75 + code=self.args["code"], session=session, reset=reset
76 )
77 elif runtime == "terminal":
78 response = await self.execute_terminal_command(
78 - command=self.args["code"], session=session
79 + command=self.args["code"], session=session, reset=reset
80 )
81 elif runtime == "output":
82 response = await self.get_terminal_output(
webui/js/scroller.js
+7 -1
@@ -49,7 +49,13 @@ export class Scroller {
49 const delta = nextHeight - prevHeight;
50 this._lastClientHeight = nextHeight;
51
52 - if (this.wasAtBottom) {
52 + const scrollTop = this._getEffectiveScrollTop();
53 + const bottomDistanceBefore =
54 + this.element.scrollHeight - scrollTop - prevHeight;
55 + const wasAtBottom = bottomDistanceBefore <= this.tolerance;
56 + this.wasAtBottom = wasAtBottom;
57 +
58 + if (wasAtBottom) {
59 this.scrollToBottom();
60 return;
61 }