@andares/pi-toolkits 0.5.0 → 0.7.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,8 +1,9 @@
1
1
  <!-- markdownlint-disable MD033 -->
2
- <!-- Inline <a name> anchors are the only reliable TOC targets for CJK headers on GitHub. -->
2
+ <!-- Inline <a name> anchors keep the TOC targets stable and identical across README.md and README.zh-CN.md. -->
3
3
  # ⚙️ @andares/pi-toolkits
4
4
 
5
- > pi 编码代理的集成扩展工具包 — 一个包,持续生长新能力。
5
+ **English** · [中文](README.zh-CN.md)
6
+
6
7
  > Integrated toolkit extension for [pi](https://github.com/earendil-works/pi-coding-agent) — one package, growing new capabilities over time.
7
8
 
8
9
  [![npm version](https://img.shields.io/npm/v/@andares/pi-toolkits?label=npm&logo=npm)](https://www.npmjs.com/package/@andares/pi-toolkits)
@@ -11,99 +12,100 @@
11
12
  [![pi >= 0.86](https://img.shields.io/badge/pi-%3E%3D0.86.0%20%3C2.0.0-blueviolet)](https://github.com/earendil-works/pi)
12
13
  [![GitHub](https://img.shields.io/badge/github-andares%2Fpi--toolkits-181717?logo=github)](https://github.com/andares/pi-toolkits)
13
14
 
14
- 一句话介绍:目前包含五个开箱即用的功能——**只读咨询模式** `ask`、**模型收藏** `favorites`、**提示词暂存** `stash`、**第三方代码评审** `third-review`、**独立压缩模型** `compact-model`,后续持续追加。
15
- Currently ships five ready-to-use capabilities — **ask mode**, **model favorites**, **prompt stash**, **third-party code review** and a **dedicated compaction model** — with more to come.
15
+ In a nutshell: six ready-to-use capabilities — **read-only consult mode** `ask`, **model favorites** `favorites`, **prompt stash** `stash`, **third-party code review** `third-review`, **dedicated compaction model** `compact-model` and **session startup automation** `autostart` — with more to come.
16
16
 
17
- **版本要求 · Requirements**:pi `>=0.86.0 <2.0.0`(覆盖最近 4 个中版本线 0.86.x / 0.87.x / 0.99.x / 1.0.x —— 0.88–0.98 从未发布。区间内全部 10 个已发布版本逐版本比对宿主 dist:用到的扩展 API 无差异,favorites 两处运行时 patch 目标 `ModelSelectorComponent` / `AgentSession.cycleModel` 字节级一致;并在 0.86.0、0.86.1、0.87.1、0.99.2、1.0.2 上逐一通过 typecheck + 全量测试,在真实 pi 1.0.2 上冒烟加载无警告)。注:pi ≥ 0.99 的宿主要求 `@earendil-works/pi-tui` 声明为 peerDependencies `"*"`(由宿主提供),本包已按要求声明。
17
+ **Requirements**: pi `>=0.86.0 <2.0.0` (covering the four most recently released minor lines — 0.86.x / 0.87.x / 0.99.x / 1.0.x; 0.88–0.98 were never released). Every one of the 10 published versions inside that range was compared against the host `dist`: no differences in the extension APIs we use, and the two runtime patch targets used by favorites — `ModelSelectorComponent` / `AgentSession.cycleModel` — are byte-identical. `typecheck` plus the full test suite pass on each of 0.86.0, 0.86.1, 0.87.1, 0.99.2 and 1.0.2, and smoke-loading on real pi 1.0.2 produces no warnings. Note: pi ≥ 0.99 hosts require `@earendil-works/pi-tui` to be declared in `peerDependencies` as `"*"` (provided by the host); this package declares it as required.
18
18
 
19
19
  ---
20
20
 
21
- ## 📦 安装 Installation
21
+ ## 📦 Installation
22
22
 
23
23
  <a name="install"></a>
24
24
 
25
25
  ```bash
26
- # 从 npm 安装(推荐)· from npm
26
+ # from npm (recommended)
27
27
  pi install npm:@andares/pi-toolkits
28
28
 
29
- # 本地开发安装 · local development
29
+ # local development install
30
30
  pi install .
31
31
 
32
- # 单次会话加载,不安装 · one-off session, no install
32
+ # one-off session load, no install
33
33
  pi -e ./src/index.ts
34
34
  ```
35
35
 
36
- 安装后在任意 pi 会话中验证:
36
+ After installing, verify in any pi session:
37
37
 
38
- - `/ask` → footer 出现灰色 `ask` 状态,`write`/`edit` 被硬禁用
39
- - `/model`(或 `ctrl+l`)→ 选择器顶部出现收藏提示行
40
- - 输入框内按 `ctrl+alt+y` → 当前提示词被暂存并清空输入框
41
- - 完成一个开发任务后输入 `/third-review` → 切换到评审模型执行查+修
42
- - `/compact-model` 选一个便宜快模型 → 之后 `/compact` 与自动压缩的总结都由它执行(footer 出现灰色 `compact` 状态)
38
+ - `/ask` → a grey `ask` status appears in the footer, `write`/`edit` are hard-disabled
39
+ - `/model` (or `ctrl+l`) → a favorites hint line appears at the top of the selector
40
+ - press `ctrl+alt+y` in the input box → the current prompt is stashed and the input box is cleared
41
+ - after finishing a development task, type `/third-review` → switches to the review model and runs check + fix
42
+ - `/compact-model`, pick a cheap fast model → from then on both `/compact` and auto-compaction summarize with it (a grey `compact` status appears in the footer)
43
43
 
44
44
  ---
45
45
 
46
- ## 📚 目录 Contents
46
+ ## 📚 Contents
47
47
 
48
- - [安装 Installation](#install)
49
- - [功能总览 Features at a glance](#features)
50
- - [🛡️ ask — 只读咨询模式](#ask)
51
- - [⭐ favorites — 模型收藏](#favorites)
52
- - [📥 stash — 提示词暂存](#stash)
53
- - [🔎 review — 第三方代码评审](#review)
54
- - [🗜️ compact — 独立压缩模型](#compact)
55
- - [开发 Development](#development)
56
- - [贡献 Contributing](#contributing)
57
- - [许可 License](#license)
48
+ - [Installation](#install)
49
+ - [Features at a glance](#features)
50
+ - [🛡️ ask — read-only consult mode](#ask)
51
+ - [⭐ favorites — model favorites](#favorites)
52
+ - [📥 stash — prompt stash](#stash)
53
+ - [🔎 review — third-party code review](#review)
54
+ - [🗜️ compact — dedicated compaction model](#compact)
55
+ - [🚀 autostart — session startup automation](#autostart)
56
+ - [Development](#development)
57
+ - [Contributing](#contributing)
58
+ - [License](#license)
58
59
 
59
60
  ---
60
61
 
61
- ## ✨ 功能总览 Features at a glance
62
+ ## ✨ Features at a glance
62
63
 
63
64
  <a name="features"></a>
64
65
 
65
- | 功能 | 入口 | 一句话说明 |
66
+ | Feature | Entry point | One-line description |
66
67
  | --- | --- | --- |
67
- | 🛡️ **ask** 只读咨询模式 | `/ask` | 进入只读问答模式,`write`/`edit` 硬禁用,`bash` 只读沙箱 |
68
- | ⭐ **favorites** 模型收藏 | `/model` 内 `ctrl+F` / `ctrl+J` | 收藏常用模型(加粗亮黄标记),`ctrl+p` 仅在收藏间循环 |
69
- | 📥 **stash** 提示词暂存 | `ctrl+alt+y` | 一段提示词的暂存槽,按键交换 / 连按两次暂存并清空输入框 |
70
- | 🔎 **review** 第三方代码评审 | `/third-review` | 召唤配置的评审模型,对刚完成的任务做查+修,重点检查「本轮需求实现 / 是否有遗漏 / 是否有错误」 |
71
- | 🗜️ **compact** 独立压缩模型 | `/compact-model` | 给 `/compact` 与 auto-compact 配一个便宜快模型做总结,主模型专注对话;未配置零开销、任何异常回落 pi 默认 |
68
+ | 🛡️ **ask** read-only consult mode | `/ask` | enter read-only Q&A mode: `write`/`edit` hard-disabled, `bash` runs in a read-only sandbox |
69
+ | ⭐ **favorites** model favorites | `ctrl+alt+F` / `ctrl+J` inside `/model` | favorite the models you use most (marked in bold bright yellow), `ctrl+p` cycles only among favorites |
70
+ | 📥 **stash** prompt stash | `ctrl+alt+y` | a stash slot for one prompt: press to swap, press twice to stash and clear the input box |
71
+ | 🔎 **review** third-party code review | `/third-review` | summon the configured review model to check + fix the task just finished, focusing on "is this round's requirement implemented / is anything missing / is anything wrong" |
72
+ | 🗜️ **compact** dedicated compaction model | `/compact-model` | give `/compact` and auto-compact a cheap fast model to summarize with, leaving the main model free to focus on the conversation; zero overhead when unconfigured, falls back to pi's default on any failure |
73
+ | 🚀 **autostart** session startup automation | `.pi/autostart.toml` | declare slash commands to run automatically at session start, per project (first use case: mounting multi-repo directories with `/add-dir`); never runs in untrusted directories, unregistered commands are skipped instead of being sent to the model |
72
74
 
73
75
  ---
74
76
 
75
- ## 🛡️ ask — 只读咨询模式
77
+ ## 🛡️ ask — read-only consult mode
76
78
 
77
79
  <a name="ask"></a>
78
80
 
79
- 用 `/ask` 进入(再按一次退出)。适合只想要"问问题、读代码",绝不希望模型改动任何文件的场景。
81
+ Enter with `/ask` (press it again to exit). Meant for the case where you only want to "ask questions and read code", and absolutely never want the model to modify any file.
80
82
 
81
- **进入后**:
83
+ **While active**:
82
84
 
83
- - **`write` / `edit` 硬禁用** —— 从活跃工具集中移除,pi 运行时对未激活工具的调用直接拒绝("Tool not found"),文件修改在机制上不可能发生
84
- - **`bash` 保留但只读沙箱** —— 基于 shell 分词 + 写盘意图检测(`curl -o/-O`、`wget -O`、`dd of=`、`tee`、重定向等一律拦截)。启发式,非安全边界
85
- - **系统提示词追加** —— 追加一段模式说明,模型会遵守只读约束行事
86
- - **灰色 `ask` footer 状态** —— 常驻提示当前处于只读模式
85
+ - **`write` / `edit` hard-disabled** — removed from the active tool set; pi rejects calls to inactive tools outright ("Tool not found"), so file modification becomes mechanically impossible
86
+ - **`bash` kept, but sandboxed to read-only** — based on shell tokenization plus write-intent detection (blocks `curl -o/-O`, `wget -O`, `dd of=`, `tee`, redirections, and the like). Heuristic, not a security boundary
87
+ - **System prompt appendix** — a mode description is appended so the model behaves along the read-only constraint
88
+ - **Grey `ask` footer status** — a permanent reminder that read-only mode is on
87
89
 
88
- **退出**:再按 `/ask`,完整恢复进入前的工具集快照。
90
+ **Exit**: press `/ask` again; the tool-set snapshot taken on entry is fully restored.
89
91
 
90
92
  ---
91
93
 
92
- ## ⭐ favorites — 模型收藏
94
+ ## ⭐ favorites — model favorites
93
95
 
94
96
  <a name="favorites"></a>
95
97
 
96
- 标记常用模型,让模型切换「粘」在收藏上。收藏**跨会话、跨项目全局持久化**。
98
+ Mark the models you use often so that model switching "sticks" to them. Favorites are **persisted globally, across sessions and projects**.
97
99
 
98
- **在 `/model` 选择器内**(`/model` 或 `ctrl+l` 打开):
100
+ **Inside the `/model` selector** (open it with `/model` or `ctrl+l`):
99
101
 
100
- - 顶部提示行显示按键与当前过滤状态
101
- - `ctrl+F` —— 对当前选中模型开/关收藏;收藏的模型文字显示为**加粗亮黄**
102
- - `ctrl+J` —— 开/关「仅显示收藏模型」过滤(可与内置搜索叠加使用)
102
+ - The top hint line shows the keys and the current filter state
103
+ - `ctrl+alt+F` — toggle the favorite flag on the currently selected model; favorite models are rendered in **bold bright yellow**
104
+ - `ctrl+J` — toggle the "show only favorite models" filter (composable with the built-in search)
103
105
 
104
- **模型循环**:只要存在 ≥1 个收藏,`ctrl+p` / `ctrl+shift+p` 就**只在收藏模型间循环**。当前模型不是收藏时,`ctrl+p` 跳到第一个收藏、`ctrl+shift+p` 跳到最后一个;收藏仅 1 个时停在原地(`Only one model available`)。`ctrl+l` / `/model` 始终可自由选择任意模型(含非收藏)。在状态文件中设 `"cycleOnlyFavorites": false` 可恢复全量循环。
106
+ **Model cycling**: as long as ≥1 favorite exists, `ctrl+p` / `ctrl+shift+p` cycle **only among favorite models**. When the current model is not a favorite, `ctrl+p` jumps to the first favorite and `ctrl+shift+p` to the last; with exactly one favorite it stays put (`Only one model available`). `ctrl+l` / `/model` always allow picking any model freely, favorites or not. Set `"cycleOnlyFavorites": false` in the state file to restore full cycling.
105
107
 
106
- **状态文件**:`<agent-dir>/pi-toolkits-favorites.json`(默认 `~/.pi/agent/`,与 auto-naming-session 配置同目录):
108
+ **State file**: `<agent-dir>/pi-toolkits-favorites.json` (defaults to `~/.pi/agent/`, the same directory as the auto-naming-session config):
107
109
 
108
110
  ```json
109
111
  {
@@ -112,117 +114,159 @@ pi -e ./src/index.ts
112
114
  }
113
115
  ```
114
116
 
115
- `/favorites` 命令列出当前收藏与循环模式。
117
+ The `/favorites` command lists the current favorites and the cycling mode.
116
118
 
117
- > **实现说明**:pi 的 `app.model.cycleForward`(`ctrl+p`)与 `cycleBackward` 是**保留键位**,扩展快捷键无法覆盖;且扩展快捷键只在编辑器聚焦时生效。因此本功能不重绑任何按键,而是在运行时 patch 两个内置原型(带版本守卫、`/reload` 幂等):`ModelSelectorComponent`(提示行、`ctrl+F`/`ctrl+J`、亮黄渲染、仅收藏过滤——按键仅在选择器内消费,编辑器里 `ctrl+f` 光标右移、`ctrl+j` 换行不受影响)与 `AgentSession.cycleModel`(收藏循环)。若 pi 升级导致 patch 无法应用,会 warn 并优雅降级,不影响其它功能。
119
+ > **Implementation notes**: pi's `app.model.cycleForward` (`ctrl+p`) and `cycleBackward` are **reserved keybindings** that extension shortcuts cannot override; extension shortcuts also only fire while the editor is focused. This feature therefore rebinds nothing; instead it patches two built-in prototypes at runtime (version-guarded, idempotent under `/reload`): `ModelSelectorComponent` (hint line, `ctrl+alt+F`/`ctrl+J`, bright-yellow rendering, favorites-only filter — the keys are consumed only inside the selector, so in the editor `ctrl+j` still inserts a newline) and `AgentSession.cycleModel` (favorites-only cycling). If a pi upgrade makes the patch inapplicable, it warns and degrades gracefully without affecting the other features.
120
+ >
121
+ > **Why `ctrl+alt+F` and not `ctrl+F`**: since pi 1.0 the default `tuiMode` is `fullscreen` (0.86–0.99 defaulted to `regular`), and on Windows/WSL the host resolves `tui.altScreen.search` to `ctrl+f`; `TuiAltScreen.handleViewportInput()` checks that binding **before** handing input to the focused overlay, so `ctrl+f` opened the transcript search instead of reaching the selector. `alt+f`, `shift+f` and `ctrl+shift+f` are all taken or unreliable as well — see `src/features/favorites/constants.ts` and `pnpm check:keybindings`.
118
122
 
119
123
  ---
120
124
 
121
- ## 📥 stash — 提示词暂存
125
+ ## 📥 stash — prompt stash
122
126
 
123
127
  <a name="stash"></a>
124
128
 
125
- 一个热键 + 一个暂存槽,在「当前提示词」与「暂存提示词」之间腾挪,方便把一段提示词先放一边、空出输入框写新的,需要时再取回。
129
+ One hotkey plus one stash slot, shuffling between "the prompt I am writing" and "the prompt I stashed": park a prompt to one side, free the input box for a new one, and take the old one back when you need it.
126
130
 
127
- | 操作 | 效果 |
131
+ | Action | Effect |
128
132
  | --- | --- |
129
- | 按一次 `ctrl+alt+y` | 当前提示词 → 入缓存;缓存内容 → 填入输入框(**交换**) |
130
- | 间隔再按 | 在两段提示词之间**来回切换** |
131
- | **400ms 内连按两次** | 当前提示词入缓存 + **清空输入框**(旧暂存被丢弃),直接开写新提示词;之后按一次取回 |
133
+ | Press `ctrl+alt+y` once | current prompt → stash; stashed content → input box (**swap**) |
134
+ | Press again after a while | **toggle back and forth** between the two prompts |
135
+ | Press twice **within 400ms** | current prompt goes to the stash + **input box is cleared** (the old stash is discarded), so you can start writing the new prompt right away; later press once to take it back |
132
136
 
133
- 缓存为空时,单按一次即「暂存 + 清空」。缓存为**进程内内存、不落盘**(提示词可能含敏感内容);`/new` 切会话不清缓存,`/reload` 清空。选择器(`/model`、`/tree` 等)打开时按键不生效(焦点在组件,不在编辑器)。
137
+ When the stash is empty, a single press means "stash + clear". The stash is **in-process memory and never written to disk** (prompts may contain sensitive content); `/new` switches sessions without clearing the stash, `/reload` clears it. While a selector (`/model`, `/tree`, …) is open the key does nothing (focus is on the component, not the editor).
134
138
 
135
- **为什么是 `ctrl+alt+y`**(四级兼容性调研结论):
139
+ **Why `ctrl+alt+y`** (the conclusion of a four-layer compatibility survey):
136
140
 
137
- | 层面 | 状态 | 说明 |
141
+ | Layer | Status | Notes |
138
142
  | --- | --- | --- |
139
- | pi 键位 | ✅ | 无默认 `ctrl+alt+字母` 绑定;扩展快捷键在编辑器内最先分发 |
140
- | Linux 终端 | ✅ | `alt` 以 ESC 前缀编码(`ctrl+alt+y` = `ESC + ctrl+y`),不依赖 kitty 协议即可区分 |
141
- | Windows Terminal | ✅ | 无默认 `ctrl+alt` 绑定 |
142
- | Windows 操作系统 | ✅ | 系统级仅保留 `ctrl+alt+del` |
143
+ | pi keybindings | ✅ | no default `ctrl+alt+<letter>` binding; extension shortcuts are dispatched first inside the editor |
144
+ | Linux terminals | ✅ | `alt` is encoded as an ESC prefix (`ctrl+alt+y` = `ESC + ctrl+y`), distinguishable without the kitty protocol |
145
+ | Windows Terminal | ✅ | no default `ctrl+alt` binding |
146
+ | Windows OS | ✅ | only `ctrl+alt+del` is reserved system-wide |
143
147
 
144
- **被排除的候选**:`ctrl+shift+字母` —— Linux 与 Windows 的终端 emulator 都占用复制/粘贴/标签页;且无 kitty 协议的终端上会坍缩成 `ctrl+字母`(`ctrl+shift+m` 即回车,会直接提交提示词,危险)。纯 `ctrl+字母` —— pi 几乎全部占用,唯一空闲的 `ctrl+q` 是 XON 流控字符,有历史包袱。
148
+ **Rejected candidates**: `ctrl+shift+<letter>` — terminal emulators on both Linux and Windows grab copy/paste/tabs; and on terminals without the kitty protocol it collapses into `ctrl+<letter>` (`ctrl+shift+m` is Enter, which would submit the prompt immediately — dangerous). Plain `ctrl+<letter>` — pi occupies almost all of them, and the only free one, `ctrl+q`, is the XON flow-control character, with historical baggage.
145
149
 
146
150
  ---
147
151
 
148
- ## 🔎 review — 第三方代码评审
152
+ ## 🔎 review — third-party code review
149
153
 
150
154
  <a name="review"></a>
151
155
 
152
- 开发任务完成后,输入 `/third-review` 指令召唤**另一个模型**以第三方身份,对刚完成的代码做「查 + 修」:评审模型拥有**完整工具权限**,确认的问题直接改,不是只读审计。评审回合留在当前会话记录里,评审完成后**会话保持评审模型**(不自动切回)。
156
+ After a development task is done, type the `/third-review` command to summon **a different model** as a third party to "check + fix" the code just written: the review model has **full tool permissions**, and confirmed problems are edited in place — this is not a read-only audit. The review turn stays in the current session transcript, and after the review **the session keeps the review model** (it does not switch back automatically).
153
157
 
154
- > **仅指令触发**:只有 `/third-review` 能发起评审。聊天中直接输入 `third-review` 不会触发(作为普通消息发给模型),避免误发。
158
+ > **Command-triggered only**: only `/third-review` starts a review. Typing `third-review` as chat text does not trigger it (that is sent to the model as an ordinary message), which avoids accidental launches.
155
159
 
156
- **评审提示词重点检查三点**(逐项给出结论):
160
+ **The review prompt focuses on three checks** (each gets an explicit verdict):
157
161
 
158
- 1. **本轮需求实现** —— 需求是否已完整、正确地实现,与需求描述是否一致
159
- 2. **是否有遗漏** —— 功能点、边界情况、异常处理、兼容性、测试等
160
- 3. **是否有错误** —— 逻辑错误、潜在 bug、类型/编译错误、安全与性能隐患等
162
+ 1. **Is this round's requirement implemented** — is the requirement fully and correctly implemented, consistent with the requirement description
163
+ 2. **Is anything missing** — feature points, edge cases, error handling, compatibility, tests, etc.
164
+ 3. **Is anything wrong** — logic errors, potential bugs, type/compile errors, security and performance hazards, etc.
161
165
 
162
- **范围强约束** —— 评审仅限**当前本轮修改内容**,避免扩大范围;本轮改动范围内确认的问题才直接修复,范围外的历史遗留/无关问题只记录提示、不动手改。
166
+ **Strict scope constraint** — the review is limited to **the changes made in the current round**, to avoid scope creep; only problems confirmed inside this round's changes are fixed directly, while pre-existing or unrelated issues outside that range are only recorded as notes and left untouched.
163
167
 
164
- **评审模型选择**(每次 `/third-review` 都会弹出选择界面):
168
+ **Choosing the review model** (every `/third-review` opens a picker):
165
169
 
166
- - `/third-review` → 弹出 **`/model` 同款选择器**(限高滚动 + 模糊搜索):**默认选中当前配置的模型**(✓ 标记),直接**回车**即用它开始评审
167
- - **换选其他模型** → 立即写回配置(**落盘 + 内存**),**下次默认使用该模型**
168
- - **取消**(Esc)→ 不执行评审,配置不变
169
- - 配置持久化于 `<agent-dir>/pi-toolkits-review.json`(默认 `~/.pi/agent/`):
170
+ - `/third-review` → opens the **same selector as `/model`** (height-limited scrolling + fuzzy search): **the currently configured model is selected by default** (✓ marker), so pressing **Enter** starts the review with it
171
+ - **Pick another model** → written back to the config immediately (**both on disk and in memory**), and **that model becomes the default next time**
172
+ - **Cancel** (Esc) → no review is run, the config is unchanged
173
+ - The config is persisted in `<agent-dir>/pi-toolkits-review.json` (defaults to `~/.pi/agent/`):
170
174
 
171
175
  ```json
172
176
  { "model": "anthropic/claude-sonnet-4" }
173
177
  ```
174
178
 
175
- - `/review-model` —— 单独的配置入口:弹出同一列表(不改会话模型,只更新默认配置)
176
- - **未配置 / 配置的模型已不可用**(如在 pi 的 models.json 里删掉了该模型)→ 提示后照常弹出列表(此时无默认项)
177
- - 任务仍在进行中(agent 未空闲)时触发 → 提示等待,不执行;同一时间只允许一个评审
178
- - footer 出现灰色 `review` 状态 = 已配置评审模型
179
+ - `/review-model` — a separate config entry point: opens the same list (without changing the session model, only updating the default config)
180
+ - **Unconfigured / the configured model is no longer available** (e.g. it was deleted from pi's models.json) → a notice is shown and the list opens as usual (with no default entry in that case)
181
+ - Triggered while a task is still in progress (the agent is not idle) → you are told to wait and nothing runs; only one review may be active at a time
182
+ - A grey `review` status in the footer means a review model is configured
179
183
 
180
184
  ---
181
185
 
182
- ## 🗜️ compact — 独立压缩模型
186
+ ## 🗜️ compact — dedicated compaction model
183
187
 
184
188
  <a name="compact"></a>
185
189
 
186
- pi 的 `/compact` 与 auto-compact 默认**用当前会话模型**做上下文总结——主模型往往贵且慢,而压缩总结是典型的「便宜快模型就能干好」的任务。本功能配置一个独立模型接管**全部三种压缩触发**的总结:
190
+ pi's `/compact` and auto-compact summarize the context **with the current session model** by default — the main model is usually expensive and slow, while compaction summarization is a textbook "a cheap fast model does this well" job. This feature configures a dedicated model to take over summarization for **all three compaction triggers**:
187
191
 
188
- | 触发 | 接管后 |
192
+ | Trigger | After takeover |
189
193
  | --- | --- |
190
- | 手动 `/compact [instructions]` | 压缩模型总结,自定义 focus 照常注入 |
191
- | auto-compact 阈值触发 | 压缩模型总结 |
192
- | context overflow 恢复 | 压缩模型总结,重试行为不变 |
194
+ | Manual `/compact [instructions]` | summarized by the compaction model, custom focus is injected as usual |
195
+ | auto-compact threshold reached | summarized by the compaction model |
196
+ | context overflow recovery | summarized by the compaction model, retry behavior unchanged |
193
197
 
194
- **接管后与 pi 内建行为完全一致的部分**(逐字同步 pi 内建实现,0.87.1 起字节级不变、已核对至 1.0.2,只换执行模型):
198
+ **Parts that are identical to pi's built-in behavior after takeover** (the built-in implementation is mirrored verbatim — byte-identical since 0.87.1, verified up to 1.0.2 — and only the executing model changes):
195
199
 
196
- - **摘要格式** —— Goal / Progress / Key Decisions 结构化 checkpoint;已有摘要时用迭代更新版 prompt,信息延续不丢
197
- - **切分行为** —— 保留最近 `keepRecentTokens` 的策略、`firstKeptEntryId` / `tokensBefore` 原样回传,不动
198
- - **输出预算** —— 与内建同公式(历史段 0.8×、切分前缀段 0.5× `reserveTokens`,再按模型输出上限收敛)
199
- - **文件清单尾部** —— `<read-files>` / `<modified-files>` 标签照常拼在摘要尾部,details 同形状维护
200
- - **用量统计** —— 压缩模型的 token/cost 计入 session 统计
201
- - **可取消** —— 压缩进行中 `Esc` 干净取消(信号透传到底层调用)
200
+ - **Summary format** — the structured Goal / Progress / Key Decisions checkpoint; when a summary already exists, the iterative-update prompt is used so information carries over instead of being lost
201
+ - **Split behavior** — the `keepRecentTokens` retention policy, and `firstKeptEntryId` / `tokensBefore` passed back unchanged
202
+ - **Output budget** — the same formula as the built-in (history segment 0.8×, split-prefix segment 0.5× of `reserveTokens`, then capped by the model's max output)
203
+ - **File-list tail** — `<read-files>` / `<modified-files>` tags are appended to the summary as usual, with details maintained in the same shape
204
+ - **Usage accounting** — the compaction model's tokens/cost are counted in the session statistics
205
+ - **Cancellable** — `Esc` during compaction cancels cleanly (the signal is passed through to the underlying call)
202
206
 
203
- **配置**(`<agent-dir>/pi-toolkits-compact.json`,默认 `~/.pi/agent/`):
207
+ **Configuration** (`<agent-dir>/pi-toolkits-compact.json`, defaults to `~/.pi/agent/`):
204
208
 
205
209
  ```json
206
210
  { "model": "google/gemini-2.5-flash" }
207
211
  ```
208
212
 
209
- - `/compact-model` —— 查看/更换:`/model` 同款选择器(限高滚动 + 模糊搜索),**默认选中当前配置的模型**,回车即确认;换选即写入;取消则不变(清除配置:编辑 `pi-toolkits-compact.json` 把 `model` 置为 `null`)
210
- - 未配置 = 功能未启用,全部走 pi 默认,零开销;footer 出现灰色 `compact` 状态 = 已配置
213
+ - `/compact-model` — view/replace: the **same selector as `/model`** (height-limited scrolling + fuzzy search), with **the currently configured model selected by default**; Enter confirms, picking another model writes it, cancelling leaves it unchanged (to clear the config: edit `pi-toolkits-compact.json` and set `model` to `null`)
214
+ - Unconfigured = feature disabled, everything goes through pi's default at zero overhead; a grey `compact` status in the footer means it is configured
211
215
 
212
- **无损回落**(本功能永远不会把压缩「做挂」):
216
+ **Lossless fallback** (this feature can never "break" compaction):
213
217
 
214
- | 情形 | 行为 |
218
+ | Situation | Behavior |
215
219
  | --- | --- |
216
- | 未配置 | 直接回落 pi 默认压缩 |
217
- | 配置的模型不可用(如从 models.json 删除) | warning 提示 + 回落 |
218
- | 总结失败 / 摘要为空 / 命中 token 上限 | 提示 + 回落 pi 默认压缩 |
219
- | 用户取消(`Esc`) | 干净取消,无错误刷屏 |
220
+ | Not configured | falls straight back to pi's default compaction |
221
+ | Configured model unavailable (e.g. deleted from models.json) | warning + fallback |
222
+ | Summarization failed / empty summary / token limit hit | notice + fallback to pi's default compaction |
223
+ | User cancelled (`Esc`) | clean cancel, no error spam |
224
+
225
+ > **Implementation notes**: the takeover point is the official `session_before_compact` extension event (all three triggers pass through it); returning a compaction result takes over completely, returning `undefined` falls back to the built-in. The auto-compact path never shows any dialog (the handler only calls `notify`). `/tree` branch summarization (`session_before_tree`) is a different event and is not taken over in this iteration — it is left for later.
226
+
227
+ ---
228
+
229
+ ## 🚀 autostart — session startup automation
230
+
231
+ <a name="autostart"></a>
232
+
233
+ A first step for multi-repo projects: declare inside the project which slash commands should run automatically "when a new session starts" — the first use case being `/add-dir` mounting sibling repositories, so a new session does not have to replay them by hand.
234
+
235
+ **Configuration** (`<project root>/.pi/autostart.toml`, committed with the project; `.pi/` is pi's project-level config convention, following `.pi/mcp.json`):
236
+
237
+ ```toml
238
+ version = 1
239
+
240
+ [command]
241
+ run = [
242
+ "/add-dir ../shop-frontend",
243
+ "/add-dir ../shop-api",
244
+ ]
245
+ ```
246
+
247
+ No file = feature disabled, zero overhead, silently skipped.
248
+
249
+ **When it runs**:
250
+
251
+ | session_start reason | Replayed | Why |
252
+ | --- | --- | --- |
253
+ | `startup` / `new` | ✅ | a new session, replay as declared |
254
+ | `fork` | ✅ | the branch point may predate the config's appearance |
255
+ | `resume` | ❌ | the restored branch already carries the mount state from its time, replaying would conflict |
256
+ | `reload` | ❌ | extensions are rebuilt, replaying would duplicate side effects |
257
+
258
+ **Safety gates** (in order):
259
+
260
+ 1. **project trust** — no command runs automatically in an untrusted directory (a warning is shown); a config parse failure likewise prevents execution (an error is shown)
261
+ 2. **Command pre-validation** — only commands **registered by extensions** are executed; an unregistered command name is **skipped with a warning** and never sent to the model (for an unhandled `/x`, `sendUserMessage` treats the text as an ordinary message and sends it to the LLM — this is exactly why pre-validation is mandatory)
262
+
263
+ **Key constraint: extension commands only**. Commands registered via `registerCommand` such as `/add-dir` (pi-add-dir) and `/cd` (pi-cd) work; built-in commands (`/compact`, `/reload`, `/resume`, …) are dispatched in the TUI layer and cannot be triggered from the extension layer; skill commands (`/skill:name`) are an expansion mechanism rather than an execution mechanism. The target extension you depend on (e.g. pi-add-dir) must be installed first.
220
264
 
221
- > **实现说明**:接管点是官方的 `session_before_compact` 扩展事件(三种触发都会先经过);返回压缩结果即完全接管,返回 `undefined` 即回落内建。auto-compact 路径绝不弹任何对话框(handler 内只 notify)。`/tree` 分支总结(`session_before_tree`)是另一个事件,本期不接管,留作后续迭代。
265
+ > **Implementation notes**: execution uses `sendUserMessage(cmd, { expandPromptTemplates: true })` — that option routes `/cmd args` into command dispatch instead of the model prompt path (the wrapper defaults to `false`; verified against pi 0.86–1.0.4 sources, see the host-compatibility discipline in AGENTS.md). Pre-validation uses `pi.getCommands()` (accepting only `source: "extension"`). Depends on `smol-toml` (zero-dependency, ~10KB, TOML 1.0).
222
266
 
223
267
  ---
224
268
 
225
- ## 🛠️ 开发 Development
269
+ ## 🛠️ Development
226
270
 
227
271
  <a name="development"></a>
228
272
 
@@ -234,7 +278,7 @@ pnpm typecheck # tsc --noEmit
234
278
  pnpm test # vitest (all feature unit tests)
235
279
  ```
236
280
 
237
- ### 项目结构 Project structure
281
+ ### Project structure
238
282
 
239
283
  ```text
240
284
  src/
@@ -244,6 +288,8 @@ src/
244
288
  └── features/ # feature modules — one directory per feature
245
289
  ├── ask/ # ask mode: command + state machine, bash sandbox,
246
290
  │ # system prompt banner, tests
291
+ ├── autostart/ # session startup automation: autostart.toml parsing,
292
+ │ # command pre-validation + replay, tests
247
293
  ├── compact/ # dedicated compaction model: session_before_compact
248
294
  │ # takeover + /compact-model, store, prompts,
249
295
  │ # tests
@@ -254,9 +300,9 @@ src/
254
300
  └── stash/ # prompt stash: hotkey state machine + tests
255
301
  ```
256
302
 
257
- **新增功能 · 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).
303
+ **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).
258
304
 
259
- **发布 · publishing**(pnpm-only,one command):
305
+ **Publishing** (pnpm-only, one command):
260
306
 
261
307
  ```bash
262
308
  pnpm release patch # 0.1.2 → 0.1.3
@@ -265,11 +311,11 @@ pnpm release major # 0.1.2 → 1.0.0 (minor + patch zeroed)
265
311
  pnpm release patch --dry-run # preview without changing anything
266
312
  ```
267
313
 
268
- `release` 要求且仅要求 `major | minor | patch` 之一;上级递增清零下级。执行链:**工作区必须干净(有未提交变更直接中止,保证 tag 内容 == 发布内容)** → `typecheck + test` 门禁 → 改版本 → git commit + `vX.Y.Z` tag(自检 tag==HEAD 且工作区干净) → `pnpm publish`(`prepublishOnly` 二次门禁) → 只推当前分支 + 当前 tag 并校验远端哈希一致(远端 tag 不一致则跳过 Release 创建)。
314
+ `release` requires exactly one of `major | minor | patch`; incrementing a higher level zeroes the lower ones. The chain is: **the working tree must be clean (any uncommitted change aborts before anything happens, guaranteeing tag content == published content)** → `typecheck + test` gate → version bump → git commit + `vX.Y.Z` tag (self-check that tag == HEAD and the tree is clean) → `pnpm publish` (with `prepublishOnly` as a second gate) → push only the current branch + the current tag and verify the remote hashes match (if the remote tag differs, GitHub Release creation is skipped).
269
315
 
270
316
  ---
271
317
 
272
- ## 🤝 贡献 Contributing
318
+ ## 🤝 Contributing
273
319
 
274
320
  <a name="contributing"></a>
275
321
 
@@ -280,7 +326,7 @@ PRs and issues welcome. A few conventions:
280
326
  - **Tests** — every feature ships vitest cases; keep them deterministic (injectable clocks/state), no writes to the real agent dir
281
327
  - **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
282
328
  - **Built-in prompt sync** (compact) — the summarization prompts in `src/features/compact/prompt.ts` are copied verbatim from pi's built-in compaction; when upgrading the pi dependency, diff `dist/core/compaction/compaction.js` (and `utils.js`) and update the strings + assembly helpers to match, keeping takeover output byte-compatible with stock
283
- - **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
329
+ - **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. Do not stop at "it works on my machine in the main screen": in `fullscreen` mode (pi's default since 1.0) the alt-screen layer consumes `tui.altScreen.*` **before** dialogs see the key, and on Windows/WSL several of those bindings differ from the Linux defaults. Run `pnpm check:keybindings [candidate...]` (and `pnpm check:keybindings --all` after a pi upgrade) — it probes the installed host's resolved keybinding table with the host's own `matchesKey`.
284
330
  - **Quality gate** — `pnpm typecheck && pnpm test` must pass before submitting
285
331
 
286
332
  ---