@gavin-hu/my-pi-agent 0.13.0 → 0.14.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 +14 -11
- package/README.zh-CN.md +12 -12
- package/extensions/bytefly/README.md +163 -61
- package/extensions/bytefly/doctor/config.ts +4 -1
- package/extensions/bytefly/doctor/runtime.ts +2 -0
- package/extensions/bytefly/footer/budget.ts +64 -0
- package/extensions/bytefly/footer/collect/snapshot.ts +22 -4
- package/extensions/bytefly/footer/price/config.ts +18 -1
- package/extensions/bytefly/footer/price/types.ts +5 -0
- package/extensions/bytefly/footer/register.ts +34 -3
- package/extensions/bytefly/header/component.ts +30 -8
- package/extensions/bytefly/header/config.ts +22 -0
- package/extensions/bytefly/header/register.ts +2 -1
- package/extensions/bytefly/index.ts +7 -5
- package/extensions/bytefly/notify/config.ts +1 -1
- package/extensions/bytefly/notify/register.ts +15 -1
- package/extensions/bytefly/panel/commands.ts +1 -1
- package/extensions/bytefly/panel/format.ts +12 -19
- package/extensions/bytefly/panel/settings-runtime.ts +62 -18
- package/extensions/bytefly/panel/settings.ts +269 -42
- package/extensions/bytefly/panel/tui/settings-view.ts +49 -3
- package/extensions/bytefly/panel/tui.ts +87 -19
- package/extensions/bytefly/separator/component.ts +7 -6
- package/extensions/bytefly/separator/config.ts +15 -0
- package/extensions/bytefly/separator/format.ts +60 -6
- package/extensions/bytefly/separator/register.ts +68 -9
- package/extensions/bytefly/separator/types.ts +8 -0
- package/extensions/bytefly/working/config.ts +4 -5
- package/extensions/bytefly/working/format.ts +24 -7
- package/extensions/bytefly/working/register.ts +34 -3
- package/extensions/job/format.ts +4 -7
- package/extensions/memory/README.md +2 -0
- package/extensions/plan/README.md +12 -0
- package/extensions/subagent/README.md +60 -5
- package/extensions/subagent/config.ts +58 -0
- package/extensions/subagent/index.ts +27 -1
- package/extensions/subagent/orchestrate.ts +16 -3
- package/extensions/subagent/render.ts +12 -0
- package/extensions/subagent/run.ts +100 -37
- package/extensions/subagent/transcripts.ts +202 -0
- package/extensions/subagent/types.ts +12 -0
- package/extensions/todo/nudge.ts +5 -1
- package/extensions/watch/README.md +13 -5
- package/extensions/watch/commands.ts +4 -3
- package/extensions/watch/config.ts +1 -1
- package/extensions/watch/format.ts +4 -7
- package/extensions/watch/runtime.ts +83 -12
- package/extensions/wechat/README.md +2 -0
- package/extensions/worktree/README.md +7 -1
- package/extensions/worktree/enter.ts +10 -3
- package/extensions/worktree/exit.ts +25 -5
- package/extensions/worktree/git.ts +28 -0
- package/extensions/worktree/index.ts +2 -0
- package/extensions/worktree/root-tools.ts +1 -1
- package/extensions/worktree/runtime.ts +5 -0
- package/lib/README.md +5 -3
- package/lib/config.ts +33 -9
- package/lib/format.ts +6 -0
- package/lib/requirements.ts +80 -1
- package/lib/tui/columns.ts +17 -0
- package/lib/tui/tool.ts +6 -2
- package/package.json +2 -1
- package/themes/bytefly-dark.json +2 -3
- package/themes/bytefly-light.json +2 -3
package/README.md
CHANGED
|
@@ -31,13 +31,16 @@ want the agent to *think first and work safely*:
|
|
|
31
31
|
- **Plan, then execute.** A read-only planning mode turns a task into a reviewed
|
|
32
32
|
plan file that the agent then follows step by step.
|
|
33
33
|
- **Delegate and parallelize.** Run specialist subagents in their own Pi
|
|
34
|
-
processes
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
processes, push a long build into a background job, and let a watcher tail a
|
|
35
|
+
log until it matters — all while you keep the thread.
|
|
36
|
+
- **Never wreck the checkout.** Isolation is one command: the task moves onto its
|
|
37
|
+
own branch in a `git worktree`, and every prompt is snapshotted so a bad turn
|
|
38
|
+
is one `/rewind` away.
|
|
37
39
|
- **Remember across sessions.** Durable notes live in plain markdown that you
|
|
38
40
|
can read, edit, and version.
|
|
39
41
|
- **Reach the web and your files.** Search, fetch, browse, open, and read
|
|
40
|
-
documents
|
|
42
|
+
documents from inside the session, and answer a WeChat chat through a bridge to
|
|
43
|
+
the live session.
|
|
41
44
|
|
|
42
45
|
Everything is optional and independently toggleable. Nothing is patched or
|
|
43
46
|
forked: Pi discovers the resources through the `pi` manifest in
|
|
@@ -49,13 +52,13 @@ other.
|
|
|
49
52
|
Requires a working [Pi](https://pi.dev) installation.
|
|
50
53
|
|
|
51
54
|
```bash
|
|
52
|
-
pi install npm:@gavin-hu/my-pi-agent
|
|
53
|
-
pi install git:github.com/gavin-hu/my-pi-agent # install from git
|
|
54
|
-
pi install git:github.com/gavin-hu/my-pi-agent@v0.13.0 # pin a release
|
|
55
|
-
pi install ./ -l # project-local (.pi/settings.json)
|
|
56
|
-
pi -e . # try it for one run
|
|
55
|
+
pi install npm:@gavin-hu/my-pi-agent
|
|
57
56
|
```
|
|
58
57
|
|
|
58
|
+
[Getting started](./docs/getting-started.md) has the other sources — git, a
|
|
59
|
+
pinned release, a project-local install, and a trial that writes nothing — plus
|
|
60
|
+
the fit decision, the first workflows, and how to remove the pack.
|
|
61
|
+
|
|
59
62
|
`git` on `PATH` is needed by [`worktree`](./extensions/worktree/) and
|
|
60
63
|
[`rewind`](./extensions/rewind/); everything else degrades or disables cleanly,
|
|
61
64
|
and `/bytefly doctor` names what is missing, including optional runtime pieces.
|
|
@@ -121,7 +124,7 @@ extension's own `README.md` has the full tool and command surface.
|
|
|
121
124
|
|
|
122
125
|
| Extension | Tools and commands | What it does |
|
|
123
126
|
|---|---|---|
|
|
124
|
-
| [`bytefly`](./extensions/bytefly/) | `/bytefly` (with the `doctor` and `settings` subcommands), `run_doctor` | The visible layer: a themed header with a width-adaptive footer, a live
|
|
127
|
+
| [`bytefly`](./extensions/bytefly/) | `/bytefly` (with the `doctor` and `settings` subcommands), `run_doctor` | The visible layer: a themed header with a width-adaptive footer, a live run line on Pi's working row (tool, tool count, and elapsed time), and a transcript where every tool block leads with its call line and rails its result under it. `/bytefly` switches extensions and holds the curated settings; opt-in `notify` raises OS notifications when a run, a job, or a question needs you. `bytefly.json` is the config document every extension reads. |
|
|
125
128
|
|
|
126
129
|
### Themes
|
|
127
130
|
|
|
@@ -184,7 +187,7 @@ stops the factories from registering; to drop the whole package, use Pi's
|
|
|
184
187
|
|
|
185
188
|
| Guide | What it covers |
|
|
186
189
|
|---|---|
|
|
187
|
-
| [Getting started](./docs/getting-started.md) |
|
|
190
|
+
| [Getting started](./docs/getting-started.md) | Whether the pack fits, a trial run, install options, verifying the load, first workflows, and removal. |
|
|
188
191
|
| [Extensions](./docs/extensions.md) | The full catalog of every extension and theme. |
|
|
189
192
|
| [Configuration](./docs/configuration.md) | Config-file resolution, the per-extension index, environment variables. |
|
|
190
193
|
| [Configuration reference](./docs/references/bytefly-config.md) | Every `bytefly.json` section and key, with its type, default, and bounds. |
|
package/README.zh-CN.md
CHANGED
|
@@ -29,12 +29,13 @@ Pi 提供一个精简而锐利的内核。这个包是在其之上的一层,
|
|
|
29
29
|
|
|
30
30
|
- **先规划,再执行。** 只读的规划模式把一次任务变成一份可审阅的计划文件,智能体
|
|
31
31
|
随后按步骤执行。
|
|
32
|
-
- **委派与并行。** 在各自的 Pi
|
|
33
|
-
你继续把握主线。
|
|
34
|
-
- **绝不搞乱检出区。**
|
|
35
|
-
|
|
32
|
+
- **委派与并行。** 在各自的 Pi 进程中运行专职子智能体,把耗时构建交给后台任务,
|
|
33
|
+
让 watcher 盯住日志直到出现关键行 —— 你继续把握主线。
|
|
34
|
+
- **绝不搞乱检出区。** 隔离只需一条命令:任务切到自己分支的 `git worktree` 中,
|
|
35
|
+
每次提示还会生成快照,因此一次糟糕的回合只需一个 `/rewind` 就能回退。
|
|
36
36
|
- **跨会话记忆。** 持久笔记以纯 Markdown 保存,可读、可改、可纳入版本控制。
|
|
37
|
-
- **连通网络与文件。**
|
|
37
|
+
- **连通网络与文件。** 在会话内搜索、抓取、浏览、打开和读取文档,还可通过桥接
|
|
38
|
+
在微信里直接回答当前会话。
|
|
38
39
|
|
|
39
40
|
一切都是可选的,且可独立开关。没有任何东西被补丁或分叉:Pi 通过
|
|
40
41
|
[`package.json`](./package.json) 里的 `pi` manifest 发现这些资源,因此该包能像
|
|
@@ -45,13 +46,12 @@ Pi 提供一个精简而锐利的内核。这个包是在其之上的一层,
|
|
|
45
46
|
需要一个可用的 [Pi](https://pi.dev) 安装。
|
|
46
47
|
|
|
47
48
|
```bash
|
|
48
|
-
pi install npm:@gavin-hu/my-pi-agent
|
|
49
|
-
pi install git:github.com/gavin-hu/my-pi-agent # 从 git 安装
|
|
50
|
-
pi install git:github.com/gavin-hu/my-pi-agent@v0.13.0 # 固定到某个版本
|
|
51
|
-
pi install ./ -l # 仅项目本地(.pi/settings.json)
|
|
52
|
-
pi -e . # 试运行一次
|
|
49
|
+
pi install npm:@gavin-hu/my-pi-agent
|
|
53
50
|
```
|
|
54
51
|
|
|
52
|
+
[快速开始](./docs/getting-started.md) 介绍其余安装方式——git、固定版本、
|
|
53
|
+
仅项目本地安装,以及不写入任何内容的试用——还有适用性判断、首个工作流和移除方式。
|
|
54
|
+
|
|
55
55
|
`git` 需在 `PATH` 上,供 [`worktree`](./extensions/worktree/) 与
|
|
56
56
|
[`rewind`](./extensions/rewind/) 使用;其余部分会优雅降级或禁用,
|
|
57
57
|
`/bytefly doctor` 会指出缺少什么,包括可选的运行时组件。
|
|
@@ -112,7 +112,7 @@ Windows、macOS 和 Linux 均可运行,完整检查套件在每个平台上都
|
|
|
112
112
|
|
|
113
113
|
| 扩展 | 工具与命令 | 说明 |
|
|
114
114
|
|---|---|---|
|
|
115
|
-
| [`bytefly`](./extensions/bytefly/) | `/bytefly`(`doctor`、`settings` 子命令)、`run_doctor` | 可见的那一层:主题化头部配宽度自适应页脚,Pi
|
|
115
|
+
| [`bytefly`](./extensions/bytefly/) | `/bytefly`(`doctor`、`settings` 子命令)、`run_doctor` | 可见的那一层:主题化头部配宽度自适应页脚,Pi 工作行上实时显示工具、调用次数与计时,转录中每个工具块以调用行为标题、结果正文挂在其下方。`/bytefly` 可开关扩展并集中存放精选设置;可选的 `notify` 会在一次运行、后台任务或待回答的问题需要你时发出系统通知。`bytefly.json` 是每个扩展都会读取的配置文档。 |
|
|
116
116
|
|
|
117
117
|
### 主题
|
|
118
118
|
|
|
@@ -171,7 +171,7 @@ Pi 的 `--no-extensions`,或从你的设置中删除该包。
|
|
|
171
171
|
|
|
172
172
|
| 指南 | 内容 |
|
|
173
173
|
|---|---|
|
|
174
|
-
| [快速开始](./docs/getting-started.md) |
|
|
174
|
+
| [快速开始](./docs/getting-started.md) | 是否适合你、试用、安装选项、验证加载、首个工作流、移除。 |
|
|
175
175
|
| [扩展](./docs/extensions.md) | 所有扩展与主题的完整目录。 |
|
|
176
176
|
| [配置](./docs/configuration.md) | 配置文件解析、按扩展索引、环境变量。 |
|
|
177
177
|
| [配置参考](./docs/references/bytefly-config.md) | 列出 `bytefly.json` 的每个 section 与键,包括类型、默认值和取值范围。 |
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
`bytefly` owns the terminal chrome, configuration, and diagnostics surfaces
|
|
4
4
|
this package adds: one themed startup header whose two-tone nameplate carries
|
|
5
5
|
the agent and chrome identities, one compact, colorful, width-adaptive two-line
|
|
6
|
-
footer, a two-row `You` nameplate that opens each user message, a
|
|
7
|
-
|
|
6
|
+
footer, a two-row `You` nameplate that opens each user message, a receipt rule that
|
|
7
|
+
records each completed turn in the transcript, one keyboard-driven screen with two
|
|
8
8
|
sections — Extensions, every resolved Pi extension with its enable checkbox and
|
|
9
9
|
its health, and Settings, the common app and `bytefly.json` preferences — and
|
|
10
10
|
an opt-in notify capability that raises an OS notification when a run finishes,
|
|
@@ -33,7 +33,7 @@ How the `run_doctor` call and its result look in the transcript — the call lin
|
|
|
33
33
|
|
|
34
34
|
The extension owns ten surfaces: the startup header, the footer, the
|
|
35
35
|
user-message marker, the rule between completed turns, the notice block for
|
|
36
|
-
shared transcript notices, the tool-block frame, the live working
|
|
36
|
+
shared transcript notices, the tool-block frame, the live working line, the
|
|
37
37
|
two-section control center, notifications, and the published-version check.
|
|
38
38
|
|
|
39
39
|
**Header.** A nameplate: a two-tone half-block mark from the active theme's
|
|
@@ -59,10 +59,15 @@ that cannot render half blocks the mark falls back to a two-tone `Pi` wordmark.
|
|
|
59
59
|
|
|
60
60
|
As the terminal narrows, the identity sheds the update marker, then the chrome
|
|
61
61
|
version, then the chrome line, then the agent name, and the help rows drop whole
|
|
62
|
-
keys, so nothing wraps or clips mid-word.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
keys, so nothing wraps or clips mid-word. Height sheds the same way: at 28 rows
|
|
63
|
+
all three help groups print, below 28 the middle group (the expand and model
|
|
64
|
+
chords) goes first, below 22 only the `/` commands row survives, and below 16 the
|
|
65
|
+
help block and the leading blank row go, leaving the nameplate and its rule. An
|
|
66
|
+
unknown height keeps the full header. The nameplate sits on the transcript
|
|
67
|
+
margin, which follows Pi's `outputPad` (the value the tool frame and the notice
|
|
68
|
+
use too), and the help hangs one body indent inside it. The mark, tokens,
|
|
69
|
+
identity, and grouped help are tuned in
|
|
70
|
+
[`header/config.ts`](./header/config.ts).
|
|
66
71
|
|
|
67
72
|
**Footer.** Two lines, each with a left and right zone:
|
|
68
73
|
|
|
@@ -126,14 +131,26 @@ shows as `¥<0.01` rather than `¥0.00`.
|
|
|
126
131
|
|
|
127
132
|
DeepSeek needs no config file at all: the bar prices it from the published yuan
|
|
128
133
|
rates and peak tariff built into [`footer/price/config.ts`](./footer/price/config.ts).
|
|
129
|
-
|
|
130
|
-
|
|
134
|
+
Those tables record the day they were last checked against the published tariff,
|
|
135
|
+
and `doctor` reports how old that is, so a re-pricing shows up as a warning instead
|
|
136
|
+
of a quietly wrong total. A `bytefly.json` can switch to the published dollar table,
|
|
137
|
+
add models of your own, or replace a built-in entry:
|
|
131
138
|
|
|
132
139
|
```
|
|
133
140
|
~/repo/project ⎇ main
|
|
134
141
|
▰▰▰▰▰▰▱▱▱▱ 62%/200k · ¥2.50 · ↑42k ↓8.0k · R96k CH 87% opus-4.5 · high
|
|
135
142
|
```
|
|
136
143
|
|
|
144
|
+
**Session budget.** `price.budget` puts a threshold under that total, in the same
|
|
145
|
+
currency: when the session's cost reaches it, one `bytefly · Session budget
|
|
146
|
+
reached` notice names what was spent against the budget, and one OS notification
|
|
147
|
+
follows when notify is enabled. It is an alert, not a limit — no turn is blocked or
|
|
148
|
+
aborted — and it fires once per session, on the turn where the crossing becomes
|
|
149
|
+
final (the run settling), because a warning per turn after that is noise. `0`, the
|
|
150
|
+
default, turns it off. The check reads the total the footer already priced, and
|
|
151
|
+
the footer exists only in `tui` sessions, so a print or JSON run has no budget
|
|
152
|
+
alert; the footer's own numbers are visible in every interactive session.
|
|
153
|
+
|
|
137
154
|
**User message.** Every user message opens with a two-row `You` nameplate —
|
|
138
155
|
the label over a rule that spans the width — above the message:
|
|
139
156
|
|
|
@@ -156,26 +173,36 @@ as it would without it, and a soft wrap of one long line stays at the margin
|
|
|
156
173
|
because the renderer wraps it, not bytefly. The label and the rule are tuned
|
|
157
174
|
in [`message/config.ts`](./message/config.ts).
|
|
158
175
|
|
|
159
|
-
**Working
|
|
176
|
+
**Working line.** Pi's working row shows a static `Working`, so a long run
|
|
160
177
|
reads the same as a short one. While the row is up, bytefly advances its
|
|
161
|
-
message once a second and hands it back to Pi when the row comes down
|
|
178
|
+
message once a second and hands it back to Pi when the row comes down. Before
|
|
179
|
+
the first tool starts it is a count:
|
|
162
180
|
|
|
163
181
|
```
|
|
164
182
|
Working… 12s
|
|
165
183
|
```
|
|
166
184
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
185
|
+
Once a top-level tool starts, the row becomes a live run line: the tool, how
|
|
186
|
+
many top-level tools this run has started, and the elapsed time.
|
|
187
|
+
|
|
188
|
+
```
|
|
189
|
+
edit · 3 tools · 12s
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
A nested tool call (one carrying `parentToolCallId`, such as a codemode script's
|
|
193
|
+
inner call) neither counts nor takes over the line, so the number matches the
|
|
194
|
+
tool blocks in the transcript. The line keeps the last tool name while the
|
|
195
|
+
model streams after it, and a tool event repaints the row immediately instead
|
|
196
|
+
of waiting for the next tick. The line covers the whole run, tool calls
|
|
197
|
+
included. It is tied to the row's visibility: it starts on `turn_start`, stops
|
|
198
|
+
on `agent_end`, and is reset on `session_shutdown`; turns inside one run do not
|
|
199
|
+
restart it, and a retry starts a new run. The words and the interval are tuned
|
|
200
|
+
in [`working/config.ts`](./working/config.ts).
|
|
174
201
|
|
|
175
202
|
**Turn separator.** After each completed turn the extension appends an inert
|
|
176
|
-
entry and draws a centered `╌╌╌ turn N
|
|
177
|
-
[Turn separator](#turn-separator). No config file is
|
|
178
|
-
command.
|
|
203
|
+
entry and draws a centered receipt rule — `╌╌╌ turn N · duration · N tools ╌╌╌`
|
|
204
|
+
— across the transcript; see [Turn separator](#turn-separator). No config file is
|
|
205
|
+
needed and there is no command.
|
|
179
206
|
|
|
180
207
|
**Notices.** Any extension in the package can post a transcript notice under the
|
|
181
208
|
shared `my-pi-agent/notice` type; bytefly draws it at the transcript's margin —
|
|
@@ -207,6 +234,15 @@ are tuned in [`notice/config.ts`](./notice/config.ts). Every field is sanitized
|
|
|
207
234
|
and clipped at the boundary, and a message without `details` keeps Pi's default
|
|
208
235
|
custom-message box.
|
|
209
236
|
|
|
237
|
+
**Compaction.** `/compact` is Pi's own surface: its summary block is a built-in
|
|
238
|
+
message component, so bytefly cannot replace, hide, or shorten it. The shipped
|
|
239
|
+
themes only remove its fill — `customMessageBg` is the terminal default — and
|
|
240
|
+
paint the `[compaction]` label in the accent, so the block sits on the canvas
|
|
241
|
+
like the rest of the transcript. Pi's branch summaries and skill invocations
|
|
242
|
+
share the same tokens.
|
|
243
|
+
|
|
244
|
+
<img src="../../assets/compaction.png" alt="The /compact summary block: a [compaction] label, the compacted token count, and the summary Markdown on the terminal canvas, with no background band" width="100%">
|
|
245
|
+
|
|
210
246
|
**Tool blocks.** Every tool block leads with the tool's own call line as the
|
|
211
247
|
headline — the tool name in the theme's tool-title colour — and its result body
|
|
212
248
|
sits two columns in directly beneath it, led by the transcript rail, instead of
|
|
@@ -336,7 +372,7 @@ identity tokens, tagline, grouped help), the footer in
|
|
|
336
372
|
[`footer/config.ts`](./footer/config.ts) (thresholds, gauge glyphs and widths,
|
|
337
373
|
separators, icons, status keys), and the turn separator in
|
|
338
374
|
[`separator/config.ts`](./separator/config.ts) (glyph, label prefix, padding,
|
|
339
|
-
colors).
|
|
375
|
+
minimum duration, outcome wording, colors).
|
|
340
376
|
|
|
341
377
|
Every key of every section is listed with its type, default, and bounds in the
|
|
342
378
|
[configuration reference](../../docs/references/bytefly-config.md); this section
|
|
@@ -495,32 +531,46 @@ the model, which sits at the end of the line.
|
|
|
495
531
|
`agent_settled` fires once after an agent run fully settles — exactly one user
|
|
496
532
|
turn — which is why it is used instead of `turn_end` (that fires once per
|
|
497
533
|
assistant message, so tool-calling rounds would each get a line). On each
|
|
498
|
-
settled run the extension appends an inert custom entry and a renderer draws
|
|
499
|
-
|
|
534
|
+
settled run the extension appends an inert custom entry and a renderer draws it
|
|
535
|
+
as a receipt: the turn number, then the run's duration, top-level tool count,
|
|
536
|
+
and outcome as the width allows.
|
|
500
537
|
|
|
501
538
|
```
|
|
502
|
-
|
|
539
|
+
╌╌╌╌╌╌╌╌╌╌╌╌ turn 3 · 1m12s · 7 tools ╌╌╌╌╌╌╌╌╌╌╌╌
|
|
503
540
|
```
|
|
504
541
|
|
|
505
542
|
- The turn number is `count(separators on the current branch) + 1`, so a
|
|
506
543
|
resumed or forked session continues the parent's numbering and abandoned
|
|
507
544
|
branches do not leak counts.
|
|
545
|
+
- The receipt opens on the run's first `agent_start` and closes on
|
|
546
|
+
`agent_settled`, so a retry stays inside one duration. It counts only
|
|
547
|
+
top-level tool calls; a nested call (one carrying `parentToolCallId`) is an
|
|
548
|
+
implementation detail of its parent and does not inflate the number.
|
|
549
|
+
- The outcome is part of the receipt: a failed tool adds `✕N`, and an aborted
|
|
550
|
+
run adds `aborted` instead of the failure count. A sub-second run prints no
|
|
551
|
+
duration, so quick turns stay quiet. Entries written before the receipt
|
|
552
|
+
existed have only a turn number and still render as `turn N`.
|
|
553
|
+
- The label sheds fields rather than overflowing: the tool count first, then
|
|
554
|
+
the duration, then the outcome. When even the turn number does not fit, the
|
|
555
|
+
line becomes a plain dashed rule instead of clipping.
|
|
556
|
+
- A clean turn paints the label `meta`, a turn with a failed tool paints it
|
|
557
|
+
`bad`, and an aborted turn paints it `warn`.
|
|
508
558
|
- The entry is excluded from LLM context, so it costs no tokens, and it
|
|
509
559
|
survives resume and fork. It is drawn under the `bytefly-separator` custom
|
|
510
560
|
entry type.
|
|
511
|
-
- The line is centered and width-adaptive: the label is filled out with the
|
|
512
|
-
glyph, and when it cannot fit the line becomes a plain dashed rule rather
|
|
513
|
-
than overflowing.
|
|
514
561
|
- The rule is installed only in interactive (`tui`) sessions; RPC, JSON, and
|
|
515
562
|
print sessions append nothing.
|
|
516
563
|
- Separators recorded by the retired `turn-separator` extension are not
|
|
517
564
|
rendered, and `PI_DISABLED_EXTENSIONS=turn-separator` no longer affects the
|
|
518
565
|
rule; disable the whole extension with `bytefly` instead.
|
|
519
|
-
- There is no runtime command; the glyph, label prefix, padding,
|
|
520
|
-
tuned in
|
|
566
|
+
- There is no runtime command; the glyph, label prefix, padding, colors, and
|
|
567
|
+
minimum duration are tuned in
|
|
568
|
+
[`separator/config.ts`](./separator/config.ts).
|
|
521
569
|
|
|
522
570
|
## The control center
|
|
523
571
|
|
|
572
|
+
<img src="../../assets/bytefly.png" alt="The /bytefly control center: the Extensions and Settings section bar with the `Global · 10 extensions · 2 off · 1 missing` counts, one checkbox row per extension with its verdict, the focused extension's report, and the key hints" width="100%">
|
|
573
|
+
|
|
524
574
|
`/bytefly [extension] [refresh]` opens the control center on **Extensions**: a
|
|
525
575
|
keyboard-driven dock list of every extension Pi resolves for the session, so the
|
|
526
576
|
list matches what actually loads. `←`/`→` switch to **Settings**, where the same
|
|
@@ -585,11 +635,11 @@ installs or fetches a package.
|
|
|
585
635
|
without leaving the session.
|
|
586
636
|
|
|
587
637
|
**Settings.** The second section uses the same frame and the same `Tab` scope
|
|
588
|
-
switch, with its own cursor. It lists
|
|
638
|
+
switch, with its own cursor. It lists twenty-eight preferences in ten groups:
|
|
589
639
|
|
|
590
640
|
```
|
|
591
641
|
bytefly ──────────────────────────────────────────────────────────────
|
|
592
|
-
Extensions · Settings Global ·
|
|
642
|
+
Extensions · Settings Global · 28 settings
|
|
593
643
|
|
|
594
644
|
Startup (1)
|
|
595
645
|
❯ ◻ Bytefly startup TUI Off
|
|
@@ -604,19 +654,36 @@ bytefly ────────────────────────
|
|
|
604
654
|
Diagnostics (2)
|
|
605
655
|
◼ Proactive health check On
|
|
606
656
|
Probe timeout 2000
|
|
607
|
-
Pricing (
|
|
657
|
+
Pricing (3)
|
|
608
658
|
Currency CNY (¥)
|
|
609
659
|
Cost decimals 2
|
|
610
|
-
|
|
660
|
+
Session budget 0
|
|
661
|
+
Transcript (3)
|
|
611
662
|
Rail glyph ╎
|
|
663
|
+
Achieved goal Hide
|
|
612
664
|
Output padding 1
|
|
613
665
|
Terminal (1)
|
|
614
666
|
◻ Hardware cursor Off
|
|
667
|
+
Worktree (4)
|
|
668
|
+
◼ Fetch remote On
|
|
669
|
+
Base ref Fresh
|
|
670
|
+
Branch prefix worktree-
|
|
671
|
+
Prune after (days) 7
|
|
672
|
+
Snapshots (3)
|
|
673
|
+
◼ Automatic snapshots On
|
|
674
|
+
Snapshots kept 20
|
|
675
|
+
◼ Safety snapshot On
|
|
676
|
+
Jobs and watchers (3)
|
|
677
|
+
◻ Wake when a job finishes Off
|
|
678
|
+
◻ Keep jobs after exit Off
|
|
679
|
+
◻ Wake on a match Off
|
|
680
|
+
Memory (1)
|
|
681
|
+
◼ Inject notes On
|
|
615
682
|
Bytefly startup TUI — Pi setting
|
|
616
683
|
Use bytefly's startup header in place of Pi's startup TUI.
|
|
617
684
|
Default · ~/.pi/agent/settings.json
|
|
618
685
|
|
|
619
|
-
Esc close · ←/→ · Space change · Tab scope ·
|
|
686
|
+
Esc close · ←/→ · Space change · Tab scope · u reset · J JSON · [ ] group
|
|
620
687
|
```
|
|
621
688
|
|
|
622
689
|
| Group | Row | Source | Values |
|
|
@@ -633,22 +700,45 @@ bytefly ────────────────────────
|
|
|
633
700
|
| Diagnostics | Probe timeout | `doctor.timeoutMs` | Number, 100–30000 ms |
|
|
634
701
|
| Pricing | Currency | `price.currency.code` | CNY, USD |
|
|
635
702
|
| Pricing | Cost decimals | `price.currency.decimals` | 0, 1, 2, 3, 4 |
|
|
703
|
+
| Pricing | Session budget | `price.budget` | Number, `0` = off |
|
|
636
704
|
| Transcript | Rail glyph | `chrome.rail` | Text, exactly one column |
|
|
705
|
+
| Transcript | Achieved goal | `goal.achieved` | Show, Hide |
|
|
637
706
|
| Transcript | Output padding | Pi `settings.json` | 0, 1 |
|
|
638
707
|
| Terminal | Hardware cursor | Pi `settings.json` | Off, On |
|
|
708
|
+
| Worktree | Base ref | `worktree.baseRef` | Fresh, Head |
|
|
709
|
+
| Worktree | Branch prefix | `worktree.branchPrefix` | Text, trimmed, required |
|
|
710
|
+
| Worktree | Fetch remote | `worktree.fetchRemote` | Off, On |
|
|
711
|
+
| Worktree | Prune after (days) | `worktree.pruneAfterDays` | Number, 0–3650 |
|
|
712
|
+
| Snapshots | Automatic snapshots | `rewind.autoSnapshots` | Off, On |
|
|
713
|
+
| Snapshots | Snapshots kept | `rewind.max` | Number, 0–1000 |
|
|
714
|
+
| Snapshots | Safety snapshot | `rewind.safetySnapshot` | Off, On |
|
|
715
|
+
| Jobs and watchers | Wake when a job finishes | `job.wakeOnFinish` | Off, On |
|
|
716
|
+
| Jobs and watchers | Keep jobs after exit | `job.detachedByDefault` | Off, On |
|
|
717
|
+
| Jobs and watchers | Wake on a match | `watch.wakeOnMatch` | Off, On |
|
|
718
|
+
| Memory | Inject notes | `memory.inject` | Off, On |
|
|
639
719
|
|
|
640
720
|
Choosing **Currency** also writes that currency's default precision. Both rows
|
|
641
721
|
stay editable afterwards, so the footer follows the explicit values.
|
|
642
722
|
|
|
643
723
|
`Space` (or `Enter`) changes the focused row: a boolean toggles, an enum cycles
|
|
644
724
|
forward, and a text row opens an inline editor on its value — the notification
|
|
645
|
-
title, the probe timeout, and the rail glyph.
|
|
725
|
+
title, the probe timeout, the branch prefix, and the rail glyph. `u` deletes the
|
|
726
|
+
focused row's key so its default applies again (`Already at its default.` when
|
|
727
|
+
nothing is stored), `J` swaps the detail pane for the focused row's whole section
|
|
728
|
+
as the active scope stores it — the only view of the keys this screen leaves to
|
|
729
|
+
JSON — and `[` / `]` jump to the previous or next group. The detail pane names
|
|
730
|
+
the source, describes the preference, and shows
|
|
646
731
|
where the value is written — `Global · ~/.pi/agent/settings.json`, `Project ·
|
|
647
732
|
.pi/bytefly.json`, or `Inherited from Global · .pi/bytefly.json`. A successful
|
|
648
733
|
change marks the screen `Saved · reload to apply` — even when the terminal is too
|
|
649
734
|
short for the detail body — and closing offers the same
|
|
650
735
|
reload confirm as an extension toggle.
|
|
651
736
|
|
|
737
|
+
Six of the ten groups belong to other extensions. The screen cannot import their
|
|
738
|
+
normalizers, so it reports the leaf as the file states it and declares the
|
|
739
|
+
loader's default; `test/settings-coverage.test.ts` holds the catalogue to every
|
|
740
|
+
loader's defaults and bounds in both directions.
|
|
741
|
+
|
|
652
742
|
**Bytefly startup TUI** is the one row whose label differs from the Pi key it
|
|
653
743
|
writes: On writes `"quietStartup": true` (bytefly's header replaces Pi's startup
|
|
654
744
|
detail), and Off writes `false` (Pi's built-in header stays). A hand-set
|
|
@@ -657,17 +747,18 @@ with `true` or `false`.
|
|
|
657
747
|
|
|
658
748
|
App rows are **Global only**: Pi's setters for them write the personal
|
|
659
749
|
`settings.json`, and only resource paths have public project setters. Project
|
|
660
|
-
scope therefore lists the
|
|
750
|
+
scope therefore lists the twenty-five `bytefly.json` rows and a
|
|
661
751
|
`App settings are Global only.` note rather than promising a write that cannot
|
|
662
752
|
happen. A `bytefly.json` row writes one leaf in the selected scope (a depth-1
|
|
663
753
|
key, or a nested one such as `price.currency.decimals`) through a per-key
|
|
664
754
|
writer, so every sibling key, section, `$schema`, and `version` is preserved. A
|
|
665
|
-
malformed document is refused with a notice instead of overwritten
|
|
755
|
+
malformed document is refused with a notice instead of overwritten, and `u`
|
|
756
|
+
removes that one leaf through the same writer's `unsetConfigValueAt`.
|
|
666
757
|
|
|
667
758
|
The non-`tui` form prints the headline, the groups, and `Label: Value` rows:
|
|
668
759
|
|
|
669
760
|
```
|
|
670
|
-
bytefly: Settings · Global ·
|
|
761
|
+
bytefly: Settings · Global · 28 settings
|
|
671
762
|
|
|
672
763
|
Startup (1)
|
|
673
764
|
Bytefly startup TUI: Off
|
|
@@ -691,6 +782,12 @@ means reduced capability — an optional package that is absent, a config file
|
|
|
691
782
|
that fails to parse, a login that has not happened. Doctor never changes
|
|
692
783
|
anything and never installs anything.
|
|
693
784
|
|
|
785
|
+
It also reports what has **aged**: the built-in DeepSeek rate tables carry the day
|
|
786
|
+
they were last checked against the published tariff (`PRICE_VERIFIED_AT` in
|
|
787
|
+
`footer/price/config.ts`), and the report says how old that is — `ok` inside the
|
|
788
|
+
90-day window, `degraded` beyond it with the source URL to re-check. A tariff change
|
|
789
|
+
therefore becomes a visible warning instead of a quietly wrong cost total.
|
|
790
|
+
|
|
694
791
|
`web-access` publishes what it resolved at `session_start`, so the report names
|
|
695
792
|
the search provider and why it won (an explicit choice, the `auto` rule, or the
|
|
696
793
|
keyless default), and — when the provider takes a key and no literal `apiKey` is
|
|
@@ -946,6 +1043,9 @@ command.
|
|
|
946
1043
|
- **Notifications are not focus-aware.** They fire whether or not the terminal
|
|
947
1044
|
has focus, and once per trigger rather than once per unseen event. There is
|
|
948
1045
|
no focus API to consult.
|
|
1046
|
+
- **`/compact` is Pi's block.** The summary component is built in, so bytefly
|
|
1047
|
+
cannot render, hide, or shorten it; the themes only choose its fill and label
|
|
1048
|
+
color. Branch summaries and skill invocations share the same theme tokens.
|
|
949
1049
|
- **A background job cannot ask for input.** The `needsInput` trigger is a
|
|
950
1050
|
prompt raised during a run, not a process waiting on stdin: jobs are
|
|
951
1051
|
fire-and-observe, so that state does not exist.
|
|
@@ -953,11 +1053,11 @@ command.
|
|
|
953
1053
|
host lacks (or an OSC method off a TTY) and the notification is dropped; only
|
|
954
1054
|
`auto` inspects the environment. `doctor` now reports the mismatch as a
|
|
955
1055
|
`degraded` finding, which says what to change but does not fix it for you.
|
|
956
|
-
- **The working
|
|
1056
|
+
- **The working line is one global row.** `setWorkingMessage` drives the
|
|
957
1057
|
single working row, so bytefly and any other extension setting it race — last
|
|
958
1058
|
writer wins — and the message is reset to Pi's default at `agent_end`. If the
|
|
959
|
-
row is hidden (`ctx.ui.setWorkingVisible(false)`) the
|
|
960
|
-
and a reload mid-run does not resume
|
|
1059
|
+
row is hidden (`ctx.ui.setWorkingVisible(false)`) the line has no surface,
|
|
1060
|
+
and a reload mid-run does not resume the count until the next turn.
|
|
961
1061
|
|
|
962
1062
|
## Non-goals
|
|
963
1063
|
|
|
@@ -981,7 +1081,7 @@ command.
|
|
|
981
1081
|
match — are the whole surface.
|
|
982
1082
|
- No sound, action buttons, notification history, or de-duplication; a
|
|
983
1083
|
notification is a fire-and-forget message, not an inbox.
|
|
984
|
-
- No frozen per-run working duration: the
|
|
1084
|
+
- No frozen per-run working duration: the line is live and is handed back to
|
|
985
1085
|
Pi when the working row comes down, because the extension API exposes no hook
|
|
986
1086
|
to keep a finished run's total.
|
|
987
1087
|
|
|
@@ -994,18 +1094,18 @@ rather than showing a wrong value.
|
|
|
994
1094
|
|
|
995
1095
|
| Integration point | Details |
|
|
996
1096
|
|---|---|
|
|
997
|
-
| Header | `ctx.ui.setHeader` with a custom component, replacing Pi's built-in header; installed only when `ctx.mode === "tui"` and `pi.getSettings().quietStartup === true` (the **Bytefly startup TUI** row). `false`, `"header"`, and unset call `setHeader(undefined)`, leaving Pi's built-in header in place. The nameplate insets by Pi's `outputPad` (read through `pi.getSettings()`), so it sits on the transcript margin, and the help hangs one body indent inside it. The mark and text are drawn from the active theme's tokens, the help keys resolve live through `keyText`, and the mark falls back to a wordmark on Apple Terminal (`isAppleTerminalSession`), mirroring Pi's built-in. The chrome version gains `↑<latest>` from the `UpdateSource`, and `registerHeader` returns a `refresh()` handle that re-installs the last context's header when that value arrives. |
|
|
1097
|
+
| Header | `ctx.ui.setHeader` with a custom component, replacing Pi's built-in header; installed only when `ctx.mode === "tui"` and `pi.getSettings().quietStartup === true` (the **Bytefly startup TUI** row). `false`, `"header"`, and unset call `setHeader(undefined)`, leaving Pi's built-in header in place. The nameplate insets by Pi's `outputPad` (read through `pi.getSettings()`), so it sits on the transcript margin, and the help hangs one body indent inside it. The mark and text are drawn from the active theme's tokens, the help keys resolve live through `keyText`, and the mark falls back to a wordmark on Apple Terminal (`isAppleTerminalSession`), mirroring Pi's built-in. The factory reads `tui.terminal.rows` on every render, so the height ladder in `header/config.ts` sheds help groups and then the leading blank row as the terminal shortens (unknown height keeps the full header). The chrome version gains `↑<latest>` from the `UpdateSource`, and `registerHeader` returns a `refresh()` handle that re-installs the last context's header when that value arrives. |
|
|
998
1098
|
| Footer | `ctx.ui.setFooter` with a custom component, replacing Pi's built-in footer; installed only when `ctx.mode === "tui"`. |
|
|
999
1099
|
| User message | `pi.registerMarkdownTransformer` puts a two-row `You` nameplate (the label over a full-width rule) above each user message; one padded level-2 heading carries the accent through `mdHeading` for both rows, and the shipped themes set `userMessageBg` to the terminal default, so the block has no fill. Pi renders the result as Markdown, so the surface adds no component or color of its own. |
|
|
1000
1100
|
| Notice | `registerMessageRenderer(NOTICE_TYPE)` draws every shared transcript notice at the margin from its `details`; the headline stays at the margin and its rows hang from the transcript rail, painted by the notice's worst severity, whose glyph comes from the shared `RailSource`. `job` and `watch` post one when their work settles, and `doctor` posts one at `session_start` for a missing hard requirement. The type and shape come from `lib/notice.ts`. A message without `details` falls back to Pi's default custom-message box. |
|
|
1001
1101
|
| Tool blocks | `registerToolRenderer` returns, for every tool, `renderShell: "self"`; `renderCall` leaves the tool's own first line as the block's headline (a shell prompt shown as the tool name, its command repainted in the body colour, and a primary subject demoted to the body colour) and indents the rest of the call two columns under it, `renderResult` indents its body the same and leads it with the status-coloured rail, and each wraps the tool's own renderer (or a generic fallback). `edit` and `write` carry their result on the call body, so that body is railed too. |
|
|
1002
1102
|
| Screen command | `pi.registerCommand("bytefly")` takes `[doctor] [settings] [extension] [refresh]`: `tui` mounts a dock screen via `ctx.ui.custom()` with the rails suppressed; other modes print through `ctx.ui.notify()` — the grouped listing, `run_doctor`'s report for `doctor`, or the grouped settings listing with values for `settings`. A named extension is checked against the discovered set before any probe. Tab completes the subcommands, extension names after `doctor`, and `refresh`; `/bytefly settings` rejects a name. |
|
|
1003
|
-
| Turn separator | `registerEntryRenderer("bytefly-separator")` draws each
|
|
1004
|
-
| Working
|
|
1103
|
+
| Turn separator | `registerEntryRenderer("bytefly-separator")` draws each stored receipt; `agent_start` opens it, top-level `tool_execution_start`/`tool_execution_end` count tools and failures, and `agent_settled` appends `pi.appendEntry("bytefly-separator", { turn, durationMs, tools, failures, aborted })` in `tui` mode only. The receipt fields are omitted when no `agent_start` was seen, so an older or partially observed entry stays `{ turn }`. |
|
|
1104
|
+
| Working line | `turn_start` starts a 1s tick that drives `ctx.ui.setWorkingMessage` in `tui` mode; before a tool runs the message is `Working… Ns`, and each top-level `tool_execution_start` repaints it as `tool · N tools · Ns` (nested calls carrying `parentToolCallId` are skipped). `agent_end` restores Pi's default and cancels the tick (also on `session_shutdown`). No config file and no persisted state; the count lives in the register's closure. |
|
|
1005
1105
|
| Notifications | `agent_settled` (skipped when aborted), `ui_prompt_start` only while `agent_start`…`agent_settled` marks a run active, and `my-pi-agent/job-finished` on `pi.events`; the `notify` section of `bytefly.json` gates each. Delivery writes an OSC 777/99 sequence to stdout or spawns `osascript`, `notify-send`, or `powershell.exe`. The bus subscription is created in `session_start` and released in `session_shutdown`, and the `job` extension never imports bytefly. |
|
|
1006
1106
|
| Picker discovery | `SettingsManager.create(...)` plus `DefaultPackageManager.resolve({ onMissing: "skip" })`, both public exports; both views drop `bytefly`'s own entrypoint. |
|
|
1007
1107
|
| Picker writes | `SettingsManager` setters (`setExtensionPaths`, `setPackages`, `setProjectExtensionPaths`, `setProjectPackages`) then `flush()`; `ctx.reload()` after the screen closes when changes are pending. |
|
|
1008
|
-
| Settings writes | App rows call `SettingsManager` setters (`setQuietStartup`, `setOutputPad`, `setShowHardwareCursor`) on the global store and `flush()`, then surface `drainErrors()`; `bytefly.json` rows call `writeConfigValueAt` on the selected scope's document with the row's leaf path, so a nested key (`price.currency.decimals`) and a flat one (`notify.method`) share one writer. A failed or refused write shows a notice in the screen's hint row and leaves the displayed value unchanged; a successful one marks the screen dirty. |
|
|
1108
|
+
| Settings writes | App rows call `SettingsManager` setters (`setQuietStartup`, `setOutputPad`, `setShowHardwareCursor`) on the global store and `flush()`, then surface `drainErrors()`; `bytefly.json` rows call `writeConfigValueAt` on the selected scope's document with the row's leaf path, so a nested key (`price.currency.decimals`) and a flat one (`notify.method`) share one writer, and `u` calls `unsetConfigValueAt` with the same path. A failed or refused write shows a notice in the screen's hint row and leaves the displayed value unchanged; a successful one marks the screen dirty. |
|
|
1009
1109
|
| Doctor tool | `pi.registerTool("run_doctor")`, read-only (`readOnlyHint: true`, `openWorldHint: false`), direct exposure and active on registration (the defaults, so not declared), with a typed `outputSchema` mirroring `structuredContent`. Its `readOnlyHint` is what the shared default-deny policy in `lib/policy.ts` reads to allow it in plan mode. |
|
|
1010
1110
|
| Doctor probes | `run_doctor` and the screen share the session cache created by `registerDoctor`; the screen mounts on that cache and probes on the first Extensions view (the command's `refresh` forces it), while the text modes probe before printing, and `/bytefly refresh` and `refresh: true` re-probe. Probes spawn `<binary> --version`, lazily import optional packages, and read config files through `lib/requirements.ts`; nothing is ever written. |
|
|
1011
1111
|
| Status routing | Reads `footerData.getExtensionStatuses()` (a custom footer replaces the built-in one entirely); `worktree` routes to line 1, plan/alert statuses to line 2's trailing slot. |
|
|
@@ -1098,8 +1198,10 @@ rather than showing a wrong value.
|
|
|
1098
1198
|
and a grouped help block. It takes its margin from Pi's `outputPad`, like the
|
|
1099
1199
|
tool frame and the notice, and hangs the help one body indent inside it, so the
|
|
1100
1200
|
header follows a non-default pad instead of assuming a column. It adds no
|
|
1101
|
-
session or model data — that is the footer's job — and
|
|
1102
|
-
|
|
1201
|
+
session or model data — that is the footer's job — and its shape follows the
|
|
1202
|
+
terminal: the height ladder drops whole help groups, then the leading blank
|
|
1203
|
+
row, before the nameplate gives up anything, so a short pane spends its rows
|
|
1204
|
+
on the transcript instead of chrome.
|
|
1103
1205
|
- **Two lines, four zones.** Line 1 is identity (`pwd` left, branch + worktree
|
|
1104
1206
|
right); line 2 is resources (meters left, model + level right). This keeps
|
|
1105
1207
|
"where am I / what state" separate from "how much am I burning".
|
|
@@ -1254,7 +1356,7 @@ rather than showing a wrong value.
|
|
|
1254
1356
|
The surfaces are folders: `header/`, `footer/` (the status bar and its price
|
|
1255
1357
|
calculation), `message/` (the user-message marker), `notice/` (the shared notice),
|
|
1256
1358
|
`block/` (the tool-block frame), `separator/`, `working/` (the live
|
|
1257
|
-
|
|
1359
|
+
run line on Pi's working row), `panel/` (the
|
|
1258
1360
|
unified screen and its merged model),
|
|
1259
1361
|
`picker/` (discovery and the settings store), `doctor/` (the `run_doctor` tool
|
|
1260
1362
|
and its probe runtime), `notify/`, and `update/` (the published-version check
|
|
@@ -1296,14 +1398,14 @@ columns, gauge), so the look follows the active theme.
|
|
|
1296
1398
|
| `block/component.ts` | Pure `toolBlockLines`, `headlineWithToolName`, `recolorShellCall`, `recolorCallHeadline`, and `ToolBlock`: the headline, the body's two-column indent (optionally rail-led), the reduced-width inner render, the leading-blank trim, the shell-prompt rewrite (the name keeps the accent, the command reopens in `label`), the subject demotion (a path, URL, query, or pattern reads in `label` so the name is the line's only accent, including the tail a bare `edit <path>` headline wraps onto the body), and the image-line passthrough. |
|
|
1297
1399
|
| `block/fallback.ts` | Generic `callFallback` / `resultFallback` for a tool with no renderer: the subject in the body colour, its options faint, and a capped result preview. |
|
|
1298
1400
|
| `block/register.ts` | The `registerToolRenderer` resolver that frames every tool; it recolours a shell call's string before the frame wraps it, rails the result body by status, and rails the call body for `edit`/`write` (the two whose call body carries the result). |
|
|
1299
|
-
| `separator/config.ts` | Turn-rule tuning: `customType`, glyph, label prefix, padding, and roles. |
|
|
1300
|
-
| `separator/register.ts` | Registers the entry renderer and appends
|
|
1401
|
+
| `separator/config.ts` | Turn-rule tuning: `customType`, glyph, label prefix, padding, receipt minimum duration and outcome wording, and roles. |
|
|
1402
|
+
| `separator/register.ts` | Registers the entry renderer, tracks the run's tools and failures, and appends the receipt on `agent_settled`. |
|
|
1301
1403
|
| `separator/component.ts` | `SeparatorComponent`: the stateless entry renderer. |
|
|
1302
|
-
| `separator/format.ts` | Pure `
|
|
1303
|
-
| `separator/types.ts` | `TurnSeparatorData
|
|
1304
|
-
| `working/config.ts` | Counter tuning (`WORKING_CONFIG`): the
|
|
1305
|
-
| `working/format.ts` | Pure `formatElapsed` (whole seconds) and the working-message shape. |
|
|
1306
|
-
| `working/register.ts` | Starts the tick on `turn_start` and cancels
|
|
1404
|
+
| `separator/format.ts` | Pure `receiptLabel` (the width ladder), `receiptRole`, and `separatorLine`, drawn by the kit's `centeredRule`. |
|
|
1405
|
+
| `separator/types.ts` | `TurnSeparatorData`: the turn plus the optional receipt fields. |
|
|
1406
|
+
| `working/config.ts` | Counter tuning (`WORKING_CONFIG`): the words, the tool singular/plural, and the tick interval. |
|
|
1407
|
+
| `working/format.ts` | Pure `formatElapsed` (whole seconds) and the working-message shape: the plain count and the `tool · N tools · elapsed` run line. |
|
|
1408
|
+
| `working/register.ts` | Starts the tick on `turn_start`, tracks top-level tools on `tool_execution_start`, and cancels on `agent_end`/`session_shutdown`. |
|
|
1307
1409
|
| `panel/types.ts` | `PanelSection` (`extensions` | `settings`), `PanelRow`, and `PanelModel`, the merged row model. |
|
|
1308
1410
|
| `panel/join.ts` | The item/report union with the unambiguous-name health rule and unique row keys, groups, and ordering. |
|
|
1309
1411
|
| `panel/format.ts` | Non-TUI text: the extension headline and grouped listing with a per-row health suffix, plus the section segments, the Settings counts/headline, and the grouped Settings listing. |
|
|
@@ -1355,10 +1457,10 @@ folding across a width sweep from 6 to 120 plus wide characters
|
|
|
1355
1457
|
(`footer/render/layout`), exact
|
|
1356
1458
|
golden output at fixed widths (`footer/render/render`), and the install/skip/
|
|
1357
1459
|
restore/toggle lifecycle plus a config-driven price (`extension`). The turn
|
|
1358
|
-
separator
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1460
|
+
separator is covered by its pure formatting (`separator/format`, including the
|
|
1461
|
+
receipt's width ladder), its register/append/render/disable lifecycle
|
|
1462
|
+
(`separator/register`), and the run stats it records. The picker helpers are
|
|
1463
|
+
covered by the pure helpers (`picker/resources`), the toggle
|
|
1362
1464
|
transforms (`picker/toggle`), discovery with an injected factory
|
|
1363
1465
|
(`picker/discovery`), and the runtime state machine (`picker/runtime`). The
|
|
1364
1466
|
unified screen is covered by its pure model merge (`panel/join`), its text
|
|
@@ -14,6 +14,9 @@ import { clampInteger, loadConfigSection } from "../../../lib/config.ts";
|
|
|
14
14
|
/** How long a single probe may take before it counts as unusable. */
|
|
15
15
|
const DEFAULT_TIMEOUT_MS = 2_000;
|
|
16
16
|
|
|
17
|
+
/** The probe deadline range, in milliseconds; the panel's editor offers the same bounds. */
|
|
18
|
+
export const TIMEOUT_MS_RANGE = { min: 100, max: 30_000 } as const;
|
|
19
|
+
|
|
17
20
|
export interface DoctorConfig {
|
|
18
21
|
/** Probe enabled extensions at session start and warn when one is broken. */
|
|
19
22
|
proactive: boolean;
|
|
@@ -34,7 +37,7 @@ export function normalizeConfig(raw: Record<string, unknown> | undefined, base:
|
|
|
34
37
|
if (!raw) return base;
|
|
35
38
|
return {
|
|
36
39
|
proactive: typeof raw.proactive === "boolean" ? raw.proactive : base.proactive,
|
|
37
|
-
timeoutMs: clampInteger(raw.timeoutMs, base.timeoutMs,
|
|
40
|
+
timeoutMs: clampInteger(raw.timeoutMs, base.timeoutMs, TIMEOUT_MS_RANGE.min, TIMEOUT_MS_RANGE.max),
|
|
38
41
|
skip: Array.isArray(raw.skip)
|
|
39
42
|
? raw.skip.filter((name): name is string => typeof name === "string" && name.trim().length > 0)
|
|
40
43
|
: base.skip,
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import { CONFIG_DIR_NAME, getAgentDir, type ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
12
12
|
import type { WebSearchProviderEvent } from "../../../lib/events.ts";
|
|
13
|
+
import { PRICE_VERIFIED_AT } from "../footer/price/config.ts";
|
|
13
14
|
import { readJsonResult } from "../../../lib/config.ts";
|
|
14
15
|
import { isExtensionEnabled } from "../../../lib/env.ts";
|
|
15
16
|
import {
|
|
@@ -96,6 +97,7 @@ export function createDoctorRuntime(
|
|
|
96
97
|
searchProvider: () => searchProvider,
|
|
97
98
|
reach: probeReach,
|
|
98
99
|
refresh,
|
|
100
|
+
priceVerifiedAt: () => PRICE_VERIFIED_AT,
|
|
99
101
|
...deps.seams,
|
|
100
102
|
});
|
|
101
103
|
|