fix(herdr): support Herdr 0.8.0 pane allocation, agent prompt, and length limits
This commit is contained in:
+77
-20
@@ -188,6 +188,18 @@ _real_herdr() {
|
||||
fi
|
||||
}
|
||||
|
||||
_sanitize_herdr_agent_name() {
|
||||
local n="$1"
|
||||
if [ "${#n}" -le 32 ]; then
|
||||
printf '%s\n' "$n"
|
||||
return 0
|
||||
fi
|
||||
local p="${n:0:16}"
|
||||
local s="${n: -15}"
|
||||
local res="${p}-${s}"
|
||||
printf '%s\n' "${res:0:32}"
|
||||
}
|
||||
|
||||
wrapper_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
cmd="${1:-}"
|
||||
if [ -z "$cmd" ]; then
|
||||
@@ -196,7 +208,6 @@ if [ -z "$cmd" ]; then
|
||||
fi
|
||||
shift
|
||||
|
||||
|
||||
case "$cmd" in
|
||||
has-session)
|
||||
sess=""
|
||||
@@ -213,7 +224,7 @@ case "$cmd" in
|
||||
*) shift ;;
|
||||
esac
|
||||
done
|
||||
_real_herdr agent get "$sess" >/dev/null
|
||||
_real_herdr agent get "$(_sanitize_herdr_agent_name "$sess")" >/dev/null 2>&1 || _real_herdr agent get "$sess" >/dev/null
|
||||
;;
|
||||
new-session)
|
||||
name="" ws="" run_cmd=""
|
||||
@@ -317,8 +328,7 @@ except Exception:
|
||||
" 2>/dev/null || echo "")
|
||||
|
||||
ws_id=""
|
||||
split_arg=""
|
||||
|
||||
target_pane=""
|
||||
if [ -n "$existing_ws" ]; then
|
||||
# W2a: Determine split direction policy via pane layout
|
||||
sample_pane=$(_real_herdr pane list 2>/dev/null | TARGET_WS="$existing_ws" python3 -c "
|
||||
@@ -367,26 +377,42 @@ except Exception:
|
||||
fi
|
||||
|
||||
if [ "$split_dir" = "right" ] || [ "$split_dir" = "down" ]; then
|
||||
ws_id="$existing_ws"
|
||||
split_arg="--split $split_dir"
|
||||
split_json=$(_real_herdr pane split --pane "$sample_pane" --direction "$split_dir" --cwd "${ws:-.}" --no-focus 2>/dev/null || echo "")
|
||||
target_pane=$(echo "$split_json" | python3 -c "
|
||||
import sys, json
|
||||
try:
|
||||
d = json.loads(sys.stdin.read())
|
||||
res = d.get('result', {})
|
||||
print(res.get('pane', {}).get('pane_id') or res.get('pane_id', ''))
|
||||
except Exception:
|
||||
pass
|
||||
" 2>/dev/null || echo "")
|
||||
elif [ "$split_dir" = "overflow" ]; then
|
||||
# W2b: Overflow threshold reached — force create fresh workspace
|
||||
existing_ws=""
|
||||
else
|
||||
ws_id="$existing_ws"
|
||||
split_arg="--split right"
|
||||
split_json=$(_real_herdr pane split --pane "$sample_pane" --direction right --cwd "${ws:-.}" --no-focus 2>/dev/null || echo "")
|
||||
target_pane=$(echo "$split_json" | python3 -c "
|
||||
import sys, json
|
||||
try:
|
||||
d = json.loads(sys.stdin.read())
|
||||
res = d.get('result', {})
|
||||
print(res.get('pane', {}).get('pane_id') or res.get('pane_id', ''))
|
||||
except Exception:
|
||||
pass
|
||||
" 2>/dev/null || echo "")
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$existing_ws" ]; then
|
||||
if [ -z "$existing_ws" ] || [ -z "$target_pane" ]; then
|
||||
ws_json=$(_real_herdr workspace create --cwd "${ws:-.}" --no-focus 2>/dev/null || echo "")
|
||||
ws_id=$(echo "$ws_json" | python3 -c "
|
||||
target_pane=$(echo "$ws_json" | python3 -c "
|
||||
import sys, json
|
||||
try:
|
||||
d = json.loads(sys.stdin.read())
|
||||
res = d.get('result', {})
|
||||
w_obj = res.get('workspace', {})
|
||||
print(w_obj.get('workspace_id') or res.get('workspace_id', ''))
|
||||
print(res.get('root_pane', {}).get('pane_id') or w_obj.get('root_pane_id') or res.get('root_pane_id') or res.get('pane_id', ''))
|
||||
except Exception:
|
||||
pass
|
||||
" 2>/dev/null || echo "")
|
||||
@@ -396,11 +422,20 @@ except Exception:
|
||||
res=""
|
||||
success=0
|
||||
backoffs=(0.5 1 2)
|
||||
agent_name=$(_sanitize_herdr_agent_name "$name")
|
||||
for i in $(seq 0 2); do
|
||||
if [ -n "$ws_id" ]; then
|
||||
res=$(eval "_real_herdr agent start \"$name\" --workspace \"$ws_id\" --cwd \"${ws:-.}\" $split_arg $env_flags -- $final_cmd" 2>&1 || true)
|
||||
if [ -n "$target_pane" ]; then
|
||||
if [ -n "$final_cmd" ]; then
|
||||
res=$(eval "_real_herdr agent start \"$agent_name\" --kind \"${kind:-claude}\" --pane \"$target_pane\" $env_flags -- $final_cmd" 2>&1 || true)
|
||||
else
|
||||
res=$(eval "_real_herdr agent start \"$agent_name\" --kind \"${kind:-claude}\" --pane \"$target_pane\" $env_flags" 2>&1 || true)
|
||||
fi
|
||||
else
|
||||
res=$(eval "_real_herdr agent start \"$name\" --cwd \"${ws:-.}\" $split_arg $env_flags -- $final_cmd" 2>&1 || true)
|
||||
if [ -n "$final_cmd" ]; then
|
||||
res=$(eval "_real_herdr agent start \"$agent_name\" --kind \"${kind:-claude}\" $env_flags -- $final_cmd" 2>&1 || true)
|
||||
else
|
||||
res=$(eval "_real_herdr agent start \"$agent_name\" --kind \"${kind:-claude}\" $env_flags" 2>&1 || true)
|
||||
fi
|
||||
fi
|
||||
if echo "$res" | grep -q "agent_started"; then
|
||||
success=1
|
||||
@@ -438,7 +473,14 @@ except Exception:
|
||||
# `herdr session list`), not individual agent panes — `session stop/delete
|
||||
# "$sess"` with a MAM session name always fails (silently, via `|| true`).
|
||||
# Resolve the real pane_id via `agent get` and close just that pane instead.
|
||||
pane_id=$(_real_herdr agent get "$sess" 2>/dev/null | python3 -c "
|
||||
agent_target=$(_sanitize_herdr_agent_name "$sess")
|
||||
pane_id=$(_real_herdr agent get "$agent_target" 2>/dev/null | python3 -c "
|
||||
import sys, json
|
||||
try:
|
||||
print(json.load(sys.stdin).get('result', {}).get('agent', {}).get('pane_id', ''))
|
||||
except Exception:
|
||||
pass
|
||||
" 2>/dev/null || _real_herdr agent get "$sess" 2>/dev/null | python3 -c "
|
||||
import sys, json
|
||||
try:
|
||||
print(json.load(sys.stdin).get('result', {}).get('agent', {}).get('pane_id', ''))
|
||||
@@ -448,7 +490,7 @@ except Exception:
|
||||
if [ -n "$pane_id" ]; then
|
||||
_real_herdr pane close "$pane_id" >/dev/null 2>&1 || true
|
||||
fi
|
||||
_real_herdr kill-session -t "$sess" >/dev/null 2>&1 || true
|
||||
_real_herdr kill-session -t "$agent_target" >/dev/null 2>&1 || _real_herdr kill-session -t "$sess" >/dev/null 2>&1 || true
|
||||
;;
|
||||
list-panes)
|
||||
sess="" format=""
|
||||
@@ -477,7 +519,8 @@ except Exception:
|
||||
# there is no top-level "pane" key, and no "pid" field at all (only
|
||||
# "pane_id", herdr's own wN:pN identifier). The real OS pid requires a
|
||||
# second call to `pane process-info --pane <pane_id>`.
|
||||
info=$(_real_herdr agent get "$sess" 2>/dev/null || true)
|
||||
agent_target=$(_sanitize_herdr_agent_name "$sess")
|
||||
info=$(_real_herdr agent get "$agent_target" 2>/dev/null || _real_herdr agent get "$sess" 2>/dev/null || true)
|
||||
pane_id="" cwd="" cmd=""
|
||||
if [ -n "$info" ]; then
|
||||
parsed=$(python3 -c "
|
||||
@@ -546,7 +589,8 @@ except Exception:
|
||||
*) shift ;;
|
||||
esac
|
||||
done
|
||||
_real_herdr agent read "$sess" --source visible --lines 100 2>/dev/null || true
|
||||
agent_target=$(_sanitize_herdr_agent_name "$sess")
|
||||
_real_herdr agent read "$agent_target" --source visible --lines 100 2>/dev/null || _real_herdr agent read "$sess" --source visible --lines 100 2>/dev/null || true
|
||||
;;
|
||||
send-keys)
|
||||
sess="" key=""
|
||||
@@ -568,7 +612,14 @@ except Exception:
|
||||
fi
|
||||
# `pane send-keys` requires a real pane_id ("wN:pN"), not an agent name —
|
||||
# resolve it via `agent get` first (agent-level commands accept names).
|
||||
pane_id=$(_real_herdr agent get "$sess" 2>/dev/null | python3 -c "
|
||||
agent_target=$(_sanitize_herdr_agent_name "$sess")
|
||||
pane_id=$(_real_herdr agent get "$agent_target" 2>/dev/null | python3 -c "
|
||||
import sys, json
|
||||
try:
|
||||
print(json.load(sys.stdin).get('result', {}).get('agent', {}).get('pane_id', ''))
|
||||
except Exception:
|
||||
pass
|
||||
" 2>/dev/null || _real_herdr agent get "$sess" 2>/dev/null | python3 -c "
|
||||
import sys, json
|
||||
try:
|
||||
print(json.load(sys.stdin).get('result', {}).get('agent', {}).get('pane_id', ''))
|
||||
@@ -578,7 +629,7 @@ except Exception:
|
||||
if [ -n "$pane_id" ]; then
|
||||
_real_herdr pane send-keys "$pane_id" "$key" >/dev/null 2>&1 || true
|
||||
else
|
||||
_real_herdr pane send-keys "$sess" "$key" >/dev/null 2>&1 || true
|
||||
_real_herdr pane send-keys "$agent_target" "$key" >/dev/null 2>&1 || _real_herdr pane send-keys "$sess" "$key" >/dev/null 2>&1 || true
|
||||
fi
|
||||
;;
|
||||
set-buffer)
|
||||
@@ -1551,6 +1602,12 @@ _pane_dialog_open() {
|
||||
# changed); retry up to 3 times.
|
||||
send_keys_safe() {
|
||||
local sess="$1" text="$2" job_id="${3:-adhoc}"
|
||||
|
||||
# Native herdr 0.8+ fast path: agent prompt handles atomic text + enter submission
|
||||
if _sks_herdr agent prompt "$sess" "$text" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local marker pre_submit deadline try
|
||||
# Verification token: last 24 *characters* (not bytes — `tail -c` can split a
|
||||
# multi-byte UTF-8 char, e.g. Korean, producing a marker that can never match
|
||||
|
||||
Reference in New Issue
Block a user