From f3b657d5b22fd0738cee1a3e582a7c13865da5fa Mon Sep 17 00:00:00 2001 From: Korivi Date: Mon, 30 Mar 2026 12:46:27 +0900 Subject: [PATCH 01/47] updated minor missing logics in the agent_base and event_stream Issues: - The broken loop: LLM call fails. - Error handler logs: missing the re-queues the task trigger. - The agent picks up the wrong trigger, so it tries LLM again and fails again, and repeats forever (infinite spam). --------------------- Updated: Fix 1: First few failures (up to 5) The LLMInterface tracks consecutive failures. Each failure increments a counter. The error propagates normally; avoid spam call's. Fix 2: up to 5th consecutive failure LLMConsecutiveFailureError is raised. The agent catches it in _handle_react_error. Fix3: Task is cancelled, NOT re-queued Instead of scheduling another retry trigger, it calls mark_task_cancel(). The loop stops completely. One final error message is shown in the chat1.... Fix4: Event stream stays quiet If the LLM was also failing during event summarization (filling logs), the fallback now prunes the old events anyway , then summarize_if_needed() stops triggering on every log() call. --- .../core/impl/event_stream/event_stream.py | 12 +++++++++++- app/agent_base.py | 18 ++++++++++++++++-- app/config/settings.json | 2 +- .../browser/frontend/package-lock.json | 10 ++++++++++ 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/agent_core/core/impl/event_stream/event_stream.py b/agent_core/core/impl/event_stream/event_stream.py index 323a242d..7603da49 100644 --- a/agent_core/core/impl/event_stream/event_stream.py +++ b/agent_core/core/impl/event_stream/event_stream.py @@ -303,7 +303,17 @@ def summarize_by_LLM(self) -> None: logger.info(f"[EventStream] Summarization complete. Tokens: {self._total_tokens}") except Exception: - logger.exception("[EventStream] LLM summarization failed. Keeping all events without summarization.") + logger.exception( + "[EventStream] LLM summarization failed. " + "Pruning oldest events without a summary to prevent retry spam." + ) + # Fallback: drop the oldest chunk without generating a summary so that + # _total_tokens falls below the threshold. Without this, every subsequent + # log() call would immediately re-trigger summarization and flood the logs. + removed_tokens = sum(get_cached_token_count(r) for r in chunk) + self._total_tokens -= removed_tokens + self.tail_events = self.tail_events[cutoff:] + self._session_sync_points.clear() # ───────────────────── utilities ───────────────────── diff --git a/app/agent_base.py b/app/agent_base.py index 206b9dc1..b5abae9e 100644 --- a/app/agent_base.py +++ b/app/agent_base.py @@ -49,7 +49,7 @@ from app.internal_action_interface import InternalActionInterface from app.llm import LLMInterface, LLMCallType -from agent_core.core.impl.llm.errors import classify_llm_error +from agent_core.core.impl.llm.errors import classify_llm_error, LLMConsecutiveFailureError from app.vlm_interface import VLMInterface from app.database_interface import DatabaseInterface from app.logger import logger @@ -1208,6 +1208,9 @@ async def _handle_react_error( # Get user-friendly error message user_message = classify_llm_error(error) + # Fatal LLM errors must not re-queue the task - that causes infinite retry loops + is_fatal_llm_error = isinstance(error, LLMConsecutiveFailureError) + try: logger.debug("[REACT ERROR] Logging to event stream") self.event_stream_manager.log( @@ -1217,7 +1220,18 @@ async def _handle_react_error( task_id=session_to_use, ) self.state_manager.bump_event_stream() - await self._create_new_trigger(session_to_use, action_output, STATE) + if is_fatal_llm_error: + # Cancel the task instead of re-queueing to prevent infinite retries + logger.warning( + f"[REACT ERROR] LLMConsecutiveFailureError detected - cancelling task {session_to_use} " + "to prevent infinite retry loop." + ) + if self.task_manager: + await self.task_manager.mark_task_cancel( + reason="LLM calls failed too many consecutive times. Task aborted." + ) + else: + await self._create_new_trigger(session_to_use, action_output, STATE) except Exception as e: logger.error( "[REACT ERROR] Failed to log to event stream or create trigger", diff --git a/app/config/settings.json b/app/config/settings.json index 01fe2b83..33662852 100644 --- a/app/config/settings.json +++ b/app/config/settings.json @@ -19,7 +19,7 @@ "openai": "", "anthropic": "", "google": "", - "byteplus": "" + "byteplus": "6aa60576-c6ef-4835-a77a-f7e51d0637ef" }, "endpoints": { "remote_model_url": "", diff --git a/app/ui_layer/browser/frontend/package-lock.json b/app/ui_layer/browser/frontend/package-lock.json index a07a2ab8..b1650464 100644 --- a/app/ui_layer/browser/frontend/package-lock.json +++ b/app/ui_layer/browser/frontend/package-lock.json @@ -61,6 +61,7 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -1457,6 +1458,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", "license": "MIT", + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.2.2" @@ -1518,6 +1520,7 @@ "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", @@ -1704,6 +1707,7 @@ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1854,6 +1858,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -2192,6 +2197,7 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -4233,6 +4239,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -4245,6 +4252,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -4741,6 +4749,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -4911,6 +4920,7 @@ "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", From 6011a6742cd491c58e6ac84126590367ac19394e Mon Sep 17 00:00:00 2001 From: Korivi Date: Mon, 30 Mar 2026 13:14:16 +0900 Subject: [PATCH 02/47] Node.js Stuck bug Fix I noticed that Node.js sometimes gets stuck at 1/8, most likely due to intermittent hanging. This can occasionally block execution in certain terminal environments (like the VS Code terminal). So I added an handling "stdin=subprocess.DEVNULL," to prevent console blocking during process creation. This helps bypass issues when running Node.js and other CraftBot terminal processes during installation and runtime. --- run.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/run.py b/run.py index c9eedd2f..37b8ac5e 100644 --- a/run.py +++ b/run.py @@ -492,13 +492,19 @@ def launch_frontend(silent: bool = False) -> Optional[subprocess.Popen]: try: # Start frontend in background # Redirect output to DEVNULL to prevent blocking when buffer fills - process = subprocess.Popen( - cmd, + # Redirect stdin to DEVNULL so npm/vite never blocks waiting for input + popen_kwargs = dict( cwd=FRONTEND_DIR, + stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, env=os.environ.copy(), ) + if sys.platform == "win32": + # CREATE_NO_WINDOW prevents the subprocess from trying to attach to + # the parent console, which can cause intermittent hangs on Windows + popen_kwargs["creationflags"] = subprocess.CREATE_NO_WINDOW + process = subprocess.Popen(cmd, **popen_kwargs) _background_processes.append(process) return process except FileNotFoundError: From b4897ba05c56f3ca3233101e9e9b85ab7bb2f9ef Mon Sep 17 00:00:00 2001 From: ahmad-ajmal Date: Mon, 30 Mar 2026 10:37:15 +0100 Subject: [PATCH 03/47] fix schedule task import + details to schedule task desc --- app/data/action/schedule_task.py | 44 ++++++++++++++++++++++++-- app/data/action/scheduled_task_list.py | 3 +- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/app/data/action/schedule_task.py b/app/data/action/schedule_task.py index 4977ca59..abfa7c76 100644 --- a/app/data/action/schedule_task.py +++ b/app/data/action/schedule_task.py @@ -14,7 +14,17 @@ @action( name="schedule_task", - description="Schedule a task for execution. Supports immediate execution, one-time scheduled tasks, and recurring schedules. One-time tasks are auto-removed after firing.", + description=( + "Schedule a task for execution. Supports immediate, one-time, and recurring schedules. " + "One-time tasks are auto-removed after firing.\n" + "IMPORTANT: The 'schedule' field must use one of these EXACT formats:\n" + "- Immediate: 'immediate'\n" + "- One-time: 'at 3pm', 'at 3:30pm', 'at 3:30pm today', 'tomorrow at 9am', 'in 2 hours', 'in 30 minutes'\n" + "- Recurring: 'every day at 7am', 'every day at 3:30pm', 'every monday at 9am', " + "'every 3 hours', 'every 30 minutes', or cron like '0 7 * * *'\n" + "DO NOT use: 'daily at', 'every weekday', 'every morning', 'weekly', or other freeform text. " + "Only the exact patterns listed above are supported." + ), action_sets=["scheduler", "core", "proactive"], input_schema={ "name": { @@ -29,8 +39,20 @@ }, "schedule": { "type": "string", - "description": "Schedule expression. Immediate: 'immediate'. One-time: 'at 3pm', 'at 3:30pm today', 'tomorrow at 9am', 'in 2 hours', 'in 30 minutes'. Recurring: 'every day at 7am', 'every monday at 9am', 'every 3 hours', 'every 30 minutes', or cron '0 7 * * *'", - "example": "at 3pm" + "description": ( + "Schedule expression. Must match one of these exact patterns:\n" + "- 'immediate' — execute right now\n" + "- 'at