-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcmd_list.py
More file actions
138 lines (119 loc) · 4.27 KB
/
Copy pathcmd_list.py
File metadata and controls
138 lines (119 loc) · 4.27 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
128
129
130
131
132
133
134
135
136
137
138
"""Команда list: список сессий с фильтрацией и сортировкой."""
import argparse
from typing import Literal
import db as db_module
from db import get_session_title, parse_model
from formatters import print_json, print_table_simple
from i18n import _
from utils import build_help_epilog, format_ts
_LIST_EXAMPLES = [
("", "help.list.e0"),
("--limit 10", "help.list.e1"),
("--sort cost", "help.list.e2"),
("--project proj_xxx", "help.list.e3"),
("--json", "help.list.e4"),
]
def register(subparsers) -> None:
p = subparsers.add_parser(
"list",
help=_("help.cmd.list"),
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=build_help_epilog("list", _LIST_EXAMPLES),
)
p.add_argument("--limit", type=int, default=25, help="Max results (default 25)")
p.add_argument("--offset", type=int, default=0, help="Offset")
p.add_argument("--project", type=str, help="Filter by project ID")
p.add_argument("--agent", type=str, help="Filter by agent type")
p.add_argument("--model", type=str, help="Filter by model name")
p.add_argument(
"--sort",
choices=["date", "cost", "tokens", "messages"],
default="date",
help="Sort order (default: date)",
)
p.add_argument("--json", action="store_true", help="JSON output")
p.add_argument("--all", action="store_true", help="Show all (no limit)")
def run(args, db) -> Literal[0]:
conditions = []
params = []
if args.project:
conditions.append("s.project_id = ?")
params.append(args.project)
if args.agent:
conditions.append("s.agent = ?")
params.append(args.agent)
if args.model:
conditions.append("s.model LIKE ?")
params.append(f"%{args.model}%")
where = " AND ".join(conditions) if conditions else "1=1"
sort_map = {
"date": "COALESCE(MAX(m.time_created), s.time_created) DESC",
"cost": "s.cost DESC",
"tokens": "(s.tokens_input + s.tokens_output) DESC",
"messages": "msg_count DESC",
}
order = sort_map.get(args.sort, "COALESCE(MAX(m.time_created), s.time_created) DESC")
limit = 999999 if args.all else args.limit
rows = db.execute(
f"""
SELECT s.id, s.title, s.model, s.project_id, s.agent,
s.cost, s.tokens_input, s.tokens_output,
MAX(m.time_created) as last_time,
COUNT(DISTINCT m.id) as msg_count
FROM session s
LEFT JOIN message m ON m.session_id = s.id
WHERE {where}
GROUP BY s.id
ORDER BY {order}
LIMIT ? OFFSET ?
""",
(*params, limit, args.offset),
).fetchall()
if args.json:
data = []
for r in rows:
data.append(
{
"id": r["id"],
"title": get_session_title(r),
"project_id": r["project_id"],
"model": parse_model(r),
"agent": r["agent"],
"cost": r["cost"],
"tokens_input": r["tokens_input"],
"tokens_output": r["tokens_output"],
"messages": r["msg_count"],
"last_activity": format_ts(r["last_time"]) if r["last_time"] else None,
}
)
print_json(data)
return 0
table_rows = []
for r in rows:
project_name = db_module.get_project_name(db, r["project_id"]) if r["project_id"] else "—"
model_name = parse_model(r)
last_act = format_ts(r["last_time"], "%Y-%m-%d %H:%M") if r["last_time"] else "—"
table_rows.append(
[
r["id"][:24],
get_session_title(r)[:32],
project_name[:16],
model_name[:20],
last_act,
str(r["msg_count"]),
f"${r['cost']:.4f}" if r["cost"] else "—",
]
)
print_table_simple(
[
_("list.header.id"),
_("list.header.title"),
_("list.header.project"),
_("list.header.model"),
_("list.header.activity"),
_("list.header.messages"),
_("list.header.cost"),
],
table_rows,
)
return 0