- lib_py/registry_format.py: a pure, idempotent migrate() drops kill_command/start_command and rebuilds attach_command on every row (stopped/terminated included) and sets the top-level registry_format key. - atomic_dump_yaml migrates an older registry under its lock, before the caller's mutation, and then rewrites the YAML as well as the DB (the YAML write is otherwise skipped when only fields change). load_state_json stays read-only. New registries are written with the current version. - Entry point for #72: `python -m lib_py.registry_format --yaml <path>` runs the migration through the writer and prints `registry-format: <from> -> <to>, rows changed: <n>`. Refs #71 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
44 lines
1.4 KiB
Python
44 lines
1.4 KiB
Python
import hashlib
|
|
import re
|
|
import shlex
|
|
|
|
def sanitize_herdr_agent_name(name: str) -> str:
|
|
"""
|
|
Sanitizes an agent name according to herdr 0.8.0 rules:
|
|
1. Convert to lowercase.
|
|
2. Replace invalid characters ([^a-z0-9_-]) with '-'.
|
|
3. Ensure starts with a lowercase letter [a-z], prefixing with 'x-' if needed.
|
|
4. Truncate to maximum 32 characters using 8-char SHA-1 hash suffix (s[:23] + '-' + sha1[:8]).
|
|
"""
|
|
if not name:
|
|
return "agent"
|
|
|
|
# 1. Lowercase
|
|
s = str(name).lower()
|
|
|
|
# 2. Replace illegal characters with '-'
|
|
s = re.sub(r'[^a-z0-9_-]', '-', s)
|
|
|
|
# 3. Ensure starts with a letter [a-z]
|
|
if not s or not s[0].isalpha():
|
|
s = "x-" + s
|
|
|
|
# 4. Truncate to 32 chars if needed using collision-free SHA-1 hash suffix
|
|
if len(s) > 32:
|
|
h = hashlib.sha1(s.encode('utf-8')).hexdigest()[:8]
|
|
s = f"{s[:23]}-{h}"
|
|
|
|
return s
|
|
|
|
|
|
def attach_command(server, name):
|
|
"""The registry row's attach_command (Issue #71).
|
|
|
|
A native herdr command, so it works from any shell: the server is always
|
|
named (`default` too - herdr's env-free default), and the agent by the name
|
|
herdr registered (sanitize_herdr_agent_name). create, resume and reconcile
|
|
all write it from here.
|
|
"""
|
|
return "herdr --session %s agent attach %s" % (
|
|
shlex.quote(server or "default"), shlex.quote(sanitize_herdr_agent_name(name)))
|