@kairyou/agent-tools 0.11.0 → 0.13.0
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/config.default.jsonc +12 -2
- package/dist/log/hook.mjs +1581 -0
- package/dist/log/opencode-plugin.mjs +113 -0
- package/docs/en/extras.md +90 -8
- package/docs/zh-CN/extras.md +89 -8
- package/integrations/log/hook.mjs +926 -0
- package/integrations/log/opencode-plugin.mjs +137 -0
- package/package.json +1 -1
- package/scripts/build.mjs +6 -0
- package/scripts/install.mjs +110 -7
- package/skills/workflow/at-daily-log/SKILL.md +56 -29
- package/skills/workflow/at-self-eval/SKILL.md +10 -3
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// integrations/log/opencode-plugin.mjs
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
var HOOK = path.join(path.dirname(fileURLToPath(import.meta.url)), "hook.mjs");
|
|
6
|
+
var sendQueue = Promise.resolve();
|
|
7
|
+
function send(payload) {
|
|
8
|
+
sendQueue = sendQueue.then(
|
|
9
|
+
() => new Promise((resolve) => {
|
|
10
|
+
try {
|
|
11
|
+
const child = spawn("node", [HOOK], {
|
|
12
|
+
stdio: ["pipe", "ignore", "ignore"],
|
|
13
|
+
windowsHide: true
|
|
14
|
+
});
|
|
15
|
+
child.on("error", () => resolve());
|
|
16
|
+
child.on("exit", () => resolve());
|
|
17
|
+
child.stdin.write(JSON.stringify(payload));
|
|
18
|
+
child.stdin.end();
|
|
19
|
+
} catch {
|
|
20
|
+
resolve();
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
var AgentToolsLog = async ({ directory, project } = {}) => {
|
|
26
|
+
const cwd = directory || project?.worktree || process.cwd();
|
|
27
|
+
const assistantMessageIds = /* @__PURE__ */ new Set();
|
|
28
|
+
const lastAssistantText = /* @__PURE__ */ new Map();
|
|
29
|
+
return {
|
|
30
|
+
"chat.message": async (_input, output) => {
|
|
31
|
+
const message = output?.message;
|
|
32
|
+
if (message?.role !== "user") return;
|
|
33
|
+
const text = (output?.parts || []).filter((part) => part?.type === "text" && typeof part.text === "string").map((part) => part.text).join("\n");
|
|
34
|
+
if (!text.trim()) return;
|
|
35
|
+
send({
|
|
36
|
+
hook_event_name: "UserPromptSubmit",
|
|
37
|
+
session_id: message.sessionID,
|
|
38
|
+
cwd,
|
|
39
|
+
prompt: text
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
"tool.execute.before": async (input, output) => {
|
|
43
|
+
const tool = String(input?.tool || "");
|
|
44
|
+
if (tool === "bash") return;
|
|
45
|
+
const args = output?.args;
|
|
46
|
+
if (!args || typeof args !== "object") return;
|
|
47
|
+
send({
|
|
48
|
+
hook_event_name: "PreToolUse",
|
|
49
|
+
session_id: input?.sessionID,
|
|
50
|
+
cwd,
|
|
51
|
+
tool_name: tool === "write" ? "Write" : "Edit",
|
|
52
|
+
tool_input: args
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
"tool.execute.after": async (input, output) => {
|
|
56
|
+
const sessionId = input?.sessionID;
|
|
57
|
+
const tool = String(input?.tool || "");
|
|
58
|
+
if (tool === "bash") {
|
|
59
|
+
send({
|
|
60
|
+
hook_event_name: "PostToolUse",
|
|
61
|
+
session_id: sessionId,
|
|
62
|
+
cwd,
|
|
63
|
+
tool_name: "Bash",
|
|
64
|
+
tool_input: { command: String(input?.args?.command || "") }
|
|
65
|
+
});
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const files = output?.metadata?.files;
|
|
69
|
+
if (!Array.isArray(files)) return;
|
|
70
|
+
for (const file of files) {
|
|
71
|
+
if (!file?.filePath) continue;
|
|
72
|
+
send({
|
|
73
|
+
hook_event_name: "PostToolUse",
|
|
74
|
+
session_id: sessionId,
|
|
75
|
+
cwd,
|
|
76
|
+
tool_name: tool === "write" ? "Write" : "Edit",
|
|
77
|
+
tool_input: { file_path: file.filePath }
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
event: async ({ event }) => {
|
|
82
|
+
const type = event?.type;
|
|
83
|
+
const properties = event?.properties || {};
|
|
84
|
+
if (type === "message.updated") {
|
|
85
|
+
if (properties.info?.role === "assistant") assistantMessageIds.add(properties.info.id);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (type === "message.part.updated") {
|
|
89
|
+
const part = properties.part;
|
|
90
|
+
if (part?.type === "text" && assistantMessageIds.has(part.messageID)) {
|
|
91
|
+
lastAssistantText.set(part.sessionID, String(part.text || ""));
|
|
92
|
+
}
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (type === "session.idle") {
|
|
96
|
+
send({
|
|
97
|
+
hook_event_name: "Stop",
|
|
98
|
+
session_id: properties.sessionID,
|
|
99
|
+
cwd,
|
|
100
|
+
last_assistant_message: lastAssistantText.get(properties.sessionID) || ""
|
|
101
|
+
});
|
|
102
|
+
lastAssistantText.delete(properties.sessionID);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (type === "session.deleted") {
|
|
106
|
+
lastAssistantText.delete(properties.sessionID);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
export {
|
|
112
|
+
AgentToolsLog
|
|
113
|
+
};
|
package/docs/en/extras.md
CHANGED
|
@@ -19,13 +19,13 @@ Usage:
|
|
|
19
19
|
- `/at-self-eval summarize July for C:\projects\project-a and C:\projects\project-b` — only those projects
|
|
20
20
|
- `/at-self-eval also include C:\projects\project-c` — add to the default scope
|
|
21
21
|
- Paste a daily/weekly log, or give a file path, to add business context
|
|
22
|
-
- `/at-self-eval summarize from C:\
|
|
22
|
+
- `/at-self-eval summarize from C:\logs\daily-log.md only` — log only, Git is not read
|
|
23
23
|
|
|
24
24
|
Review the generated result before use.
|
|
25
25
|
|
|
26
26
|
## at-daily-log
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
Distill each day's Git commits across projects into a work report; runs when invoked.
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
31
|
npx -y skills@latest add kairyou/agent-tools --skill at-daily-log -g -y
|
|
@@ -35,29 +35,111 @@ Usage:
|
|
|
35
35
|
|
|
36
36
|
- `/at-daily-log` — print today's log
|
|
37
37
|
- `/at-daily-log 2026-07-31` — pick the date
|
|
38
|
+
- `/at-daily-log last week` / `/at-daily-log the last two weeks` — one entry per active day, empty days skipped
|
|
38
39
|
- `/at-daily-log summarize today for C:\projects\project-a` — only that project
|
|
39
40
|
- `/at-daily-log also include C:\projects\project-c` — add to the default scope
|
|
40
41
|
- `/at-daily-log record the log` — record to the configured file; rerunning a day only refreshes the generated part
|
|
41
|
-
- `/at-daily-log record it to C:\
|
|
42
|
-
- `/at-daily-log record
|
|
42
|
+
- `/at-daily-log record it to C:\logs\daily-log.md` — record to that file
|
|
43
|
+
- `/at-daily-log record daily at 18:00` — guides you through an OS scheduled task; days without commits are not written
|
|
43
44
|
|
|
45
|
+
Recorded output example:
|
|
46
|
+
|
|
47
|
+
```markdown
|
|
48
|
+
+ 2026-08-03
|
|
49
|
+
<!-- daily-log:2026-08-03:start 5,a1b2c3d -->
|
|
50
|
+
1. project-a: finished the login module refactor with regression coverage.
|
|
51
|
+
2. project-b: fixed the timezone offset in report exports.
|
|
52
|
+
<!-- daily-log:2026-08-03:end -->
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The `<!-- ... -->` comments are boundary markers: an update rewrites only what sits
|
|
56
|
+
between them, and everything else in the file (such as your own notes) is left alone.
|
|
57
|
+
|
|
58
|
+
Paired with the `log` capability below, work that ships no code, such as troubleshooting, also reaches the report.
|
|
44
59
|
Review the generated result before use.
|
|
45
60
|
|
|
46
|
-
##
|
|
61
|
+
## log
|
|
62
|
+
|
|
63
|
+
Record each day's AI sessions across projects into a work log; runs automatically
|
|
64
|
+
once installed.
|
|
65
|
+
|
|
66
|
+
Independent of and complementary to `at-daily-log` above; use them together or alone.
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
npx -y @kairyou/agent-tools@latest log -a claude codex opencode
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- `format: "daily"` (default): a single markdown file, one dated entry per day, each turn summarized into one line
|
|
73
|
+
- `format: "detailed"`: one full report per day with each turn's request and outcome, the files changed, and approximate lines added/removed (measured against the current file when several turns touch one)
|
|
74
|
+
- Codex: run `/hooks` once after installing to approve it; opencode: restart after installing or updating
|
|
75
|
+
|
|
76
|
+
`daily` output example:
|
|
77
|
+
|
|
78
|
+
```markdown
|
|
79
|
+
+ 2026-08-03
|
|
80
|
+
<!-- log:2026-08-03:start -->
|
|
81
|
+
1. project-a: traced the login timeout to sessions never renewing.
|
|
82
|
+
2. project-a: fixed the login timeout, added regression tests.
|
|
83
|
+
3. project-b: traced empty report exports to an inverted permission filter.
|
|
84
|
+
<!-- log:2026-08-03:end -->
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
One line per turn, written from the AI's own summary at the end of that turn; no
|
|
88
|
+
cross-turn consolidation. Updates likewise rewrite only what sits between the markers.
|
|
89
|
+
|
|
90
|
+
`detailed` output example (excerpt):
|
|
91
|
+
|
|
92
|
+
```markdown
|
|
93
|
+
# AI Log - 2026-08-03
|
|
94
|
+
|
|
95
|
+
## Overview
|
|
96
|
+
|
|
97
|
+
- Prompts: 5
|
|
98
|
+
- Changed files: 3
|
|
99
|
+
- Line changes: +120/-30
|
|
100
|
+
|
|
101
|
+
## Sessions
|
|
102
|
+
|
|
103
|
+
- Time: 2026-08-03 10:12:01 -> 2026-08-03 10:20:45
|
|
104
|
+
- Project: project-a
|
|
105
|
+
|
|
106
|
+
Request
|
|
107
|
+
(request excerpt)
|
|
108
|
+
|
|
109
|
+
Outcome
|
|
110
|
+
(outcome summary)
|
|
111
|
+
|
|
112
|
+
Changes
|
|
113
|
+
- src/auth/session.ts | diff +42/-8 | 3 ops
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Configuration
|
|
47
117
|
|
|
48
118
|
All in `~/.agent-tools/config.jsonc`:
|
|
49
119
|
|
|
50
120
|
```jsonc
|
|
51
121
|
{
|
|
52
|
-
//
|
|
122
|
+
// log capability: AI session log
|
|
123
|
+
"log": {
|
|
124
|
+
"enabled": true, // false: pause recording without uninstalling
|
|
125
|
+
"output": "C:\\logs\\ai-log.md", // daily: one file; detailed: a directory
|
|
126
|
+
"language": "zh", // zh | en
|
|
127
|
+
"format": "daily", // daily | detailed
|
|
128
|
+
"projects": [ // optional: record only these; entries may override the keys above
|
|
129
|
+
"C:\\projects\\project-a",
|
|
130
|
+
{ "path": "C:\\projects\\project-b", "format": "detailed", "output": "C:\\logs\\project-b" }
|
|
131
|
+
]
|
|
132
|
+
},
|
|
133
|
+
// at-self-eval, at-daily-log: default projects (otherwise just the current repo);
|
|
134
|
+
// prompt: free text that tunes how that project is summarized
|
|
53
135
|
"workProjects": [
|
|
54
136
|
"C:\\projects\\project-a",
|
|
55
|
-
"C:\\projects\\project-b"
|
|
137
|
+
{ "path": "C:\\projects\\project-b", "prompt": "refer to `phoenix` as `Shop App` in the output; skip commits starting with `test:`" }
|
|
56
138
|
// "C:\\projects\\temporarily-disabled"
|
|
57
139
|
],
|
|
58
140
|
// at-daily-log: default file when asked to record; at-self-eval also reads it as fallback
|
|
59
141
|
"dailyLog": {
|
|
60
|
-
"output": "C:\\
|
|
142
|
+
"output": "C:\\logs\\daily-log.md"
|
|
61
143
|
}
|
|
62
144
|
}
|
|
63
145
|
```
|
package/docs/zh-CN/extras.md
CHANGED
|
@@ -18,13 +18,13 @@ npx -y skills@latest add kairyou/agent-tools --skill at-self-eval -g -y
|
|
|
18
18
|
- `/at-self-eval 统计 C:\projects\project-a 和 C:\projects\project-b 的 7 月工作` — 只统计指定项目
|
|
19
19
|
- `/at-self-eval 另外包含 C:\projects\project-c` — 在默认范围上追加
|
|
20
20
|
- 可粘贴日报或周报文本, 也可提供文件路径补充业务背景
|
|
21
|
-
- `/at-self-eval 只根据 C:\
|
|
21
|
+
- `/at-self-eval 只根据 C:\logs\daily-log.md 总结` — 只凭日志生成, 不读 Git
|
|
22
22
|
|
|
23
23
|
生成的结果请人工核对.
|
|
24
24
|
|
|
25
25
|
## at-daily-log
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
按天把各项目的 Git 提交提炼成工作日报, 调用时生成.
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
30
|
npx -y skills@latest add kairyou/agent-tools --skill at-daily-log -g -y
|
|
@@ -34,29 +34,110 @@ npx -y skills@latest add kairyou/agent-tools --skill at-daily-log -g -y
|
|
|
34
34
|
|
|
35
35
|
- `/at-daily-log` — 输出今天的日报
|
|
36
36
|
- `/at-daily-log 2026-07-31` — 指定日期
|
|
37
|
+
- `/at-daily-log 上周` / `/at-daily-log 最近两周` — 范围内每天一条, 跳过没有提交的日子
|
|
37
38
|
- `/at-daily-log 统计 C:\projects\project-a 今天的工作` — 只统计指定项目
|
|
38
39
|
- `/at-daily-log 另外包含 C:\projects\project-c` — 在默认范围上追加
|
|
39
40
|
- `/at-daily-log 记录日报` — 记录到配置的文件; 同一天重复执行只更新生成的部分
|
|
40
|
-
- `/at-daily-log 记录到 C:\
|
|
41
|
-
- `/at-daily-log
|
|
41
|
+
- `/at-daily-log 记录到 C:\logs\daily-log.md` — 记录到指定文件
|
|
42
|
+
- `/at-daily-log 每天 18:00 自动记录` — 引导搭建系统定时任务; 没有提交的日子不会写入
|
|
42
43
|
|
|
44
|
+
记录到文件的示例:
|
|
45
|
+
|
|
46
|
+
```markdown
|
|
47
|
+
+ 2026-08-03
|
|
48
|
+
<!-- daily-log:2026-08-03:start 5,a1b2c3d -->
|
|
49
|
+
1. project-a: 完成登录模块重构, 覆盖回归用例.
|
|
50
|
+
2. project-b: 修复导出报表的时区偏移.
|
|
51
|
+
<!-- daily-log:2026-08-03:end -->
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`<!-- ... -->` 注释是边界标记: 更新只重写两个标记之间的内容, 文件里的其他部分
|
|
55
|
+
(比如你手写的备注)不会被碰.
|
|
56
|
+
|
|
57
|
+
搭配下方的 `log` 使用时, 排查问题这类没提交代码的工作也能进日报.
|
|
43
58
|
生成的结果请人工核对.
|
|
44
59
|
|
|
45
|
-
##
|
|
60
|
+
## log
|
|
61
|
+
|
|
62
|
+
按天把各项目的 AI 会话记录成工作日志, 安装后自动运行.
|
|
63
|
+
|
|
64
|
+
和上面的 `at-daily-log` 独立互补, 可一起使用或单独使用.
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npx -y @kairyou/agent-tools@latest log -a claude codex opencode
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
- `format: "daily"` (默认): 单一 md 文件, 每天一个日期条目, 每轮对话总结成一行
|
|
71
|
+
- `format: "detailed"`: 每天一份详细报告, 含每轮的请求与结果, 改动的文件和近似的增删行数(多轮改同一文件时按当前文件计算)
|
|
72
|
+
- Codex 安装后运行 `/hooks` 批准一次; opencode 安装或更新后需要重启
|
|
73
|
+
|
|
74
|
+
`daily` 输出示例:
|
|
75
|
+
|
|
76
|
+
```markdown
|
|
77
|
+
+ 2026-08-03
|
|
78
|
+
<!-- log:2026-08-03:start -->
|
|
79
|
+
1. project-a: 排查登录超时, 定位到会话缓存没有续期.
|
|
80
|
+
2. project-a: 修复登录超时, 补充回归用例.
|
|
81
|
+
3. project-b: 定位报表导出为空的问题, 原因是权限过滤条件写反.
|
|
82
|
+
<!-- log:2026-08-03:end -->
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
每轮一行, 内容是那一轮结束时 AI 自己写的总结, 不做跨轮归纳; 同样只重写标记之间
|
|
86
|
+
的部分, 文件里的其他内容不会被碰.
|
|
87
|
+
|
|
88
|
+
`detailed` 输出示例(节选):
|
|
89
|
+
|
|
90
|
+
```markdown
|
|
91
|
+
# AI 日报 - 2026-08-03
|
|
92
|
+
|
|
93
|
+
## 今日概览
|
|
94
|
+
|
|
95
|
+
- 请求次数: 5
|
|
96
|
+
- 变更文件数: 3
|
|
97
|
+
- 总行变更: +120/-30
|
|
98
|
+
|
|
99
|
+
## 会话记录
|
|
100
|
+
|
|
101
|
+
- Time: 2026-08-03 10:12:01 -> 2026-08-03 10:20:45
|
|
102
|
+
- Project: project-a
|
|
103
|
+
|
|
104
|
+
Request
|
|
105
|
+
(请求原文摘录)
|
|
106
|
+
|
|
107
|
+
Outcome
|
|
108
|
+
(结果摘要)
|
|
109
|
+
|
|
110
|
+
Changes
|
|
111
|
+
- src/auth/session.ts | 变更 +42/-8 | 操作 3 次
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## 配置
|
|
46
115
|
|
|
47
116
|
都在 `~/.agent-tools/config.jsonc`:
|
|
48
117
|
|
|
49
118
|
```jsonc
|
|
50
119
|
{
|
|
51
|
-
//
|
|
120
|
+
// log capability: AI 会话日志
|
|
121
|
+
"log": {
|
|
122
|
+
"enabled": true, // false: 临时停止记录, 不用卸载
|
|
123
|
+
"output": "C:\\logs\\ai-log.md", // daily: 单一文件; detailed: 目录
|
|
124
|
+
"language": "zh", // zh | en
|
|
125
|
+
"format": "daily", // daily | detailed
|
|
126
|
+
"projects": [ // 可选: 只记录这些目录, 条目可覆盖上面的键
|
|
127
|
+
"C:\\projects\\project-a",
|
|
128
|
+
{ "path": "C:\\projects\\project-b", "format": "detailed", "output": "C:\\logs\\project-b" }
|
|
129
|
+
]
|
|
130
|
+
},
|
|
131
|
+
// at-self-eval, at-daily-log: 默认统计的项目(不配则只统计当前项目);
|
|
132
|
+
// prompt: 该项目的提示词, 用来优化生成的日报和总结
|
|
52
133
|
"workProjects": [
|
|
53
134
|
"C:\\projects\\project-a",
|
|
54
|
-
"C:\\projects\\project-b"
|
|
135
|
+
{ "path": "C:\\projects\\project-b", "prompt": "输出里把 `phoenix` 称作 `商城App`, 跳过 `test:` 开头的提交" }
|
|
55
136
|
// "C:\\projects\\temporarily-disabled"
|
|
56
137
|
],
|
|
57
138
|
// at-daily-log: 记录日报的默认文件; 未提供日志时 at-self-eval 也读它作补充
|
|
58
139
|
"dailyLog": {
|
|
59
|
-
"output": "C:\\
|
|
140
|
+
"output": "C:\\logs\\daily-log.md"
|
|
60
141
|
}
|
|
61
142
|
}
|
|
62
143
|
```
|