AQIT 0.1.0
Loading...
Searching...
No Matches
command_log.py
Go to the documentation of this file.
1# Copyright (c) 2025-present Aquin Labs Private Limited. All Rights Reserved.
2"""Local command tracking — ~/.aquin/commands/"""
3from __future__ import annotations
4
5import json
6import re
7import uuid
8from datetime import datetime, timezone
9from pathlib import Path
10from typing import Any
11
12_COMMANDS_DIR = Path.home() / ".aquin" / "commands"
13_INDEX_PATH = _COMMANDS_DIR / "index.json"
14
15_CATEGORY_BY_TOOL: dict[str, str] = {
16 "run_full_inspection": "inspection",
17 "get_feature_logits": "inspection",
18 "get_feature_neighbors": "inspection",
19 "run_attention_routing": "inspection",
20 "run_layer_analysis": "inspection",
21 "run_perturbation_sensitivity": "inspection",
22 "check_weights": "inspection",
23 "run_simulation": "simulation",
24 "run_sae_stats": "sae",
25 "run_find_feature": "sae",
26 "run_confidence_analysis": "sae",
27 "run_sae_diff": "sae",
28 "run_sae_align": "sae",
29 "run_sae_train": "sae",
30 "run_capture_activations": "capture",
31 "run_weight_diff": "checkpoint",
32 "run_merge_analysis": "checkpoint",
33 "run_trajectory_analysis": "checkpoint",
34 "run_residual_drift": "checkpoint",
35 "ensure_umap_loaded": "inspection",
36 "run_steer_and_show": "sae",
37 "run_multi_steer": "sae",
38 "extract_steer_vector": "sae",
39}
40
41_TOOL_TO_CLI: dict[str, str] = {
42 "run_full_inspection": "trace",
43 "get_feature_logits": "feature logit",
44 "get_feature_neighbors": "feature neighbor",
45 "run_attention_routing": "check attention",
46 "run_layer_analysis": "check layer",
47 "run_perturbation_sensitivity": "check perturbation",
48 "check_weights": "check weight",
49 "run_simulation": "simulate",
50 "run_merge_analysis": "diff weight",
51 "run_trajectory_analysis": "check trajectory",
52 "run_residual_drift": "diff residue",
53 "run_sae_stats": "sae-stats",
54 "run_find_feature": "feature locate",
55 "run_confidence_analysis": "check confidence",
56 "run_capture_activations": "activations capture",
57 "run_custom_eval": "eval custom",
58 "run_consistency_eval": "eval consistency",
59 "run_suppression_eval": "eval suppress",
60 "run_boundary_eval": "eval boundary",
61}
62
63
64def _now_iso() -> str:
65 return datetime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
66
67
68def _ensure_dir() -> None:
69 _COMMANDS_DIR.mkdir(parents=True, exist_ok=True)
70
71
72def _load_index() -> list[dict[str, Any]]:
74 if not _INDEX_PATH.exists():
75 return []
76 try:
77 data = json.loads(_INDEX_PATH.read_text())
78 return data if isinstance(data, list) else []
79 except Exception:
80 return []
81
82
83def _save_index(rows: list[dict[str, Any]]) -> None:
85 _INDEX_PATH.write_text(json.dumps(rows, indent=2))
86
88def category_for_tool(tool_name: str) -> str:
89 return _CATEGORY_BY_TOOL.get(tool_name, "other")
90
91
92def cli_name_for_tool(tool_name: str) -> str:
93 return _TOOL_TO_CLI.get(tool_name, tool_name.replace("run_", "").replace("_", "-"))
94
95
97 *,
98 command: str,
99 tool_name: str,
100 model_id: str | None,
101 result: Any,
102 card: dict[str, Any] | None,
103) -> str:
104 parts = [command]
105 if model_id:
106 parts.append(model_id)
107 hint = ""
108 if isinstance(result, dict):
109 if result.get("error"):
110 hint = "error"
111 elif isinstance(result.get("top_features"), list) and result["top_features"]:
112 f0 = result["top_features"][0]
113 if isinstance(f0, dict) and "feature_idx" in f0:
114 hint = f"F{f0['feature_idx']}"
115 elif result.get("mergeVerdict"):
116 hint = str(result["mergeVerdict"])
117 elif result.get("nChanged") is not None:
118 hint = f"{result['nChanged']} changed"
119 elif card and isinstance(card.get("type"), str):
120 hint = card["type"]
121 if hint:
122 parts.append(hint)
123 return " · ".join(parts)
124
125
126def append_record(
127 *,
128 tool_name: str,
129 command: str | None = None,
130 args: dict[str, Any] | None = None,
131 result: Any = None,
132 card: dict[str, Any] | None = None,
133 model_id: str | None = None,
134 duration_ms: int | None = None,
135 exit_ok: bool = True,
136) -> str:
137 """Persist a command run locally. Returns record id."""
138 record_id = str(uuid.uuid4())
139 cmd = command or cli_name_for_tool(tool_name)
140 category = category_for_tool(tool_name)
141
142 if not model_id:
143 try:
144 from aquin.compute.model_loader import get_active_model_id
145
146 model_id = get_active_model_id() or None
147 except Exception:
148 model_id = None
149
150 record: dict[str, Any] = {
151 "id": record_id,
152 "ts": _now_iso(),
153 "command": cmd,
154 "tool_name": tool_name,
155 "category": category,
156 "model_id": model_id,
157 "args": args or {},
158 "result": result,
159 "card": card,
160 "summary": _build_summary(
161 command=cmd,
162 tool_name=tool_name,
163 model_id=model_id,
164 result=result,
165 card=card,
166 ),
167 "duration_ms": duration_ms,
168 "exit_ok": exit_ok,
169 }
170
172 (_COMMANDS_DIR / f"{record_id}.json").write_text(json.dumps(record, indent=2, default=str))
173
174 index = _load_index()
175 index.insert(0, {
176 "id": record_id,
177 "ts": record["ts"],
178 "command": cmd,
179 "tool_name": tool_name,
180 "category": category,
181 "model_id": model_id,
182 "summary": record["summary"],
183 "exit_ok": exit_ok,
184 })
185 _save_index(index[:5000])
186 return record_id
187
188
189def load_record(record_id: str) -> dict[str, Any] | None:
190 path = _COMMANDS_DIR / f"{record_id}.json"
191 if not path.exists():
192 return None
193 try:
194 return json.loads(path.read_text())
195 except Exception:
196 return None
197
198
199def _parse_since(value: str) -> datetime | None:
200 value = value.strip().lower()
201 m = re.fullmatch(r"(\d+)(m|h|d)", value)
202 if m:
203 n, unit = int(m.group(1)), m.group(2)
204 from datetime import timedelta
205
206 delta = {"m": timedelta(minutes=n), "h": timedelta(hours=n), "d": timedelta(days=n)}[unit]
207 return datetime.now(timezone.utc) - delta
208 try:
209 return datetime.fromisoformat(value.replace("Z", "+00:00"))
210 except Exception:
211 return None
212
213
214def list_records(
215 *,
216 last: int | None = None,
217 since: str | None = None,
218 category: str | None = None,
219 model_id: str | None = None,
220 command: str | None = None,
221) -> list[dict[str, Any]]:
222 rows = _load_index()
223 since_dt = _parse_since(since) if since else None
224 out: list[dict[str, Any]] = []
225 for row in rows:
226 if category and row.get("category") != category:
227 continue
228 if model_id and row.get("model_id") != model_id:
229 continue
230 if command and row.get("command") != command:
231 continue
232 if since_dt:
233 try:
234 ts = datetime.fromisoformat(str(row.get("ts", "")).replace("Z", "+00:00"))
235 if ts < since_dt:
236 continue
237 except Exception:
238 pass
239 out.append(row)
240 if last is not None and len(out) >= last:
241 break
242 return out
243
244
245def clear_records(*, before: str | None = None) -> int:
246 rows = _load_index()
247 if not before:
248 count = len(rows)
249 for row in rows:
250 rid = row.get("id")
251 if rid:
252 p = _COMMANDS_DIR / f"{rid}.json"
253 if p.exists():
254 p.unlink()
255 _save_index([])
256 return count
257
258 cutoff = _parse_since(before)
259 if cutoff is None:
260 return 0
261
262 kept: list[dict[str, Any]] = []
263 removed = 0
264 for row in rows:
265 try:
266 ts = datetime.fromisoformat(str(row.get("ts", "")).replace("Z", "+00:00"))
267 except Exception:
268 kept.append(row)
269 continue
270 if ts < cutoff:
271 rid = row.get("id")
272 if rid:
273 p = _COMMANDS_DIR / f"{rid}.json"
274 if p.exists():
275 p.unlink()
276 removed += 1
277 else:
278 kept.append(row)
279 _save_index(kept)
280 return removed
datetime|None _parse_since(str value)
None _save_index(list[dict[str, Any]] rows)
list[dict[str, Any]] _load_index()
str _build_summary(*, str command, str tool_name, str|None model_id, Any result, dict[str, Any]|None card)
dict[str, Any]|None load_record(str record_id)
int clear_records(*, str|None before=None)
str cli_name_for_tool(str tool_name)
str append_record(*, str tool_name, str|None command=None, dict[str, Any]|None args=None, Any result=None, dict[str, Any]|None card=None, str|None model_id=None, int|None duration_ms=None, bool exit_ok=True)
str category_for_tool(str tool_name)
list[dict[str, Any]] list_records(*, int|None last=None, str|None since=None, str|None category=None, str|None model_id=None, str|None command=None)