diff --git a/swarmforge/scripts/swarm-terminal-adapter.sh b/swarmforge/scripts/swarm-terminal-adapter.sh index 62ea0f55..cae073e3 100755 --- a/swarmforge/scripts/swarm-terminal-adapter.sh +++ b/swarmforge/scripts/swarm-terminal-adapter.sh @@ -15,6 +15,9 @@ normalize_terminal_backend() { windows|windows-terminal|wt) echo "windows-terminal" ;; + wezterm|wez) + echo "wezterm" + ;; none|current|fallback) echo "none" ;; @@ -30,6 +33,11 @@ detect_terminal_backend() { return fi + if [[ "${TERM_PROGRAM:-}" == "WezTerm" ]] || [[ -n "${WEZTERM_PANE:-}" ]]; then + echo "wezterm" + return + fi + if has_command osascript; then if [[ "${TERM_PROGRAM:-}" == "iTerm.app" ]]; then echo "iterm2" diff --git a/swarmforge/scripts/swarmforge.bb b/swarmforge/scripts/swarmforge.bb index b26322c5..c4961622 100755 --- a/swarmforge/scripts/swarmforge.bb +++ b/swarmforge/scripts/swarmforge.bb @@ -46,6 +46,7 @@ ("iterm" "iterm2" "iterm.app") "iterm2" ("terminal" "terminal-app" "terminal.app") "terminal-app" ("windows" "windows-terminal" "wt") "windows-terminal" + ("wezterm" "wez") "wezterm" ("none" "current" "fallback") "none" (str/lower-case backend))) @@ -53,6 +54,8 @@ (if-let [backend (System/getenv "SWARMFORGE_TERMINAL")] (normalize-terminal-backend backend) (cond + (or (= (System/getenv "TERM_PROGRAM") "WezTerm") + (some? (System/getenv "WEZTERM_PANE"))) "wezterm" (command-exists? "osascript") (if (= (System/getenv "TERM_PROGRAM") "iTerm.app") "iterm2" "terminal-app") @@ -226,7 +229,7 @@ "swarm-terminal-adapter.sh" "swarmforge.sh" "swarmforge.bb"]) (def terminal-helpers - ["terminal-app.sh" "iterm2.sh" "ghostty.sh" "windows-terminal.sh" "none.sh"]) + ["terminal-app.sh" "iterm2.sh" "ghostty.sh" "windows-terminal.sh" "wezterm.sh" "none.sh"]) (defn check-helper-scripts! [ctx] (doseq [helper required-helpers] diff --git a/swarmforge/scripts/terminal-adapters/wezterm.sh b/swarmforge/scripts/terminal-adapters/wezterm.sh new file mode 100755 index 00000000..4a7f1736 --- /dev/null +++ b/swarmforge/scripts/terminal-adapters/wezterm.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env zsh + +terminal_backend_label() { + echo "WezTerm" +} + +terminal_backend_can_open_sessions() { + return 0 +} + +terminal_backend_tracks_windows() { + return 0 +} + +terminal_window_exists() { + local pane_id="$1" + [[ -n "$pane_id" ]] || return 1 + + local list + list="$(wezterm cli list --format json 2>/dev/null)" || return 1 + + if command -v jq &>/dev/null; then + echo "$list" | jq -e --argjson id "$pane_id" 'any(.[]; .pane_id == $id)' &>/dev/null + else + echo "$list" | python3 -c " +import sys, json +data = json.load(sys.stdin) +sys.exit(0 if any(p['pane_id'] == $pane_id for p in data) else 1) +" 2>/dev/null + fi +} + +terminal_open_session() { + local session="$1" + local title="$2" + local sibling_id="${3:-}" + + local spawn_args=() + + if [[ -n "$sibling_id" ]]; then + local list window_id + list="$(wezterm cli list --format json 2>/dev/null)" + if command -v jq &>/dev/null; then + window_id="$(echo "$list" | jq -r --argjson id "$sibling_id" \ + '.[] | select(.pane_id == $id) | .window_id')" + else + window_id="$(echo "$list" | python3 -c " +import sys, json +data = json.load(sys.stdin) +matches = [str(p['window_id']) for p in data if p['pane_id'] == $sibling_id] +if matches: print(matches[0]) +" 2>/dev/null)" + fi + [[ -n "$window_id" ]] && spawn_args+=(--window-id "$window_id") + fi + + local pane_id + pane_id="$(wezterm cli spawn "${spawn_args[@]}" --cwd "$WORKING_DIR" \ + -- bash -lc "exec tmux -S $(printf '%q' "$TMUX_SOCKET") attach-session -t $(printf '%q' "$session")")" + + [[ -n "$pane_id" ]] && wezterm cli set-tab-title --pane-id "$pane_id" "$title" 2>/dev/null || true + + echo "$pane_id" +} + +terminal_close_window() { + local pane_id="$1" + [[ -n "$pane_id" ]] || return 0 + + wezterm cli kill-pane --pane-id "$pane_id" 2>/dev/null || true +}