feat(cli,registry): introduce --herdr-workspace option and decouple socket fallback chains
This commit is contained in:
@@ -132,7 +132,8 @@ _changed = False
|
||||
for s in d.get('herdr_sessions', []):
|
||||
if s.get('delegate_job_id') == _jid and s.get('status') == 'running':
|
||||
_name = s.get('name')
|
||||
_srv = s.get('herdr_session') or s.get('herdr_server') or s.get('herdr_workspace') or 'default'
|
||||
# herdr_workspace 는 워크스페이스 *라벨* 이지 소켓 이름이 아니다.
|
||||
_srv = s.get('herdr_session') or s.get('herdr_server') or 'default'
|
||||
if _event in ('completed', 'cancelled'):
|
||||
s['delegate_job_id'] = None
|
||||
print('MQTT Monitor: job ' + _event + ' on ' + str(_name) + ' — session kept alive', flush=True)
|
||||
@@ -316,12 +317,23 @@ fi
|
||||
# atomic_dump_yaml(flock + temp+rename) 로 같은 소스를 돌린다. atomic 래퍼에서는
|
||||
# 'actions' 가 없으면 SystemExit(0) 으로 쓰기를 건너뛴다 (불필요한 재포맷 방지).
|
||||
read -r -d '' RECON_SRC <<'PYEOF' || true
|
||||
import os, json, glob, subprocess, time, sqlite3
|
||||
import os, json, glob, subprocess, time, sqlite3, re
|
||||
from datetime import datetime, timezone
|
||||
import yaml
|
||||
|
||||
from lib_py.verify_session import verify_session_uuid, workspace_key
|
||||
|
||||
def _slug(path):
|
||||
if not path:
|
||||
return ''
|
||||
a = os.path.abspath(path)
|
||||
parent = os.path.basename(os.path.dirname(a)) or 'workspace'
|
||||
work = os.path.basename(a) or 'root'
|
||||
if parent in ('/', '.'): parent = 'workspace'
|
||||
if work in ('/', '.'): work = 'root'
|
||||
s = f'{parent}-{work}'.lower().replace('_', '-')
|
||||
return re.sub(r'[^a-zA-Z0-9-]', '', s).lstrip('-')
|
||||
|
||||
yaml_path = os.environ['YAML_PATH']
|
||||
home = os.environ['HOME_DIR']
|
||||
skills_dir = os.environ.get('SKILLS_DIR', '')
|
||||
@@ -386,7 +398,8 @@ if 'HERDR_SESSION_NAME' in os.environ:
|
||||
elif 'HERDR_SERVER_NAME' in os.environ:
|
||||
unique_servers.add(os.environ['HERDR_SERVER_NAME'])
|
||||
for s in d.get('herdr_sessions', []):
|
||||
srv = s.get('herdr_session') or s.get('herdr_server') or s.get('herdr_workspace') or 'default'
|
||||
# herdr_workspace 는 워크스페이스 *라벨* 이지 소켓 이름이 아니다.
|
||||
srv = s.get('herdr_session') or s.get('herdr_server') or 'default'
|
||||
unique_servers.add(srv)
|
||||
|
||||
try:
|
||||
@@ -396,8 +409,6 @@ try:
|
||||
cmd += ['-L', srv]
|
||||
cmd += ['ls', '-F', '#{session_name}|#{session_created}']
|
||||
r = subprocess.run(cmd, capture_output=True, text=True)
|
||||
import sys
|
||||
sys.stderr.write(f"LS CMD: {cmd} | RC: {r.returncode} | STDOUT: {r.stdout} | STDERR: {r.stderr}\n")
|
||||
if r.returncode == 0:
|
||||
for line in r.stdout.strip().split('\n'):
|
||||
if not line or '|' not in line:
|
||||
@@ -423,9 +434,7 @@ try:
|
||||
is_empty = ('no server running' in err) or ('no sessions' in err) or ('failed to connect' in err)
|
||||
if not is_empty:
|
||||
herdr_confirmed = False
|
||||
except Exception as ex:
|
||||
import sys
|
||||
sys.stderr.write(f"EX IN RECONCILE LS: {ex}\n")
|
||||
except Exception:
|
||||
herdr_confirmed = False
|
||||
|
||||
|
||||
@@ -472,8 +481,7 @@ yaml_sessions = d.get('herdr_sessions', [])
|
||||
yaml_session_names = {s['name'] for s in yaml_sessions if s.get('name')}
|
||||
alive_set = {(t['name'], t.get('server', 'default')) for t in herdr_sessions}
|
||||
|
||||
# === drift A: herdr dead + YAML running → auto-terminate ===
|
||||
# herdr 응답을 확정했을 때만. transient 실패 시 모두 terminated 로 마크하지 않음 (P1-E)
|
||||
# === drift A: YAML running + herdr dead → mark terminated ===
|
||||
if herdr_confirmed:
|
||||
for s in yaml_sessions:
|
||||
name = s.get('name')
|
||||
@@ -483,7 +491,8 @@ if herdr_confirmed:
|
||||
# (없으면 herdr-dead stopped 세션을 'terminated' 로 덮어써 resumable 플래그가 소실됨)
|
||||
if s.get('status') in ('terminated', 'archived', 'stopped'):
|
||||
continue
|
||||
srv = s.get('herdr_session') or s.get('herdr_server') or s.get('herdr_workspace') or 'default'
|
||||
# herdr_workspace 는 워크스페이스 *라벨* 이지 소켓 이름이 아니다.
|
||||
srv = s.get('herdr_session') or s.get('herdr_server') or 'default'
|
||||
if (name, srv) not in alive_set and (_sanitize(name), srv) not in alive_set:
|
||||
s['status'] = 'terminated'
|
||||
s['terminated_at'] = now_iso
|
||||
@@ -498,7 +507,8 @@ if herdr_confirmed:
|
||||
if herdr_confirmed:
|
||||
for t in herdr_sessions:
|
||||
name = t['name']
|
||||
if name in yaml_session_names or any(_sanitize(y) == name for y in yaml_session_names):
|
||||
srv = t.get('server', 'default')
|
||||
if (name, srv) in yaml_session_names or any(_sanitize(y) == name for y in yaml_session_names):
|
||||
continue
|
||||
workspace_root = os.environ.get('WORKSPACE_ROOT')
|
||||
if not workspace_root:
|
||||
@@ -518,8 +528,7 @@ if herdr_confirmed:
|
||||
|
||||
if not agent:
|
||||
# Check MAM_MANAGED env marker from pane process environment if available
|
||||
srv_opt = t.get('server', 'default')
|
||||
pm_check = pane_meta(name, srv_opt)
|
||||
pm_check = pane_meta(name, srv)
|
||||
if pm_check and pm_check.get('pid'):
|
||||
try:
|
||||
pid_val = pm_check['pid']
|
||||
@@ -539,7 +548,6 @@ if herdr_confirmed:
|
||||
if not agent:
|
||||
continue
|
||||
|
||||
srv = t.get('server', 'default')
|
||||
pm = pane_meta(name, srv)
|
||||
if not pm:
|
||||
continue
|
||||
@@ -564,6 +572,8 @@ if herdr_confirmed:
|
||||
'herdr_session_created_at': datetime.fromtimestamp(created_epoch, tz=timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ'),
|
||||
'herdr_session_epoch': created_epoch,
|
||||
'herdr_session': srv,
|
||||
'herdr_server': srv,
|
||||
'herdr_workspace': _slug(pm['cwd']),
|
||||
'pane': {'index': 0, 'pid': pm['pid'], 'cmd': agent, 'cmd_full': cmd_full, 'cwd': pm['cwd']},
|
||||
'start_command': f'HERDR_SESSION_NAME={srv} herdr new-session -d -s "{name}" -x 140 -y 40 -c "{pm["cwd"]}" "{cmd_full}"',
|
||||
'attach_command': f'HERDR_SESSION_NAME={srv} herdr agent attach {name}',
|
||||
|
||||
Reference in New Issue
Block a user