This repository was archived by the owner on Oct 17, 2026. It is now read-only.
Repository navigation
Expand file tree
/
Copy pathcli.py
More file actions
98 lines (74 loc) · 2.83 KB
/
Copy pathcli.py
File metadata and controls
98 lines (74 loc) · 2.83 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
"""AgentTrace CLI — click group with 4 commands."""
from __future__ import annotations
import json
import os
from datetime import datetime
from pathlib import Path
from typing import Optional
import click
import agenttrace
from utils import format_timestamp, parse_timestamp
DEFAULT_LOGS_PATH = "logs.json"
DEFAULT_NOTES_PATH = "notes.json"
def _logs_path() -> Path:
return Path(os.environ.get("AGENTTRACE_LOGS_PATH", DEFAULT_LOGS_PATH))
def _notes_path() -> Path:
return Path(os.environ.get("AGENTTRACE_NOTES_PATH", DEFAULT_NOTES_PATH))
def _resolve_now() -> Optional[datetime]:
raw = os.environ.get("AGENTTRACE_NOW")
if raw is None:
return None
return parse_timestamp(raw)
def _emit(obj: dict) -> None:
# One JSON object per line (order preserved by dict insertion).
click.echo(json.dumps(obj))
@click.group()
def cli() -> None:
"""AgentTrace — log code-change reasoning and manage spaced-repetition notes."""
@cli.command("log-change")
@click.option("--file", "file_", required=True, type=str, help="File name of the change")
@click.option("--line", required=True, type=int, help="Line number of the change")
@click.option("--description", required=True, type=str, help="Brief change description")
def log_change(file_: str, line: int, description: str) -> None:
"""Log a code change."""
change = agenttrace.log_code_change(
_logs_path(), file=file_, line=line, description=description
)
_emit({
"file": change.file,
"line": change.line,
"description": change.description,
})
@cli.command("view-logs")
def view_logs() -> None:
"""View all logged code changes (one JSON object per line)."""
for change in agenttrace.view_logs(_logs_path()):
_emit({
"file": change.file,
"line": change.line,
"description": change.description,
})
@cli.command("add-note")
@click.option("--timestamp", "timestamp", required=True, type=str,
help="Timestamp in 'YYYY-MM-DD HH:MM:SS' format")
@click.option("--description", required=True, type=str, help="Note description")
def add_note(timestamp: str, description: str) -> None:
"""Add a spaced-repetition podcast note."""
ts = parse_timestamp(timestamp)
note = agenttrace.add_note(_notes_path(), ts, description)
_emit({
"timestamp": format_timestamp(note.timestamp),
"description": note.description,
"next_review": format_timestamp(note.next_review),
})
@cli.command("review-notes")
def review_notes() -> None:
"""Display all notes whose next_review is due."""
now = _resolve_now()
for note in agenttrace.review_notes(_notes_path(), now=now):
_emit({
"timestamp": format_timestamp(note.timestamp),
"description": note.description,
})
if __name__ == "__main__":
cli()