init: company-haness 설계
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
"""Trusted bridge from Agent PreToolUse package validation to native SubagentStart.
|
||||
|
||||
Native SubagentStart payloads may omit the spawning prompt. PreToolUse therefore appends a
|
||||
pending exact package binding; SubagentStart claims the oldest unclaimed binding for the same
|
||||
concrete agent type. The log is append-only and protected by guard_tools.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import uuid
|
||||
from datetime import datetime, timezone
|
||||
|
||||
import _workspace as W
|
||||
|
||||
|
||||
def _path() -> str:
|
||||
return os.path.join(W.state_dir(), "spawn-bindings.jsonl")
|
||||
|
||||
|
||||
def _rows() -> list[dict]:
|
||||
path = _path()
|
||||
if not os.path.exists(path):
|
||||
return []
|
||||
rows = []
|
||||
for line in open(path, encoding="utf-8"):
|
||||
try:
|
||||
value = json.loads(line)
|
||||
if isinstance(value, dict):
|
||||
rows.append(value)
|
||||
except Exception:
|
||||
continue
|
||||
return rows
|
||||
|
||||
|
||||
def _append(record: dict) -> None:
|
||||
path = _path()
|
||||
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||
with open(path, "a", encoding="utf-8") as handle:
|
||||
try:
|
||||
import fcntl
|
||||
fcntl.flock(handle.fileno(), fcntl.LOCK_EX)
|
||||
except Exception:
|
||||
pass
|
||||
handle.write(json.dumps(record, ensure_ascii=False) + "\n")
|
||||
handle.flush()
|
||||
os.fsync(handle.fileno())
|
||||
|
||||
|
||||
def record_pending(
|
||||
agent_type: str,
|
||||
package_path: str,
|
||||
package_sha256: str,
|
||||
session_id: str | None = None,
|
||||
) -> str | None:
|
||||
try:
|
||||
binding_id = "spb-" + uuid.uuid4().hex
|
||||
_append({
|
||||
"event-type": "spawn-binding-pending",
|
||||
"binding-id": binding_id,
|
||||
"agent-type": str(agent_type).lower(),
|
||||
"context-package": package_path,
|
||||
"context-package-sha256": package_sha256,
|
||||
"session-id": session_id,
|
||||
"at": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||
})
|
||||
return binding_id
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def claim_pending(agent_type: str, agent_id: str, session_id: str | None = None) -> dict | None:
|
||||
try:
|
||||
path = _path()
|
||||
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||
with open(path, "a+", encoding="utf-8") as handle:
|
||||
try:
|
||||
import fcntl
|
||||
fcntl.flock(handle.fileno(), fcntl.LOCK_EX)
|
||||
except Exception:
|
||||
pass
|
||||
handle.seek(0)
|
||||
rows = []
|
||||
for line in handle:
|
||||
try:
|
||||
value = json.loads(line)
|
||||
if isinstance(value, dict):
|
||||
rows.append(value)
|
||||
except Exception:
|
||||
continue
|
||||
consumed = {row.get("binding-id") for row in rows
|
||||
if row.get("event-type") == "spawn-binding-claimed"}
|
||||
pending = [row for row in rows
|
||||
if row.get("event-type") == "spawn-binding-pending"
|
||||
and row.get("agent-type") == str(agent_type).lower()
|
||||
and row.get("binding-id") not in consumed
|
||||
and (not session_id or not row.get("session-id")
|
||||
or row.get("session-id") == session_id)]
|
||||
if not pending:
|
||||
return None
|
||||
record = pending[0]
|
||||
claimed = {
|
||||
"event-type": "spawn-binding-claimed",
|
||||
"binding-id": record["binding-id"],
|
||||
"agent-id": agent_id,
|
||||
"session-id": session_id,
|
||||
"at": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||
}
|
||||
handle.seek(0, os.SEEK_END)
|
||||
handle.write(json.dumps(claimed, ensure_ascii=False) + "\n")
|
||||
handle.flush()
|
||||
os.fsync(handle.fileno())
|
||||
return record
|
||||
except Exception:
|
||||
return None
|
||||
Reference in New Issue
Block a user