pi-one-ui 0.3.0 → 0.4.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/CHANGELOG.md +31 -1
- package/README.en.md +39 -35
- package/README.md +20 -16
- package/extensions/app/commands/settings-previews.ts +4 -16
- package/extensions/app/config/renderer.ts +7 -6
- package/extensions/app/config/shell.ts +15 -137
- package/extensions/app/overlay/selector-border.ts +5 -5
- package/extensions/app/ownership.ts +1 -1
- package/extensions/app/panel.ts +19 -25
- package/extensions/app/runtime/tui-runtime.ts +31 -56
- package/extensions/features/context-inspector/index.ts +3 -3
- package/extensions/features/session-reference/index.ts +5 -5
- package/extensions/features/subagent-autocomplete.ts +1 -1
- package/extensions/layouts/context/index.ts +9 -12
- package/extensions/layouts/context/renderer/compact-mode.ts +24 -24
- package/extensions/layouts/context/renderer/default-mode.ts +21 -16
- package/extensions/layouts/context/renderer/index.ts +24 -24
- package/extensions/layouts/context/renderer/mouse/hover.ts +6 -6
- package/extensions/layouts/context/renderer/mouse/interaction.ts +35 -35
- package/extensions/layouts/context/renderer/mouse/packets.ts +3 -2
- package/extensions/layouts/context/renderer/mouse/scroll.ts +2 -2
- package/extensions/layouts/context/renderer/tool/diff/diff-component.ts +2 -1
- package/extensions/layouts/context/renderer/tool/diff/diff-edit-render.ts +21 -21
- package/extensions/layouts/context/renderer/tool/diff/diff-header.ts +4 -4
- package/extensions/layouts/context/renderer/tool/diff/diff-highlight.ts +6 -6
- package/extensions/layouts/context/renderer/tool/diff/diff-inline.ts +1 -1
- package/extensions/layouts/context/renderer/tool/diff/diff-layout.ts +18 -18
- package/extensions/layouts/context/renderer/tool/diff/diff-limits.ts +5 -5
- package/extensions/layouts/context/renderer/tool/diff/diff-palette.ts +3 -3
- package/extensions/layouts/context/renderer/tool/diff/diff-presentation.ts +1 -1
- package/extensions/layouts/context/renderer/tool/diff/diff-renderer.ts +2 -1
- package/extensions/layouts/context/renderer/tool/diff/diff-write-render.ts +31 -31
- package/extensions/layouts/context/renderer/tool/diff/index.ts +4 -4
- package/extensions/layouts/context/renderer/tool/diff/line-width-safety.ts +1 -1
- package/extensions/layouts/context/renderer/tool/diff/write-execution.ts +1 -1
- package/extensions/layouts/context/renderer/tool/grouping.ts +12 -12
- package/extensions/layouts/context/renderer/tool/message-display.ts +2 -2
- package/extensions/layouts/context/renderer/tool/result.ts +199 -19
- package/extensions/layouts/context/summary/core.ts +1 -0
- package/extensions/layouts/context/summary/index.ts +3 -3
- package/extensions/layouts/context/thinking/compact-thinking.ts +12 -13
- package/extensions/layouts/editor/controller.ts +3 -57
- package/extensions/layouts/editor/editor-metadata-format.ts +4 -4
- package/extensions/layouts/editor/factory.ts +5 -23
- package/extensions/layouts/editor/index.ts +2 -8
- package/extensions/layouts/editor/minimalist-editor.ts +1 -52
- package/extensions/layouts/editor/ui.ts +23 -255
- package/extensions/layouts/footer/controller.ts +3 -3
- package/extensions/layouts/footer/footer.ts +21 -21
- package/extensions/layouts/footer/index.ts +8 -8
- package/extensions/layouts/header/index.ts +1 -1
- package/extensions/layouts/header/startup-header.ts +3 -2
- package/extensions/layouts/working-line/controller.ts +6 -6
- package/extensions/layouts/working-line/interaction-summary.ts +47 -7
- package/extensions/layouts/working-line/working-line.ts +24 -3
- package/extensions/services/project-refresh.ts +2 -2
- package/extensions/services/session-state.ts +1 -1
- package/extensions/shared/format.ts +2 -2
- package/extensions/shared/icons.ts +0 -4
- package/package.json +9 -12
- package/extensions/features/legacy/working-message.ts +0 -226
- package/extensions/layouts/editor/accent-rail-editor.ts +0 -112
- package/extensions/layouts/editor/accent-rail-layout-patch.ts +0 -530
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,34 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.4.0] - 2026-09-03
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Simplified Editor styling to the `opencode` and `minimalist` options; removed Minimalist context-usage metadata in favor of Footer's more complete context configuration.
|
|
14
|
+
- Added response-local live output throughput to the WorkingLine token segment after a bounded sampling window.
|
|
15
|
+
|
|
16
|
+
### Removed
|
|
17
|
+
|
|
18
|
+
- Removed the `opencode-copy-friendly` and `accent-rail` Editor styles, including Accent Rail layout patching and style-specific settings.
|
|
19
|
+
- Removed the inherited upstream image from pi-one-ui's package-gallery metadata.
|
|
20
|
+
|
|
21
|
+
### Migration
|
|
22
|
+
|
|
23
|
+
- Existing `opencode-copy-friendly` or `accent-rail` selections fall back to `opencode`; remove obsolete nested settings for those styles when convenient.
|
|
24
|
+
- Configure context percentage, token totals, thresholds, and gauges through Footer instead of Minimalist Editor settings.
|
|
25
|
+
|
|
26
|
+
## [0.3.1] - 2026-08-31
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- Unified the test suite on Vitest and reorganized tests into domain-oriented directories.
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
- Keep `/oneui` open and focused during in-place Editor changes, restore effective values after persistence failures, and position the panel closer to the top.
|
|
35
|
+
- Reduced global tool expansion latency and preserved pi-subagents' dedicated live progress renderer instead of wrapping and grouping it as a generic tool.
|
|
36
|
+
|
|
9
37
|
## [0.3.0] - 2026-08-30
|
|
10
38
|
|
|
11
39
|
### Added
|
|
@@ -34,6 +62,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
34
62
|
|
|
35
63
|
- Reduced rendering lag when expanding settled tool groups by reusing cached child output.
|
|
36
64
|
|
|
37
|
-
[Unreleased]: https://github.com/kerolt/pi-one-ui/compare/v0.
|
|
65
|
+
[Unreleased]: https://github.com/kerolt/pi-one-ui/compare/v0.4.0...HEAD
|
|
66
|
+
[0.4.0]: https://github.com/kerolt/pi-one-ui/compare/v0.3.1...v0.4.0
|
|
67
|
+
[0.3.1]: https://github.com/kerolt/pi-one-ui/compare/v0.3.0...v0.3.1
|
|
38
68
|
[0.3.0]: https://github.com/kerolt/pi-one-ui/compare/v0.2.2...v0.3.0
|
|
39
69
|
[0.2.2]: https://github.com/kerolt/pi-one-ui/compare/v0.2.1...v0.2.2
|
package/README.en.md
CHANGED
|
@@ -25,23 +25,24 @@ Header → Context → WorkingLine → Editor → Footer
|
|
|
25
25
|
|
|
26
26
|
- **Header**: startup information, logo, and shortcut hints.
|
|
27
27
|
- **Context**: the conversation area, including user messages, assistant messages, thinking, tools, diffs, Markdown, and summaries.
|
|
28
|
-
- **WorkingLine**: working state, spinner, token/thought/elapsed information, and turn summaries.
|
|
29
|
-
- **Editor**: input editor, completion, metadata,
|
|
28
|
+
- **WorkingLine**: working state, spinner, token/thought/elapsed information, live output rate, and turn summaries.
|
|
29
|
+
- **Editor**: input editor, completion, metadata, and the Opencode and Minimalist styles.
|
|
30
30
|
- **Footer**: current directory, Git, runtime, token, cost, and extension status information.
|
|
31
31
|
- **Overlay**: temporary interfaces such as the settings panel and Context Inspector, managed by a shared OverlayManager.
|
|
32
32
|
|
|
33
33
|
### Built-in functionality
|
|
34
34
|
|
|
35
|
-
| Feature
|
|
36
|
-
|
|
|
37
|
-
| Unified settings panel | Organizes settings by Header, Context, WorkingLine, Editor, Footer, and Features
|
|
38
|
-
| Context Inspector
|
|
39
|
-
| Session reference
|
|
40
|
-
| Subagent autocomplete
|
|
41
|
-
| Tool / Diff renderer
|
|
42
|
-
|
|
|
43
|
-
|
|
|
44
|
-
|
|
|
35
|
+
| Feature | Description | Entry point |
|
|
36
|
+
| ---------------------- | ------------------------------------------------------------------------------------------- | ----------------- |
|
|
37
|
+
| Unified settings panel | Organizes settings by Header, Context, WorkingLine, Editor, Footer, and Features | `/oneui` |
|
|
38
|
+
| Context Inspector | Shows context usage and previews the system prompt, memory, skills, tools, and messages | `/context` |
|
|
39
|
+
| Session reference | Searches previous Pi sessions or SubAgents and injects their useful context | `@` completion |
|
|
40
|
+
| Subagent autocomplete | Completes SubAgent names and delegation hints | `@` completion |
|
|
41
|
+
| Tool / Diff renderer | Provides unified rendering for tool calls, results, collapsed content, and Edit/Write diffs | Automatic |
|
|
42
|
+
| Subagent live renderer | Preserves pi-subagents' dedicated progress cards and keeps them out of generic tool groups | Automatic |
|
|
43
|
+
| Markdown enhancement | Adds Mermaid, admonitions, URL linking, and related rendering improvements | Automatic |
|
|
44
|
+
| Built-in themes | Provides CC Dark and CC Light themes | `/theme` |
|
|
45
|
+
| Compatibility aliases | Optionally provides common command aliases | `/clear`, `/exit` |
|
|
45
46
|
|
|
46
47
|
## Quick start
|
|
47
48
|
|
|
@@ -82,7 +83,7 @@ The configuration file is located at:
|
|
|
82
83
|
~/.pi/agent/pi-one-ui.json
|
|
83
84
|
```
|
|
84
85
|
|
|
85
|
-
Using the `/oneui` settings panel is recommended. The current configuration uses the v1 structure, for example:
|
|
86
|
+
Using the `/oneui` settings panel is recommended. The panel uses a top-centered layout, stays open while Editor enablement or style changes are applied, restores focus after Editor replacement, and restores the effective list value when persistence fails. The current configuration uses the v1 structure, for example:
|
|
86
87
|
|
|
87
88
|
```json
|
|
88
89
|
{
|
|
@@ -110,6 +111,10 @@ Using the `/oneui` settings panel is recommended. The current configuration uses
|
|
|
110
111
|
}
|
|
111
112
|
```
|
|
112
113
|
|
|
114
|
+
The Editor now supports only the `opencode` and `minimalist` styles. `minimalist` no longer duplicates context-usage information; context percentage, token totals, thresholds, gauges, and related presentation are configured through Footer. Existing configurations that select the removed `opencode-copy-friendly` or `accent-rail` styles safely fall back to the default `opencode`, and their old nested style settings are ignored.
|
|
115
|
+
|
|
116
|
+
The WorkingLine token segment appends live output throughput, such as `⚡12 tok/s`, after a model response has run for at least 500ms. Throughput is calculated independently for the current response and resets on the next `turn_start`; disabling the token segment hides it as well.
|
|
117
|
+
|
|
113
118
|
Available layout and renderer options may change between versions, so prefer configuring them through `/oneui`.
|
|
114
119
|
|
|
115
120
|
### Canonical configuration policy
|
|
@@ -126,9 +131,9 @@ It does not automatically read, merge, or migrate historical configuration files
|
|
|
126
131
|
|
|
127
132
|
`pi-one-ui` originally combined source from the following open-source projects. Many thanks to their maintainers and contributors for providing the initial foundation.
|
|
128
133
|
|
|
129
|
-
| Upstream project
|
|
130
|
-
|
|
|
131
|
-
| [pi-zentui](https://github.com/lmilojevicc/pi-zentui)
|
|
134
|
+
| Upstream project | Capabilities incorporated into `pi-one-ui` | Reference baseline |
|
|
135
|
+
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------- |
|
|
136
|
+
| [pi-zentui](https://github.com/lmilojevicc/pi-zentui) | Starship-style Footer, Opencode-style Editor, layouts, and shell capabilities | v0.21.0, commit `5341b38` |
|
|
132
137
|
| [pi-cc-extensions](https://github.com/minuque/pi-cc-extensions) | Claude Code-style Context renderer, Tool/Diff rendering, Context Inspector, and references | v0.8.67, commit `dba37e5` |
|
|
133
138
|
|
|
134
139
|
Production code lives in `extensions/`. The project has since unified its entry point, configuration storage, lifecycle, layout ownership, overlays, and input routing. The current implementation is no longer equivalent to either upstream project and does not automatically track upstream changes.
|
|
@@ -177,18 +182,16 @@ After changing the source, run the following command in Pi:
|
|
|
177
182
|
|
|
178
183
|
### Development commands
|
|
179
184
|
|
|
180
|
-
| Command
|
|
181
|
-
|
|
|
182
|
-
| `npm install`
|
|
183
|
-
| `npm run format`
|
|
184
|
-
| `npm run
|
|
185
|
-
| `npm run
|
|
186
|
-
| `npm run typecheck`
|
|
187
|
-
| `npm test`
|
|
188
|
-
| `npm run
|
|
189
|
-
| `npm run
|
|
190
|
-
| `npm run pack:check` | Preview the npm package contents |
|
|
191
|
-
| `npm run verify` | Run formatting, lint, type checking, and all tests |
|
|
185
|
+
| Command | Purpose |
|
|
186
|
+
| -------------------- | ---------------------------------------------- |
|
|
187
|
+
| `npm install` | Install dependencies |
|
|
188
|
+
| `npm run format` | Format source, tests, and configuration files |
|
|
189
|
+
| `npm run check` | Check formatting and import organization |
|
|
190
|
+
| `npm run fix` | Fix formatting and organize imports |
|
|
191
|
+
| `npm run typecheck` | Run TypeScript type checking |
|
|
192
|
+
| `npm test` | Run all tests with Vitest |
|
|
193
|
+
| `npm run pack:check` | Preview the npm package contents |
|
|
194
|
+
| `npm run verify` | Run Biome checks, type checking, and all tests |
|
|
192
195
|
|
|
193
196
|
Before submitting changes, run at least:
|
|
194
197
|
|
|
@@ -199,14 +202,15 @@ npm run pack:check
|
|
|
199
202
|
|
|
200
203
|
### Test organization
|
|
201
204
|
|
|
202
|
-
|
|
205
|
+
All tests run through Vitest and are organized into domain directories:
|
|
203
206
|
|
|
204
|
-
- `tests/
|
|
205
|
-
- `tests/
|
|
206
|
-
- `tests/editor
|
|
207
|
-
- `tests/
|
|
208
|
-
- `tests/services
|
|
209
|
-
- `tests/shell
|
|
207
|
+
- `tests/config/`: canonical configuration, storage, and compatibility boundaries.
|
|
208
|
+
- `tests/context/`: Context content, tools, diffs, thinking, and mouse interaction.
|
|
209
|
+
- `tests/header/`, `tests/working-line/`, `tests/editor/`, and `tests/footer/`: Layout behavior and lifecycle coverage.
|
|
210
|
+
- `tests/runtime/`, `tests/overlay/`, and `tests/integration/`: runtime infrastructure, overlays, and the composed entry point.
|
|
211
|
+
- `tests/services/`: Git, runtime, project, session, and telemetry data.
|
|
212
|
+
- `tests/shell/`: remaining layout lifecycle glue and standalone compatibility.
|
|
213
|
+
- `tests/support/` and `tests/fixtures/`: shared test helpers and fixtures.
|
|
210
214
|
|
|
211
215
|
Changes involving the TUI lifecycle should specifically cover reloads, session tree rebuilds, compaction, regular/fullscreen TUI modes, headless mode, overlays, and third-party patch ownership.
|
|
212
216
|
|
package/README.md
CHANGED
|
@@ -25,8 +25,8 @@ Header → Context → WorkingLine → Editor → Footer
|
|
|
25
25
|
|
|
26
26
|
- **Header**:启动信息、Logo 和快捷键提示。
|
|
27
27
|
- **Context**:对话内容区,包含用户消息、Assistant 消息、Thinking、Tool、Diff、Markdown 和 Summary。
|
|
28
|
-
- **WorkingLine**:工作状态、spinner、token/thought/elapsed
|
|
29
|
-
- **Editor**:输入编辑器、completion、metadata
|
|
28
|
+
- **WorkingLine**:工作状态、spinner、token/thought/elapsed、实时输出速率和回合摘要。
|
|
29
|
+
- **Editor**:输入编辑器、completion、metadata,以及 Opencode 和 Minimalist 样式。
|
|
30
30
|
- **Footer**:目录、Git、runtime、token、cost 和扩展状态等信息。
|
|
31
31
|
- **Overlay**:设置面板、Context Inspector 等临时浮层由统一的 OverlayManager 管理。
|
|
32
32
|
|
|
@@ -39,6 +39,7 @@ Header → Context → WorkingLine → Editor → Footer
|
|
|
39
39
|
| Session reference | 搜索并注入历史 Pi session 或 SubAgent 的有效上下文 | `@` 补全 |
|
|
40
40
|
| Subagent autocomplete | 提供 SubAgent 名称补全和委派提示 | `@` 补全 |
|
|
41
41
|
| Tool / Diff renderer | 工具调用、结果、折叠内容和 Edit/Write diff 的统一展示 | 自动生效 |
|
|
42
|
+
| Subagent live renderer | 保留 pi-subagents 专用进度卡,并避免纳入通用工具分组 | 自动生效 |
|
|
42
43
|
| Markdown enhancement | 支持 Mermaid、提示框和 URL 链接化等增强渲染 | 自动生效 |
|
|
43
44
|
| Built-in themes | 提供 CC Dark 和 CC Light 主题 | `/theme` |
|
|
44
45
|
| Compatibility aliases | 可选提供常用命令别名 | `/clear`、`/exit` |
|
|
@@ -82,7 +83,7 @@ pi install git:github.com/kerolt/pi-one-ui
|
|
|
82
83
|
~/.pi/agent/pi-one-ui.json
|
|
83
84
|
```
|
|
84
85
|
|
|
85
|
-
推荐通过 `/oneui`
|
|
86
|
+
推荐通过 `/oneui` 设置面板修改配置。面板采用更靠近顶部的居中布局;切换 Editor 启用状态或样式时会保持打开并在 Editor 替换后恢复焦点,持久化失败时则恢复列表中的有效旧值。当前配置仍使用 v1 结构,例如:
|
|
86
87
|
|
|
87
88
|
```json
|
|
88
89
|
{
|
|
@@ -110,6 +111,10 @@ pi install git:github.com/kerolt/pi-one-ui
|
|
|
110
111
|
}
|
|
111
112
|
```
|
|
112
113
|
|
|
114
|
+
Editor 当前只支持 `opencode` 和 `minimalist` 两种样式。`minimalist` 不再重复显示上下文占用信息;上下文百分比、token 总量、阈值和 gauge 等展示统一由 Footer 配置。已有配置若选择了已移除的 `opencode-copy-friendly` 或 `accent-rail`,运行时会安全回退到默认的 `opencode`,相应的旧嵌套样式配置会被忽略。
|
|
115
|
+
|
|
116
|
+
WorkingLine 的 token segment 会在一次模型响应持续至少 500ms 后追加实时输出速率,例如 `⚡12 tok/s`。速率按当前响应独立计算,在下一次 `turn_start` 时重置;关闭 token segment 时也会一并隐藏。
|
|
117
|
+
|
|
113
118
|
不同布局和渲染器的可用选项会随版本变化,建议优先使用 `/oneui` 面板进行配置。
|
|
114
119
|
|
|
115
120
|
### Canonical 配置约定
|
|
@@ -181,14 +186,12 @@ npm run pi:install-local
|
|
|
181
186
|
| ---------------------- | ---------------------------------- |
|
|
182
187
|
| `npm install` | 安装依赖 |
|
|
183
188
|
| `npm run format` | 格式化源码、测试和配置文件 |
|
|
184
|
-
| `npm run
|
|
185
|
-
| `npm run
|
|
189
|
+
| `npm run check` | 检查格式和 import organization |
|
|
190
|
+
| `npm run fix` | 修复格式并整理 imports |
|
|
186
191
|
| `npm run typecheck` | 执行 TypeScript 类型检查 |
|
|
187
|
-
| `npm test` | 运行全部测试
|
|
188
|
-
| `npm run test:node` | 运行 Node.js test runner 测试 |
|
|
189
|
-
| `npm run test:vitest` | 运行 Vitest 测试 |
|
|
192
|
+
| `npm test` | 使用 Vitest 运行全部测试 |
|
|
190
193
|
| `npm run pack:check` | 预览 npm 实际打包内容 |
|
|
191
|
-
| `npm run verify` |
|
|
194
|
+
| `npm run verify` | 执行 Biome check、类型检查和全部测试 |
|
|
192
195
|
|
|
193
196
|
提交修改前建议至少运行:
|
|
194
197
|
|
|
@@ -199,14 +202,15 @@ npm run pack:check
|
|
|
199
202
|
|
|
200
203
|
### 测试组织
|
|
201
204
|
|
|
202
|
-
|
|
205
|
+
所有测试统一由 Vitest 执行,并按照功能领域组织在子目录中:
|
|
203
206
|
|
|
204
|
-
- `tests/
|
|
205
|
-
- `tests/
|
|
206
|
-
- `tests/editor
|
|
207
|
-
- `tests/
|
|
208
|
-
- `tests/services
|
|
209
|
-
- `tests/shell
|
|
207
|
+
- `tests/config/`:canonical 配置、存储和兼容性边界。
|
|
208
|
+
- `tests/context/`:Context 内容区、Tool、Diff、Thinking 和鼠标交互。
|
|
209
|
+
- `tests/header/`、`tests/working-line/`、`tests/editor/`、`tests/footer/`:各 Layout 的行为和生命周期。
|
|
210
|
+
- `tests/runtime/`、`tests/overlay/`、`tests/integration/`:运行时基础设施、Overlay 和组合入口。
|
|
211
|
+
- `tests/services/`:Git、runtime、project、session 和 telemetry。
|
|
212
|
+
- `tests/shell/`:剩余布局生命周期 glue 和 standalone compatibility。
|
|
213
|
+
- `tests/support/`、`tests/fixtures/`:共享测试工具和 fixtures。
|
|
210
214
|
|
|
211
215
|
涉及 TUI 生命周期的修改,应特别覆盖 reload、session tree rebuild、compact、regular/fullscreen TUI、headless mode、overlay 和第三方 patch ownership 等场景。
|
|
212
216
|
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
3
|
-
import {
|
|
4
|
-
import type { PolishedTuiConfig } from "../config/shell.ts";
|
|
3
|
+
import { renderUserMessageStyle } from "../../layouts/context/message/user-message-styles.ts";
|
|
5
4
|
import { sanitizeEditorMetadataText } from "../../layouts/editor/editor-metadata-format.ts";
|
|
6
5
|
import { renderMinimalistFrame } from "../../layouts/editor/minimalist-editor.ts";
|
|
7
|
-
import { safeThemeFg } from "../../shared/style.ts";
|
|
8
6
|
import { renderPolishedEditorFrame } from "../../layouts/editor/ui.ts";
|
|
9
|
-
import {
|
|
7
|
+
import { safeThemeFg } from "../../shared/style.ts";
|
|
8
|
+
import type { PolishedTuiConfig } from "../config/shell.ts";
|
|
10
9
|
|
|
11
10
|
export const SETTINGS_PREVIEW_MAX_WIDTH = 72;
|
|
12
11
|
export const SETTINGS_PREVIEW_MAX_ROWS = 10;
|
|
@@ -61,16 +60,7 @@ export function renderEditorSettingsPreview(
|
|
|
61
60
|
? { above: "2", below: "3" }
|
|
62
61
|
: undefined;
|
|
63
62
|
let frame: string[];
|
|
64
|
-
if (editor.style === "
|
|
65
|
-
frame = renderAccentRailEditorFrame({
|
|
66
|
-
width: previewWidth,
|
|
67
|
-
editorLines,
|
|
68
|
-
autocompleteLines,
|
|
69
|
-
viewport,
|
|
70
|
-
uiTheme: theme,
|
|
71
|
-
config: safeConfig,
|
|
72
|
-
});
|
|
73
|
-
} else if (editor.style === "minimalist") {
|
|
63
|
+
if (editor.style === "minimalist") {
|
|
74
64
|
frame = renderMinimalistFrame({
|
|
75
65
|
width: previewWidth,
|
|
76
66
|
editorLines,
|
|
@@ -86,8 +76,6 @@ export function renderEditorSettingsPreview(
|
|
|
86
76
|
costLabel: "$.12",
|
|
87
77
|
modelLabel,
|
|
88
78
|
thinkingLevel: "high",
|
|
89
|
-
contextPercent: 75,
|
|
90
|
-
contextWindow: 372_000,
|
|
91
79
|
sessionName: "Preview",
|
|
92
80
|
agentDurationMs: 12_000,
|
|
93
81
|
agentActive: true,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CompactThinkingConfig } from "../../layouts/context/thinking/compact-thinking.ts";
|
|
2
|
-
import {
|
|
2
|
+
import { type ConfigRecord, configStore } from "./store.ts";
|
|
3
3
|
|
|
4
4
|
export type CompactStyleMode = "on" | "compact" | "off";
|
|
5
5
|
|
|
@@ -371,17 +371,18 @@ function loadConfig(): Config {
|
|
|
371
371
|
/**
|
|
372
372
|
* Persists the in-memory renderer projection through the shared store.
|
|
373
373
|
*/
|
|
374
|
-
export function saveConfig() {
|
|
374
|
+
export function saveConfig(next: Config = config) {
|
|
375
375
|
configStore.update((record) => {
|
|
376
376
|
record.version = 1;
|
|
377
|
-
record.renderer =
|
|
377
|
+
record.renderer = next;
|
|
378
378
|
});
|
|
379
379
|
}
|
|
380
380
|
|
|
381
|
-
/**
|
|
381
|
+
/** 运行时配置写入的唯一入口:规范化并持久化成功后再提交到活动配置。 */
|
|
382
382
|
export function updateConfig(partial: Partial<Config>): void {
|
|
383
|
-
|
|
384
|
-
saveConfig();
|
|
383
|
+
const next = normalizeConfig({ ...config, ...partial });
|
|
384
|
+
saveConfig(next);
|
|
385
|
+
Object.assign(config, next);
|
|
385
386
|
}
|
|
386
387
|
|
|
387
388
|
/** 整体替换配置(default export 的 configOverride 注入路径;就地覆盖,不持久化)。 */
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { normalizeWorkingLineMessages } from "../../layouts/working-line/working-line.ts";
|
|
2
|
+
import { PI_WORKING_LINE_MESSAGES } from "../../layouts/working-line/working-line-messages.ts";
|
|
1
3
|
import {
|
|
2
4
|
ICON_GLYPH_KEYS,
|
|
3
5
|
type IconGlyphs,
|
|
@@ -8,13 +10,11 @@ import {
|
|
|
8
10
|
resolveConfiguredIcons,
|
|
9
11
|
} from "../../shared/icons.ts";
|
|
10
12
|
import { isSupportedColorSpec } from "../../shared/style.ts";
|
|
11
|
-
import { normalizeWorkingLineMessages } from "../../layouts/working-line/working-line.ts";
|
|
12
|
-
import { PI_WORKING_LINE_MESSAGES } from "../../layouts/working-line/working-line-messages.ts";
|
|
13
13
|
import {
|
|
14
|
-
|
|
14
|
+
type ConfigRecord,
|
|
15
15
|
configStore,
|
|
16
|
+
configPath as defaultConfigPath,
|
|
16
17
|
mutateConfigFile,
|
|
17
|
-
type ConfigRecord,
|
|
18
18
|
} from "./store.ts";
|
|
19
19
|
|
|
20
20
|
export type ColorSpec = string;
|
|
@@ -24,11 +24,7 @@ export type { IconMode } from "../../shared/icons.ts";
|
|
|
24
24
|
export type ContextStyle = "text" | "gauge" | "text+gauge";
|
|
25
25
|
export type SeparatorStyle = "pipe" | "dot" | "chevron" | "none";
|
|
26
26
|
export type ModelLabelSource = "id" | "name";
|
|
27
|
-
export type EditorStyle =
|
|
28
|
-
| "opencode"
|
|
29
|
-
| "opencode-copy-friendly"
|
|
30
|
-
| "accent-rail"
|
|
31
|
-
| "minimalist";
|
|
27
|
+
export type EditorStyle = "opencode" | "minimalist";
|
|
32
28
|
export type UserMessageStyle =
|
|
33
29
|
| "framed"
|
|
34
30
|
| "framed-copy-friendly"
|
|
@@ -49,7 +45,6 @@ export type ComponentStyleOwner =
|
|
|
49
45
|
| "selectorBorders"
|
|
50
46
|
| "footer";
|
|
51
47
|
export type MinimalistPathDisplayMode = "compact" | "project" | "full";
|
|
52
|
-
export type MinimalistContextFormat = "percent" | "percent-total";
|
|
53
48
|
export type EditorBorderColorMode = "static" | "adaptive";
|
|
54
49
|
export type CompletionMenuStyle = "native" | "palette";
|
|
55
50
|
export type CompactFooterMaxLines = 1 | 2 | 3 | "unlimited";
|
|
@@ -113,26 +108,12 @@ export type PolishedEditorStyleConfig = {
|
|
|
113
108
|
completionMenu: CompletionMenuStyle;
|
|
114
109
|
};
|
|
115
110
|
|
|
116
|
-
export type PolishedCopyFriendlyEditorStyleConfig = {
|
|
117
|
-
metadataFormat: string;
|
|
118
|
-
completionMenu: CompletionMenuStyle;
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
export type AccentRailEditorStyleConfig = {
|
|
122
|
-
rail: string;
|
|
123
|
-
asciiRail: string;
|
|
124
|
-
transparent: boolean;
|
|
125
|
-
};
|
|
126
|
-
|
|
127
111
|
export type MinimalistEditorStyleConfig = {
|
|
128
112
|
pathDisplay: MinimalistPathDisplayMode;
|
|
129
|
-
contextFormat: MinimalistContextFormat;
|
|
130
|
-
contextGauge: boolean;
|
|
131
113
|
showSessionName: boolean;
|
|
132
114
|
showTimer: boolean;
|
|
133
115
|
showCost: boolean;
|
|
134
116
|
showGit: boolean;
|
|
135
|
-
contextThresholds: ContextThresholds;
|
|
136
117
|
};
|
|
137
118
|
|
|
138
119
|
/** Temporary name retained for existing settings consumers. */
|
|
@@ -151,8 +132,6 @@ export type EditorComponentConfig = {
|
|
|
151
132
|
viewportIndicators: boolean;
|
|
152
133
|
styles: {
|
|
153
134
|
opencode: PolishedEditorStyleConfig;
|
|
154
|
-
"opencode-copy-friendly": PolishedCopyFriendlyEditorStyleConfig;
|
|
155
|
-
"accent-rail": AccentRailEditorStyleConfig;
|
|
156
135
|
minimalist: MinimalistEditorStyleConfig;
|
|
157
136
|
};
|
|
158
137
|
};
|
|
@@ -323,8 +302,6 @@ export type PolishedTuiColors = {
|
|
|
323
302
|
time: ColorSpec;
|
|
324
303
|
os: ColorSpec;
|
|
325
304
|
editorAccent?: ColorSpec;
|
|
326
|
-
editorRail?: ColorSpec;
|
|
327
|
-
editorPrompt?: ColorSpec;
|
|
328
305
|
editorBorder?: ColorSpec;
|
|
329
306
|
editorGitBranch?: ColorSpec;
|
|
330
307
|
editorModel?: ColorSpec;
|
|
@@ -439,21 +416,12 @@ const defaultFooterSegments: FooterSegmentsConfig = {
|
|
|
439
416
|
|
|
440
417
|
const DEFAULT_COMPLETION_MENU: CompletionMenuStyle = "palette";
|
|
441
418
|
|
|
442
|
-
const defaultAccentRailStyle: AccentRailEditorStyleConfig = {
|
|
443
|
-
rail: "▎",
|
|
444
|
-
asciiRail: "|",
|
|
445
|
-
transparent: false,
|
|
446
|
-
};
|
|
447
|
-
|
|
448
419
|
const defaultMinimalistStyle: MinimalistEditorStyleConfig = {
|
|
449
420
|
pathDisplay: "compact",
|
|
450
|
-
contextFormat: "percent",
|
|
451
|
-
contextGauge: false,
|
|
452
421
|
showSessionName: true,
|
|
453
422
|
showTimer: true,
|
|
454
423
|
showCost: true,
|
|
455
424
|
showGit: true,
|
|
456
|
-
contextThresholds: { warning: 70, error: 90 },
|
|
457
425
|
};
|
|
458
426
|
|
|
459
427
|
const defaultStarshipStyle: StarshipFooterStyleConfig = {
|
|
@@ -489,11 +457,6 @@ const defaultComponents: ComponentsConfig = {
|
|
|
489
457
|
metadataFormat: DEFAULT_EDITOR_METADATA_FORMAT,
|
|
490
458
|
completionMenu: DEFAULT_COMPLETION_MENU,
|
|
491
459
|
},
|
|
492
|
-
"opencode-copy-friendly": {
|
|
493
|
-
metadataFormat: DEFAULT_EDITOR_METADATA_FORMAT,
|
|
494
|
-
completionMenu: DEFAULT_COMPLETION_MENU,
|
|
495
|
-
},
|
|
496
|
-
"accent-rail": defaultAccentRailStyle,
|
|
497
460
|
minimalist: defaultMinimalistStyle,
|
|
498
461
|
},
|
|
499
462
|
},
|
|
@@ -615,14 +578,7 @@ function parseEditorModelLabel(
|
|
|
615
578
|
}
|
|
616
579
|
|
|
617
580
|
function parseEditorStyle(value: unknown): EditorStyle {
|
|
618
|
-
if (
|
|
619
|
-
value === "opencode" ||
|
|
620
|
-
value === "opencode-copy-friendly" ||
|
|
621
|
-
value === "accent-rail" ||
|
|
622
|
-
value === "minimalist"
|
|
623
|
-
) {
|
|
624
|
-
return value;
|
|
625
|
-
}
|
|
581
|
+
if (value === "opencode" || value === "minimalist") return value;
|
|
626
582
|
return defaultComponents.editor.style;
|
|
627
583
|
}
|
|
628
584
|
|
|
@@ -775,8 +731,6 @@ function normalizeColors(
|
|
|
775
731
|
time: colorValue(record, "time"),
|
|
776
732
|
os: colorValue(record, "os"),
|
|
777
733
|
editorAccent: colorValue(record, "editorAccent"),
|
|
778
|
-
editorRail: colorValue(record, "editorRail"),
|
|
779
|
-
editorPrompt: colorValue(record, "editorPrompt"),
|
|
780
734
|
editorBorder: colorValue(record, "editorBorder"),
|
|
781
735
|
editorGitBranch: colorValue(record, "editorGitBranch"),
|
|
782
736
|
editorModel: colorValue(record, "editorModel"),
|
|
@@ -1074,10 +1028,6 @@ function resolveComponents(config: ConfigRecord): ComponentsConfig {
|
|
|
1074
1028
|
const editor = recordValue(components.editor);
|
|
1075
1029
|
const editorStyles = recordValue(editor.styles);
|
|
1076
1030
|
const opencode = recordValue(editorStyles.opencode);
|
|
1077
|
-
const opencodeCopyFriendly = recordValue(
|
|
1078
|
-
editorStyles["opencode-copy-friendly"],
|
|
1079
|
-
);
|
|
1080
|
-
const accentRail = recordValue(editorStyles["accent-rail"]);
|
|
1081
1031
|
const minimalist = recordValue(editorStyles.minimalist);
|
|
1082
1032
|
const userMessages = recordValue(components.userMessages);
|
|
1083
1033
|
const workingLine = recordValue(components.workingLine);
|
|
@@ -1113,29 +1063,6 @@ function resolveComponents(config: ConfigRecord): ComponentsConfig {
|
|
|
1113
1063
|
),
|
|
1114
1064
|
completionMenu: parseCompletionMenuStyle(opencode.completionMenu),
|
|
1115
1065
|
},
|
|
1116
|
-
"opencode-copy-friendly": {
|
|
1117
|
-
metadataFormat: parseNonEmptyString(
|
|
1118
|
-
opencodeCopyFriendly.metadataFormat,
|
|
1119
|
-
DEFAULT_EDITOR_METADATA_FORMAT,
|
|
1120
|
-
),
|
|
1121
|
-
completionMenu: parseCompletionMenuStyle(
|
|
1122
|
-
opencodeCopyFriendly.completionMenu,
|
|
1123
|
-
),
|
|
1124
|
-
},
|
|
1125
|
-
"accent-rail": {
|
|
1126
|
-
rail: parseNonEmptyString(
|
|
1127
|
-
accentRail.rail,
|
|
1128
|
-
defaultAccentRailStyle.rail,
|
|
1129
|
-
),
|
|
1130
|
-
asciiRail: parseNonEmptyString(
|
|
1131
|
-
accentRail.asciiRail,
|
|
1132
|
-
defaultAccentRailStyle.asciiRail,
|
|
1133
|
-
),
|
|
1134
|
-
transparent: parseBoolean(
|
|
1135
|
-
accentRail.transparent,
|
|
1136
|
-
defaultAccentRailStyle.transparent,
|
|
1137
|
-
),
|
|
1138
|
-
},
|
|
1139
1066
|
minimalist: {
|
|
1140
1067
|
pathDisplay:
|
|
1141
1068
|
minimalist.pathDisplay === "compact" ||
|
|
@@ -1143,15 +1070,6 @@ function resolveComponents(config: ConfigRecord): ComponentsConfig {
|
|
|
1143
1070
|
minimalist.pathDisplay === "full"
|
|
1144
1071
|
? minimalist.pathDisplay
|
|
1145
1072
|
: defaultMinimalistStyle.pathDisplay,
|
|
1146
|
-
contextFormat:
|
|
1147
|
-
minimalist.contextFormat === "percent" ||
|
|
1148
|
-
minimalist.contextFormat === "percent-total"
|
|
1149
|
-
? minimalist.contextFormat
|
|
1150
|
-
: defaultMinimalistStyle.contextFormat,
|
|
1151
|
-
contextGauge: parseBoolean(
|
|
1152
|
-
minimalist.contextGauge,
|
|
1153
|
-
defaultMinimalistStyle.contextGauge,
|
|
1154
|
-
),
|
|
1155
1073
|
showSessionName: parseBoolean(
|
|
1156
1074
|
minimalist.showSessionName,
|
|
1157
1075
|
defaultMinimalistStyle.showSessionName,
|
|
@@ -1168,10 +1086,6 @@ function resolveComponents(config: ConfigRecord): ComponentsConfig {
|
|
|
1168
1086
|
minimalist.showGit,
|
|
1169
1087
|
defaultMinimalistStyle.showGit,
|
|
1170
1088
|
),
|
|
1171
|
-
contextThresholds: resolveContextThresholds(
|
|
1172
|
-
minimalist.contextThresholds,
|
|
1173
|
-
defaultMinimalistStyle.contextThresholds,
|
|
1174
|
-
),
|
|
1175
1089
|
},
|
|
1176
1090
|
},
|
|
1177
1091
|
},
|
|
@@ -1349,16 +1263,17 @@ const unsupportedComponentStyles = new WeakMap<
|
|
|
1349
1263
|
ReadonlySet<ComponentStyleOwner>
|
|
1350
1264
|
>();
|
|
1351
1265
|
|
|
1266
|
+
// Retired selections migrate to Opencode instead of disabling the custom Editor.
|
|
1267
|
+
const retiredEditorStyleIds: ReadonlySet<string> = new Set([
|
|
1268
|
+
"opencode-copy-friendly",
|
|
1269
|
+
"accent-rail",
|
|
1270
|
+
]);
|
|
1271
|
+
|
|
1352
1272
|
const knownComponentStyleIds: Record<
|
|
1353
1273
|
ComponentStyleOwner,
|
|
1354
1274
|
ReadonlySet<string>
|
|
1355
1275
|
> = {
|
|
1356
|
-
editor: new Set([
|
|
1357
|
-
"opencode",
|
|
1358
|
-
"opencode-copy-friendly",
|
|
1359
|
-
"accent-rail",
|
|
1360
|
-
"minimalist",
|
|
1361
|
-
]),
|
|
1276
|
+
editor: new Set(["opencode", "minimalist"]),
|
|
1362
1277
|
userMessages: new Set([
|
|
1363
1278
|
"framed",
|
|
1364
1279
|
"framed-copy-friendly",
|
|
@@ -1378,7 +1293,8 @@ function unsupportedSelectedStyleId(
|
|
|
1378
1293
|
const style = component.style;
|
|
1379
1294
|
return typeof style === "string" &&
|
|
1380
1295
|
style.trim() &&
|
|
1381
|
-
!knownComponentStyleIds[owner].has(style)
|
|
1296
|
+
!knownComponentStyleIds[owner].has(style) &&
|
|
1297
|
+
!(owner === "editor" && retiredEditorStyleIds.has(style))
|
|
1382
1298
|
? style
|
|
1383
1299
|
: undefined;
|
|
1384
1300
|
}
|
|
@@ -1580,50 +1496,16 @@ export function savePolishedEditorStylePatch(
|
|
|
1580
1496
|
}, path);
|
|
1581
1497
|
}
|
|
1582
1498
|
|
|
1583
|
-
export function savePolishedCopyFriendlyEditorStylePatch(
|
|
1584
|
-
patch: Partial<PolishedCopyFriendlyEditorStyleConfig>,
|
|
1585
|
-
path = configPath,
|
|
1586
|
-
): PolishedTuiConfig {
|
|
1587
|
-
return saveComponentsMutation((components) => {
|
|
1588
|
-
const style = components.editor.styles["opencode-copy-friendly"];
|
|
1589
|
-
if (patch.metadataFormat !== undefined)
|
|
1590
|
-
style.metadataFormat = patch.metadataFormat;
|
|
1591
|
-
if (patch.completionMenu !== undefined)
|
|
1592
|
-
style.completionMenu = patch.completionMenu;
|
|
1593
|
-
}, path);
|
|
1594
|
-
}
|
|
1595
|
-
|
|
1596
|
-
export function saveAccentRailEditorStylePatch(
|
|
1597
|
-
patch: Partial<AccentRailEditorStyleConfig>,
|
|
1598
|
-
path = configPath,
|
|
1599
|
-
): PolishedTuiConfig {
|
|
1600
|
-
return saveComponentsMutation((components) => {
|
|
1601
|
-
const style = components.editor.styles["accent-rail"];
|
|
1602
|
-
if (patch.rail !== undefined) style.rail = patch.rail;
|
|
1603
|
-
if (patch.asciiRail !== undefined) style.asciiRail = patch.asciiRail;
|
|
1604
|
-
if (patch.transparent !== undefined) style.transparent = patch.transparent;
|
|
1605
|
-
}, path);
|
|
1606
|
-
}
|
|
1607
|
-
|
|
1608
1499
|
function applyMinimalistStylePatch(
|
|
1609
1500
|
style: MinimalistEditorStyleConfig,
|
|
1610
1501
|
patch: Partial<MinimalistEditorStyleConfig>,
|
|
1611
1502
|
): void {
|
|
1612
1503
|
if (patch.pathDisplay !== undefined) style.pathDisplay = patch.pathDisplay;
|
|
1613
|
-
if (patch.contextFormat !== undefined)
|
|
1614
|
-
style.contextFormat = patch.contextFormat;
|
|
1615
|
-
if (patch.contextGauge !== undefined) style.contextGauge = patch.contextGauge;
|
|
1616
1504
|
if (patch.showSessionName !== undefined)
|
|
1617
1505
|
style.showSessionName = patch.showSessionName;
|
|
1618
1506
|
if (patch.showTimer !== undefined) style.showTimer = patch.showTimer;
|
|
1619
1507
|
if (patch.showCost !== undefined) style.showCost = patch.showCost;
|
|
1620
1508
|
if (patch.showGit !== undefined) style.showGit = patch.showGit;
|
|
1621
|
-
if (patch.contextThresholds !== undefined) {
|
|
1622
|
-
style.contextThresholds = {
|
|
1623
|
-
...style.contextThresholds,
|
|
1624
|
-
...patch.contextThresholds,
|
|
1625
|
-
};
|
|
1626
|
-
}
|
|
1627
1509
|
}
|
|
1628
1510
|
|
|
1629
1511
|
export function saveMinimalistEditorStylePatch(
|
|
@@ -1912,10 +1794,6 @@ export function saveContextThresholdsPatch(
|
|
|
1912
1794
|
throw new TypeError("Context thresholds must be JSON-serializable numbers");
|
|
1913
1795
|
}
|
|
1914
1796
|
return saveComponentsMutation((components) => {
|
|
1915
|
-
components.editor.styles.minimalist.contextThresholds = {
|
|
1916
|
-
...components.editor.styles.minimalist.contextThresholds,
|
|
1917
|
-
...thresholds,
|
|
1918
|
-
};
|
|
1919
1797
|
components.footer.styles.starship.contextThresholds = {
|
|
1920
1798
|
...components.footer.styles.starship.contextThresholds,
|
|
1921
1799
|
...thresholds,
|
|
@@ -3,16 +3,16 @@ import {
|
|
|
3
3
|
SettingsSelectorComponent,
|
|
4
4
|
type Theme,
|
|
5
5
|
} from "@earendil-works/pi-coding-agent";
|
|
6
|
-
import type { ZentuiConfig } from "../config/shell.ts";
|
|
7
|
-
import {
|
|
8
|
-
installPrototypePatch,
|
|
9
|
-
removePrototypePatch,
|
|
10
|
-
} from "../ownership/prototype-patch-registry.ts";
|
|
11
6
|
import {
|
|
12
7
|
EDITOR_BORDER_STYLE,
|
|
13
8
|
renderChromeBorder,
|
|
14
9
|
renderEditorBorder,
|
|
15
10
|
} from "../../shared/style.ts";
|
|
11
|
+
import type { ZentuiConfig } from "../config/shell.ts";
|
|
12
|
+
import {
|
|
13
|
+
installPrototypePatch,
|
|
14
|
+
removePrototypePatch,
|
|
15
|
+
} from "../ownership/prototype-patch-registry.ts";
|
|
16
16
|
|
|
17
17
|
type PatchableSelectorPrototype = {
|
|
18
18
|
render: (width: number) => string[];
|