Imrpove cue scanner and remove false positives

This commit is contained in:
2026-04-20 17:48:12 +02:00
parent b859aff3c5
commit 402e10901a
2 changed files with 269 additions and 7 deletions
+178 -6
View File
@@ -770,6 +770,81 @@ async def iknowthat(request: Request) -> dict:
}
# ---------------------------------------------------------------------------
# /models — LLM model management
# ---------------------------------------------------------------------------
@app.get("/models")
async def list_models(request: Request) -> dict:
pool = request.app.state.pool
async with pool.acquire() as conn:
rows = await conn.fetch(
"SELECT id, provider, model_name, created_at FROM models ORDER BY id"
)
return {"models": [
{"id": r["id"], "provider": r["provider"], "model_name": r["model_name"],
"created_at": r["created_at"].isoformat()}
for r in rows
]}
@app.post("/models")
async def create_model(request: Request) -> dict:
pool = request.app.state.pool
data = await request.json()
provider = data.get("provider", "").strip()
model_name = data.get("model_name", "").strip()
api_key = data.get("api_key", "").strip()
if not provider or not model_name or not api_key:
return {"error": "provider, model_name, and api_key are required"}
if provider not in ("claude", "openai"):
return {"error": "provider must be 'claude' or 'openai'"}
async with pool.acquire() as conn:
row = await conn.fetchrow(
"INSERT INTO models (provider, model_name, api_key) VALUES ($1,$2,$3) RETURNING id",
provider, model_name, api_key,
)
log.info("model created id=%d provider=%s model=%s", row["id"], provider, model_name)
return {"status": "ok", "id": row["id"]}
@app.delete("/models/{model_id}")
async def delete_model(model_id: int, request: Request) -> dict:
pool = request.app.state.pool
async with pool.acquire() as conn:
result = await conn.execute("DELETE FROM models WHERE id=$1", model_id)
deleted = int(result.split()[-1]) if result else 0
if not deleted:
return {"error": f"model {model_id} not found"}
log.info("model deleted id=%d", model_id)
return {"status": "ok", "deleted": model_id}
@app.get("/config")
async def get_all_config(request: Request) -> dict:
pool = request.app.state.pool
async with pool.acquire() as conn:
rows = await conn.fetch("SELECT key, value, updated_at FROM config ORDER BY key")
return {"config": {r["key"]: r["value"] for r in rows}}
@app.post("/config")
async def update_config(request: Request) -> dict:
pool = request.app.state.pool
data = await request.json()
key = data.get("key", "").strip()
value = str(data.get("value", "")).strip()
if not key:
return {"error": "key is required"}
async with pool.acquire() as conn:
await conn.execute(
"UPDATE config SET value=$1, updated_at=now() WHERE key=$2",
value, key,
)
log.info("config updated key=%s value=%s", key, value)
return {"status": "ok", "key": key, "value": value}
# ---------------------------------------------------------------------------
# /resolve/run — manually trigger resolution job
# ---------------------------------------------------------------------------
@@ -897,15 +972,19 @@ async def kg_log(request: Request, limit: int = 100, offset: int = 0, op: str =
count_query = "SELECT COUNT(*) FROM kg_write_log {where}"
if op:
where = "WHERE op = $3"
async with pool.acquire() as conn:
rows = await conn.fetch(query.format(where=where), limit, offset, op)
total = await conn.fetchval(count_query.format(where=where), op)
rows = await conn.fetch(
query.format(where="WHERE op = $3"),
limit, offset, op,
)
total = await conn.fetchval(
"SELECT COUNT(*) FROM kg_write_log WHERE op = $1",
op,
)
else:
where = ""
async with pool.acquire() as conn:
rows = await conn.fetch(query.format(where=where), limit, offset)
total = await conn.fetchval(count_query.format(where=where))
rows = await conn.fetch(query.format(where=""), limit, offset)
total = await conn.fetchval("SELECT COUNT(*) FROM kg_write_log")
def fmt(r):
return {
@@ -1642,6 +1721,34 @@ ADMIN_HTML = """<!DOCTYPE html>
<div class="stat"><div class="stat-label">Last resolution</div><div class="stat-value" style="font-size:0.85em" id="s-lastrun">…</div></div>
</div>
<h2>Resolution model</h2>
<div id="models-section">
<table id="models-table" style="margin-bottom:0.8em">
<thead><tr><th>ID</th><th>Provider</th><th>Model name</th><th>resolve?</th><th>write?</th><th></th></tr></thead>
<tbody id="models-tbody"><tr><td colspan="6">Loading…</td></tr></tbody>
</table>
<details style="margin-bottom:1em">
<summary style="cursor:pointer;font-size:0.9em;color:#555">Add model…</summary>
<div style="margin-top:0.6em;display:flex;gap:0.7em;flex-wrap:wrap;align-items:flex-end">
<label style="font-size:0.85em">Provider
<select id="m-provider" style="font-family:monospace;padding:4px 8px;display:block;margin-top:2px">
<option value="claude">claude</option>
<option value="openai">openai</option>
</select>
</label>
<label style="font-size:0.85em">Model name
<input id="m-name" type="text" value="claude-opus-4-6"
style="font-family:monospace;padding:5px 8px;border:1px solid #ccc;border-radius:3px;display:block;margin-top:2px;width:200px">
</label>
<label style="font-size:0.85em">API key
<input id="m-key" type="password" placeholder="sk-ant-…"
style="font-family:monospace;padding:5px 8px;border:1px solid #ccc;border-radius:3px;display:block;margin-top:2px;width:260px">
</label>
<button onclick="addModel(this)" style="height:32px">Add</button>
</div>
</details>
</div>
<h2>Actions</h2>
<div class="actions">
<button class="primary" onclick="runResolution(this)">Run conflict resolution now</button>
@@ -1694,6 +1801,70 @@ ADMIN_HTML = """<!DOCTYPE html>
: 'never';
}}
let _cfg = {{}};
async function loadModels() {{
const [mr, cr] = await Promise.all([fetch('/models'), fetch('/config')]);
const md = await mr.json();
_cfg = (await cr.json()).config;
const resolveId = _cfg['resolve_model_id'] || '';
const writeId = _cfg['write_model_id'] || '';
const tbody = document.getElementById('models-tbody');
if (!md.models.length) {{
tbody.innerHTML = '<tr><td colspan="6" style="color:#999">No models yet — add one below.</td></tr>';
return;
}}
tbody.innerHTML = md.models.map(m => `
<tr>
<td>${{m.id}}</td>
<td>${{m.provider}}</td>
<td>${{m.model_name}}</td>
<td><button onclick="setConfig('resolve_model_id','${{m.id}}')" style="padding:2px 8px;font-size:0.8em;${{resolveId==String(m.id)?'background:#2a7a2a;color:#fff;border-color:#2a7a2a':''}}">${{resolveId==String(m.id)?'✓ active':'set'}}</button></td>
<td><button onclick="setConfig('write_model_id','${{m.id}}')" style="padding:2px 8px;font-size:0.8em;${{writeId==String(m.id)?'background:#2a7a2a;color:#fff;border-color:#2a7a2a':''}}">${{writeId==String(m.id)?'✓ active':'set'}}</button></td>
<td><button onclick="deleteModel(${{m.id}},this)" style="padding:2px 8px;font-size:0.8em;color:#b00;border-color:#b00">✕</button></td>
</tr>`).join('');
}}
async function addModel(btn) {{
const provider = document.getElementById('m-provider').value;
const model_name = document.getElementById('m-name').value.trim();
const api_key = document.getElementById('m-key').value.trim();
if (!model_name || !api_key) {{ alert('Model name and API key are required.'); return; }}
btn.disabled = true;
try {{
const r = await fetch('/models', {{method:'POST', headers:{{'Content-Type':'application/json'}},
body: JSON.stringify({{provider, model_name, api_key}})}});
const d = await r.json();
if (d.error) {{ showResult('Error: ' + d.error, false); return; }}
showResult('Model added (id=' + d.id + '). You can now set it as the resolve model.', true);
document.getElementById('m-key').value = '';
await loadModels();
}} catch(e) {{ showResult('Error: ' + e.message, false); }}
finally {{ btn.disabled = false; }}
}}
async function deleteModel(id, btn) {{
if (!confirm('Delete model ' + id + '?')) return;
btn.disabled = true;
try {{
const r = await fetch('/models/' + id, {{method:'DELETE'}});
const d = await r.json();
if (d.error) {{ showResult('Error: ' + d.error, false); return; }}
await loadModels();
}} catch(e) {{ showResult('Error: ' + e.message, false); }}
finally {{ btn.disabled = false; }}
}}
async function setConfig(key, value) {{
const r = await fetch('/config', {{method:'POST', headers:{{'Content-Type':'application/json'}},
body: JSON.stringify({{key, value}})}});
const d = await r.json();
if (d.error) {{ showResult('Error: ' + d.error, false); return; }}
showResult('Config updated: ' + key + ' = ' + value, true);
await loadModels();
}}
async function loadConflicts() {{
const r = await fetch('/conflicts');
const d = await r.json();
@@ -1819,6 +1990,7 @@ ADMIN_HTML = """<!DOCTYPE html>
loadStats();
loadConflicts();
loadLog(0);
loadModels();
</script>
</body>
</html>