-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathapi.py
More file actions
127 lines (97 loc) · 3.94 KB
/
Copy pathapi.py
File metadata and controls
127 lines (97 loc) · 3.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/usr/bin/env python3
"""DevTrack-AI HTTP API — serves real-time engineering data for OpenClaw/Alfred.
Exposes DevTrack metrics as REST endpoints so AI agents (OpenClaw, etc.)
can query live engineering data without SSH access.
Usage:
pip install fastapi uvicorn
uvicorn api:app --host 0.0.0.0 --port 8099
Security: Bind to a private network (Tailscale, VPN) or add auth.
"""
from __future__ import annotations
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from dotenv import load_dotenv
load_dotenv(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".env"))
from fastapi import FastAPI, Query
from datetime import datetime, timedelta, timezone
from devtrack_ai.git_client import fetch_commits, fetch_issues, fetch_prs, fetch_repo_stats
from devtrack_ai.metrics import calc_velocity, calc_code_health, calc_work_patterns
from devtrack_ai.langfuse_client import fetch_lubot_traces
from devtrack_ai.ccusage_client import fetch_claude_usage
app = FastAPI(title="DevTrack-AI API", version="1.0")
def filter_by_days(commits: list[dict], days: int) -> list[dict]:
cutoff = datetime.now(timezone.utc) - timedelta(days=days)
result = []
for c in commits:
try:
dt = datetime.fromisoformat(c["date"].replace("Z", "+00:00"))
if dt >= cutoff:
result.append(c)
except (ValueError, KeyError):
continue
return result
@app.get("/commits")
def get_commits(days: int = Query(7), limit: int = Query(50)):
commits = fetch_commits(limit=limit, sha="develop")
if days:
commits = filter_by_days(commits, days)
return {"commits": commits, "count": len(commits), "days": days}
@app.get("/metrics")
def get_metrics(days: int = Query(7)):
commits = fetch_commits(limit=100, sha="develop")
if days:
commits = filter_by_days(commits, days)
velocity = calc_velocity(commits)
health = calc_code_health(commits)
return {"velocity": velocity, "code_health": health, "period_days": days, "commits_analyzed": len(commits)}
@app.get("/work-patterns")
def get_work_patterns(days: int = Query(7)):
commits = fetch_commits(limit=100, sha="develop")
if days:
commits = filter_by_days(commits, days)
patterns = calc_work_patterns(commits)
late = patterns["late_night_commits"]
patterns["burnout_risk"] = "high" if late > 5 else "moderate" if late > 3 else "low"
return {"work_patterns": patterns, "period_days": days}
@app.get("/issues")
def get_issues(state: str = Query("open")):
issues = fetch_issues(state=state)
return {"issues": issues, "count": len(issues), "state": state}
@app.get("/prs")
def get_prs(state: str = Query("all")):
prs = fetch_prs(state=state)
return {"pull_requests": prs, "count": len(prs), "state": state}
@app.get("/langfuse")
def get_langfuse(days: int = Query(7)):
data = fetch_lubot_traces(days=days)
return {"langfuse": data, "period_days": days}
@app.get("/ccusage")
def get_ccusage(days: int = Query(7)):
data = fetch_claude_usage(days=days)
return {"ccusage": data, "period_days": days}
@app.get("/repo-stats")
def get_repo_stats():
return {"repo": fetch_repo_stats()}
@app.get("/full-status")
def get_full_status(days: int = Query(7)):
commits = fetch_commits(limit=100, sha="develop")
if days:
commits = filter_by_days(commits, days)
velocity = calc_velocity(commits)
health = calc_code_health(commits)
patterns = calc_work_patterns(commits)
late = patterns["late_night_commits"]
patterns["burnout_risk"] = "high" if late > 5 else "moderate" if late > 3 else "low"
langfuse = fetch_lubot_traces(days=days)
repo = fetch_repo_stats()
return {
"period_days": days,
"commits_analyzed": len(commits),
"recent_commits": commits[:5],
"velocity": velocity,
"code_health": health,
"work_patterns": patterns,
"langfuse": langfuse,
"repo": repo,
}