fix: context-hub — healthcheck curl->python, seed ON CONFLICT DO NOTHING (preserve PATCH agents)

This commit is contained in:
bolbol 2026-06-29 20:25:52 +00:00
parent 395381ae07
commit 31af09f84a
1 changed files with 37 additions and 26 deletions

View File

@ -2,15 +2,30 @@ import asyncio
import os import os
from dotenv import load_dotenv from dotenv import load_dotenv
from app.models import init_db, set_rule, add_api_key, add_port from app.models import init_db, set_rule, add_api_key, add_port
import aiosqlite
load_dotenv() load_dotenv()
DB_PATH = "data/context_hub.db"
async def scope_exists(scope: str) -> bool:
async with aiosqlite.connect(DB_PATH) as db:
async with db.execute("SELECT 1 FROM rules WHERE scope=?", (scope,)) as cur:
return await cur.fetchone() is not None
async def seed_rule_if_absent(scope: str, content: dict):
"""Insere uniquement si le scope n existe pas — preserve les PATCH agents."""
async with aiosqlite.connect(DB_PATH) as db:
await db.execute(
"INSERT INTO rules (scope, content) VALUES (?, ?) ON CONFLICT(scope) DO NOTHING",
(scope, __import__('json').dumps(content))
)
await db.commit()
async def seed_data(): async def seed_data():
await init_db() await init_db()
print("Database initialized.") print("Database initialized.")
# Rules seed
infra_rule = { infra_rule = {
"ssh": {"host": "192.168.100.33", "port": 22222, "user": "Best0f"}, "ssh": {"host": "192.168.100.33", "port": 22222, "user": "Best0f"},
"docker": {"uid": 1026, "gid": 100}, "docker": {"uid": 1026, "gid": 100},
@ -19,7 +34,6 @@ async def seed_data():
"git_push_pattern": "http://bolbol:PWD@172.17.0.1:3232/bolbol/REPO.git", "git_push_pattern": "http://bolbol:PWD@172.17.0.1:3232/bolbol/REPO.git",
"mcp_nas": "heredoc->timeout, heredoc->printf/python, limit=350chars, session-poison-apres-3-erreurs" "mcp_nas": "heredoc->timeout, heredoc->printf/python, limit=350chars, session-poison-apres-3-erreurs"
} }
llm_rule = { llm_rule = {
"bifrost_internal": "http://bifrost:8080/v1", "bifrost_internal": "http://bifrost:8080/v1",
"bifrost_lan": "http://192.168.100.33:3085/v1", "bifrost_lan": "http://192.168.100.33:3085/v1",
@ -32,18 +46,17 @@ async def seed_data():
"deepseek_limitation": "text-only, 404 sur images", "deepseek_limitation": "text-only, 404 sur images",
"openrouter": "urgence uniquement" "openrouter": "urgence uniquement"
} }
nyora_rule = { nyora_rule = {
"apps": "family-help:3041, nyora-veille:3055, redaction-pro:3092", "apps": "family-help:3041, nyora-veille:3055, redaction-pro:3092",
"dr_nexum": {"deadline": "2026-11-15", "target_subs": 1000, "target_revenue_eur": 300}, "dr_nexum": {"deadline": "2026-11-15", "target_subs": 1000, "target_revenue_eur": 300},
"footer": {"color": "#d4a01a", "line1": "gradient-or", "line2": "NYORA", "line3": "Crafted with precision", "line4": "2026"}, "footer": {"color": "#d4a01a", "line1": "gradient-or", "line2": "NYORA",
"line3": "Crafted with precision", "line4": "2026"},
"rules": [ "rules": [
"Ne jamais ecrire Tunisie Telecom ou Zone Sud dans apps Nyora", "Ne jamais ecrire Tunisie Telecom ou Zone Sud dans apps Nyora",
"Login forms : placeholder=Identifiant uniquement", "Login forms : placeholder=Identifiant uniquement",
"Footer Nyora obligatoire sur toutes les apps personnelles" "Footer Nyora obligatoire sur toutes les apps personnelles"
] ]
} }
perso_rule = { perso_rule = {
"family": { "family": {
"nedya": "nee 1983, coeliaque", "nedya": "nee 1983, coeliaque",
@ -53,7 +66,6 @@ async def seed_data():
}, },
"yasmi": "marque artisanale mode, jasmine, Sfax" "yasmi": "marque artisanale mode, jasmine, Sfax"
} }
tt_rule = { tt_rule = {
"baserow_token": "deT2PW3ZFZ0h3euxhKDFnlZhKNrcckYV", "baserow_token": "deT2PW3ZFZ0h3euxhKDFnlZhKNrcckYV",
"zone": "Gabes, Gafsa, Kebili, Medenine, Sfax, Tataouine, Tozeur", "zone": "Gabes, Gafsa, Kebili, Medenine, Sfax, Tataouine, Tozeur",
@ -66,24 +78,24 @@ async def seed_data():
] ]
} }
await set_rule("infra", infra_rule) # ON CONFLICT DO NOTHING — les PATCH des agents survivent aux restarts
await set_rule("llm", llm_rule) for scope, rule in [("infra", infra_rule), ("llm", llm_rule),
await set_rule("nyora", nyora_rule) ("nyora", nyora_rule), ("perso", perso_rule), ("tt", tt_rule)]:
await set_rule("perso", perso_rule) await seed_rule_if_absent(scope, rule)
await set_rule("tt", tt_rule) print(f"Rule '{scope}': seeded (or already present)")
print("Rules seeded.")
# Ports seed
await add_port(3093, "context-hub", "Source de verite unique")
await add_port(8787, "nyora-notes", "Ne jamais reutiliser")
await add_port(3041, "family-help", "App Nyora")
await add_port(3055, "nyora-veille", "App Nyora")
await add_port(3092, "redaction-pro", "App Nyora")
# Ports : upsert OK (reference statique)
ports = [
(3093, "context-hub", "Source de verite unique"),
(8787, "nyora-notes", "Ne jamais reutiliser"),
(3041, "family-help", "App Nyora"), (3055, "nyora-veille", "App Nyora"),
(3092, "redaction-pro", "App Nyora"),
]
for port, name, desc in ports:
await add_port(port, name, desc)
print("Ports seeded.") print("Ports seeded.")
# API Keys seed # API Keys : upsert OK (sync avec .env — volontaire)
keys = { keys = {
"CLAUDE": os.environ.get("API_KEY_CLAUDE"), "CLAUDE": os.environ.get("API_KEY_CLAUDE"),
"HERMES_TT": os.environ.get("API_KEY_HERMES_TT"), "HERMES_TT": os.environ.get("API_KEY_HERMES_TT"),
@ -91,15 +103,14 @@ async def seed_data():
"HERMES_PERSO": os.environ.get("API_KEY_HERMES_PERSO"), "HERMES_PERSO": os.environ.get("API_KEY_HERMES_PERSO"),
"GEMINI": os.environ.get("API_KEY_GEMINI") "GEMINI": os.environ.get("API_KEY_GEMINI")
} }
for agent, key in keys.items(): for agent, key in keys.items():
if key: if key:
await add_api_key(agent, key) await add_api_key(agent, key)
print(f"Added API key for {agent}") print(f"API key synced: {agent}")
else: else:
print(f"Warning: API key for {agent} not found in .env") print(f"Warning: API_KEY_{agent} absent du .env")
print("Seed process completed.") print("Seed complete.")
if __name__ == "__main__": if __name__ == "__main__":
asyncio.run(seed_data()) asyncio.run(seed_data())