fix(issue-31): a claude purge removes every path the session owns, reports what is left, and waits for the process; the stop docs say a purge removes the row #59
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
# __main__.py — CLI bridge for lib_py.agents facts and resolution (N4)
|
# __main__.py — CLI bridge for lib_py.agents facts and resolution (N4)
|
||||||
|
|
||||||
import os, sys, json, shlex
|
import os, sys, json, shlex, time
|
||||||
from lib_py.agents.registry import get_adapter, own_key, agent_of_row
|
from lib_py.agents.registry import get_adapter, own_key, agent_of_row
|
||||||
|
|
||||||
# `purge auto` probes adapters in this order; opencode last because its
|
# `purge auto` probes adapters in this order; opencode last because its
|
||||||
@@ -151,6 +151,38 @@ def main():
|
|||||||
print(json.dumps({"agent": name, "purged": purged, "residual": residual, "in_use": False}))
|
print(json.dumps({"agent": name, "purged": purged, "residual": residual, "in_use": False}))
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
elif cmd == 'in-use':
|
||||||
|
# in-use <agent> <uuid> [workspace] [--wait <sec>] (Issue #31)
|
||||||
|
# The purge CLI's own in-use verdict, for stop_session.sh to ask
|
||||||
|
# before it purges. Re-checks every 0.25 s for up to --wait seconds.
|
||||||
|
# Prints {"agent", "in_use"}. Exit 0 free; 4 still in use; 1 bad args.
|
||||||
|
args = sys.argv[2:]
|
||||||
|
wait = 0.0
|
||||||
|
if '--wait' in args:
|
||||||
|
i = args.index('--wait')
|
||||||
|
try:
|
||||||
|
wait = float(args[i + 1])
|
||||||
|
except (IndexError, ValueError):
|
||||||
|
print("ERROR: --wait requires seconds", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
del args[i:i + 2]
|
||||||
|
agent_name = args[0] if args else ''
|
||||||
|
uuid = args[1] if len(args) > 1 else ''
|
||||||
|
workspace = args[2] if len(args) > 2 and args[2] else os.getcwd()
|
||||||
|
adapter = get_adapter(agent_name)
|
||||||
|
if not adapter or not uuid:
|
||||||
|
print("ERROR: in-use requires <agent> <uuid>", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
from lib_py.agents.base import DiscoveryContext
|
||||||
|
ctx = DiscoveryContext(workspace, agent_name)
|
||||||
|
deadline = time.monotonic() + wait
|
||||||
|
in_use = adapter.conversation_in_use(uuid, ctx)
|
||||||
|
while in_use and time.monotonic() < deadline:
|
||||||
|
time.sleep(0.25)
|
||||||
|
in_use = adapter.conversation_in_use(uuid, ctx)
|
||||||
|
print(json.dumps({"agent": agent_name, "in_use": in_use}))
|
||||||
|
sys.exit(4 if in_use else 0)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print(f"ERROR: Unknown CLI command {cmd!r}", file=sys.stderr)
|
print(f"ERROR: Unknown CLI command {cmd!r}", file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|||||||
@@ -282,6 +282,23 @@ if [ "$PURGE" = "1" ] && [ "$HERDR_ALIVE" = "1" ]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Purge process gate (Issue #31): a closed herdr session is not an exited
|
||||||
|
# agent - the process may still be shutting down, or may have outlived a dead
|
||||||
|
# herdr ("herdr already dead" above runs no gate at all). The purge asks the
|
||||||
|
# adapter's own in-use verdict, the one the purge CLI uses, outside the
|
||||||
|
# registry lock. Any answer but "free" (0) keeps everything.
|
||||||
|
if [ "$PURGE" = "1" ] && [ -n "$PURGE_UUID" ]; then
|
||||||
|
inuse_rc=0
|
||||||
|
"$(_delegate_py_bin)" -m lib_py.agents in-use "$AGENT" "$PURGE_UUID" "$TARGET_CWD" --wait 5 >/dev/null || inuse_rc=$?
|
||||||
|
if [ "$inuse_rc" != "0" ]; then
|
||||||
|
echo "ERROR: conversation $PURGE_UUID is still held by a live agent process (rc=$inuse_rc)." >&2
|
||||||
|
echo " Refusing purge — records preserved (no state was modified)." >&2
|
||||||
|
echo " For claude, see the session files naming it under ~/.claude/sessions/." >&2
|
||||||
|
delegate_publish_event "$DELEGATE_JOB_ID" cancelled "purge aborted: conversation still in use; no state was modified" "$DELEGATE_JOB_TOKEN" "$DELEGATE_JOB_ATTEMPT"
|
||||||
|
exit 4
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# INVARIANT: Terminal events for a job must be published AFTER atomic_dump_yaml updates the session status
|
# INVARIANT: Terminal events for a job must be published AFTER atomic_dump_yaml updates the session status
|
||||||
atomic_dump_yaml "$AGENT_SESSIONS_YAML" \
|
atomic_dump_yaml "$AGENT_SESSIONS_YAML" \
|
||||||
SESSION_NAME="$SESSION_NAME" AGENT="$AGENT" PURGE="$PURGE" \
|
SESSION_NAME="$SESSION_NAME" AGENT="$AGENT" PURGE="$PURGE" \
|
||||||
|
|||||||
Reference in new issue
Block a user