mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
fix(copilot): sandbox kill, tool event logging, and background task UX
- Fix sandbox process kill: use start_new_session + os.killpg to kill the entire bwrap process group on timeout (proc.kill alone only kills the parent, leaving children running until natural completion) - Add StreamToolInputAvailable/StreamToolOutputAvailable to publish_chunk logging filter so tool events are visible in Docker logs - Add system prompt instruction telling Claude not to use run_in_background on Task tool (gets denied by security hooks) - Add tool event debug logging in SDK streaming loop for tracing tool execution visibility issues
This commit is contained in:
@@ -100,6 +100,8 @@ _SDK_TOOL_SUPPLEMENT = """
|
||||
- Long-running tools (create_agent, edit_agent, etc.) are handled
|
||||
asynchronously. You will receive an immediate response; the actual result
|
||||
is delivered to the user via a background stream.
|
||||
- When using the Task tool, NEVER set `run_in_background` to true.
|
||||
All tasks must run in the foreground.
|
||||
"""
|
||||
|
||||
|
||||
@@ -680,6 +682,17 @@ async def stream_chat_completion_sdk(
|
||||
if isinstance(response, StreamStart):
|
||||
continue
|
||||
|
||||
# Log tool events for debugging visibility issues
|
||||
if isinstance(
|
||||
response,
|
||||
(StreamToolInputAvailable, StreamToolOutputAvailable),
|
||||
):
|
||||
logger.info(
|
||||
"[SDK] Tool event: %s, tool=%s",
|
||||
type(response).__name__,
|
||||
getattr(response, "toolName", "N/A"),
|
||||
)
|
||||
|
||||
yield response
|
||||
|
||||
if isinstance(response, StreamTextDelta):
|
||||
|
||||
@@ -227,7 +227,14 @@ async def publish_chunk(
|
||||
# Only log timing for significant chunks or slow operations
|
||||
if (
|
||||
chunk_type
|
||||
in ("StreamStart", "StreamFinish", "StreamTextStart", "StreamTextEnd")
|
||||
in (
|
||||
"StreamStart",
|
||||
"StreamFinish",
|
||||
"StreamTextStart",
|
||||
"StreamTextEnd",
|
||||
"StreamToolInputAvailable",
|
||||
"StreamToolOutputAvailable",
|
||||
)
|
||||
or total_time > 50
|
||||
):
|
||||
logger.info(
|
||||
|
||||
@@ -13,6 +13,7 @@ import logging
|
||||
import os
|
||||
import platform
|
||||
import shutil
|
||||
import signal
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -245,6 +246,7 @@ async def run_sandboxed(
|
||||
stderr=asyncio.subprocess.PIPE,
|
||||
cwd=cwd,
|
||||
env=safe_env,
|
||||
start_new_session=True, # Own process group for clean kill
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -255,7 +257,13 @@ async def run_sandboxed(
|
||||
stderr = stderr_bytes.decode("utf-8", errors="replace")
|
||||
return stdout, stderr, proc.returncode or 0, False
|
||||
except asyncio.TimeoutError:
|
||||
proc.kill()
|
||||
# Kill entire process group (bwrap + all children).
|
||||
# proc.kill() alone only kills the bwrap parent, leaving
|
||||
# children running until they finish naturally.
|
||||
try:
|
||||
os.killpg(proc.pid, signal.SIGKILL)
|
||||
except ProcessLookupError:
|
||||
pass # Already exited
|
||||
await proc.communicate()
|
||||
return "", f"Execution timed out after {timeout}s", -1, True
|
||||
|
||||
|
||||
Reference in New Issue
Block a user