Simplify code documentation, remove organism terminology
- Remove biological metaphors from docstrings (organism, sensory, genetic, nutrient, etc.) - Simplify documentation to be minimal and structured for fast model parsing - Complete SQLite to JSON storage migration (project_manager.py, json_store.py) - Add Integrations and IntegrationHealth classes to json_store.py - Add kill_port() function to server.py for port conflict handling - All 33 tests pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -960,6 +960,164 @@ class TokenDrift:
|
||||
return None
|
||||
|
||||
|
||||
# === Integrations ===
|
||||
|
||||
class Integrations:
|
||||
"""Project integration configuration storage."""
|
||||
|
||||
@staticmethod
|
||||
def _integrations_path(project_id: str) -> Path:
|
||||
return PROJECTS_DIR / project_id / "integrations.json"
|
||||
|
||||
@staticmethod
|
||||
def list(project_id: str, user_id: int = None) -> List[Dict]:
|
||||
"""List integrations for a project."""
|
||||
data = read_json(Integrations._integrations_path(project_id), {"integrations": []})
|
||||
integrations = data.get("integrations", [])
|
||||
|
||||
if user_id is not None:
|
||||
integrations = [i for i in integrations if i.get("user_id") == user_id]
|
||||
|
||||
return integrations
|
||||
|
||||
@staticmethod
|
||||
def get(project_id: str, user_id: int, integration_type: str) -> Optional[Dict]:
|
||||
"""Get specific integration."""
|
||||
integrations = Integrations.list(project_id, user_id)
|
||||
for i in integrations:
|
||||
if i.get("integration_type") == integration_type:
|
||||
return i
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def upsert(project_id: str, user_id: int, integration_type: str,
|
||||
config: str, enabled: bool = True) -> Dict:
|
||||
"""Create or update integration."""
|
||||
path = Integrations._integrations_path(project_id)
|
||||
data = read_json(path, {"integrations": []})
|
||||
now = datetime.utcnow().isoformat()
|
||||
|
||||
# Find existing
|
||||
for i in data["integrations"]:
|
||||
if i.get("user_id") == user_id and i.get("integration_type") == integration_type:
|
||||
i["config"] = config
|
||||
i["enabled"] = enabled
|
||||
i["updated_at"] = now
|
||||
write_json(path, data)
|
||||
return i
|
||||
|
||||
# Create new
|
||||
new_integration = {
|
||||
"id": str(uuid.uuid4())[:8],
|
||||
"project_id": project_id,
|
||||
"user_id": user_id,
|
||||
"integration_type": integration_type,
|
||||
"config": config,
|
||||
"enabled": enabled,
|
||||
"created_at": now,
|
||||
"updated_at": now,
|
||||
"last_used_at": None
|
||||
}
|
||||
|
||||
data["integrations"].append(new_integration)
|
||||
write_json(path, data)
|
||||
return new_integration
|
||||
|
||||
@staticmethod
|
||||
def update(project_id: str, user_id: int, integration_type: str,
|
||||
config: str = None, enabled: bool = None) -> Optional[Dict]:
|
||||
"""Update integration fields."""
|
||||
path = Integrations._integrations_path(project_id)
|
||||
data = read_json(path, {"integrations": []})
|
||||
|
||||
for i in data["integrations"]:
|
||||
if i.get("user_id") == user_id and i.get("integration_type") == integration_type:
|
||||
if config is not None:
|
||||
i["config"] = config
|
||||
if enabled is not None:
|
||||
i["enabled"] = enabled
|
||||
i["updated_at"] = datetime.utcnow().isoformat()
|
||||
write_json(path, data)
|
||||
return i
|
||||
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def delete(project_id: str, user_id: int, integration_type: str) -> bool:
|
||||
"""Delete integration."""
|
||||
path = Integrations._integrations_path(project_id)
|
||||
data = read_json(path, {"integrations": []})
|
||||
|
||||
original_len = len(data["integrations"])
|
||||
data["integrations"] = [
|
||||
i for i in data["integrations"]
|
||||
if not (i.get("user_id") == user_id and i.get("integration_type") == integration_type)
|
||||
]
|
||||
|
||||
if len(data["integrations"]) < original_len:
|
||||
write_json(path, data)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class IntegrationHealth:
|
||||
"""Integration health tracking."""
|
||||
|
||||
@staticmethod
|
||||
def _health_path() -> Path:
|
||||
return SYSTEM_DIR / "integration_health.json"
|
||||
|
||||
@staticmethod
|
||||
def list_all() -> List[Dict]:
|
||||
"""List all integration health status."""
|
||||
data = read_json(IntegrationHealth._health_path(), {"health": {}})
|
||||
return [
|
||||
{"integration_type": k, **v}
|
||||
for k, v in data.get("health", {}).items()
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def get(integration_type: str) -> Optional[Dict]:
|
||||
"""Get health for specific integration."""
|
||||
data = read_json(IntegrationHealth._health_path(), {"health": {}})
|
||||
if integration_type in data.get("health", {}):
|
||||
return {"integration_type": integration_type, **data["health"][integration_type]}
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def update(integration_type: str, is_healthy: bool = True,
|
||||
failure_count: int = None, circuit_open_until: str = None) -> Dict:
|
||||
"""Update integration health."""
|
||||
path = IntegrationHealth._health_path()
|
||||
data = read_json(path, {"health": {}})
|
||||
|
||||
if integration_type not in data["health"]:
|
||||
data["health"][integration_type] = {
|
||||
"is_healthy": True,
|
||||
"failure_count": 0,
|
||||
"last_failure_at": None,
|
||||
"last_success_at": None,
|
||||
"circuit_open_until": None
|
||||
}
|
||||
|
||||
now = datetime.utcnow().isoformat()
|
||||
data["health"][integration_type]["is_healthy"] = is_healthy
|
||||
|
||||
if is_healthy:
|
||||
data["health"][integration_type]["last_success_at"] = now
|
||||
else:
|
||||
data["health"][integration_type]["last_failure_at"] = now
|
||||
|
||||
if failure_count is not None:
|
||||
data["health"][integration_type]["failure_count"] = failure_count
|
||||
|
||||
if circuit_open_until is not None:
|
||||
data["health"][integration_type]["circuit_open_until"] = circuit_open_until
|
||||
|
||||
write_json(path, data)
|
||||
return {"integration_type": integration_type, **data["health"][integration_type]}
|
||||
|
||||
|
||||
# === Stats ===
|
||||
|
||||
def get_stats() -> Dict:
|
||||
|
||||
Reference in New Issue
Block a user