Repository navigation
Fix example tmux socket paths - #5494
Conversation
Use a short per-example TMUX_TMPDIR so tmux socket names remain under Unix path limits while preserving test isolation.\n\nCo-authored-by: openhands <openhands@all-hands.dev>
|
🧹 PR Artifact Cleanup Queued The |
REST API breakage checks (OpenAPI) — ✅ PASSEDResult: ✅ PASSED |
🔄 Running Examples with
|
| Example | Status | Duration | Cost |
|---|---|---|---|
| 01_standalone_sdk/02_custom_tools.py | ✅ PASS | 25.5s | $0.03 |
| 01_standalone_sdk/03_activate_skill.py | ✅ PASS | 24.0s | $0.03 |
| 01_standalone_sdk/05_use_llm_registry.py | ✅ PASS | 12.6s | $0.01 |
| 01_standalone_sdk/07_mcp_integration.py | ✅ PASS | 34.8s | $0.03 |
| 01_standalone_sdk/09_pause_example.py | ✅ PASS | 15.1s | $0.01 |
| 01_standalone_sdk/10_persistence.py | ✅ PASS | 25.3s | $0.02 |
| 01_standalone_sdk/11_async.py | ✅ PASS | 32.9s | $0.04 |
| 01_standalone_sdk/12_custom_secrets.py | ✅ PASS | 13.7s | $0.01 |
| 01_standalone_sdk/13_get_llm_metrics.py | ✅ PASS | 28.0s | $0.03 |
| 01_standalone_sdk/14_context_condenser.py | ✅ PASS | 1m 41s | $0.11 |
| 01_standalone_sdk/17_image_input.py | ✅ PASS | 22.3s | $0.02 |
| 01_standalone_sdk/18_send_message_while_processing.py | ✅ PASS | 23.2s | $0.01 |
| 01_standalone_sdk/19_llm_routing.py | ✅ PASS | 20.5s | $0.02 |
| 01_standalone_sdk/20_stuck_detector.py | ✅ PASS | 21.1s | $0.03 |
| 01_standalone_sdk/21_generate_extraneous_conversation_costs.py | ✅ PASS | 10.4s | $0.00 |
| 01_standalone_sdk/22_anthropic_thinking.py | ✅ PASS | 19.9s | $0.01 |
| 01_standalone_sdk/23_responses_reasoning.py | ✅ PASS | 43.3s | $0.01 |
| 01_standalone_sdk/24_planning_agent_workflow.py | ✅ PASS | 3m 49s | $0.28 |
| 01_standalone_sdk/25_agent_delegation.py | ✅ PASS | 1m 1s | $0.06 |
| 01_standalone_sdk/26_custom_visualizer.py | ✅ PASS | 17.0s | $0.02 |
| 01_standalone_sdk/28_ask_agent_example.py | ✅ PASS | 30.5s | $0.03 |
| 01_standalone_sdk/29_llm_streaming.py | ✅ PASS | 40.0s | $0.02 |
| 01_standalone_sdk/30_tom_agent.py | ✅ PASS | 11.7s | $0.01 |
| 01_standalone_sdk/31_iterative_refinement.py | ✅ PASS | 1m 17s | $0.08 |
| 01_standalone_sdk/32_configurable_security_policy.py | ✅ PASS | 23.0s | $0.02 |
| 01_standalone_sdk/33_hooks/main.py | ✅ PASS | 39.7s | $0.04 |
| 01_standalone_sdk/34_critic_example.py | ✅ PASS | 2m 4s | $0.02 |
| 01_standalone_sdk/36_event_json_to_openai_messages.py | ✅ PASS | 10.9s | $0.00 |
| 01_standalone_sdk/37_llm_profile_store/main.py | ✅ PASS | 9.3s | $0.00 |
| 01_standalone_sdk/38_browser_session_recording.py | ✅ PASS | 44.0s | $0.04 |
| 01_standalone_sdk/39_llm_fallback.py | ✅ PASS | 12.5s | $0.01 |
| 01_standalone_sdk/40_acp_agent_example.py | ✅ PASS | 57.2s | $0.41 |
| 01_standalone_sdk/41_task_tool_set.py | ✅ PASS | 25.7s | $0.03 |
| 01_standalone_sdk/42_file_based_subagents.py | ✅ PASS | 43.5s | $0.05 |
| 01_standalone_sdk/44_model_switching_in_convo.py | ✅ PASS | 10.1s | $0.01 |
| 01_standalone_sdk/45_parallel_tool_execution.py | ✅ PASS | 2m 56s | $0.46 |
| 01_standalone_sdk/46_agent_settings.py | ✅ PASS | 11.8s | $0.00 |
| 01_standalone_sdk/47_defense_in_depth_security.py | ✅ PASS | 4.4s | $0.00 |
| 01_standalone_sdk/48_conversation_fork.py | ✅ PASS | 20.1s | $0.01 |
| 01_standalone_sdk/49_switch_llm_tool.py | ✅ PASS | 8.0s | $0.04 |
| 01_standalone_sdk/50_async_cancellation.py | ✅ PASS | 14.0s | $0.00 |
| 01_standalone_sdk/51_agent_hooks/main.py | ✅ PASS | 39.2s | $0.05 |
| 01_standalone_sdk/52_dynamic_workflow.py | ✅ PASS | 4m 29s | $0.16 |
| 01_standalone_sdk/53_client_defined_tools.py | ✅ PASS | 14.2s | $0.01 |
| 01_standalone_sdk/54_goal_completion_loop.py | ✅ PASS | 26.3s | $0.02 |
| 01_standalone_sdk/55_persistent_memory.py | ✅ PASS | 24.6s | $0.02 |
| 01_standalone_sdk/56_structured_output.py | ✅ PASS | 44.2s | $0.06 |
| 01_standalone_sdk/57_prompt_hooks/main.py | ✅ PASS | 16.1s | $0.00 |
| 01_standalone_sdk/58_ask_oracle_tool/main.py | ✅ PASS | 15.3s | $0.01 |
| 01_standalone_sdk/59_route_task_to_model.py | ✅ PASS | 9.4s | $0.05 |
| 02_remote_agent_server/01_convo_with_local_agent_server.py | ✅ PASS | 34.9s | $0.02 |
| 02_remote_agent_server/02_convo_with_docker_sandboxed_server.py | ✅ PASS | 57.0s | $0.04 |
| 02_remote_agent_server/03_browser_use_with_docker_sandboxed_server.py | ✅ PASS | 1m 49s | -- |
| 02_remote_agent_server/04_convo_with_api_sandboxed_server.py | ✅ PASS | 1m 36s | $0.02 |
| 02_remote_agent_server/06_custom_tool/main.py | ✅ PASS | 5m 28s | $0.05 |
| 02_remote_agent_server/07_convo_with_cloud_workspace.py | ✅ PASS | 41.4s | $0.03 |
| 02_remote_agent_server/08_convo_with_apptainer_sandboxed_server.py | ✅ PASS | 3m 41s | $0.02 |
| 02_remote_agent_server/09_acp_agent_with_remote_runtime.py | ✅ PASS | 1m 12s | $0.43 |
| 02_remote_agent_server/10_cloud_workspace_share_credentials.py | ✅ PASS | 51.5s | $0.00 |
| 02_remote_agent_server/11_conversation_fork.py | ✅ PASS | 43.9s | $0.00 |
| 02_remote_agent_server/12_settings_and_secrets_api.py | ✅ PASS | 2m 23s | $0.02 |
| 02_remote_agent_server/13_workspace_get_llm.py | ✅ PASS | 30.1s | $0.01 |
| 02_remote_agent_server/14_client_defined_tools.py | ✅ PASS | 35.5s | $0.02 |
| 02_remote_agent_server/15_openai_compatible_gateway.py | ✅ PASS | 18.5s | $0.02 |
| 02_remote_agent_server/16_deferred_init.py | ✅ PASS | 24.6s | $0.00 |
| 04_llm_specific_tools/01_gpt5_apply_patch_preset.py | ✅ PASS | 25.5s | $0.03 |
| 04_llm_specific_tools/02_gemini_file_tools.py | ✅ PASS | 38.8s | $0.08 |
| 05_skills_and_plugins/01_loading_agentskills/main.py | ✅ PASS | 18.2s | $0.02 |
| 05_skills_and_plugins/02_loading_plugins/main.py | ✅ PASS | 22.3s | $0.03 |
| 05_skills_and_plugins/04_mixed_marketplace_skills/main.py | ✅ PASS | 4.5s | $0.00 |
✅ All tests passed!
Total: 70 | Passed: 70 | Failed: 0 | Total Cost: $3.30
all-hands-bot
left a comment
There was a problem hiding this comment.
This review was posted by an AI agent (OpenHands).
Review: Fix example tmux socket paths
Scope. Test-only CI harness change in tests/examples/test_examples.py. It belongs in this repository (the examples workflow and its harness are owned here) and the product/architecture direction is unchanged; production tmux socket isolation is untouched.
Root cause verified. The old harness set TMUX_TMPDIR to pytest's long per-test tmp_path. tmux resolves its socket as <TMUX_TMPDIR>/tmux-<uid>/<socket_name>, and the unique socket names (openhands-<uuid4().hex>) push the combined path past the Unix sun_path limit. I reproduced this directly with tmux 3.5a:
- long pytest-style dir: path length 159 ->
error connecting to ... (File name too long) - short
/tmp/oh-ex-...dir: path length 71 -> rc=0
The change to tempfile.TemporaryDirectory(prefix="oh-ex-", dir="/tmp") keeps each example's socket dir short and still unique per test invocation, so parallel -n 4 workers stay isolated. Cleanup is handled by the context manager, which is strictly better than the mkdtemp approach suggested in #4049 (no leaked directories). The subprocess call and all result handling remain inside the with block, and stdout/stderr/returncode are assigned on both the success and TimeoutExpired paths, so no downstream reference is left unbound.
Verification. The test-examples workflow on the exact head 3e901e4 completed with all 70 examples passing (Run Examples Scripts, run 37250898290). The full head check set is green, including windows-tests, pre-commit, tools-tests, and agent-server-tests. I also ran the focused default-mode test locally on the checked-out head: 1 passed, 70 skipped. The linked issue #4049 (closed) already carries the port-collision half of the flake fixed separately (14_client_defined_tools.py now uses port 8004, distinct from 01's 8001), so this PR's narrower tmux scope is appropriate.
The hardcoded dir="/tmp" is Linux-only by design, which is acceptable here because the run-examples workflow runs on ubuntu-24.04 and tmux is Unix-only.
No material correctness, security, compatibility, or acceptance-criterion findings on the current head.
✅ APPROVED
HUMAN:
This is a CI fix and does not require manual QA
AGENT:
Why
The examples workflow can fail after tmux sockets became uniquely named per terminal pool. The existing test harness sets
TMUX_TMPDIRto pytest's long per-testtmp_path; tmux then appendstmux-<uid>/<socket_name>, and the longer unique socket name can exceed Unix socket path limits.Summary
TMUX_TMPDIRunder/tmpintests/examples/test_examples.py.Issue Number
#4049
How to Test
Commands run:
Results:
uv run pytest tests/examples/test_examples.py -qpassed in default mode:1 passed, 70 skipped.TerminalExecutorwith a shortTMUX_TMPDIRsuch as/tmp/oh-ex-jk3oxtivand returnedreturncode: 0.I did not run the full
--run-examplesworkflow locally because it exercises many LLM-backed examples and requires CI-provided model/runtime credentials. The focused smoke test covers the failing tmux initialization path from the release PR logs.Video/Screenshots
N/A
Design Doc
N/A
Type
Notes
This PR was created by an AI agent (OpenHands) on behalf of the user.
@malhotra5 can click here to continue refining the PR
🐳 Agent Server images for this PR — GHCR package, pull/run commands, and all pushed tags (click to expand)
• GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server
Variants & Base Images
eclipse-temurin:17-jdkpython-node-runtimepython-node-runtimepython-node-runtimegolang:1.21-bookwormPull (multi-arch manifest)
# Each variant is a multi-arch manifest supporting both amd64 and arm64 docker pull ghcr.io/openhands/agent-server:3e901e4-pythonRun
All tags pushed for this build
About Multi-Architecture Support
3e901e4-python) is a multi-arch manifest supporting both amd64 and arm643e901e4-python-amd64) are also available if needed