@andares/pi-toolkits 0.1.0 → 0.3.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.md CHANGED
@@ -1,51 +1,230 @@
1
- # @andares/pi-toolkits
1
+ <!-- markdownlint-disable MD033 -->
2
+ <!-- Inline <a name> anchors are the only reliable TOC targets for CJK headers on GitHub. -->
3
+ # ⚙️ @andares/pi-toolkits
2
4
 
3
- Integrated toolkit extension for [pi](https://github.com/earendil-works/pi-coding-agent) — a single npm package that grows new capabilities over time. Currently provides **ask mode**.
5
+ > pi 编码代理的集成扩展工具包 — 一个包,持续生长新能力。
6
+ > Integrated toolkit extension for [pi](https://github.com/earendil-works/pi-coding-agent) — one package, growing new capabilities over time.
4
7
 
5
- ## Features
8
+ [![npm version](https://img.shields.io/npm/v/@andares/pi-toolkits?label=npm&logo=npm)](https://www.npmjs.com/package/@andares/pi-toolkits)
9
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
10
+ [![Package Manager](https://img.shields.io/badge/package%20manager-pnpm-orange?logo=pnpm)](https://pnpm.io)
11
+ [![pi >= 0.84](https://img.shields.io/badge/pi-%3E%3D0.84.0-blueviolet)](https://github.com/earendil-works/pi)
12
+ [![GitHub](https://img.shields.io/badge/github-andares%2Fpi--toolkits-181717?logo=github)](https://github.com/andares/pi-toolkits)
6
13
 
7
- ### ask — read-only Q&A mode
14
+ 一句话介绍:目前包含四个开箱即用的功能——**只读咨询模式** `ask`、**模型收藏** `favorites`、**提示词暂存** `stash`、**第三方代码评审** `third-review`,后续持续追加。
15
+ Currently ships four ready-to-use capabilities — **ask mode**, **model favorites**, **prompt stash** and **third-party code review** — with more to come.
8
16
 
9
- Toggle with `/ask` (press again to exit). While active:
17
+ ---
10
18
 
11
- - **`write`/`edit` hard-disabled** — removed from the active tool set; pi's runtime rejects calls to non-active tools, so file modification is genuinely impossible
12
- - **`bash` kept but sandboxed to read-only commands** — shell-quote tokenization with per-segment validation plus write-intent detection (`curl -o/-O`, `wget -O`, `dd of=`, `tee`, redirects); heuristic, not a security boundary
13
- - **System prompt banner** appended describing the current mode and its restrictions
14
- - **Gray `ask` footer status** while active
19
+ ## 📦 安装 Installation
15
20
 
16
- Exiting restores the exact tool set from before ask mode was entered.
17
-
18
- ## Install
21
+ <a name="install"></a>
19
22
 
20
23
  ```bash
21
- # local development
24
+ # 从 npm 安装(推荐)· from npm
25
+ pi install npm:@andares/pi-toolkits
26
+
27
+ # 本地开发安装 · local development
22
28
  pi install .
23
- # or one-off session
29
+
30
+ # 单次会话加载,不安装 · one-off session, no install
24
31
  pi -e ./src/index.ts
25
32
  ```
26
33
 
27
- ## Development
34
+ 安装后在任意 pi 会话中验证:
35
+
36
+ - `/ask` → footer 出现灰色 `ask` 状态,`write`/`edit` 被硬禁用
37
+ - `/model`(或 `ctrl+l`)→ 选择器顶部出现收藏提示行
38
+ - 输入框内按 `ctrl+alt+y` → 当前提示词被暂存并清空输入框
39
+ - 完成一个开发任务后输入 `third-review` → 切换到评审模型执行查+修
40
+
41
+ ---
42
+
43
+ ## 📚 目录 Contents
44
+
45
+ - [安装 Installation](#install)
46
+ - [功能总览 Features at a glance](#features)
47
+ - [🛡️ ask — 只读咨询模式](#ask)
48
+ - [⭐ favorites — 模型收藏](#favorites)
49
+ - [📥 stash — 提示词暂存](#stash)
50
+ - [🔎 review — 第三方代码评审](#review)
51
+ - [开发 Development](#development)
52
+ - [贡献 Contributing](#contributing)
53
+ - [许可 License](#license)
54
+
55
+ ---
56
+
57
+ ## ✨ 功能总览 Features at a glance
58
+
59
+ <a name="features"></a>
60
+
61
+ | 功能 | 入口 | 一句话说明 |
62
+ | --- | --- | --- |
63
+ | 🛡️ **ask** 只读咨询模式 | `/ask` | 进入只读问答模式,`write`/`edit` 硬禁用,`bash` 只读沙箱 |
64
+ | ⭐ **favorites** 模型收藏 | `/model` 内 `ctrl+F` / `ctrl+J` | 收藏常用模型(加粗亮黄标记),`ctrl+p` 仅在收藏间循环 |
65
+ | 📥 **stash** 提示词暂存 | `ctrl+alt+y` | 一段提示词的暂存槽,按键交换 / 连按两次暂存并清空输入框 |
66
+ | 🔎 **review** 第三方代码评审 | `third-review` / `/third-review` | 召唤配置的评审模型,对刚完成的任务做查+修,重点检查「本轮需求实现 / 是否有遗漏 / 是否有错误」 |
67
+
68
+ ---
69
+
70
+ ## 🛡️ ask — 只读咨询模式
71
+
72
+ <a name="ask"></a>
73
+
74
+ 用 `/ask` 进入(再按一次退出)。适合只想要"问问题、读代码",绝不希望模型改动任何文件的场景。
75
+
76
+ **进入后**:
77
+
78
+ - **`write` / `edit` 硬禁用** —— 从活跃工具集中移除,pi 运行时对未激活工具的调用直接拒绝("Tool not found"),文件修改在机制上不可能发生
79
+ - **`bash` 保留但只读沙箱** —— 基于 shell 分词 + 写盘意图检测(`curl -o/-O`、`wget -O`、`dd of=`、`tee`、重定向等一律拦截)。启发式,非安全边界
80
+ - **系统提示词追加** —— 追加一段模式说明,模型会遵守只读约束行事
81
+ - **灰色 `ask` footer 状态** —— 常驻提示当前处于只读模式
82
+
83
+ **退出**:再按 `/ask`,完整恢复进入前的工具集快照。
84
+
85
+ ---
86
+
87
+ ## ⭐ favorites — 模型收藏
88
+
89
+ <a name="favorites"></a>
90
+
91
+ 标记常用模型,让模型切换「粘」在收藏上。收藏**跨会话、跨项目全局持久化**。
92
+
93
+ **在 `/model` 选择器内**(`/model` 或 `ctrl+l` 打开):
94
+
95
+ - 顶部提示行显示按键与当前过滤状态
96
+ - `ctrl+F` —— 对当前选中模型开/关收藏;收藏的模型文字显示为**加粗亮黄**
97
+ - `ctrl+J` —— 开/关「仅显示收藏模型」过滤(可与内置搜索叠加使用)
98
+
99
+ **模型循环**:只要存在 ≥1 个收藏,`ctrl+p` / `ctrl+shift+p` 就**只在收藏模型间循环**。当前模型不是收藏时,`ctrl+p` 跳到第一个收藏、`ctrl+shift+p` 跳到最后一个;收藏仅 1 个时停在原地(`Only one model available`)。`ctrl+l` / `/model` 始终可自由选择任意模型(含非收藏)。在状态文件中设 `"cycleOnlyFavorites": false` 可恢复全量循环。
100
+
101
+ **状态文件**:`<agent-dir>/pi-toolkits-favorites.json`(默认 `~/.pi/agent/`,与 auto-naming-session 配置同目录):
102
+
103
+ ```json
104
+ {
105
+ "favorites": ["anthropic/claude-sonnet-4"],
106
+ "config": { "cycleOnlyFavorites": true }
107
+ }
108
+ ```
109
+
110
+ `/favorites` 命令列出当前收藏与循环模式。
111
+
112
+ > **实现说明**:pi 的 `app.model.cycleForward`(`ctrl+p`)与 `cycleBackward` 是**保留键位**,扩展快捷键无法覆盖;且扩展快捷键只在编辑器聚焦时生效。因此本功能不重绑任何按键,而是在运行时 patch 两个内置原型(带版本守卫、`/reload` 幂等):`ModelSelectorComponent`(提示行、`ctrl+F`/`ctrl+J`、亮黄渲染、仅收藏过滤——按键仅在选择器内消费,编辑器里 `ctrl+f` 光标右移、`ctrl+j` 换行不受影响)与 `AgentSession.cycleModel`(收藏循环)。若 pi 升级导致 patch 无法应用,会 warn 并优雅降级,不影响其它功能。
113
+
114
+ ---
115
+
116
+ ## 📥 stash — 提示词暂存
117
+
118
+ <a name="stash"></a>
119
+
120
+ 一个热键 + 一个暂存槽,在「当前提示词」与「暂存提示词」之间腾挪,方便把一段提示词先放一边、空出输入框写新的,需要时再取回。
121
+
122
+ | 操作 | 效果 |
123
+ | --- | --- |
124
+ | 按一次 `ctrl+alt+y` | 当前提示词 → 入缓存;缓存内容 → 填入输入框(**交换**) |
125
+ | 间隔再按 | 在两段提示词之间**来回切换** |
126
+ | **400ms 内连按两次** | 当前提示词入缓存 + **清空输入框**(旧暂存被丢弃),直接开写新提示词;之后按一次取回 |
127
+
128
+ 缓存为空时,单按一次即「暂存 + 清空」。缓存为**进程内内存、不落盘**(提示词可能含敏感内容);`/new` 切会话不清缓存,`/reload` 清空。选择器(`/model`、`/tree` 等)打开时按键不生效(焦点在组件,不在编辑器)。
129
+
130
+ **为什么是 `ctrl+alt+y`**(四级兼容性调研结论):
131
+
132
+ | 层面 | 状态 | 说明 |
133
+ | --- | --- | --- |
134
+ | pi 键位 | ✅ | 无默认 `ctrl+alt+字母` 绑定;扩展快捷键在编辑器内最先分发 |
135
+ | Linux 终端 | ✅ | `alt` 以 ESC 前缀编码(`ctrl+alt+y` = `ESC + ctrl+y`),不依赖 kitty 协议即可区分 |
136
+ | Windows Terminal | ✅ | 无默认 `ctrl+alt` 绑定 |
137
+ | Windows 操作系统 | ✅ | 系统级仅保留 `ctrl+alt+del` |
138
+
139
+ **被排除的候选**:`ctrl+shift+字母` —— Linux 与 Windows 的终端 emulator 都占用复制/粘贴/标签页;且无 kitty 协议的终端上会坍缩成 `ctrl+字母`(`ctrl+shift+m` 即回车,会直接提交提示词,危险)。纯 `ctrl+字母` —— pi 几乎全部占用,唯一空闲的 `ctrl+q` 是 XON 流控字符,有历史包袱。
140
+
141
+ ---
142
+
143
+ ## 🔎 review — 第三方代码评审
144
+
145
+ <a name="review"></a>
146
+
147
+ 开发任务完成后,输入 `third-review`(或 `third review`、`/third-review`)召唤**另一个模型**以第三方身份,对刚完成的代码做「查 + 修」:评审模型拥有**完整工具权限**,确认的问题直接改,不是只读审计。评审回合留在当前会话记录里,评审完成后**会话保持评审模型**(不自动切回)。
148
+
149
+ **评审提示词重点检查三点**(逐项给出结论):
150
+
151
+ 1. **本轮需求实现** —— 需求是否已完整、正确地实现,与需求描述是否一致
152
+ 2. **是否有遗漏** —— 功能点、边界情况、异常处理、兼容性、测试等
153
+ 3. **是否有错误** —— 逻辑错误、潜在 bug、类型/编译错误、安全与性能隐患等
154
+
155
+ **评审模型配置**(`<agent-dir>/pi-toolkits-review.json`,默认 `~/.pi/agent/`):
156
+
157
+ ```json
158
+ { "model": "anthropic/claude-sonnet-4" }
159
+ ```
160
+
161
+ - `/review-model` —— 查看/更换评审模型:弹出模型列表(标题显示当前配置),选中即写入;取消则不修改配置
162
+ - **未配置 / 配置的模型已不可用**(如在 pi 的 models.json 里删掉了该模型)→ 提示「评审模型不存在」,弹出**可用模型选择列表**(与 `/model` 同源);选中后**写回配置并立即执行**
163
+ - 任务仍在进行中(agent 未空闲)时触发 → 提示等待,不执行;同一时间只允许一个评审
164
+ - footer 出现灰色 `review` 状态 = 已配置评审模型
165
+
166
+ ---
167
+
168
+ ## 🛠️ 开发 Development
169
+
170
+ <a name="development"></a>
171
+
172
+ **pnpm is the only supported toolchain** — never use `npm install` / `npm publish` in this repo.
28
173
 
29
174
  ```bash
30
- pnpm install # install deps (pnpm is the only supported toolchain)
175
+ pnpm install # install deps
31
176
  pnpm typecheck # tsc --noEmit
32
- pnpm test # vitest (bash sandbox boundary cases)
177
+ pnpm test # vitest (all feature unit tests)
33
178
  ```
34
179
 
35
- ## Project structure
180
+ ### 项目结构 Project structure
36
181
 
37
182
  ```text
38
183
  src/
39
184
  ├── index.ts # entry point: aggregates feature modules
40
185
  ├── lib/ # shared infrastructure (tool-set snapshot/restore)
41
186
  └── features/ # feature modules — one directory per feature
42
- └── ask/ # ask mode: command + state machine, bash sandbox,
43
- # system prompt banner, tests
187
+ ├── ask/ # ask mode: command + state machine, bash sandbox,
188
+ │ # system prompt banner, tests
189
+ ├── favorites/ # model favorites: selector + cycle patches,
190
+ │ # persisted store, tests
191
+ ├── review/ # third-party review: input/command triggers,
192
+ │ # review-model config store, prompt, tests
193
+ └── stash/ # prompt stash: hotkey state machine + tests
194
+ ```
195
+
196
+ **新增功能 · adding a feature**:create `src/features/<name>/` exporting `registerXxx(pi)` and call it from `src/index.ts`. Existing modules stay untouched. Each feature ships its own `*.test.ts` (vitest) — keep them deterministic (inject clocks/state, no real agent-dir writes).
197
+
198
+ **发布 · publishing**(pnpm-only,one command):
199
+
200
+ ```bash
201
+ pnpm release patch # 0.1.2 → 0.1.3
202
+ pnpm release minor # 0.1.2 → 0.2.0 (patch zeroed)
203
+ pnpm release major # 0.1.2 → 1.0.0 (minor + patch zeroed)
204
+ pnpm release patch --dry-run # preview without changing anything
44
205
  ```
45
206
 
46
- Adding a new feature = create `src/features/<name>/` exporting `registerXxx(pi)`
47
- and call it from `src/index.ts`. Existing modules stay untouched.
207
+ `release` 要求且仅要求 `major | minor | patch` 之一;上级递增清零下级。执行链:校验 → `typecheck + test` 门禁 → 改版本 → git commit + `vX.Y.Z` tag → `pnpm publish`(`prepublishOnly` 二次门禁)。
208
+
209
+ ---
210
+
211
+ ## 🤝 贡献 Contributing
212
+
213
+ <a name="contributing"></a>
214
+
215
+ PRs and issues welcome. A few conventions:
216
+
217
+ - **pnpm only** — never `npm install` / `npm publish`; use `pnpm add` / `pnpm publish`
218
+ - **Feature-module pattern** — one directory per feature (`src/features/<name>/`), export `registerXxx(pi)`, register in `src/index.ts`; shared infra goes in `src/lib/`
219
+ - **Tests** — every feature ships vitest cases; keep them deterministic (injectable clocks/state), no writes to the real agent dir
220
+ - **Built-in patches** (favorites) must stay **version-guarded and idempotent** — verify the target prototype members exist before patching, guard against double-apply, degrade with a `console.warn` instead of breaking the extension
221
+ - **Keybindings** — before picking a new shortcut, check pi defaults + reserved keys, terminal control chars, and OS/terminal-emulator grabs; prefer `ctrl+alt+<letter>` for cross-platform safety
222
+ - **Quality gate** — `pnpm typecheck && pnpm test` must pass before submitting
223
+
224
+ ---
225
+
226
+ ## 📄 License
48
227
 
49
- ## License
228
+ <a name="license"></a>
50
229
 
51
- MIT
230
+ MIT © 2026 Andares Cui. See [LICENSE](LICENSE).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andares/pi-toolkits",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Integrated toolkit extension for pi — currently provides ask mode (read-only Q&A); more features to come",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -25,9 +25,11 @@
25
25
  "@earendil-works/pi-coding-agent": "*"
26
26
  },
27
27
  "dependencies": {
28
- "@dreki-gg/pi-command-sandbox": "^0.4.3"
28
+ "@dreki-gg/pi-command-sandbox": "^0.4.3",
29
+ "@earendil-works/pi-tui": "^0.84.0"
29
30
  },
30
31
  "devDependencies": {
32
+ "@earendil-works/pi-ai": "^0.84.0",
31
33
  "@earendil-works/pi-coding-agent": "^0.84.0",
32
34
  "typescript": "^5.6.0",
33
35
  "vitest": "^4.1.10"
@@ -39,6 +41,8 @@
39
41
  },
40
42
  "scripts": {
41
43
  "typecheck": "tsc --noEmit",
42
- "test": "vitest run"
44
+ "test": "vitest run",
45
+ "release": "node ./scripts/publish.mjs",
46
+ "tag-current": "node ./scripts/tag-current.mjs"
43
47
  }
44
48
  }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * favorites feature — constants.
3
+ *
4
+ * Keybindings are only active INSIDE the /model model selector (the
5
+ * ModelSelectorComponent consumes input before the search box, see
6
+ * patch-selector.ts). Outside the selector the default pi bindings are
7
+ * untouched: ctrl+f stays "cursor right" in the editor, ctrl+j stays
8
+ * "new line". ctrl+p/ctrl+shift+p keep their bindings — only the cycle
9
+ * semantics change (patch-cycle.ts), so no keybinding conflicts arise.
10
+ */
11
+ export const FAVORITES_STATUS_KEY = "favorites";
12
+
13
+ /** State file, written next to the auto-naming-session config convention. */
14
+ export const FAVORITES_FILE = "pi-toolkits-favorites.json";
15
+
16
+ /** Selector-scoped keybindings (only honored while the model selector is open). */
17
+ export const FAVORITE_TOGGLE_KEY = "ctrl+f";
18
+ export const FAVORITES_ONLY_KEY = "ctrl+j";
19
+
20
+ /**
21
+ * Bold bright yellow — ANSI 16-color bright yellow (93) + bold (1).
22
+ * Standard escape sequences that render in any terminal color mode
23
+ * (16/256/truecolor), independent of the active pi theme.
24
+ */
25
+ export const FAVORITE_STYLE_OPEN = "\x1b[1;93m";
26
+ export const STYLE_RESET = "\x1b[0m";
27
+
28
+ /** Wrap model id text in the bold-bright-yellow favorite style. */
29
+ export function styleFavorite(text: string): string {
30
+ return `${FAVORITE_STYLE_OPEN}${text}${STYLE_RESET}`;
31
+ }