From 9720a9d2bef8d106739d986a767f967fda376867 Mon Sep 17 00:00:00 2001 From: brettheap Date: Sat, 25 Jul 2026 02:18:40 -0400 Subject: [PATCH 1/2] fix: make Wave bench launches responsive --- README.md | 4 ++++ bin/wave-container-shell.sh | 31 +++++++++++++++++++++++++++++++ docs/workbenches-widgets.md | 4 ++++ 3 files changed, 39 insertions(+) diff --git a/README.md b/README.md index 330dc63..415c260 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,10 @@ recreates it directly with the Wave Docker Compose override. This avoids a known Dev Containers CLI hang where the container starts but the CLI never returns, so Wave never reaches the final interactive shell. +For a running container, the launcher displays startup status immediately and +skips profile-launcher copies when the previously installed content hash still +matches. + The fallback override mounts shell and agent configuration from the WSL home directory so the container shell keeps the same `zsh`, Oh My Zsh, Powerlevel10k, Git, GitHub CLI, SSH, and agent settings. diff --git a/bin/wave-container-shell.sh b/bin/wave-container-shell.sh index 9a41791..3547b39 100755 --- a/bin/wave-container-shell.sh +++ b/bin/wave-container-shell.sh @@ -91,6 +91,11 @@ if ! command -v docker >/dev/null 2>&1; then exit 1 fi +if [[ "$check_only" != true ]]; then + printf '\033]0;%s\007' "$block_title" + echo "Opening '$block_title' container shell..." +fi + run_devcontainer_up() { local remove_flag=() local devcontainer_timeout="${WAVE_DEVCONTAINER_UP_TIMEOUT:-25s}" @@ -304,6 +309,30 @@ install_ai_profile_launchers() { local pi_launcher="$workbenches_root/base-image/files/pi-profile" [[ -f "$claude_launcher" ]] || return 0 + local marker="/usr/local/share/workbenches/profile-launchers.sha256" + local launchers=( + "$claude_launcher" + "$codex_launcher" + "$provider_launcher" + "$pi_launcher" + ) + local bundle_hash + bundle_hash="$( + for launcher in "${launchers[@]}"; do + if [[ -f "$launcher" ]]; then + sha256sum "$launcher" | awk '{print $1}' + else + printf '%s\n' missing + fi + done | sha256sum | awk '{print $1}' + )" + + local installed_hash + installed_hash="$(docker exec --user root "$container" sh -c "cat '$marker' 2>/dev/null" || true)" + if [[ "$installed_hash" == "$bundle_hash" ]]; then + return 0 + fi + docker cp "$claude_launcher" "$container:/usr/local/bin/claude-profile" docker exec --user root "$container" sh -c \ 'chmod 0755 /usr/local/bin/claude-profile && ln -sfn claude-profile /usr/local/bin/pclaude' @@ -329,6 +358,8 @@ install_ai_profile_launchers() { "mkdir -p '/home/${container_user}/.local/bin' && chown '${container_user}:${container_user}' '/home/${container_user}/.local' '/home/${container_user}/.local/bin'" docker exec --user "$container_user" "$container" sh -c \ 'if [ ! -e "$HOME/.local/bin/claude" ]; then ln -s /usr/local/bin/claude "$HOME/.local/bin/claude"; fi' + docker exec --user root "$container" sh -c \ + "mkdir -p '$(dirname "$marker")' && printf '%s\n' '$bundle_hash' > '$marker'" } ensure_container_history diff --git a/docs/workbenches-widgets.md b/docs/workbenches-widgets.md index 48b4947..e7a0f4b 100644 --- a/docs/workbenches-widgets.md +++ b/docs/workbenches-widgets.md @@ -26,6 +26,10 @@ shell with `wave-container-shell.sh`. The launcher makes sure the Docker container exists, starts it if needed, and runs an interactive login `zsh` shell inside the container. +The launcher prints an `Opening ...` status immediately. Shared AI profile +launchers are synchronized only when their combined content hash changes, so a +healthy running bench is not delayed by repeated `docker cp` operations. + The widget title is set in two ways: - terminal OSC title escape From 33d5577ba970b053b9080479790a72f1f888d505 Mon Sep 17 00:00:00 2001 From: brettheap Date: Sat, 25 Jul 2026 02:22:36 -0400 Subject: [PATCH 2/2] fix: preserve cached launcher repair --- bin/wave-container-shell.sh | 57 +++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/bin/wave-container-shell.sh b/bin/wave-container-shell.sh index 3547b39..7126178 100755 --- a/bin/wave-container-shell.sh +++ b/bin/wave-container-shell.sh @@ -12,6 +12,7 @@ workdir="/workspace" shell_path="zsh" block_title="pyBench" check_only=false +profile_launcher_marker="/usr/local/share/workbenches/profile-launchers.sha256" bench_dir="$workbenches_root/devBenches/pyBench" compose_file="$bench_dir/.devcontainer/docker-compose.yml" @@ -92,7 +93,9 @@ if ! command -v docker >/dev/null 2>&1; then fi if [[ "$check_only" != true ]]; then - printf '\033]0;%s\007' "$block_title" + if [[ -t 1 ]]; then + printf '\033]0;%s\007' "$block_title" + fi echo "Opening '$block_title' container shell..." fi @@ -309,7 +312,6 @@ install_ai_profile_launchers() { local pi_launcher="$workbenches_root/base-image/files/pi-profile" [[ -f "$claude_launcher" ]] || return 0 - local marker="/usr/local/share/workbenches/profile-launchers.sha256" local launchers=( "$claude_launcher" "$codex_launcher" @@ -328,38 +330,37 @@ install_ai_profile_launchers() { )" local installed_hash - installed_hash="$(docker exec --user root "$container" sh -c "cat '$marker' 2>/dev/null" || true)" - if [[ "$installed_hash" == "$bundle_hash" ]]; then - return 0 - fi - - docker cp "$claude_launcher" "$container:/usr/local/bin/claude-profile" - docker exec --user root "$container" sh -c \ - 'chmod 0755 /usr/local/bin/claude-profile && ln -sfn claude-profile /usr/local/bin/pclaude' - if [[ -f "$codex_launcher" ]]; then - docker cp "$codex_launcher" "$container:/usr/local/bin/codex-profile" - docker exec --user root "$container" sh -c \ - 'chmod 0755 /usr/local/bin/codex-profile && ln -sfn codex-profile /usr/local/bin/pcodex' - fi - if [[ -f "$provider_launcher" ]]; then - docker cp "$provider_launcher" "$container:/usr/local/bin/provider-profile" + installed_hash="$(docker exec --user root "$container" sh -c "cat '$profile_launcher_marker' 2>/dev/null" || true)" + if [[ "$installed_hash" != "$bundle_hash" ]]; then + docker cp "$claude_launcher" "$container:/usr/local/bin/claude-profile" docker exec --user root "$container" sh -c \ - 'chmod 0755 /usr/local/bin/provider-profile - for name in gemini-profile pgemini grok-profile pgrok glm-profile zai-profile pglm pzai; do - ln -sfn provider-profile "/usr/local/bin/$name" - done' - fi - if [[ -f "$pi_launcher" ]]; then - docker cp "$pi_launcher" "$container:/usr/local/bin/pi-profile" + 'chmod 0755 /usr/local/bin/claude-profile && ln -sfn claude-profile /usr/local/bin/pclaude' + if [[ -f "$codex_launcher" ]]; then + docker cp "$codex_launcher" "$container:/usr/local/bin/codex-profile" + docker exec --user root "$container" sh -c \ + 'chmod 0755 /usr/local/bin/codex-profile && ln -sfn codex-profile /usr/local/bin/pcodex' + fi + if [[ -f "$provider_launcher" ]]; then + docker cp "$provider_launcher" "$container:/usr/local/bin/provider-profile" + docker exec --user root "$container" sh -c \ + 'chmod 0755 /usr/local/bin/provider-profile + for name in gemini-profile pgemini grok-profile pgrok glm-profile zai-profile pglm pzai; do + ln -sfn provider-profile "/usr/local/bin/$name" + done' + fi + if [[ -f "$pi_launcher" ]]; then + docker cp "$pi_launcher" "$container:/usr/local/bin/pi-profile" + docker exec --user root "$container" sh -c \ + 'chmod 0755 /usr/local/bin/pi-profile && ln -sfn pi-profile /usr/local/bin/ppi' + fi docker exec --user root "$container" sh -c \ - 'chmod 0755 /usr/local/bin/pi-profile && ln -sfn pi-profile /usr/local/bin/ppi' + "mkdir -p '$(dirname "$profile_launcher_marker")' && printf '%s\n' '$bundle_hash' > '$profile_launcher_marker'" fi + docker exec --user root "$container" sh -c \ "mkdir -p '/home/${container_user}/.local/bin' && chown '${container_user}:${container_user}' '/home/${container_user}/.local' '/home/${container_user}/.local/bin'" docker exec --user "$container_user" "$container" sh -c \ - 'if [ ! -e "$HOME/.local/bin/claude" ]; then ln -s /usr/local/bin/claude "$HOME/.local/bin/claude"; fi' - docker exec --user root "$container" sh -c \ - "mkdir -p '$(dirname "$marker")' && printf '%s\n' '$bundle_hash' > '$marker'" + 'ln -sfn /usr/local/bin/claude "$HOME/.local/bin/claude"' } ensure_container_history