From afbd04b5d62a890984764cc67efcb2c4ff67b4fe Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Tue, 27 Jan 2026 22:48:40 +1100 Subject: [PATCH 1/7] debug --- crates/goose/src/agents/subagent_handler.rs | 18 + .../goose/src/providers/formats/anthropic.rs | 16 + scripts/test_compaction.sh | 413 ++++++++++-------- 3 files changed, 259 insertions(+), 188 deletions(-) diff --git a/crates/goose/src/agents/subagent_handler.rs b/crates/goose/src/agents/subagent_handler.rs index 54e0d2dab827..c2683421894d 100644 --- a/crates/goose/src/agents/subagent_handler.rs +++ b/crates/goose/src/agents/subagent_handler.rs @@ -186,7 +186,22 @@ fn get_agent_messages( .reply(user_message, session_config, cancellation_token) .await .map_err(|e| anyhow!("Failed to get reply from agent: {}", e))?; + + // Stream diagnostics for debugging hangs + let mut event_count = 0u64; + let stream_start = std::time::Instant::now(); + let mut last_event_time = stream_start; + tracing::info!(target: "stream_diag", "[STREAM] subagent: starting to consume agent events"); + while let Some(message_result) = stream.next().await { + event_count += 1; + let now = std::time::Instant::now(); + let since_last = now.duration_since(last_event_time); + if since_last.as_secs() >= 5 { + tracing::warn!(target: "stream_diag", "[STREAM] subagent: event #{} after {:.1}s delay", event_count, since_last.as_secs_f64()); + } + last_event_time = now; + match message_result { Ok(AgentEvent::Message(msg)) => conversation.push(msg), Ok(AgentEvent::McpNotification(_)) | Ok(AgentEvent::ModelChange { .. }) => {} @@ -200,6 +215,9 @@ fn get_agent_messages( } } + let total_duration = stream_start.elapsed(); + tracing::info!(target: "stream_diag", "[STREAM] subagent: stream ended after {} events in {:.1}s", event_count, total_duration.as_secs_f64()); + let final_output = if has_response_schema { agent .final_output_tool diff --git a/crates/goose/src/providers/formats/anthropic.rs b/crates/goose/src/providers/formats/anthropic.rs index 7e3dd161515a..61d6622563ff 100644 --- a/crates/goose/src/providers/formats/anthropic.rs +++ b/crates/goose/src/providers/formats/anthropic.rs @@ -494,7 +494,20 @@ where let mut final_usage: Option = None; let mut message_id: Option = None; + // Stream diagnostics for debugging hangs + let mut chunk_count = 0u64; + let stream_start = std::time::Instant::now(); + let mut last_chunk_time = stream_start; + tracing::info!(target: "stream_diag", "[STREAM] anthropic: starting stream consumption"); + while let Some(line_result) = stream.next().await { + chunk_count += 1; + let now = std::time::Instant::now(); + let since_last = now.duration_since(last_chunk_time); + if since_last.as_secs() >= 5 { + tracing::warn!(target: "stream_diag", "[STREAM] anthropic: chunk #{} after {:.1}s delay", chunk_count, since_last.as_secs_f64()); + } + last_chunk_time = now; let line = line_result?; // Skip empty lines and non-data lines @@ -696,6 +709,9 @@ where } } + let total_duration = stream_start.elapsed(); + tracing::info!(target: "stream_diag", "[STREAM] anthropic: stream ended after {} chunks in {:.1}s", chunk_count, total_duration.as_secs_f64()); + // Yield final usage information if available if let Some(usage) = final_usage { yield (None, Some(usage)); diff --git a/scripts/test_compaction.sh b/scripts/test_compaction.sh index baa3b7ca9660..ef95556bcb3f 100755 --- a/scripts/test_compaction.sh +++ b/scripts/test_compaction.sh @@ -19,6 +19,43 @@ fi SCRIPT_DIR=$(pwd) GOOSE_BIN="$SCRIPT_DIR/target/release/goose" +# Timeout for goose commands (default 5 minutes) +GOOSE_TIMEOUT=${GOOSE_TIMEOUT:-300} + +# Log directory for diagnostics +LOG_DIR="$HOME/.config/goose/logs/cli" + +# Helper to dump stream diagnostics from logs on timeout +dump_stream_diagnostics() { + echo "" + echo "=== STREAM DIAGNOSTICS (last 50 entries) ===" + if [ -d "$LOG_DIR" ]; then + # Find logs from the last 10 minutes and grep for stream_diag + find "$LOG_DIR" -name "*.log" -mmin -10 -exec grep -h "stream_diag" {} \; 2>/dev/null | tail -50 + else + echo "No log directory found at $LOG_DIR" + fi + echo "=== END STREAM DIAGNOSTICS ===" + echo "" +} + +# Helper to run goose with timeout and stream diagnostics enabled +run_goose() { + local exit_code=0 + # Enable stream_diag target for our diagnostic logs + RUST_LOG="${RUST_LOG:-stream_diag=info}" timeout "$GOOSE_TIMEOUT" "$GOOSE_BIN" "$@" 2>&1 || exit_code=$? + + if [ $exit_code -eq 124 ] || [ $exit_code -eq 137 ]; then + echo "" + echo "⚠️ TIMEOUT: goose command exceeded ${GOOSE_TIMEOUT}s limit" + fi + + # Always dump stream diagnostics to help debug issues + dump_stream_diagnostics + + return $exit_code +} + # Validation function to check compaction structure in session JSON validate_compaction() { local session_id=$1 @@ -102,7 +139,7 @@ echo "" OUTPUT=$(mktemp) echo "Step 1: Creating session with initial messages..." -(cd "$TESTDIR" && "$GOOSE_BIN" run --text "list files and read hello.txt" 2>&1) | tee "$OUTPUT" +(cd "$TESTDIR" && run_goose run --text "list files and read hello.txt") | tee "$OUTPUT" if ! command -v jq &> /dev/null; then echo "✗ FAILED: jq is required for this test" @@ -121,7 +158,7 @@ else echo "Step 2: Sending manual compaction trigger..." # Send the manual compact trigger prompt - (cd "$TESTDIR" && "$GOOSE_BIN" run --resume --session-id "$SESSION_ID" --text "Please compact this conversation" 2>&1) | tee -a "$OUTPUT" + (cd "$TESTDIR" && run_goose run --resume --session-id "$SESSION_ID" --text "Please compact this conversation") | tee -a "$OUTPUT" echo "" echo "Checking for compaction evidence..." @@ -147,192 +184,192 @@ fi echo "" echo "" -# ================================================== -# TEST 2: Auto Compaction -# ================================================== -echo "---------------------------------------------------" -echo "TEST 2: Auto Compaction via threshold (0.005)" -echo "---------------------------------------------------" - -TESTDIR=$(mktemp -d) -echo "test content" > "$TESTDIR/test.txt" -echo "Test directory: $TESTDIR" -echo "" - -# Set auto-compact threshold very low (.5%) to trigger it quickly -export GOOSE_AUTO_COMPACT_THRESHOLD=0.005 - -OUTPUT=$(mktemp) - -LONG_RESPONSE_PROMPT="Count from 1 to 200, one number per line." - -echo "Step 1: Creating session with first message (generating tokens for threshold)..." -(cd "$TESTDIR" && "$GOOSE_BIN" run --text "$LONG_RESPONSE_PROMPT" 2>&1) | tee "$OUTPUT" - -if ! command -v jq &> /dev/null; then - echo "✗ FAILED: jq is required for this test" - RESULTS+=("✗ Auto Compaction (jq required)") -else - SESSION_ID=$("$GOOSE_BIN" session list --format json 2>/dev/null | jq -r '.[0].id' 2>/dev/null) - - if [ -z "$SESSION_ID" ] || [ "$SESSION_ID" = "null" ]; then - echo "✗ FAILED: Could not create session" - RESULTS+=("✗ Auto Compaction (no session)") - else - echo "" - echo "Session created: $SESSION_ID" - echo "Step 2: Sending second message (should trigger auto-compact)..." - - # Send second message - auto-compaction should trigger before processing this - (cd "$TESTDIR" && "$GOOSE_BIN" run --resume --session-id "$SESSION_ID" --text "hi again" 2>&1) | tee -a "$OUTPUT" - - echo "" - echo "Checking for auto-compaction evidence..." - - if grep -qi "auto.*compact\|exceeded.*auto.*compact.*threshold" "$OUTPUT"; then - echo "✓ SUCCESS: Auto compaction was triggered" - - if validate_compaction "$SESSION_ID" "auto compaction"; then - RESULTS+=("✓ Auto Compaction") - else - RESULTS+=("✗ Auto Compaction (structure validation failed)") - fi - else - echo "✗ FAILED: Auto compaction was not triggered" - echo " Expected to see auto-compact messages with threshold of 0.005" - RESULTS+=("✗ Auto Compaction") - fi - fi -fi - -# Unset the env variable -unset GOOSE_AUTO_COMPACT_THRESHOLD - -rm -f "$OUTPUT" -rm -rf "$TESTDIR" - -echo "" -echo "" - -# ================================================== -# TEST 3: Out-of-Context Error Compaction -# ================================================== -echo "---------------------------------------------------" -echo "TEST 3: Compaction via out-of-context error (proxy)" -echo "---------------------------------------------------" - -TESTDIR=$(mktemp -d) -echo "test content" > "$TESTDIR/test.txt" -echo "Test directory: $TESTDIR" -echo "" - -# Use a random port to avoid conflicts -PROXY_PORT=$((9000 + RANDOM % 1000)) -PROXY_DIR="$SCRIPT_DIR/scripts/provider-error-proxy" - -OUTPUT=$(mktemp) -PROXY_LOG=$(mktemp) -PROXY_SETUP_LOG=$(mktemp) - -# Pre-install proxy dependencies (so first run doesn't take forever) -echo "Installing proxy dependencies..." -export UV_INDEX_URL="https://pypi.org/simple" -if ! (cd "$PROXY_DIR" && uv sync 2>&1 | tee "$PROXY_SETUP_LOG"); then - echo "✗ FAILED: Could not install proxy dependencies" - echo "Setup log:" - cat "$PROXY_SETUP_LOG" - RESULTS+=("✗ Out-of-Context Error (dependency install failed)") -else - echo "✓ Dependencies installed" - - # Start the error proxy in context-length error mode (3 errors) - echo "Starting error proxy on port $PROXY_PORT with context-length error mode..." - (cd "$PROXY_DIR" && UV_INDEX_URL="https://pypi.org/simple" uv run proxy.py --port "$PROXY_PORT" --mode "c 3" --no-stdin > "$PROXY_LOG" 2>&1) & - PROXY_PID=$! - - # Wait for proxy to be ready (check if port is listening) - echo "Waiting for proxy to be ready..." - PROXY_READY=false - for i in {1..60}; do - if kill -0 $PROXY_PID 2>/dev/null; then - # Check if port is listening using /dev/tcp - if timeout 1 bash -c "echo -n > /dev/tcp/localhost/$PROXY_PORT" 2>/dev/null; then - PROXY_READY=true - echo "✓ Proxy is ready on port $PROXY_PORT" - break - fi - else - echo "✗ FAILED: Error proxy process died" - break - fi - sleep 0.5 - done - - # Check if proxy is running and ready - if [ "$PROXY_READY" != "true" ]; then - echo "✗ FAILED: Error proxy failed to become ready" - echo "Proxy log:" - cat "$PROXY_LOG" - kill $PROXY_PID 2>/dev/null || true - RESULTS+=("✗ Out-of-Context Test Error (proxy failed)") - else - # Configure provider to use proxy and skip backoff - export ANTHROPIC_HOST="http://localhost:$PROXY_PORT" - export GOOSE_PROVIDER_SKIP_BACKOFF=true - export GOOSE_PROVIDER=anthropic - export GOOSE_MODEL=claude-haiku-4-5 - - echo "Step 1: Creating session (should trigger context-length error and compaction)..." - (cd "$TESTDIR" && "$GOOSE_BIN" run --text "hello world" 2>&1) | tee "$OUTPUT" - - SESSION_ID=$("$GOOSE_BIN" session list --format json 2>/dev/null | jq -r '.[0].id' 2>/dev/null) - - if [ -z "$SESSION_ID" ] || [ "$SESSION_ID" = "null" ]; then - echo "✗ FAILED: Could not create session" - RESULTS+=("✗ Out-of-Context Test Error (no session)") - else - echo "" - echo "Session created: $SESSION_ID" - echo "Checking for compaction evidence..." - - # Check for compaction in the output - if grep -qi "context.*length\|compacting\|compacted\|compaction" "$OUTPUT"; then - echo "✓ SUCCESS: Out-of-context Test error triggered compaction" - - if validate_compaction "$SESSION_ID" "out-of-context error compaction"; then - RESULTS+=("✓ Out-of-Context Test Error") - else - RESULTS+=("✗ Out-of-Context Test Error (structure validation failed)") - fi - else - echo "✗ FAILED: No evidence of compaction after context-length error" - echo " Output:" - cat "$OUTPUT" - RESULTS+=("✗ Out-of-Context Test Error") - fi - fi - - # Clean up - echo "" - echo "Stopping error proxy..." - # Kill the entire process group to ensure UV and Python processes are terminated - kill -- -$PROXY_PID 2>/dev/null || true - # Also explicitly kill any remaining UV processes on this port - pkill -f "uv run.*--port $PROXY_PORT" 2>/dev/null || true - wait $PROXY_PID 2>/dev/null || true - unset ANTHROPIC_HOST - unset GOOSE_PROVIDER_SKIP_BACKOFF - unset GOOSE_PROVIDER - unset GOOSE_MODEL - unset UV_INDEX_URL - fi -fi - -rm -f "$OUTPUT" "$PROXY_LOG" "$PROXY_SETUP_LOG" -rm -rf "$TESTDIR" - -echo "" -echo "" +# # ================================================== +# # TEST 2: Auto Compaction +# # ================================================== +# echo "---------------------------------------------------" +# echo "TEST 2: Auto Compaction via threshold (0.005)" +# echo "---------------------------------------------------" + +# TESTDIR=$(mktemp -d) +# echo "test content" > "$TESTDIR/test.txt" +# echo "Test directory: $TESTDIR" +# echo "" + +# # Set auto-compact threshold very low (.5%) to trigger it quickly +# export GOOSE_AUTO_COMPACT_THRESHOLD=0.005 + +# OUTPUT=$(mktemp) + +# LONG_RESPONSE_PROMPT="Count from 1 to 200, one number per line." + +# echo "Step 1: Creating session with first message (generating tokens for threshold)..." +# (cd "$TESTDIR" && "$GOOSE_BIN" run --text "$LONG_RESPONSE_PROMPT" 2>&1) | tee "$OUTPUT" + +# if ! command -v jq &> /dev/null; then +# echo "✗ FAILED: jq is required for this test" +# RESULTS+=("✗ Auto Compaction (jq required)") +# else +# SESSION_ID=$("$GOOSE_BIN" session list --format json 2>/dev/null | jq -r '.[0].id' 2>/dev/null) + +# if [ -z "$SESSION_ID" ] || [ "$SESSION_ID" = "null" ]; then +# echo "✗ FAILED: Could not create session" +# RESULTS+=("✗ Auto Compaction (no session)") +# else +# echo "" +# echo "Session created: $SESSION_ID" +# echo "Step 2: Sending second message (should trigger auto-compact)..." + +# # Send second message - auto-compaction should trigger before processing this +# (cd "$TESTDIR" && "$GOOSE_BIN" run --resume --session-id "$SESSION_ID" --text "hi again" 2>&1) | tee -a "$OUTPUT" + +# echo "" +# echo "Checking for auto-compaction evidence..." + +# if grep -qi "auto.*compact\|exceeded.*auto.*compact.*threshold" "$OUTPUT"; then +# echo "✓ SUCCESS: Auto compaction was triggered" + +# if validate_compaction "$SESSION_ID" "auto compaction"; then +# RESULTS+=("✓ Auto Compaction") +# else +# RESULTS+=("✗ Auto Compaction (structure validation failed)") +# fi +# else +# echo "✗ FAILED: Auto compaction was not triggered" +# echo " Expected to see auto-compact messages with threshold of 0.005" +# RESULTS+=("✗ Auto Compaction") +# fi +# fi +# fi + +# # Unset the env variable +# unset GOOSE_AUTO_COMPACT_THRESHOLD + +# rm -f "$OUTPUT" +# rm -rf "$TESTDIR" + +# echo "" +# echo "" + +# # ================================================== +# # TEST 3: Out-of-Context Error Compaction +# # ================================================== +# echo "---------------------------------------------------" +# echo "TEST 3: Compaction via out-of-context error (proxy)" +# echo "---------------------------------------------------" + +# TESTDIR=$(mktemp -d) +# echo "test content" > "$TESTDIR/test.txt" +# echo "Test directory: $TESTDIR" +# echo "" + +# # Use a random port to avoid conflicts +# PROXY_PORT=$((9000 + RANDOM % 1000)) +# PROXY_DIR="$SCRIPT_DIR/scripts/provider-error-proxy" + +# OUTPUT=$(mktemp) +# PROXY_LOG=$(mktemp) +# PROXY_SETUP_LOG=$(mktemp) + +# # Pre-install proxy dependencies (so first run doesn't take forever) +# echo "Installing proxy dependencies..." +# export UV_INDEX_URL="https://pypi.org/simple" +# if ! (cd "$PROXY_DIR" && uv sync 2>&1 | tee "$PROXY_SETUP_LOG"); then +# echo "✗ FAILED: Could not install proxy dependencies" +# echo "Setup log:" +# cat "$PROXY_SETUP_LOG" +# RESULTS+=("✗ Out-of-Context Error (dependency install failed)") +# else +# echo "✓ Dependencies installed" + +# # Start the error proxy in context-length error mode (3 errors) +# echo "Starting error proxy on port $PROXY_PORT with context-length error mode..." +# (cd "$PROXY_DIR" && UV_INDEX_URL="https://pypi.org/simple" uv run proxy.py --port "$PROXY_PORT" --mode "c 3" --no-stdin > "$PROXY_LOG" 2>&1) & +# PROXY_PID=$! + +# # Wait for proxy to be ready (check if port is listening) +# echo "Waiting for proxy to be ready..." +# PROXY_READY=false +# for i in {1..60}; do +# if kill -0 $PROXY_PID 2>/dev/null; then +# # Check if port is listening using /dev/tcp +# if timeout 1 bash -c "echo -n > /dev/tcp/localhost/$PROXY_PORT" 2>/dev/null; then +# PROXY_READY=true +# echo "✓ Proxy is ready on port $PROXY_PORT" +# break +# fi +# else +# echo "✗ FAILED: Error proxy process died" +# break +# fi +# sleep 0.5 +# done + +# # Check if proxy is running and ready +# if [ "$PROXY_READY" != "true" ]; then +# echo "✗ FAILED: Error proxy failed to become ready" +# echo "Proxy log:" +# cat "$PROXY_LOG" +# kill $PROXY_PID 2>/dev/null || true +# RESULTS+=("✗ Out-of-Context Test Error (proxy failed)") +# else +# # Configure provider to use proxy and skip backoff +# export ANTHROPIC_HOST="http://localhost:$PROXY_PORT" +# export GOOSE_PROVIDER_SKIP_BACKOFF=true +# export GOOSE_PROVIDER=anthropic +# export GOOSE_MODEL=claude-haiku-4-5 + +# echo "Step 1: Creating session (should trigger context-length error and compaction)..." +# (cd "$TESTDIR" && "$GOOSE_BIN" run --text "hello world" 2>&1) | tee "$OUTPUT" + +# SESSION_ID=$("$GOOSE_BIN" session list --format json 2>/dev/null | jq -r '.[0].id' 2>/dev/null) + +# if [ -z "$SESSION_ID" ] || [ "$SESSION_ID" = "null" ]; then +# echo "✗ FAILED: Could not create session" +# RESULTS+=("✗ Out-of-Context Test Error (no session)") +# else +# echo "" +# echo "Session created: $SESSION_ID" +# echo "Checking for compaction evidence..." + +# # Check for compaction in the output +# if grep -qi "context.*length\|compacting\|compacted\|compaction" "$OUTPUT"; then +# echo "✓ SUCCESS: Out-of-context Test error triggered compaction" + +# if validate_compaction "$SESSION_ID" "out-of-context error compaction"; then +# RESULTS+=("✓ Out-of-Context Test Error") +# else +# RESULTS+=("✗ Out-of-Context Test Error (structure validation failed)") +# fi +# else +# echo "✗ FAILED: No evidence of compaction after context-length error" +# echo " Output:" +# cat "$OUTPUT" +# RESULTS+=("✗ Out-of-Context Test Error") +# fi +# fi + +# # Clean up +# echo "" +# echo "Stopping error proxy..." +# # Kill the entire process group to ensure UV and Python processes are terminated +# kill -- -$PROXY_PID 2>/dev/null || true +# # Also explicitly kill any remaining UV processes on this port +# pkill -f "uv run.*--port $PROXY_PORT" 2>/dev/null || true +# wait $PROXY_PID 2>/dev/null || true +# unset ANTHROPIC_HOST +# unset GOOSE_PROVIDER_SKIP_BACKOFF +# unset GOOSE_PROVIDER +# unset GOOSE_MODEL +# unset UV_INDEX_URL +# fi +# fi + +# rm -f "$OUTPUT" "$PROXY_LOG" "$PROXY_SETUP_LOG" +# rm -rf "$TESTDIR" + +# echo "" +# echo "" # ================================================== # Summary From 512b5f6a62505bbe838290cdd9115b754f1f514f Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Tue, 27 Jan 2026 23:30:50 +1100 Subject: [PATCH 2/7] use correct logfile --- scripts/test_compaction.sh | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/scripts/test_compaction.sh b/scripts/test_compaction.sh index ef95556bcb3f..8115a01673bb 100755 --- a/scripts/test_compaction.sh +++ b/scripts/test_compaction.sh @@ -22,8 +22,19 @@ GOOSE_BIN="$SCRIPT_DIR/target/release/goose" # Timeout for goose commands (default 5 minutes) GOOSE_TIMEOUT=${GOOSE_TIMEOUT:-300} -# Log directory for diagnostics -LOG_DIR="$HOME/.config/goose/logs/cli" +# Log directory for diagnostics - must match goose's actual log path +# See crates/goose/src/config/paths.rs and crates/goose/src/logging.rs +get_log_dir() { + local today=$(date +%Y-%m-%d) + if [ -n "$GOOSE_PATH_ROOT" ]; then + echo "$GOOSE_PATH_ROOT/state/logs/cli/$today" + elif [ "$(uname)" = "Darwin" ]; then + echo "$HOME/Library/Application Support/Block.goose/logs/cli/$today" + else + echo "${XDG_STATE_HOME:-$HOME/.local/state}/goose/logs/cli/$today" + fi +} +LOG_DIR=$(get_log_dir) # Helper to dump stream diagnostics from logs on timeout dump_stream_diagnostics() { @@ -31,7 +42,7 @@ dump_stream_diagnostics() { echo "=== STREAM DIAGNOSTICS (last 50 entries) ===" if [ -d "$LOG_DIR" ]; then # Find logs from the last 10 minutes and grep for stream_diag - find "$LOG_DIR" -name "*.log" -mmin -10 -exec grep -h "stream_diag" {} \; 2>/dev/null | tail -50 + find "$LOG_DIR" -name "*.log" -mmin -10 -exec grep -h "stream_diag" {} \; 2>/dev/null | tail -200 else echo "No log directory found at $LOG_DIR" fi From ae1ade599e5070f82d1b4052db748113f6fb4950 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Wed, 28 Jan 2026 01:36:08 +1100 Subject: [PATCH 3/7] Revert "use correct logfile" This reverts commit 512b5f6a62505bbe838290cdd9115b754f1f514f. --- scripts/test_compaction.sh | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/scripts/test_compaction.sh b/scripts/test_compaction.sh index 8115a01673bb..ef95556bcb3f 100755 --- a/scripts/test_compaction.sh +++ b/scripts/test_compaction.sh @@ -22,19 +22,8 @@ GOOSE_BIN="$SCRIPT_DIR/target/release/goose" # Timeout for goose commands (default 5 minutes) GOOSE_TIMEOUT=${GOOSE_TIMEOUT:-300} -# Log directory for diagnostics - must match goose's actual log path -# See crates/goose/src/config/paths.rs and crates/goose/src/logging.rs -get_log_dir() { - local today=$(date +%Y-%m-%d) - if [ -n "$GOOSE_PATH_ROOT" ]; then - echo "$GOOSE_PATH_ROOT/state/logs/cli/$today" - elif [ "$(uname)" = "Darwin" ]; then - echo "$HOME/Library/Application Support/Block.goose/logs/cli/$today" - else - echo "${XDG_STATE_HOME:-$HOME/.local/state}/goose/logs/cli/$today" - fi -} -LOG_DIR=$(get_log_dir) +# Log directory for diagnostics +LOG_DIR="$HOME/.config/goose/logs/cli" # Helper to dump stream diagnostics from logs on timeout dump_stream_diagnostics() { @@ -42,7 +31,7 @@ dump_stream_diagnostics() { echo "=== STREAM DIAGNOSTICS (last 50 entries) ===" if [ -d "$LOG_DIR" ]; then # Find logs from the last 10 minutes and grep for stream_diag - find "$LOG_DIR" -name "*.log" -mmin -10 -exec grep -h "stream_diag" {} \; 2>/dev/null | tail -200 + find "$LOG_DIR" -name "*.log" -mmin -10 -exec grep -h "stream_diag" {} \; 2>/dev/null | tail -50 else echo "No log directory found at $LOG_DIR" fi From 41338e311ad39a05fc07486df2e27dd1a913ec92 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Wed, 28 Jan 2026 01:36:58 +1100 Subject: [PATCH 4/7] Revert "debug" This reverts commit afbd04b5d62a890984764cc67efcb2c4ff67b4fe. --- crates/goose/src/agents/subagent_handler.rs | 18 - .../goose/src/providers/formats/anthropic.rs | 16 - scripts/test_compaction.sh | 413 ++++++++---------- 3 files changed, 188 insertions(+), 259 deletions(-) diff --git a/crates/goose/src/agents/subagent_handler.rs b/crates/goose/src/agents/subagent_handler.rs index c2683421894d..54e0d2dab827 100644 --- a/crates/goose/src/agents/subagent_handler.rs +++ b/crates/goose/src/agents/subagent_handler.rs @@ -186,22 +186,7 @@ fn get_agent_messages( .reply(user_message, session_config, cancellation_token) .await .map_err(|e| anyhow!("Failed to get reply from agent: {}", e))?; - - // Stream diagnostics for debugging hangs - let mut event_count = 0u64; - let stream_start = std::time::Instant::now(); - let mut last_event_time = stream_start; - tracing::info!(target: "stream_diag", "[STREAM] subagent: starting to consume agent events"); - while let Some(message_result) = stream.next().await { - event_count += 1; - let now = std::time::Instant::now(); - let since_last = now.duration_since(last_event_time); - if since_last.as_secs() >= 5 { - tracing::warn!(target: "stream_diag", "[STREAM] subagent: event #{} after {:.1}s delay", event_count, since_last.as_secs_f64()); - } - last_event_time = now; - match message_result { Ok(AgentEvent::Message(msg)) => conversation.push(msg), Ok(AgentEvent::McpNotification(_)) | Ok(AgentEvent::ModelChange { .. }) => {} @@ -215,9 +200,6 @@ fn get_agent_messages( } } - let total_duration = stream_start.elapsed(); - tracing::info!(target: "stream_diag", "[STREAM] subagent: stream ended after {} events in {:.1}s", event_count, total_duration.as_secs_f64()); - let final_output = if has_response_schema { agent .final_output_tool diff --git a/crates/goose/src/providers/formats/anthropic.rs b/crates/goose/src/providers/formats/anthropic.rs index 61d6622563ff..7e3dd161515a 100644 --- a/crates/goose/src/providers/formats/anthropic.rs +++ b/crates/goose/src/providers/formats/anthropic.rs @@ -494,20 +494,7 @@ where let mut final_usage: Option = None; let mut message_id: Option = None; - // Stream diagnostics for debugging hangs - let mut chunk_count = 0u64; - let stream_start = std::time::Instant::now(); - let mut last_chunk_time = stream_start; - tracing::info!(target: "stream_diag", "[STREAM] anthropic: starting stream consumption"); - while let Some(line_result) = stream.next().await { - chunk_count += 1; - let now = std::time::Instant::now(); - let since_last = now.duration_since(last_chunk_time); - if since_last.as_secs() >= 5 { - tracing::warn!(target: "stream_diag", "[STREAM] anthropic: chunk #{} after {:.1}s delay", chunk_count, since_last.as_secs_f64()); - } - last_chunk_time = now; let line = line_result?; // Skip empty lines and non-data lines @@ -709,9 +696,6 @@ where } } - let total_duration = stream_start.elapsed(); - tracing::info!(target: "stream_diag", "[STREAM] anthropic: stream ended after {} chunks in {:.1}s", chunk_count, total_duration.as_secs_f64()); - // Yield final usage information if available if let Some(usage) = final_usage { yield (None, Some(usage)); diff --git a/scripts/test_compaction.sh b/scripts/test_compaction.sh index ef95556bcb3f..baa3b7ca9660 100755 --- a/scripts/test_compaction.sh +++ b/scripts/test_compaction.sh @@ -19,43 +19,6 @@ fi SCRIPT_DIR=$(pwd) GOOSE_BIN="$SCRIPT_DIR/target/release/goose" -# Timeout for goose commands (default 5 minutes) -GOOSE_TIMEOUT=${GOOSE_TIMEOUT:-300} - -# Log directory for diagnostics -LOG_DIR="$HOME/.config/goose/logs/cli" - -# Helper to dump stream diagnostics from logs on timeout -dump_stream_diagnostics() { - echo "" - echo "=== STREAM DIAGNOSTICS (last 50 entries) ===" - if [ -d "$LOG_DIR" ]; then - # Find logs from the last 10 minutes and grep for stream_diag - find "$LOG_DIR" -name "*.log" -mmin -10 -exec grep -h "stream_diag" {} \; 2>/dev/null | tail -50 - else - echo "No log directory found at $LOG_DIR" - fi - echo "=== END STREAM DIAGNOSTICS ===" - echo "" -} - -# Helper to run goose with timeout and stream diagnostics enabled -run_goose() { - local exit_code=0 - # Enable stream_diag target for our diagnostic logs - RUST_LOG="${RUST_LOG:-stream_diag=info}" timeout "$GOOSE_TIMEOUT" "$GOOSE_BIN" "$@" 2>&1 || exit_code=$? - - if [ $exit_code -eq 124 ] || [ $exit_code -eq 137 ]; then - echo "" - echo "⚠️ TIMEOUT: goose command exceeded ${GOOSE_TIMEOUT}s limit" - fi - - # Always dump stream diagnostics to help debug issues - dump_stream_diagnostics - - return $exit_code -} - # Validation function to check compaction structure in session JSON validate_compaction() { local session_id=$1 @@ -139,7 +102,7 @@ echo "" OUTPUT=$(mktemp) echo "Step 1: Creating session with initial messages..." -(cd "$TESTDIR" && run_goose run --text "list files and read hello.txt") | tee "$OUTPUT" +(cd "$TESTDIR" && "$GOOSE_BIN" run --text "list files and read hello.txt" 2>&1) | tee "$OUTPUT" if ! command -v jq &> /dev/null; then echo "✗ FAILED: jq is required for this test" @@ -158,7 +121,7 @@ else echo "Step 2: Sending manual compaction trigger..." # Send the manual compact trigger prompt - (cd "$TESTDIR" && run_goose run --resume --session-id "$SESSION_ID" --text "Please compact this conversation") | tee -a "$OUTPUT" + (cd "$TESTDIR" && "$GOOSE_BIN" run --resume --session-id "$SESSION_ID" --text "Please compact this conversation" 2>&1) | tee -a "$OUTPUT" echo "" echo "Checking for compaction evidence..." @@ -184,192 +147,192 @@ fi echo "" echo "" -# # ================================================== -# # TEST 2: Auto Compaction -# # ================================================== -# echo "---------------------------------------------------" -# echo "TEST 2: Auto Compaction via threshold (0.005)" -# echo "---------------------------------------------------" - -# TESTDIR=$(mktemp -d) -# echo "test content" > "$TESTDIR/test.txt" -# echo "Test directory: $TESTDIR" -# echo "" - -# # Set auto-compact threshold very low (.5%) to trigger it quickly -# export GOOSE_AUTO_COMPACT_THRESHOLD=0.005 - -# OUTPUT=$(mktemp) - -# LONG_RESPONSE_PROMPT="Count from 1 to 200, one number per line." - -# echo "Step 1: Creating session with first message (generating tokens for threshold)..." -# (cd "$TESTDIR" && "$GOOSE_BIN" run --text "$LONG_RESPONSE_PROMPT" 2>&1) | tee "$OUTPUT" - -# if ! command -v jq &> /dev/null; then -# echo "✗ FAILED: jq is required for this test" -# RESULTS+=("✗ Auto Compaction (jq required)") -# else -# SESSION_ID=$("$GOOSE_BIN" session list --format json 2>/dev/null | jq -r '.[0].id' 2>/dev/null) - -# if [ -z "$SESSION_ID" ] || [ "$SESSION_ID" = "null" ]; then -# echo "✗ FAILED: Could not create session" -# RESULTS+=("✗ Auto Compaction (no session)") -# else -# echo "" -# echo "Session created: $SESSION_ID" -# echo "Step 2: Sending second message (should trigger auto-compact)..." - -# # Send second message - auto-compaction should trigger before processing this -# (cd "$TESTDIR" && "$GOOSE_BIN" run --resume --session-id "$SESSION_ID" --text "hi again" 2>&1) | tee -a "$OUTPUT" - -# echo "" -# echo "Checking for auto-compaction evidence..." - -# if grep -qi "auto.*compact\|exceeded.*auto.*compact.*threshold" "$OUTPUT"; then -# echo "✓ SUCCESS: Auto compaction was triggered" - -# if validate_compaction "$SESSION_ID" "auto compaction"; then -# RESULTS+=("✓ Auto Compaction") -# else -# RESULTS+=("✗ Auto Compaction (structure validation failed)") -# fi -# else -# echo "✗ FAILED: Auto compaction was not triggered" -# echo " Expected to see auto-compact messages with threshold of 0.005" -# RESULTS+=("✗ Auto Compaction") -# fi -# fi -# fi - -# # Unset the env variable -# unset GOOSE_AUTO_COMPACT_THRESHOLD - -# rm -f "$OUTPUT" -# rm -rf "$TESTDIR" - -# echo "" -# echo "" - -# # ================================================== -# # TEST 3: Out-of-Context Error Compaction -# # ================================================== -# echo "---------------------------------------------------" -# echo "TEST 3: Compaction via out-of-context error (proxy)" -# echo "---------------------------------------------------" - -# TESTDIR=$(mktemp -d) -# echo "test content" > "$TESTDIR/test.txt" -# echo "Test directory: $TESTDIR" -# echo "" - -# # Use a random port to avoid conflicts -# PROXY_PORT=$((9000 + RANDOM % 1000)) -# PROXY_DIR="$SCRIPT_DIR/scripts/provider-error-proxy" - -# OUTPUT=$(mktemp) -# PROXY_LOG=$(mktemp) -# PROXY_SETUP_LOG=$(mktemp) - -# # Pre-install proxy dependencies (so first run doesn't take forever) -# echo "Installing proxy dependencies..." -# export UV_INDEX_URL="https://pypi.org/simple" -# if ! (cd "$PROXY_DIR" && uv sync 2>&1 | tee "$PROXY_SETUP_LOG"); then -# echo "✗ FAILED: Could not install proxy dependencies" -# echo "Setup log:" -# cat "$PROXY_SETUP_LOG" -# RESULTS+=("✗ Out-of-Context Error (dependency install failed)") -# else -# echo "✓ Dependencies installed" - -# # Start the error proxy in context-length error mode (3 errors) -# echo "Starting error proxy on port $PROXY_PORT with context-length error mode..." -# (cd "$PROXY_DIR" && UV_INDEX_URL="https://pypi.org/simple" uv run proxy.py --port "$PROXY_PORT" --mode "c 3" --no-stdin > "$PROXY_LOG" 2>&1) & -# PROXY_PID=$! - -# # Wait for proxy to be ready (check if port is listening) -# echo "Waiting for proxy to be ready..." -# PROXY_READY=false -# for i in {1..60}; do -# if kill -0 $PROXY_PID 2>/dev/null; then -# # Check if port is listening using /dev/tcp -# if timeout 1 bash -c "echo -n > /dev/tcp/localhost/$PROXY_PORT" 2>/dev/null; then -# PROXY_READY=true -# echo "✓ Proxy is ready on port $PROXY_PORT" -# break -# fi -# else -# echo "✗ FAILED: Error proxy process died" -# break -# fi -# sleep 0.5 -# done - -# # Check if proxy is running and ready -# if [ "$PROXY_READY" != "true" ]; then -# echo "✗ FAILED: Error proxy failed to become ready" -# echo "Proxy log:" -# cat "$PROXY_LOG" -# kill $PROXY_PID 2>/dev/null || true -# RESULTS+=("✗ Out-of-Context Test Error (proxy failed)") -# else -# # Configure provider to use proxy and skip backoff -# export ANTHROPIC_HOST="http://localhost:$PROXY_PORT" -# export GOOSE_PROVIDER_SKIP_BACKOFF=true -# export GOOSE_PROVIDER=anthropic -# export GOOSE_MODEL=claude-haiku-4-5 - -# echo "Step 1: Creating session (should trigger context-length error and compaction)..." -# (cd "$TESTDIR" && "$GOOSE_BIN" run --text "hello world" 2>&1) | tee "$OUTPUT" - -# SESSION_ID=$("$GOOSE_BIN" session list --format json 2>/dev/null | jq -r '.[0].id' 2>/dev/null) - -# if [ -z "$SESSION_ID" ] || [ "$SESSION_ID" = "null" ]; then -# echo "✗ FAILED: Could not create session" -# RESULTS+=("✗ Out-of-Context Test Error (no session)") -# else -# echo "" -# echo "Session created: $SESSION_ID" -# echo "Checking for compaction evidence..." - -# # Check for compaction in the output -# if grep -qi "context.*length\|compacting\|compacted\|compaction" "$OUTPUT"; then -# echo "✓ SUCCESS: Out-of-context Test error triggered compaction" - -# if validate_compaction "$SESSION_ID" "out-of-context error compaction"; then -# RESULTS+=("✓ Out-of-Context Test Error") -# else -# RESULTS+=("✗ Out-of-Context Test Error (structure validation failed)") -# fi -# else -# echo "✗ FAILED: No evidence of compaction after context-length error" -# echo " Output:" -# cat "$OUTPUT" -# RESULTS+=("✗ Out-of-Context Test Error") -# fi -# fi - -# # Clean up -# echo "" -# echo "Stopping error proxy..." -# # Kill the entire process group to ensure UV and Python processes are terminated -# kill -- -$PROXY_PID 2>/dev/null || true -# # Also explicitly kill any remaining UV processes on this port -# pkill -f "uv run.*--port $PROXY_PORT" 2>/dev/null || true -# wait $PROXY_PID 2>/dev/null || true -# unset ANTHROPIC_HOST -# unset GOOSE_PROVIDER_SKIP_BACKOFF -# unset GOOSE_PROVIDER -# unset GOOSE_MODEL -# unset UV_INDEX_URL -# fi -# fi - -# rm -f "$OUTPUT" "$PROXY_LOG" "$PROXY_SETUP_LOG" -# rm -rf "$TESTDIR" - -# echo "" -# echo "" +# ================================================== +# TEST 2: Auto Compaction +# ================================================== +echo "---------------------------------------------------" +echo "TEST 2: Auto Compaction via threshold (0.005)" +echo "---------------------------------------------------" + +TESTDIR=$(mktemp -d) +echo "test content" > "$TESTDIR/test.txt" +echo "Test directory: $TESTDIR" +echo "" + +# Set auto-compact threshold very low (.5%) to trigger it quickly +export GOOSE_AUTO_COMPACT_THRESHOLD=0.005 + +OUTPUT=$(mktemp) + +LONG_RESPONSE_PROMPT="Count from 1 to 200, one number per line." + +echo "Step 1: Creating session with first message (generating tokens for threshold)..." +(cd "$TESTDIR" && "$GOOSE_BIN" run --text "$LONG_RESPONSE_PROMPT" 2>&1) | tee "$OUTPUT" + +if ! command -v jq &> /dev/null; then + echo "✗ FAILED: jq is required for this test" + RESULTS+=("✗ Auto Compaction (jq required)") +else + SESSION_ID=$("$GOOSE_BIN" session list --format json 2>/dev/null | jq -r '.[0].id' 2>/dev/null) + + if [ -z "$SESSION_ID" ] || [ "$SESSION_ID" = "null" ]; then + echo "✗ FAILED: Could not create session" + RESULTS+=("✗ Auto Compaction (no session)") + else + echo "" + echo "Session created: $SESSION_ID" + echo "Step 2: Sending second message (should trigger auto-compact)..." + + # Send second message - auto-compaction should trigger before processing this + (cd "$TESTDIR" && "$GOOSE_BIN" run --resume --session-id "$SESSION_ID" --text "hi again" 2>&1) | tee -a "$OUTPUT" + + echo "" + echo "Checking for auto-compaction evidence..." + + if grep -qi "auto.*compact\|exceeded.*auto.*compact.*threshold" "$OUTPUT"; then + echo "✓ SUCCESS: Auto compaction was triggered" + + if validate_compaction "$SESSION_ID" "auto compaction"; then + RESULTS+=("✓ Auto Compaction") + else + RESULTS+=("✗ Auto Compaction (structure validation failed)") + fi + else + echo "✗ FAILED: Auto compaction was not triggered" + echo " Expected to see auto-compact messages with threshold of 0.005" + RESULTS+=("✗ Auto Compaction") + fi + fi +fi + +# Unset the env variable +unset GOOSE_AUTO_COMPACT_THRESHOLD + +rm -f "$OUTPUT" +rm -rf "$TESTDIR" + +echo "" +echo "" + +# ================================================== +# TEST 3: Out-of-Context Error Compaction +# ================================================== +echo "---------------------------------------------------" +echo "TEST 3: Compaction via out-of-context error (proxy)" +echo "---------------------------------------------------" + +TESTDIR=$(mktemp -d) +echo "test content" > "$TESTDIR/test.txt" +echo "Test directory: $TESTDIR" +echo "" + +# Use a random port to avoid conflicts +PROXY_PORT=$((9000 + RANDOM % 1000)) +PROXY_DIR="$SCRIPT_DIR/scripts/provider-error-proxy" + +OUTPUT=$(mktemp) +PROXY_LOG=$(mktemp) +PROXY_SETUP_LOG=$(mktemp) + +# Pre-install proxy dependencies (so first run doesn't take forever) +echo "Installing proxy dependencies..." +export UV_INDEX_URL="https://pypi.org/simple" +if ! (cd "$PROXY_DIR" && uv sync 2>&1 | tee "$PROXY_SETUP_LOG"); then + echo "✗ FAILED: Could not install proxy dependencies" + echo "Setup log:" + cat "$PROXY_SETUP_LOG" + RESULTS+=("✗ Out-of-Context Error (dependency install failed)") +else + echo "✓ Dependencies installed" + + # Start the error proxy in context-length error mode (3 errors) + echo "Starting error proxy on port $PROXY_PORT with context-length error mode..." + (cd "$PROXY_DIR" && UV_INDEX_URL="https://pypi.org/simple" uv run proxy.py --port "$PROXY_PORT" --mode "c 3" --no-stdin > "$PROXY_LOG" 2>&1) & + PROXY_PID=$! + + # Wait for proxy to be ready (check if port is listening) + echo "Waiting for proxy to be ready..." + PROXY_READY=false + for i in {1..60}; do + if kill -0 $PROXY_PID 2>/dev/null; then + # Check if port is listening using /dev/tcp + if timeout 1 bash -c "echo -n > /dev/tcp/localhost/$PROXY_PORT" 2>/dev/null; then + PROXY_READY=true + echo "✓ Proxy is ready on port $PROXY_PORT" + break + fi + else + echo "✗ FAILED: Error proxy process died" + break + fi + sleep 0.5 + done + + # Check if proxy is running and ready + if [ "$PROXY_READY" != "true" ]; then + echo "✗ FAILED: Error proxy failed to become ready" + echo "Proxy log:" + cat "$PROXY_LOG" + kill $PROXY_PID 2>/dev/null || true + RESULTS+=("✗ Out-of-Context Test Error (proxy failed)") + else + # Configure provider to use proxy and skip backoff + export ANTHROPIC_HOST="http://localhost:$PROXY_PORT" + export GOOSE_PROVIDER_SKIP_BACKOFF=true + export GOOSE_PROVIDER=anthropic + export GOOSE_MODEL=claude-haiku-4-5 + + echo "Step 1: Creating session (should trigger context-length error and compaction)..." + (cd "$TESTDIR" && "$GOOSE_BIN" run --text "hello world" 2>&1) | tee "$OUTPUT" + + SESSION_ID=$("$GOOSE_BIN" session list --format json 2>/dev/null | jq -r '.[0].id' 2>/dev/null) + + if [ -z "$SESSION_ID" ] || [ "$SESSION_ID" = "null" ]; then + echo "✗ FAILED: Could not create session" + RESULTS+=("✗ Out-of-Context Test Error (no session)") + else + echo "" + echo "Session created: $SESSION_ID" + echo "Checking for compaction evidence..." + + # Check for compaction in the output + if grep -qi "context.*length\|compacting\|compacted\|compaction" "$OUTPUT"; then + echo "✓ SUCCESS: Out-of-context Test error triggered compaction" + + if validate_compaction "$SESSION_ID" "out-of-context error compaction"; then + RESULTS+=("✓ Out-of-Context Test Error") + else + RESULTS+=("✗ Out-of-Context Test Error (structure validation failed)") + fi + else + echo "✗ FAILED: No evidence of compaction after context-length error" + echo " Output:" + cat "$OUTPUT" + RESULTS+=("✗ Out-of-Context Test Error") + fi + fi + + # Clean up + echo "" + echo "Stopping error proxy..." + # Kill the entire process group to ensure UV and Python processes are terminated + kill -- -$PROXY_PID 2>/dev/null || true + # Also explicitly kill any remaining UV processes on this port + pkill -f "uv run.*--port $PROXY_PORT" 2>/dev/null || true + wait $PROXY_PID 2>/dev/null || true + unset ANTHROPIC_HOST + unset GOOSE_PROVIDER_SKIP_BACKOFF + unset GOOSE_PROVIDER + unset GOOSE_MODEL + unset UV_INDEX_URL + fi +fi + +rm -f "$OUTPUT" "$PROXY_LOG" "$PROXY_SETUP_LOG" +rm -rf "$TESTDIR" + +echo "" +echo "" # ================================================== # Summary From e54cd999c537f9f2e5c8e2e6fa469c76db9fcf0c Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Wed, 28 Jan 2026 01:43:06 +1100 Subject: [PATCH 5/7] fix it with a prompt that does not depend on developer tool --- scripts/test_compaction.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test_compaction.sh b/scripts/test_compaction.sh index baa3b7ca9660..248dfbde3455 100755 --- a/scripts/test_compaction.sh +++ b/scripts/test_compaction.sh @@ -102,7 +102,7 @@ echo "" OUTPUT=$(mktemp) echo "Step 1: Creating session with initial messages..." -(cd "$TESTDIR" && "$GOOSE_BIN" run --text "list files and read hello.txt" 2>&1) | tee "$OUTPUT" +(cd "$TESTDIR" && "$GOOSE_BIN" run --text "describe Melbourne Australia in 100 words" 2>&1) | tee "$OUTPUT" if ! command -v jq &> /dev/null; then echo "✗ FAILED: jq is required for this test" From 136fab05f810dc79cc5f757bc6720788bb25791e Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Wed, 28 Jan 2026 16:32:30 +1100 Subject: [PATCH 6/7] fixed the deadlock when read_resource tool call --- crates/goose/src/agents/extension_manager.rs | 11 ++++++++--- crates/goose/src/prompts/system.md | 4 ++-- scripts/test_compaction.sh | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/crates/goose/src/agents/extension_manager.rs b/crates/goose/src/agents/extension_manager.rs index 13869241f09b..995cbdc84b90 100644 --- a/crates/goose/src/agents/extension_manager.rs +++ b/crates/goose/src/agents/extension_manager.rs @@ -913,9 +913,14 @@ impl ExtensionManager { // Loop through each extension and try to read the resource, don't raise an error if the resource is not found // TODO: do we want to find if a provided uri is in multiple extensions? // currently it will return the first match and skip any others - - // Collect extension names first to avoid holding the lock during iteration - let extension_names: Vec = self.extensions.lock().await.keys().cloned().collect(); + let extension_names: Vec = self + .extensions + .lock() + .await + .iter() + .filter(|(_name, ext)| ext.supports_resources()) + .map(|(name, _)| name.clone()) + .collect(); for extension_name in extension_names { let read_result = self diff --git a/crates/goose/src/prompts/system.md b/crates/goose/src/prompts/system.md index 87093d3997b8..c282d75497ac 100644 --- a/crates/goose/src/prompts/system.md +++ b/crates/goose/src/prompts/system.md @@ -31,8 +31,8 @@ in your tool specification. ## {{extension.name}} {% if extension.has_resources %} -{{extension.name}} supports resources, you can use platform__read_resource, -and platform__list_resources on this extension. +{{extension.name}} supports resources, you can use extensionmanager__read_resource, +and extensionmanager__list_resources on this extension. {% endif %} {% if extension.instructions %}### Instructions {{extension.instructions}}{% endif %} diff --git a/scripts/test_compaction.sh b/scripts/test_compaction.sh index 248dfbde3455..baa3b7ca9660 100755 --- a/scripts/test_compaction.sh +++ b/scripts/test_compaction.sh @@ -102,7 +102,7 @@ echo "" OUTPUT=$(mktemp) echo "Step 1: Creating session with initial messages..." -(cd "$TESTDIR" && "$GOOSE_BIN" run --text "describe Melbourne Australia in 100 words" 2>&1) | tee "$OUTPUT" +(cd "$TESTDIR" && "$GOOSE_BIN" run --text "list files and read hello.txt" 2>&1) | tee "$OUTPUT" if ! command -v jq &> /dev/null; then echo "✗ FAILED: jq is required for this test" From 51e38448df7c16846b3261419e54ad99119032d4 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Wed, 28 Jan 2026 16:55:40 +1100 Subject: [PATCH 7/7] fixed the test --- .../goose__agents__prompt_manager__tests__one_extension.snap | 4 ++-- .../goose__agents__prompt_manager__tests__typical_setup.snap | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/goose/src/agents/snapshots/goose__agents__prompt_manager__tests__one_extension.snap b/crates/goose/src/agents/snapshots/goose__agents__prompt_manager__tests__one_extension.snap index d7ba6de0dfec..8f02d1cf7af1 100644 --- a/crates/goose/src/agents/snapshots/goose__agents__prompt_manager__tests__one_extension.snap +++ b/crates/goose/src/agents/snapshots/goose__agents__prompt_manager__tests__one_extension.snap @@ -31,8 +31,8 @@ in your tool specification. ## test -test supports resources, you can use platform__read_resource, -and platform__list_resources on this extension. +test supports resources, you can use extensionmanager__read_resource, +and extensionmanager__list_resources on this extension. ### Instructions how to use this extension diff --git a/crates/goose/src/agents/snapshots/goose__agents__prompt_manager__tests__typical_setup.snap b/crates/goose/src/agents/snapshots/goose__agents__prompt_manager__tests__typical_setup.snap index c9848fd9ca20..719a84871da8 100644 --- a/crates/goose/src/agents/snapshots/goose__agents__prompt_manager__tests__typical_setup.snap +++ b/crates/goose/src/agents/snapshots/goose__agents__prompt_manager__tests__typical_setup.snap @@ -31,8 +31,8 @@ in your tool specification. ## extension_A -extension_A supports resources, you can use platform__read_resource, -and platform__list_resources on this extension. +extension_A supports resources, you can use extensionmanager__read_resource, +and extensionmanager__list_resources on this extension. ### Instructions ## extension_B