Download src/codex_dashboard/codex_data.py from smlflg/CodexDashBoard: direct link, hf CLI and curl.
- Browser
- Download file 8.1 kB
-
https://huggingface.co/smlflg/CodexDashBoard/resolve/main/src/codex_dashboard/codex_data.py
- Command line
-
hf download hf://smlflg/CodexDashBoard/src/codex_dashboard/codex_data.py
-
curl -L -o codex_data.py https://huggingface.co/smlflg/CodexDashBoard/resolve/main/src/codex_dashboard/codex_data.py
8.1 kB
| from __future__ import annotations | |
| from dataclasses import dataclass | |
| from datetime import datetime | |
| from pathlib import Path | |
| import sqlite3 | |
| from typing import Iterable | |
| from .paths import LOGS_DB, STATE_DB, TUI_LOG | |
| class ThreadSummary: | |
| id: str | |
| title: str | |
| cwd: str | |
| model: str | |
| reasoning_effort: str | |
| tokens_used: int | |
| archived: bool | |
| source: str | |
| git_branch: str | |
| created_ms: int | |
| updated_ms: int | |
| class LogEntry: | |
| id: int | |
| ts_ms: int | |
| level: str | |
| target: str | |
| thread_id: str | |
| message: str | |
| class DataAccessError: | |
| source: str | |
| path: Path | |
| message: str | |
| class DataResult: | |
| data: object | |
| error: DataAccessError | None = None | |
| class DashboardStats: | |
| thread_count: int | |
| archived_count: int | |
| total_tokens: int | |
| recent_hour_count: int | |
| latest_thread: ThreadSummary | None | |
| error: DataAccessError | None = None | |
| def _data_error(source: str, path: Path, exc: BaseException) -> DataAccessError: | |
| return DataAccessError(source=source, path=path, message=str(exc)) | |
| def _connect_readonly(path: Path) -> sqlite3.Connection: | |
| if not path.exists(): | |
| raise FileNotFoundError(path) | |
| uri = f"file:{path}?mode=ro" | |
| conn = sqlite3.connect(uri, uri=True, timeout=0.05) | |
| conn.row_factory = sqlite3.Row | |
| return conn | |
| def _shorten(text: str | None, limit: int = 120) -> str: | |
| value = (text or "").strip().replace("\n", " ") | |
| if len(value) <= limit: | |
| return value | |
| return value[: limit - 3].rstrip() + "..." | |
| def _thread_from_row(row: sqlite3.Row) -> ThreadSummary: | |
| title = row["title"] or row["first_user_message"] or "(untitled)" | |
| return ThreadSummary( | |
| id=row["id"], | |
| title=_shorten(title), | |
| cwd=row["cwd"] or "", | |
| model=row["model"] or row["model_provider"] or "", | |
| reasoning_effort=row["reasoning_effort"] or "", | |
| tokens_used=int(row["tokens_used"] or 0), | |
| archived=bool(row["archived"]), | |
| source=row["source"] or "", | |
| git_branch=row["git_branch"] or "", | |
| created_ms=int(row["created_ms"] or 0), | |
| updated_ms=int(row["updated_ms"] or 0), | |
| ) | |
| def list_threads( | |
| *, | |
| db_path: Path = STATE_DB, | |
| query: str = "", | |
| include_archived: bool = False, | |
| limit: int = 80, | |
| ) -> list[ThreadSummary]: | |
| return list_threads_result( | |
| db_path=db_path, | |
| query=query, | |
| include_archived=include_archived, | |
| limit=limit, | |
| ).data | |
| def list_threads_result( | |
| *, | |
| db_path: Path = STATE_DB, | |
| query: str = "", | |
| include_archived: bool = False, | |
| limit: int = 80, | |
| ) -> DataResult: | |
| clauses = [] | |
| params: list[object] = [] | |
| if not include_archived: | |
| clauses.append("archived = 0") | |
| if query.strip(): | |
| needle = f"%{query.strip()}%" | |
| clauses.append( | |
| "(title LIKE ? OR first_user_message LIKE ? OR cwd LIKE ? OR git_branch LIKE ?)" | |
| ) | |
| params.extend([needle, needle, needle, needle]) | |
| where = f"WHERE {' AND '.join(clauses)}" if clauses else "" | |
| params.append(limit) | |
| sql = f""" | |
| SELECT | |
| id, | |
| title, | |
| first_user_message, | |
| cwd, | |
| model, | |
| model_provider, | |
| reasoning_effort, | |
| tokens_used, | |
| archived, | |
| source, | |
| git_branch, | |
| COALESCE(created_at_ms, created_at * 1000) AS created_ms, | |
| COALESCE(updated_at_ms, updated_at * 1000) AS updated_ms | |
| FROM threads | |
| {where} | |
| ORDER BY updated_ms DESC, id DESC | |
| LIMIT ? | |
| """ | |
| try: | |
| with _connect_readonly(db_path) as conn: | |
| return DataResult([_thread_from_row(row) for row in conn.execute(sql, params)]) | |
| except FileNotFoundError: | |
| return DataResult([]) | |
| except (sqlite3.Error, TypeError, ValueError) as exc: | |
| return DataResult([], _data_error("state.sqlite", db_path, exc)) | |
| def get_stats(*, db_path: Path = STATE_DB) -> DashboardStats: | |
| threads_result = list_threads_result(db_path=db_path, include_archived=False, limit=1) | |
| threads = threads_result.data | |
| try: | |
| with _connect_readonly(db_path) as conn: | |
| row = conn.execute( | |
| """ | |
| SELECT | |
| COUNT(*) AS thread_count, | |
| SUM(CASE WHEN archived = 1 THEN 1 ELSE 0 END) AS archived_count, | |
| COALESCE(SUM(tokens_used), 0) AS total_tokens, | |
| SUM( | |
| CASE | |
| WHEN COALESCE(updated_at_ms, updated_at * 1000) | |
| >= (strftime('%s','now') * 1000 - 3600000) | |
| THEN 1 ELSE 0 | |
| END | |
| ) AS recent_hour_count | |
| FROM threads | |
| """ | |
| ).fetchone() | |
| except FileNotFoundError: | |
| return DashboardStats(0, 0, 0, 0, None) | |
| except sqlite3.Error as exc: | |
| return DashboardStats(0, 0, 0, 0, None, _data_error("state.sqlite", db_path, exc)) | |
| return DashboardStats( | |
| thread_count=int(row["thread_count"] or 0), | |
| archived_count=int(row["archived_count"] or 0), | |
| total_tokens=int(row["total_tokens"] or 0), | |
| recent_hour_count=int(row["recent_hour_count"] or 0), | |
| latest_thread=threads[0] if threads else None, | |
| error=threads_result.error, | |
| ) | |
| def list_logs( | |
| *, | |
| db_path: Path = LOGS_DB, | |
| query: str = "", | |
| limit: int = 150, | |
| ) -> list[LogEntry]: | |
| return list_logs_result(db_path=db_path, query=query, limit=limit).data | |
| def list_logs_result( | |
| *, | |
| db_path: Path = LOGS_DB, | |
| query: str = "", | |
| limit: int = 150, | |
| ) -> DataResult: | |
| clauses = [] | |
| params: list[object] = [] | |
| if query.strip(): | |
| needle = f"%{query.strip()}%" | |
| clauses.append( | |
| "(target LIKE ? OR module_path LIKE ? OR feedback_log_body LIKE ? OR thread_id LIKE ?)" | |
| ) | |
| params.extend([needle, needle, needle, needle]) | |
| where = f"WHERE {' AND '.join(clauses)}" if clauses else "" | |
| params.append(limit) | |
| sql = f""" | |
| SELECT | |
| id, | |
| ts, | |
| ts_nanos, | |
| level, | |
| target, | |
| thread_id, | |
| feedback_log_body | |
| FROM logs | |
| {where} | |
| ORDER BY ts DESC, ts_nanos DESC, id DESC | |
| LIMIT ? | |
| """ | |
| try: | |
| with _connect_readonly(db_path) as conn: | |
| rows = conn.execute(sql, params).fetchall() | |
| except FileNotFoundError: | |
| return DataResult([]) | |
| except sqlite3.Error as exc: | |
| return DataResult([], _data_error("logs_2.sqlite", db_path, exc)) | |
| try: | |
| return DataResult([ | |
| LogEntry( | |
| id=int(row["id"]), | |
| ts_ms=int(row["ts"] or 0) * 1000 + int((row["ts_nanos"] or 0) / 1_000_000), | |
| level=row["level"] or "", | |
| target=row["target"] or "", | |
| thread_id=row["thread_id"] or "", | |
| message=_shorten(row["feedback_log_body"], 240), | |
| ) | |
| for row in rows | |
| ]) | |
| except (TypeError, ValueError, sqlite3.Error) as exc: | |
| return DataResult([], _data_error("logs_2.sqlite", db_path, exc)) | |
| def tail_tui_log(path: Path = TUI_LOG, lines: int = 80) -> list[str]: | |
| if not path.exists(): | |
| return [] | |
| try: | |
| data = path.read_text(encoding="utf-8", errors="replace").splitlines() | |
| except OSError: | |
| return [] | |
| return data[-lines:] | |
| def format_time(ms: int) -> str: | |
| if not ms: | |
| return "-" | |
| return datetime.fromtimestamp(ms / 1000).strftime("%Y-%m-%d %H:%M") | |
| def format_tokens(value: int) -> str: | |
| if value >= 1_000_000: | |
| return f"{value / 1_000_000:.1f}M" | |
| if value >= 1_000: | |
| return f"{value / 1_000:.1f}k" | |
| return str(value) | |
| def first_existing(paths: Iterable[Path]) -> Path | None: | |
| for path in paths: | |
| if path.exists(): | |
| return path | |
| return None | |