agent-skill-installer 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -7,56 +7,45 @@ Produce a daily report from local Codex sessions.
|
|
|
7
7
|
|
|
8
8
|
## Workflow
|
|
9
9
|
|
|
10
|
-
1. Resolve target date
|
|
11
|
-
- If user says `today`,
|
|
12
|
-
- If user says relative dates (`yesterday`, `tomorrow`), convert to concrete dates first.
|
|
10
|
+
1. Resolve target date.
|
|
11
|
+
- If user says `today`, use an absolute date (e.g. `2026-03-02`).
|
|
13
12
|
|
|
14
|
-
2.
|
|
13
|
+
2. Read session files for that date.
|
|
15
14
|
|
|
16
15
|
```bash
|
|
17
|
-
|
|
16
|
+
ls -1 ~/.codex/sessions/2026/03/02/*.jsonl
|
|
18
17
|
```
|
|
19
18
|
|
|
20
|
-
3.
|
|
19
|
+
3. Extract completed assistant outputs only (`final_answer`).
|
|
21
20
|
|
|
22
21
|
```bash
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
for f in ~/.codex/sessions/2026/03/02/*.jsonl; do
|
|
23
|
+
jq -r 'select(.type=="response_item" and .payload.type=="message" and .payload.role=="assistant" and .payload.phase=="final_answer")
|
|
24
|
+
| .timestamp + "\t" + ((.payload.content // [])
|
|
25
|
+
| map(select(.type=="output_text") | .text)
|
|
26
|
+
| join(" ") | gsub("[\n\r\t]+";" ") | gsub(" +";" "))' "$f"
|
|
27
|
+
done
|
|
26
28
|
```
|
|
27
29
|
|
|
28
|
-
4. Summarize
|
|
29
|
-
- Merge similar tasks into one topic.
|
|
30
|
-
- Keep
|
|
31
|
-
- Keep neutral
|
|
30
|
+
4. Summarize by主题 and result.
|
|
31
|
+
- Merge similar tasks into one topic line.
|
|
32
|
+
- Keep key evidence: file paths, tests, and commit hashes if present.
|
|
33
|
+
- Keep neutral language and avoid guessing.
|
|
32
34
|
|
|
33
|
-
5. Output report only
|
|
35
|
+
5. Output daily report only (not logs).
|
|
34
36
|
|
|
35
37
|
## Output Format
|
|
36
38
|
|
|
37
39
|
Use this structure:
|
|
38
40
|
|
|
39
41
|
1. 日期:`YYYY-MM-DD`
|
|
40
|
-
2.
|
|
41
|
-
3.
|
|
42
|
-
4.
|
|
43
|
-
- 代码改动:关键文件路径
|
|
44
|
-
- 验证结果:命令与结论
|
|
45
|
-
- 提交记录:提交哈希与提交说明
|
|
46
|
-
5. 风险与待办:每条包含 `风险/阻塞`、`影响`、`下一步`
|
|
47
|
-
6. 数据缺口说明:若无会话文件、无 final_answer 或证据不足,明确说明影响范围
|
|
42
|
+
2. 今日业务事项:按主题列 2-6 条
|
|
43
|
+
3. 关键产出:代码改动/测试结论/提交哈希
|
|
44
|
+
4. 风险与待办:未完成项、潜在误判点
|
|
48
45
|
|
|
49
46
|
## Constraints
|
|
50
47
|
|
|
51
|
-
-
|
|
48
|
+
- Prefer `assistant final_answer` over commentary.
|
|
52
49
|
- Do not output raw JSONL unless user explicitly asks.
|
|
53
50
|
- Keep report concise and factual.
|
|
54
|
-
- If no
|
|
55
|
-
- Prefer explicit evidence fields over narrative paragraphs.
|
|
56
|
-
- If evidence is missing for a topic, mark it as `证据不足` instead of guessing.
|
|
57
|
-
|
|
58
|
-
## Resource
|
|
59
|
-
|
|
60
|
-
- `skills/codex-session-daily-report/scripts/extract_final_answers.py`
|
|
61
|
-
- Input: `--date YYYY-MM-DD`, optional `--root`.
|
|
62
|
-
- Output: `timestamp<TAB>session_file<TAB>text`.
|
|
51
|
+
- If no completed entries are found, state that clearly.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "codex-session-daily-report"
|
|
3
|
-
short_description: "
|
|
4
|
-
default_prompt: "Use $codex-session-daily-report to
|
|
3
|
+
short_description: "Generate daily reports from Codex session history."
|
|
4
|
+
default_prompt: "Use $codex-session-daily-report to read today's Codex sessions and output a concise daily report."
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Extract assistant final answers from Codex session JSONL files."""
|
|
3
|
-
|
|
4
|
-
from __future__ import annotations
|
|
5
|
-
|
|
6
|
-
import argparse
|
|
7
|
-
import glob
|
|
8
|
-
import json
|
|
9
|
-
import os
|
|
10
|
-
import re
|
|
11
|
-
import sys
|
|
12
|
-
from pathlib import Path
|
|
13
|
-
|
|
14
|
-
WHITESPACE_RE = re.compile(r"\s+")
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def normalize_text(text: str) -> str:
|
|
18
|
-
return WHITESPACE_RE.sub(" ", text).strip()
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def parse_date(value: str) -> tuple[str, str, str]:
|
|
22
|
-
parts = value.split("-")
|
|
23
|
-
if len(parts) != 3 or not all(part.isdigit() for part in parts):
|
|
24
|
-
raise ValueError("日期格式必须为 YYYY-MM-DD")
|
|
25
|
-
|
|
26
|
-
year, month, day = parts
|
|
27
|
-
if len(year) != 4 or len(month) != 2 or len(day) != 2:
|
|
28
|
-
raise ValueError("日期格式必须为 YYYY-MM-DD")
|
|
29
|
-
|
|
30
|
-
return year, month, day
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def collect_session_files(root: str, date_value: str) -> list[str]:
|
|
34
|
-
year, month, day = parse_date(date_value)
|
|
35
|
-
pattern = os.path.join(root, year, month, day, "*.jsonl")
|
|
36
|
-
return sorted(glob.glob(pattern))
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def extract_records(file_path: str) -> list[str]:
|
|
40
|
-
records: list[str] = []
|
|
41
|
-
with Path(file_path).open("r", encoding="utf-8") as handle:
|
|
42
|
-
for line in handle:
|
|
43
|
-
if not line.strip():
|
|
44
|
-
continue
|
|
45
|
-
|
|
46
|
-
try:
|
|
47
|
-
item = json.loads(line)
|
|
48
|
-
except json.JSONDecodeError:
|
|
49
|
-
continue
|
|
50
|
-
|
|
51
|
-
if item.get("type") != "response_item":
|
|
52
|
-
continue
|
|
53
|
-
|
|
54
|
-
payload = item.get("payload") or {}
|
|
55
|
-
if payload.get("type") != "message":
|
|
56
|
-
continue
|
|
57
|
-
if payload.get("role") != "assistant":
|
|
58
|
-
continue
|
|
59
|
-
if payload.get("phase") != "final_answer":
|
|
60
|
-
continue
|
|
61
|
-
|
|
62
|
-
content = payload.get("content") or []
|
|
63
|
-
text_parts = [
|
|
64
|
-
part.get("text", "")
|
|
65
|
-
for part in content
|
|
66
|
-
if isinstance(part, dict) and part.get("type") == "output_text"
|
|
67
|
-
]
|
|
68
|
-
text = normalize_text(" ".join(text_parts))
|
|
69
|
-
if not text:
|
|
70
|
-
continue
|
|
71
|
-
|
|
72
|
-
timestamp = item.get("timestamp", "")
|
|
73
|
-
session_file = os.path.basename(file_path)
|
|
74
|
-
records.append(f"{timestamp}\t{session_file}\t{text}")
|
|
75
|
-
|
|
76
|
-
return records
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def main() -> int:
|
|
80
|
-
parser = argparse.ArgumentParser(
|
|
81
|
-
description="提取指定日期的 assistant final_answer 内容",
|
|
82
|
-
)
|
|
83
|
-
parser.add_argument(
|
|
84
|
-
"--date",
|
|
85
|
-
required=True,
|
|
86
|
-
help="目标日期,格式 YYYY-MM-DD",
|
|
87
|
-
)
|
|
88
|
-
parser.add_argument(
|
|
89
|
-
"--root",
|
|
90
|
-
default="~/.codex/sessions",
|
|
91
|
-
help="sessions 根目录,默认 ~/.codex/sessions",
|
|
92
|
-
)
|
|
93
|
-
args = parser.parse_args()
|
|
94
|
-
|
|
95
|
-
root = os.path.expanduser(args.root)
|
|
96
|
-
files = collect_session_files(root, args.date)
|
|
97
|
-
|
|
98
|
-
if not files:
|
|
99
|
-
print(f"未找到会话文件: {args.date}", file=sys.stderr)
|
|
100
|
-
return 1
|
|
101
|
-
|
|
102
|
-
wrote = False
|
|
103
|
-
for file_path in files:
|
|
104
|
-
for record in extract_records(file_path):
|
|
105
|
-
print(record)
|
|
106
|
-
wrote = True
|
|
107
|
-
|
|
108
|
-
if not wrote:
|
|
109
|
-
print(f"未找到 final_answer: {args.date}", file=sys.stderr)
|
|
110
|
-
return 2
|
|
111
|
-
|
|
112
|
-
return 0
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if __name__ == "__main__":
|
|
116
|
-
sys.exit(main())
|