pi-shepherd 0.1.2 → 0.2.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/README.en.md +205 -84
- package/README.md +207 -88
- package/index.ts +262 -229
- package/package.json +60 -55
- package/rules.json +196 -33
- package/shepherd/compaction.ts +76 -0
- package/shepherd/conditions.ts +98 -0
- package/shepherd/ephemeral.ts +55 -52
- package/shepherd/git.ts +64 -0
- package/shepherd/index.ts +13 -0
- package/shepherd/line-count.ts +86 -86
- package/shepherd/message-end.ts +120 -0
- package/shepherd/rules-editor.ts +250 -215
- package/shepherd/rules-tool-helpers.ts +119 -120
- package/shepherd/rules-tool-list.ts +124 -126
- package/shepherd/rules-tool.ts +182 -142
- package/shepherd/rules-validate.ts +89 -44
- package/shepherd/rules.ts +366 -295
- package/shepherd/tool-event-types.ts +27 -14
- package/shepherd/tool-hooks.ts +165 -177
- package/shepherd/worktree-check.ts +130 -130
- package/tsconfig.json +21 -14
package/README.md
CHANGED
|
@@ -1,139 +1,258 @@
|
|
|
1
|
-
[English](README.en.md) |
|
|
1
|
+
[English](README.en.md) | [中文文档](#)
|
|
2
2
|
|
|
3
|
-
> 📖 **[pi-atelier 实战指南](https://catlain.github.io/pi-atelier/)** — 从零教会你使用 pi-atelier
|
|
3
|
+
> 📖 **[pi-atelier 实战指南](https://catlain.github.io/pi-atelier/)** — 从零教会你使用 pi-atelier 扩展生态
|
|
4
4
|
|
|
5
5
|
# pi-shepherd
|
|
6
6
|
|
|
7
7
|
[源码仓库](https://github.com/catlain/pi-shepherd) | [npm](https://www.npmjs.com/package/pi-shepherd)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
pi-coding-agent 的 **规则驱动行为守护系统** — 在工具调用、AI 回复、会话结束等关键节点,自动拦截、提醒或改写操作。
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## 解决什么问题
|
|
12
12
|
|
|
13
|
-
AI
|
|
13
|
+
AI 编程助手在长时间会话中容易跑偏:
|
|
14
14
|
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
15
|
+
- **工具滥用**:用 grep 搜符号名(应该用 code-graph)、用 bash cat 读文件(应该用 read)
|
|
16
|
+
- **忘记收尾**:改完代码不跑测试、不提交 git、不更新文档
|
|
17
|
+
- **编码规范违反**:TypeScript 用空格缩进(应该用 Tab)、Python 用 Tab(应该用空格)
|
|
18
|
+
- **重复犯错**:同一个错误反复出现,不知道翻看已有的踩坑记录
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
pi-shepherd 通过**可配置的规则引擎**,在这些关键节点自动介入,把最佳实践变成自动化的守护机制。
|
|
21
|
+
|
|
22
|
+
## 安装
|
|
21
23
|
|
|
22
24
|
```bash
|
|
23
25
|
pi install git:github.com/catlain/pi-shepherd
|
|
24
26
|
```
|
|
25
27
|
|
|
26
|
-
##
|
|
28
|
+
## 核心概念
|
|
29
|
+
|
|
30
|
+
### 钩子(Hook)
|
|
31
|
+
|
|
32
|
+
Shepherd 在 AI 工作流的 6 个关键节点插入钩子:
|
|
33
|
+
|
|
34
|
+
| 钩子 | 触发时机 | 典型用途 |
|
|
35
|
+
|------|---------|---------|
|
|
36
|
+
| `tool_call` | 工具即将执行前 | 拦截不当调用、改写命令 |
|
|
37
|
+
| `tool_result` | 工具执行完成后 | 检查结果、触发后续动作 |
|
|
38
|
+
| `agent_end` | AI 主动结束时 | 提醒提交 git、更新记忆 |
|
|
39
|
+
| `message_end` | AI 每条回复完成后 | 检测回复中的问题模式 |
|
|
40
|
+
| `session_shutdown` | 会话关闭时 | 清理资源 |
|
|
41
|
+
|
|
42
|
+
### 动作(Action)
|
|
43
|
+
|
|
44
|
+
规则匹配后可以执行 4 种动作:
|
|
45
|
+
|
|
46
|
+
| 动作 | 效果 |
|
|
47
|
+
|------|------|
|
|
48
|
+
| `block` | 阻止工具执行,返回原因 |
|
|
49
|
+
| `notify` | 弹出提醒,AI 可以选择忽略 |
|
|
50
|
+
| `steer` | 注入下一轮对话,强制 AI 响应 |
|
|
51
|
+
| `rewrite` | 改写工具参数后继续执行 |
|
|
27
52
|
|
|
28
|
-
|
|
53
|
+
### 条件匹配
|
|
29
54
|
|
|
55
|
+
**单条件模式**(简单场景):
|
|
56
|
+
```json
|
|
57
|
+
{ "pattern": "\\bcat\\b", "flags": "" }
|
|
30
58
|
```
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
59
|
+
|
|
60
|
+
**多条件模式**(精确控制):
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"conditions": [
|
|
64
|
+
{ "field": "path", "pattern": "\\.ts$" },
|
|
65
|
+
{ "field": "text", "pattern": "\\n [\\S ]" }
|
|
66
|
+
]
|
|
67
|
+
}
|
|
34
68
|
```
|
|
35
69
|
|
|
36
|
-
|
|
70
|
+
多个 `conditions` 默认是 **AND** 关系(全部满足才触发),可通过 `conditionLogic: "or"` 改为 OR。
|
|
71
|
+
|
|
72
|
+
**内置条件**(不需要正则):
|
|
73
|
+
|
|
74
|
+
| builtin | 检查内容 |
|
|
75
|
+
|---------|---------|
|
|
76
|
+
| `git_dirty` | 有已跟踪文件的未提交改动 |
|
|
77
|
+
| `git_untracked` | 有未跟踪文件 |
|
|
78
|
+
| `has_edits` | 本轮调用过 edit/write |
|
|
79
|
+
| `always` | 始终匹配 |
|
|
37
80
|
|
|
38
|
-
|
|
81
|
+
### 有状态规则
|
|
82
|
+
|
|
83
|
+
通过 `state` 字段追踪工具调用统计,实现「N 次错误后提醒」等模式:
|
|
39
84
|
|
|
40
85
|
```json
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
"name": "warn-large-edit",
|
|
51
|
-
"pattern": "edit",
|
|
52
|
-
"type": "tool_result",
|
|
53
|
-
"maxLines": 500,
|
|
54
|
-
"action": "warn",
|
|
55
|
-
"message": "Edit result is large, consider breaking into smaller changes"
|
|
56
|
-
}
|
|
57
|
-
]
|
|
86
|
+
{
|
|
87
|
+
"comment": "连续出错后提醒翻记忆",
|
|
88
|
+
"hook": "tool_result",
|
|
89
|
+
"action": "steer",
|
|
90
|
+
"state": { "countKind": "errors", "gte": 5 },
|
|
91
|
+
"reason": "工具反复出错,请检查记忆文件是否有踩坑记录"
|
|
92
|
+
}
|
|
58
93
|
```
|
|
59
94
|
|
|
60
|
-
|
|
95
|
+
支持三种计数方式:
|
|
96
|
+
- `calls`:工具调用次数
|
|
97
|
+
- `errors`:连续错误次数
|
|
98
|
+
- `chars`:工具返回的字符量
|
|
99
|
+
|
|
100
|
+
配合 `resetOn` 可以在某个工具成功后重置计数(如测试通过后清零错误计数)。
|
|
101
|
+
|
|
102
|
+
## 规则格式
|
|
103
|
+
|
|
104
|
+
完整的规则字段:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"comment": "规则描述(必填,同时作为唯一标识)",
|
|
109
|
+
"hook": "tool_call",
|
|
110
|
+
"tool": "bash",
|
|
111
|
+
"action": "block",
|
|
112
|
+
"reason": "给 AI 看的提示信息",
|
|
113
|
+
"pattern": "\\bcat\\b",
|
|
114
|
+
"conditions": [{ "field": "path", "pattern": "\\.ts$" }],
|
|
115
|
+
"conditionLogic": "and",
|
|
116
|
+
"enabled": true,
|
|
117
|
+
"state": { "countKind": "errors", "gte": 3 },
|
|
118
|
+
"resetOn": ["bash"],
|
|
119
|
+
"subagent": false,
|
|
120
|
+
"requiresTools": ["code_graph_semantic_code_search"],
|
|
121
|
+
"requireSuccess": true,
|
|
122
|
+
"stopReason": ["stop"]
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**必填字段**:`comment`、`reason`
|
|
127
|
+
|
|
128
|
+
**可选字段说明**:
|
|
129
|
+
- `enabled`:`false` 禁用规则(默认 `true`,可省略)
|
|
130
|
+
- `subagent`:`false` 表示子代理中跳过此规则
|
|
131
|
+
- `requiresTools`:只有这些工具都可用时才触发
|
|
132
|
+
- `requireSuccess`:`true` 表示跳过 isError 的 tool_result
|
|
133
|
+
- `stopReason`:`agent_end` 专用,限制只在特定结束原因时触发
|
|
61
134
|
|
|
62
|
-
|
|
63
|
-
|------|---------------|---------|
|
|
64
|
-
| `tool_call` | Before tool execution | `pass`, `block`, `modify` |
|
|
65
|
-
| `tool_result` | After tool execution | `pass`, `warn`, `truncate` |
|
|
66
|
-
| `agent_end` | When agent finishes | `enforce` |
|
|
135
|
+
## 规则存放位置
|
|
67
136
|
|
|
68
|
-
|
|
137
|
+
**全局规则**:`~/.pi/agent/extensions/shepherd/rules.json`(所有项目生效)
|
|
69
138
|
|
|
70
|
-
pi-
|
|
139
|
+
**项目规则**:`{cwd}/.pi/extensions/shepherd-rules.json`(仅当前项目生效)
|
|
140
|
+
或 `{cwd}/.pi/extensions/shepherd-rules-*.json`(多文件)
|
|
71
141
|
|
|
72
|
-
|
|
73
|
-
- Warn on overly large tool results
|
|
74
|
-
- Enforce git commit on agent end
|
|
75
|
-
- Block redundant file reads
|
|
142
|
+
项目规则和全局规则合并执行,项目规则可以补充或覆盖全局规则。
|
|
76
143
|
|
|
77
|
-
##
|
|
144
|
+
## 管理规则
|
|
145
|
+
|
|
146
|
+
使用 `shepherd_rules` 工具安全编辑规则(自动校验格式、备份、回滚):
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
# 列出所有规则
|
|
150
|
+
shepherd_rules(action: "list")
|
|
151
|
+
|
|
152
|
+
# 添加规则
|
|
153
|
+
shepherd_rules(action: "add", rule: { comment: "...", hook: "...", ... })
|
|
154
|
+
|
|
155
|
+
# 更新规则
|
|
156
|
+
shepherd_rules(action: "update", index: 2, changes: { enabled: false })
|
|
157
|
+
|
|
158
|
+
# 删除规则
|
|
159
|
+
shepherd_rules(action: "delete", index: 3)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## 实战示例
|
|
163
|
+
|
|
164
|
+
### 1. 编辑 Python 后自动跑测试
|
|
78
165
|
|
|
79
166
|
```json
|
|
80
167
|
{
|
|
81
|
-
"
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
168
|
+
"comment": "编辑 Python 后跑测试",
|
|
169
|
+
"hook": "tool_result",
|
|
170
|
+
"tool": "edit",
|
|
171
|
+
"action": "notify",
|
|
172
|
+
"conditions": [{ "field": "path", "pattern": "\\.py$" }],
|
|
173
|
+
"reason": "编辑了 Python 文件,请运行 ruff check 和单元测试"
|
|
85
174
|
}
|
|
86
175
|
```
|
|
87
176
|
|
|
88
|
-
|
|
177
|
+
### 2. 会话结束前检查 git
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"comment": "会话结束检查 git",
|
|
182
|
+
"hook": "agent_end",
|
|
183
|
+
"action": "notify",
|
|
184
|
+
"conditions": [
|
|
185
|
+
{ "builtin": "git_dirty" },
|
|
186
|
+
{ "builtin": "git_untracked" }
|
|
187
|
+
],
|
|
188
|
+
"conditionLogic": "or",
|
|
189
|
+
"reason": "Git 有未提交改动,请确认是否需要 commit + push"
|
|
190
|
+
}
|
|
191
|
+
```
|
|
89
192
|
|
|
90
|
-
|
|
91
|
-
|----------|-----------|--------|
|
|
92
|
-
| **Enforce coding standards** | `tool_call` | Block tools that don't follow conventions |
|
|
93
|
-
| **Prevent context bloat** | `tool_result` | Truncate large results |
|
|
94
|
-
| **Git discipline** | `agent_end` | Force commit at session end |
|
|
95
|
-
| **Redirect to better tools** | `tool_call` | Block grep, suggest code-graph |
|
|
96
|
-
| **Custom team rules** | All types | Project-specific guardrails |
|
|
193
|
+
### 3. 拦截 grep 搜代码,推荐 code-graph
|
|
97
194
|
|
|
98
|
-
|
|
195
|
+
```json
|
|
196
|
+
{
|
|
197
|
+
"comment": "推荐 code-graph 替代 grep",
|
|
198
|
+
"hook": "tool_result",
|
|
199
|
+
"tool": "grep",
|
|
200
|
+
"action": "notify",
|
|
201
|
+
"pattern": ".",
|
|
202
|
+
"reason": "搜代码推荐用 code-graph:semantic_code_search(模糊)、get_ast_node(精确)、find_references(引用)",
|
|
203
|
+
"requiresTools": ["code_graph_semantic_code_search"]
|
|
204
|
+
}
|
|
205
|
+
```
|
|
99
206
|
|
|
100
|
-
###
|
|
101
|
-
- Start with built-in rules, then add project-specific ones
|
|
102
|
-
- Use `warn` before `block` — give the agent a chance to learn
|
|
103
|
-
- Keep rule patterns simple and specific — regex is evaluated on every tool call
|
|
104
|
-
- Put project rules in `.pi/shepherd-rules/` for version control
|
|
207
|
+
### 4. 拦截 AI 回复中的归因猜测
|
|
105
208
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
209
|
+
```json
|
|
210
|
+
{
|
|
211
|
+
"comment": "禁止归因猜测",
|
|
212
|
+
"hook": "message_end",
|
|
213
|
+
"action": "steer",
|
|
214
|
+
"pattern": "(可能是|猜测|大概|也许是).*(jiti|缓存|工具链)",
|
|
215
|
+
"reason": "不要猜测根因——先查自己的代码逻辑,搜索最佳实践,验证后再下结论"
|
|
216
|
+
}
|
|
217
|
+
```
|
|
110
218
|
|
|
111
|
-
|
|
219
|
+
### 5. 禁止直接编辑 settings.json
|
|
112
220
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
221
|
+
```json
|
|
222
|
+
{
|
|
223
|
+
"comment": "禁止直接编辑 settings.json",
|
|
224
|
+
"hook": "tool_call",
|
|
225
|
+
"tool": "edit|write",
|
|
226
|
+
"action": "block",
|
|
227
|
+
"conditions": [{ "field": "path", "pattern": "settings\\.json$" }],
|
|
228
|
+
"reason": "直接编辑 settings.json 曾导致配置丢失,必须使用 settings_patch 工具"
|
|
229
|
+
}
|
|
230
|
+
```
|
|
119
231
|
|
|
120
|
-
##
|
|
232
|
+
## 架构
|
|
121
233
|
|
|
122
234
|
```
|
|
123
235
|
pi-shepherd/
|
|
124
|
-
├── index.ts
|
|
125
|
-
├──
|
|
126
|
-
├── rules
|
|
127
|
-
│ ├──
|
|
128
|
-
│ ├──
|
|
129
|
-
│
|
|
130
|
-
├──
|
|
131
|
-
|
|
236
|
+
├── index.ts # 入口:注册所有钩子
|
|
237
|
+
├── shepherd/
|
|
238
|
+
│ ├── rules.ts # 规则类型定义 + 加载/编译/匹配
|
|
239
|
+
│ ├── conditions.ts # Condition 类型 + builtin 条件匹配
|
|
240
|
+
│ ├── state-tracker.ts # 有状态规则的状态追踪器
|
|
241
|
+
│ ├── tool-hooks.ts # tool_call / tool_result 钩子处理
|
|
242
|
+
│ ├── message-end.ts # message_end 钩子处理
|
|
243
|
+
│ ├── rules-tool.ts # shepherd_rules 工具注册
|
|
244
|
+
│ ├── rules-editor.ts # 规则文件安全编辑(备份+校验)
|
|
245
|
+
│ ├── rules-validate.ts # 规则格式校验
|
|
246
|
+
│ ├── ephemeral.ts # 提示缓冲区(pushWarning)
|
|
247
|
+
│ ├── git.ts # git 状态检查工具函数
|
|
248
|
+
│ └── worktree-check.ts # worktree 环境检测
|
|
249
|
+
├── rules.json # 默认全局规则
|
|
250
|
+
└── tests/ # 测试
|
|
132
251
|
```
|
|
133
252
|
|
|
134
|
-
|
|
135
|
-
- `@pi-atelier/shared-utils`
|
|
136
|
-
- `@earendil-works/pi-coding-agent` — ExtensionAPI
|
|
253
|
+
**依赖**:
|
|
254
|
+
- `@pi-atelier/shared-utils` — 配置 API、工具输出格式化
|
|
255
|
+
- `@earendil-works/pi-coding-agent` — ExtensionAPI(peer)
|
|
137
256
|
|
|
138
257
|
## License
|
|
139
258
|
|