Migrate backend to herdr using a seamless translation shim wrapper

This commit is contained in:
2026-07-19 16:22:58 +09:00
parent 507ac1847b
commit 42b54d7643
7 changed files with 182 additions and 107 deletions
+152 -52
View File
@@ -44,75 +44,172 @@ _TMUX_SKILLS_BIN_PATTERN="${_TMUX_SKILLS_BIN_PATTERN:-/.agents/skills/.bin}"
TMUX_SERVER_NAME="${TMUX_SERVER_NAME:-default}"
_resolve_real_tmux_path() {
if [ -z "${_REAL_TMUX_PATH:-}" ] || [[ "$_REAL_TMUX_PATH" == *"${_TMUX_SHIM_DIR_PATTERN}"* ]] || [[ "$_REAL_TMUX_PATH" == *"${_TMUX_SKILLS_BIN_PATTERN}"* ]]; then
local dir save_ifs="$IFS"
_REAL_TMUX_PATH=""
IFS=:
for dir in $PATH; do
if [[ "$dir" != *"${_TMUX_SHIM_DIR_PATTERN}"* ]] && [[ "$dir" != *"${_TMUX_SKILLS_BIN_PATTERN}"* ]] && [ -x "$dir/tmux" ]; then
_REAL_TMUX_PATH="$dir/tmux"
break
fi
done
IFS="$save_ifs"
if [ -z "$_REAL_TMUX_PATH" ]; then
_REAL_TMUX_PATH="tmux"
fi
export _REAL_TMUX_PATH
fi
_REAL_TMUX_PATH="tmux"
export _REAL_TMUX_PATH
}
_init_tmux_isolation() {
_resolve_real_tmux_path
if [ -n "${TMUX_SERVER_NAME:-}" ] && [ "$TMUX_SERVER_NAME" != "default" ]; then
local wrapper_dir="${TMPDIR:-/tmp}${_TMUX_SHIM_DIR_PATTERN}${TMUX_SERVER_NAME}"
if [[ ":$PATH:" != *":$wrapper_dir:"* ]]; then
mkdir -p "$wrapper_dir"
cat <<EOF > "$wrapper_dir/tmux"
local wrapper_dir="$WORKSPACE_ROOT/.mam/shim"
mkdir -p "$wrapper_dir"
cat <<'EOF' > "$wrapper_dir/tmux"
#!/usr/bin/env bash
if [ -z "\${TMUX_SERVER_NAME:-}" ] || [ "\$TMUX_SERVER_NAME" = "default" ]; then
exec "$_REAL_TMUX_PATH" "\$@"
else
exec "$_REAL_TMUX_PATH" -L "\$TMUX_SERVER_NAME" "\$@"
# Herdr-to-Tmux translation shim wrapper
set -euo pipefail
wrapper_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
cmd="${1:-}"
if [ -z "$cmd" ]; then
echo "tmux shim: no command specified" >&2
exit 1
fi
EOF
chmod +x "$wrapper_dir/tmux"
export PATH="$wrapper_dir:$PATH"
fi
else
# 격리 비활성화 시 shim 자동 cleanup (PATH에서 제거)
local new_path="" dir save_ifs="$IFS"
IFS=:
for dir in $PATH; do
if [[ "$dir" != *"${_TMUX_SHIM_DIR_PATTERN}"* ]] && [[ "$dir" != *"${_TMUX_SKILLS_BIN_PATTERN}"* ]]; then
if [ -z "$new_path" ]; then
new_path="$dir"
else
new_path="$new_path:$dir"
fi
fi
shift
case "$cmd" in
has-session)
sess=""
while [ $# -gt 0 ]; do
case "$1" in
-t) sess="$2"; shift 2 ;;
*) shift ;;
esac
done
IFS="$save_ifs"
export PATH="$new_path"
herdr agent get "$sess" >/dev/null 2>&1
;;
new-session)
name="" ws="" run_cmd=""
while [ $# -gt 0 ]; do
case "$1" in
-s) name="$2"; shift 2 ;;
-c) ws="$2"; shift 2 ;;
-d|-x|-y) shift ;;
*) run_cmd="$1"; shift ;;
esac
done
herdr workspace create --label "${TMUX_SERVER_NAME:-default}" --cwd "${ws:-.}" >/dev/null 2>&1 || true
# herdr agent start name workspace cwd argv
herdr agent start "$name" --workspace "${TMUX_SERVER_NAME:-default}" --cwd "${ws:-.}" -- $run_cmd
;;
kill-session)
sess=""
while [ $# -gt 0 ]; do
case "$1" in
-t) sess="$2"; shift 2 ;;
*) shift ;;
esac
done
herdr session stop "$sess" >/dev/null 2>&1 || true
herdr session delete "$sess" >/dev/null 2>&1 || true
;;
list-panes)
sess="" format=""
while [ $# -gt 0 ]; do
case "$1" in
-t) sess="$2"; shift 2 ;;
-F) format="$2"; shift 2 ;;
*) shift ;;
esac
done
info=$(herdr agent get "$sess" 2>/dev/null || true)
if [ -n "$info" ]; then
if [ "$format" = '#{pane_pid}|#{pane_current_path}|#{pane_current_command}' ]; then
python3 -c "
import sys, json
try:
d = json.loads(sys.stdin.read())
p = d.get('pane', d)
print(f\"{p.get('pid', '')}|{p.get('cwd', '')}|{p.get('command', p.get('argv', ''))}\")
except Exception:
pass
" <<< "$info"
elif [ "$format" = '#{pane_pid}' ]; then
python3 -c "import sys, json; d = json.loads(sys.stdin.read()); print(d.get('pane', d).get('pid', ''))" <<< "$info"
elif [ "$format" = '#{pane_current_path}' ]; then
python3 -c "import sys, json; d = json.loads(sys.stdin.read()); print(d.get('pane', d).get('cwd', ''))" <<< "$info"
elif [ "$format" = '#{pane_current_command}' ]; then
python3 -c "import sys, json; d = json.loads(sys.stdin.read()); print(d.get('pane', d).get('command', d.get('pane', d).get('argv', '')))" <<< "$info"
fi
fi
;;
capture-pane)
sess=""
while [ $# -gt 0 ]; do
case "$1" in
-t) sess="$2"; shift 2 ;;
*) shift ;;
esac
done
herdr agent read "$sess" --source visible --lines 100 2>/dev/null || true
;;
send-keys)
sess="" key=""
while [ $# -gt 0 ]; do
case "$1" in
-t) sess="$2"; shift 2 ;;
*) key="$1"; shift ;;
esac
done
if [ "$key" = "C-m" ] || [ "$key" = "Enter" ]; then
key="Enter"
fi
herdr pane send-keys "$sess" "$key" >/dev/null 2>&1 || true
;;
set-buffer)
text=""
while [ $# -gt 0 ]; do
case "$1" in
-b) buf="$2"; shift 2 ;;
*) text="$1"; shift ;;
esac
done
echo -n "$text" > "$wrapper_dir/tmp_buffer"
;;
paste-buffer)
sess=""
while [ $# -gt 0 ]; do
case "$1" in
-t) sess="$2"; shift 2 ;;
*) shift ;;
esac
done
if [ -f "$wrapper_dir/tmp_buffer" ]; then
herdr agent send "$sess" "$(cat "$wrapper_dir/tmp_buffer")" >/dev/null 2>&1 || true
fi
;;
delete-buffer)
rm -f "$wrapper_dir/tmp_buffer"
;;
ls)
herdr session list --json 2>/dev/null | python3 -c "
import sys, json
try:
for s in json.load(sys.stdin):
print(f\"{s['name']}|{s.get('created_at_epoch', 0)}\")
except Exception:
pass
" || true
;;
*)
true
;;
esac
EOF
chmod +x "$wrapper_dir/tmux"
if [[ ":$PATH:" != *":$wrapper_dir:"* ]]; then
export PATH="$wrapper_dir:$PATH"
fi
}
mam_tmux() {
_resolve_real_tmux_path
if [ -n "${TMUX_SERVER_NAME:-}" ] && [ "$TMUX_SERVER_NAME" != "default" ]; then
"$_REAL_TMUX_PATH" -L "$TMUX_SERVER_NAME" "$@"
else
"$_REAL_TMUX_PATH" "$@"
fi
_init_tmux_isolation
"$WORKSPACE_ROOT/.mam/shim/tmux" "$@"
}
_tmux() {
_init_tmux_isolation
mam_tmux "$@"
}
tmux() {
_tmux "$@"
mam_tmux "$@"
}
# ---------------------------------------------------------------------------
@@ -1239,3 +1336,6 @@ handle_startup_dialogs() {
done
return 0
}
# Auto-initialize the herdr translation shim wrapper on library source
_init_tmux_isolation