Implement full E2E, integration, component, and unit tests, and resolve all leftover tmux-to-herdr issues in UI and core scripts

This commit is contained in:
2026-07-19 20:05:48 +09:00
parent 30e606b0fa
commit ff7a2873f9
29 changed files with 3099 additions and 95 deletions
+121 -21
View File
@@ -28,7 +28,7 @@ AGENT_SESSIONS_YAML="${AGENT_SESSIONS_YAML:-$WORKSPACE_ROOT/.mam/agent-sessions.
# Add common Homebrew and local binary paths to PATH to ensure they are available in non-interactive shells
for dir in /home/linuxbrew/.linuxbrew/bin /home/linuxbrew/.linuxbrew/sbin "$HOME/.local/bin" "$HOME/.npm-global/bin"; do
if [ -d "$dir" ] && [[ ":$PATH:" != *":$dir:"* ]]; then
export PATH="$dir:$PATH"
export PATH="$PATH:$dir"
fi
done
@@ -58,7 +58,16 @@ _resolve_real_herdr_path() {
_init_herdr_isolation() {
local wrapper_dir="$WORKSPACE_ROOT/.mam/shim"
mkdir -p "$wrapper_dir"
cat <<'EOF' > "$wrapper_dir/herdr"
if [ -x "$wrapper_dir/herdr" ]; then
if [[ ":$PATH:" != *":$wrapper_dir:"* ]]; then
export PATH="$wrapper_dir:$PATH"
fi
return 0
fi
local tmp_file
tmp_file=$(mktemp "$wrapper_dir/herdr.XXXXXX")
cat <<'EOF' > "$tmp_file"
#!/usr/bin/env bash
# Herdr-to-Herdr translation shim wrapper
set -euo pipefail
@@ -81,6 +90,16 @@ _resolve_real_herdr() {
}
REAL_HERDR=$(_resolve_real_herdr)
# Support parsing -L <server> before the subcommand
while [ "${1:-}" = "-L" ]; do
if [ $# -lt 2 ]; then
echo "herdr shim: -L requires an argument" >&2
exit 1
fi
export HERDR_SERVER_NAME="$2"
shift 2
done
wrapper_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
cmd="${1:-}"
if [ -z "$cmd" ]; then
@@ -89,12 +108,20 @@ if [ -z "$cmd" ]; then
fi
shift
case "$cmd" in
has-session)
sess=""
while [ $# -gt 0 ]; do
case "$1" in
-t) sess="$2"; shift 2 ;;
-t)
if [ $# -lt 2 ]; then
echo "Error: -t requires a value" >&2
exit 1
fi
sess="$2"
shift 2
;;
*) shift ;;
esac
done
@@ -104,12 +131,29 @@ case "$cmd" in
name="" ws="" run_cmd=""
while [ $# -gt 0 ]; do
case "$1" in
-s) name="$2"; shift 2 ;;
-c) ws="$2"; shift 2 ;;
-s)
if [ $# -lt 2 ]; then
echo "Error: -s requires a value" >&2
exit 1
fi
name="$2"
shift 2
;;
-c)
if [ $# -lt 2 ]; then
echo "Error: -c requires a value" >&2
exit 1
fi
ws="$2"
shift 2
;;
-d|-x|-y) shift ;;
*) run_cmd="$1"; shift ;;
esac
done
if [ -z "$run_cmd" ]; then
run_cmd="${SHELL:-/bin/bash}"
fi
"$REAL_HERDR" workspace create --label "${HERDR_SERVER_NAME:-default}" --cwd "${ws:-.}" >/dev/null 2>&1 || true
parsed=$(python3 -c "
@@ -136,13 +180,14 @@ print('\t'.join(env_flags) + '\n' + ' '.join(binary_tokens))
ws_label="${HERDR_SERVER_NAME:-default}"
ws_id="w1"
if [ "$ws_label" != "default" ]; then
ws_id=$("$REAL_HERDR" workspace list 2>/dev/null | python3 -c "
import sys, json
ws_id=$("$REAL_HERDR" workspace list 2>/dev/null | WS_LABEL="$ws_label" python3 -c "
import sys, os, json
try:
ws_label = os.environ.get('WS_LABEL', '')
data = json.loads(sys.stdin.read())
res = data.get('result', data)
for ws in res.get('workspaces', []):
if ws.get('label') == '$ws_label' or ws.get('workspace_id') == '$ws_label':
if ws.get('label') == ws_label or ws.get('workspace_id') == ws_label:
print(ws.get('workspace_id'))
sys.exit(0)
except Exception:
@@ -157,7 +202,14 @@ except Exception:
sess=""
while [ $# -gt 0 ]; do
case "$1" in
-t) sess="$2"; shift 2 ;;
-t)
if [ $# -lt 2 ]; then
echo "Error: -t requires a value" >&2
exit 1
fi
sess="$2"
shift 2
;;
*) shift ;;
esac
done
@@ -168,8 +220,22 @@ except Exception:
sess="" format=""
while [ $# -gt 0 ]; do
case "$1" in
-t) sess="$2"; shift 2 ;;
-F) format="$2"; shift 2 ;;
-t)
if [ $# -lt 2 ]; then
echo "Error: -t requires a value" >&2
exit 1
fi
sess="$2"
shift 2
;;
-F)
if [ $# -lt 2 ]; then
echo "Error: -F requires a value" >&2
exit 1
fi
format="$2"
shift 2
;;
*) shift ;;
esac
done
@@ -198,7 +264,14 @@ except Exception:
sess=""
while [ $# -gt 0 ]; do
case "$1" in
-t) sess="$2"; shift 2 ;;
-t)
if [ $# -lt 2 ]; then
echo "Error: -t requires a value" >&2
exit 1
fi
sess="$2"
shift 2
;;
*) shift ;;
esac
done
@@ -208,7 +281,14 @@ except Exception:
sess="" key=""
while [ $# -gt 0 ]; do
case "$1" in
-t) sess="$2"; shift 2 ;;
-t)
if [ $# -lt 2 ]; then
echo "Error: -t requires a value" >&2
exit 1
fi
sess="$2"
shift 2
;;
*) key="$1"; shift ;;
esac
done
@@ -221,7 +301,14 @@ except Exception:
text=""
while [ $# -gt 0 ]; do
case "$1" in
-b) buf="$2"; shift 2 ;;
-b)
if [ $# -lt 2 ]; then
echo "Error: -b requires a value" >&2
exit 1
fi
buf="$2"
shift 2
;;
*) text="$1"; shift ;;
esac
done
@@ -231,7 +318,14 @@ except Exception:
sess=""
while [ $# -gt 0 ]; do
case "$1" in
-t) sess="$2"; shift 2 ;;
-t)
if [ $# -lt 2 ]; then
echo "Error: -t requires a value" >&2
exit 1
fi
sess="$2"
shift 2
;;
*) shift ;;
esac
done
@@ -249,7 +343,11 @@ try:
data = json.load(sys.stdin)
res = data.get('result', data)
for a in res.get('agents', []):
print(f\"{a['name']}|0\")
try:
name = a.get('name') or a.get('agent') or 'unknown'
print(f\"{name}|0\")
except Exception:
pass
except Exception:
pass
" || true
@@ -259,7 +357,8 @@ except Exception:
;;
esac
EOF
chmod +x "$wrapper_dir/herdr"
chmod +x "$tmp_file"
mv -f "$tmp_file" "$wrapper_dir/herdr"
if [[ ":$PATH:" != *":$wrapper_dir:"* ]]; then
export PATH="$wrapper_dir:$PATH"
fi
@@ -334,7 +433,7 @@ name = os.environ['SESSION_NAME']
d = json.loads(os.environ.get('MAM_STATE_JSON', '{}'))
for s in d.get('herdr_sessions', []):
if s.get('name') == name:
print(s.get('herdr_workspace', 'default'))
print(s.get('herdr_workspace') or s.get('herdr_server') or 'default')
sys.exit(0)
print(os.environ.get('HERDR_SERVER_NAME', 'default'))
")
@@ -342,13 +441,14 @@ print(os.environ.get('HERDR_SERVER_NAME', 'default'))
echo "w1"
else
local ws_id
ws_id=$(herdr workspace list 2>/dev/null | python3 -c "
import sys, json
ws_id=$(herdr workspace list 2>/dev/null | RAW_LABEL="$raw_label" python3 -c "
import sys, os, json
try:
raw_label = os.environ.get('RAW_LABEL', '')
data = json.loads(sys.stdin.read())
res = data.get('result', data)
for ws in res.get('workspaces', []):
if ws.get('label') == '$raw_label' or ws.get('workspace_id') == '$raw_label':
if ws.get('label') == raw_label or ws.get('workspace_id') == raw_label:
print(ws.get('workspace_id'))
sys.exit(0)
except Exception: