pi-one-ui 0.6.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/CHANGELOG.md CHANGED
@@ -6,6 +6,28 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.7.0] - 2026-09-13
10
+
11
+ ### Added
12
+
13
+ - Added `components.editor.styles.minimalist.showCwd` to independently show or hide the Editor's working-directory label, including the `/oneui` preview. It defaults to `true`, so existing configurations need no migration. Setting it to `false` preserves `pathDisplay` and leaves Git metadata and Footer directory settings unchanged; edit the JSON configuration and run `/reload` to apply it.
14
+
15
+ ### Fixed
16
+
17
+ - Restore keyboard focus to the visible Editor after `/oneui` replaces an editor while changing its settings, including native-to-custom transitions, third-party wrappers, and replacement rollback. Closing the panel no longer sends subsequent typing to the detached previous editor in regular or fullscreen mode; existing overlays and later editor owners retain focus.
18
+
19
+ ### Migration
20
+
21
+ - No configuration migration is required. Existing configurations keep showing the Editor directory; set `components.editor.styles.minimalist.showCwd` to `false` only if you want to hide it. Footer directory settings remain independent.
22
+ - For an unpinned npm installation, run `pi update npm:pi-one-ui`; for an existing version pin, run `pi install npm:pi-one-ui@0.7.0`. Fully exit and restart Pi after updating the package. Subsequent JSON configuration edits can be applied with `/reload`.
23
+
24
+ ## [0.6.1] - 2026-09-06
25
+
26
+ ### Added
27
+
28
+ - Built-in `/effort` command for selecting the thinking effort level (interactive picker, argument autocomplete, and model-clamping feedback), gated by `renderer.enableEffortCommand` (default `true`) and toggleable from the `/oneui` Features section. Replaces the need for a standalone local effort extension — remove any self-installed `/effort` extension to avoid duplicate command registration.
29
+ - The `/oneui` settings panel overlay placement is now configurable via the optional top-level `panel` key in `pi-one-ui.json` (`anchor`, `width`, `maxHeight`, `margin`), replacing the previously hardcoded `top-center`/`85%`/`90%` layout. Invalid values fall back to the defaults, and edits apply the next time the panel opens.
30
+
9
31
  ## [0.6.0] - 2026-09-05
10
32
 
11
33
  ### Removed
@@ -108,7 +130,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
108
130
 
109
131
  - Reduced rendering lag when expanding settled tool groups by reusing cached child output.
110
132
 
111
- [Unreleased]: https://github.com/kerolt/pi-one-ui/compare/v0.6.0...HEAD
133
+ [Unreleased]: https://github.com/kerolt/pi-one-ui/compare/v0.7.0...HEAD
134
+ [0.7.0]: https://github.com/kerolt/pi-one-ui/compare/v0.6.1...v0.7.0
135
+ [0.6.1]: https://github.com/kerolt/pi-one-ui/compare/v0.6.0...v0.6.1
112
136
  [0.6.0]: https://github.com/kerolt/pi-one-ui/compare/v0.5.1...v0.6.0
113
137
  [0.5.1]: https://github.com/kerolt/pi-one-ui/compare/v0.5.0...v0.5.1
114
138
  [0.5.0]: https://github.com/kerolt/pi-one-ui/compare/v0.4.0...v0.5.0
package/README.en.md CHANGED
@@ -6,43 +6,44 @@
6
6
 
7
7
  [简体中文](./README.md) | English
8
8
 
9
- `pi-one-ui` is a unified TUI extension package for [Pi](https://pi.dev). It started as an effort to build a simple and polished terminal interface by combining, at the source level:
9
+ `pi-one-ui` is a unified TUI extension package for [Pi](https://pi.dev), designed to deliver a clean, beautiful, and efficient terminal experience. It originated as a source-level combination of:
10
10
 
11
- - the terminal shell capabilities of [pi-zentui](https://github.com/lmilojevicc/pi-zentui)
11
+ - the terminal shell and layout capabilities of [pi-zentui](https://github.com/lmilojevicc/pi-zentui)
12
12
  - the conversation rendering and productivity features of [pi-cc-extensions](https://github.com/minuque/pi-cc-extensions)
13
13
 
14
- The result is a single installable and configurable Pi package that continues to evolve through module refactoring, tighter ownership, and independent improvements.
14
+ The result is a single installable and configurable Pi package that continues to evolve through architectural refactoring, strict boundary ownership, and ongoing optimization.
15
15
 
16
16
  ## Features
17
17
 
18
18
  ### Unified interface layout
19
19
 
20
- `pi-one-ui` organizes the Pi interface into the following layouts:
20
+ `pi-one-ui` organizes the Pi interface into a clean hierarchy:
21
21
 
22
22
  ```text
23
23
  Header → Context → WorkingLine → Editor → Footer
24
24
  ```
25
25
 
26
- - **Header**: startup information, logo, and shortcut hints.
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, live output rate, and turn summaries.
29
- - **Editor**: input editor, completion, metadata, and the Minimalist style (Pi native is one toggle away).
30
- - **Footer**: current directory, Git, runtime, token, cost, and extension status information.
31
- - **Overlay**: temporary interfaces such as the settings panel and Context Inspector, managed by a shared OverlayManager.
26
+ - **Header**: Startup information, logo, and shortcut hints.
27
+ - **Context**: Conversation content area, including user messages, assistant messages, thinking blocks, tool calls, diffs, Markdown, and turn summaries.
28
+ - **WorkingLine**: Working state indicator, spinner, token/thought/elapsed statistics, live output throughput, and turn summaries.
29
+ - **Editor**: Input editor, completion menu, metadata display, and the Minimalist style (with effortless toggle to Pi native).
30
+ - **Footer**: Current directory, Git status, runtime info, token/cost tracking, and extension statuses.
31
+ - **Overlay**: Temporary views such as the settings panel and Context Inspector, managed centrally by OverlayManager.
32
32
 
33
33
  ### Built-in functionality
34
34
 
35
35
  | Feature | Description | Entry point |
36
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` |
37
+ | Unified settings panel | Centrally manages settings for Header, Context, WorkingLine, Editor, Footer, and Features | `/oneui` |
38
+ | Context Inspector | Shows context usage and previews system prompt, memory, skills, tools, and message contents | `/context` |
39
+ | Session reference | Searches previous Pi sessions or subagents and injects their relevant context | `@` completion |
40
+ | Subagent autocomplete | Provides subagent name completion and delegation hints | `@` completion |
41
+ | Tool / Diff renderer | Unified rendering for tool executions, results, collapsible blocks, and Edit/Write diffs | Automatic |
42
+ | Subagent live renderer | Preserves subagents' dedicated progress cards without grouping them into generic tool calls | Automatic |
43
+ | Markdown enhancement | Adds Mermaid diagrams, admonitions, clickable URL linking, and rendering improvements | Automatic |
44
+ | Built-in themes | Includes CC Dark and CC Light themes | `/theme` |
45
45
  | Compatibility aliases | Optionally provides common command aliases | `/clear`, `/exit` |
46
+ | Effort command | Interactively or directly switch the active model's thinking effort level | `/effort` |
46
47
 
47
48
  ## Quick start
48
49
 
@@ -75,15 +76,38 @@ Then open the unified settings panel:
75
76
  /oneui
76
77
  ```
77
78
 
79
+ ### Upgrading to 0.7.0
80
+
81
+ This release adds an Editor working-directory visibility switch and fixes invisible input after changing Editor settings and closing `/oneui`. Existing configurations need no migration; the directory remains visible by default.
82
+
83
+ For an unpinned npm installation, run:
84
+
85
+ ```bash
86
+ pi update npm:pi-one-ui
87
+ ```
88
+
89
+ If your installation pins a version, run `pi install npm:pi-one-ui@0.7.0` to update the pin. Fully exit and restart Pi after updating the package.
90
+
91
+ To hide the Editor directory, set `components.editor.styles.minimalist.showCwd: false`; Footer directory visibility is configured independently. See the complete example in the [configuration guide](./docs/configuration.md#隐藏-editor-目录在-footer-左侧显示).
92
+
78
93
  ## Configuration
79
94
 
80
- The configuration file is located at:
95
+ ### Configuration methods
96
+
97
+ `pi-one-ui` uses a single canonical v1 configuration file:
81
98
 
82
99
  ```text
83
100
  ~/.pi/agent/pi-one-ui.json
84
101
  ```
85
102
 
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:
103
+ You can configure the extension in two ways:
104
+
105
+ 1. **Interactive settings panel (recommended)**: Run `/oneui` in Pi to adjust common component toggles, styles, and border modes via a visual menu. Changes take effect immediately and are persisted automatically.
106
+ 2. **Direct JSON editing**: Advanced users can edit the JSON configuration file directly for finer-grained control. After saving edits, run `/reload` in Pi to apply changes. When the file does not exist, safe runtime defaults are used in memory.
107
+
108
+ ### Basic configuration example
109
+
110
+ Below is a typical v1 configuration structure:
87
111
 
88
112
  ```json
89
113
  {
@@ -93,52 +117,58 @@ Using the `/oneui` settings panel is recommended. The panel uses a top-centered
93
117
  "style": "on",
94
118
  "borderColorMode": "static"
95
119
  },
96
- "userMessages": {
97
- "enabled": true,
98
- "style": "framed"
120
+ "footer": {
121
+ "style": "starship"
99
122
  },
100
123
  "workingLine": {
101
124
  "enabled": true
102
125
  },
103
- "footer": {
104
- "style": "starship"
126
+ "userMessages": {
127
+ "enabled": true,
128
+ "style": "framed"
105
129
  }
106
130
  },
107
131
  "renderer": {
108
132
  "mode": "on",
109
133
  "diffViewMode": "auto"
134
+ },
135
+ "panel": {
136
+ "anchor": "top-center",
137
+ "width": "85%",
138
+ "maxHeight": "90%",
139
+ "margin": { "top": 6, "right": 1, "bottom": 1, "left": 1 }
110
140
  }
111
141
  }
112
142
  ```
113
143
 
114
- The Editor keeps a single `minimalist` decoration style controlled by `style`: `on` enables the Minimalist decoration, `off` restores Pi's native editor (the border follows the theme and effort coloring by default; when `colors.editorBorder` is explicitly configured, the off mode applies that color through theme semantics, overriding the native effort coloring). Legacy configurations migrate automatically: `enabled: false` becomes `style: "off"`, and `opencode`/`minimalist` become `style: "on"`; the `styles.opencode` block and the retired `opencode-copy-friendly`/`accent-rail` styles are ignored. Colors are always rendered with theme semantics: configured `colors.*` values resolve first as theme tokens (ANSI names such as `red` map to the semantic `error` token), unconfigured fields use the theme's dedicated tokens (`cwd`/`editorModel`/`editorBorder`, possibly referencing `vars`) and fall back to Pi's native defaults when the theme does not define them; fixed terminal colors are still available by writing hex, a 256-color index, or an `fg:`/`bg:` prefix. `borderColorMode` supports `static` (fixed `colors.editorBorder`) and `adaptive` (border uses the per-level `colors.editorThinking*` when configured and otherwise follows Pi's native effort coloring). The legacy `colorSource` field (`theme`/`terminal`) is removed and ignored; existing user files are not rewritten. For the complete color field reference, value syntax, and customization guide, see [docs/editor-colors.md](./docs/editor-colors.md). Context-usage information is presented by Footer.
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.
144
+ ### Advanced configuration & documentation guide
117
145
 
118
- Available layout and renderer options may change between versions, so prefer configuring them through `/oneui`.
146
+ To keep the configuration section clean and focused, in-depth options, template variables, and color references are organized in dedicated documentation:
119
147
 
120
- ### Canonical configuration policy
121
-
122
- `pi-one-ui` reads and writes only:
123
-
124
- ```text
125
- ~/.pi/agent/pi-one-ui.json
126
- ```
127
-
128
- It does not automatically read, merge, or migrate historical configuration files, and it does not parse legacy flat fields or old style identifiers. If the file does not exist, runtime defaults are used in memory. The file is created only after the first settings change through `/oneui`. All persisted changes use the current v1 `components` and `renderer` structure.
148
+ - **Component options & layout customization**: see [Editor & Footer Configuration Guide (docs/configuration.md)](./docs/configuration.md)
149
+ - **Editor**: Configure `style` (`on` for Minimalist decoration / `off` for Pi native), `borderColorMode` (`static` or `adaptive` to thinking effort), `modelLabel`, and granular Minimalist displays (directory visibility and format, session name, timer, cost, Git status, etc.). `components.editor.styles.minimalist.showCwd` (since 0.7.0, default `true`) can hide the directory independently of the Footer; `pathDisplay` continues to select its format.
150
+ - **Footer**: Starship-style layout powered by format templates (`$cwd`, `$git_branch`, `$tokens`, `$cost`, etc.), individual `segments` toggles, customizable separators, and context-usage indicators (gauge or text).
151
+ - **WorkingLine**: Built-in live output throughput tracking (appends e.g. `⚡12 tok/s` when a model response runs for at least 500ms, reset per turn).
152
+ - **Settings panel (`/oneui`) customization**: the optional top-level `panel` section controls the overlay placement and size (all fields default to the values shown in the example above).
153
+ - `anchor`: one of `center`, `top-left`, `top-right`, `bottom-left`, `bottom-right`, `top-center`, `bottom-center`, `left-center`, `right-center`.
154
+ - `width` / `maxHeight`: absolute column/row counts, or percentage strings like `"85%"`.
155
+ - `margin`: distance from the terminal edges — either a single number for all sides, or an object with per-edge `top`/`right`/`bottom`/`left` values.
156
+ - Saved changes apply the next time `/oneui` opens; no `/reload` needed.
157
+ - **Color system & theme customization**: see [Editor Colors Reference (docs/editor-colors.md)](./docs/editor-colors.md)
158
+ - All colors resolve through unified theme semantics. Configured `colors.*` values resolve as theme tokens (adapting automatically across themes), while ANSI names map to semantic tokens (e.g. `red` to `error`). Fixed terminal colors can be specified using hex codes, 256-color indexes, or `fg:`/`bg:` prefixes.
159
+ - Full support for adaptive thinking-effort border colors (from Low to Max) and labels.
160
+ - **Migration from legacy versions**: Field cleanups from 0.5.x/0.6.0 (such as merging `opencode` into `minimalist`, or removing `colorSource`) are covered in [docs/configuration.md: Changes and Migration](./docs/configuration.md#6-变更与迁移).
129
161
 
130
162
  ## Upstream origins and project evolution
131
163
 
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.
164
+ `pi-one-ui` was originally built upon source code from two open-source projects. We express our sincere appreciation to both upstream projects and their contributors:
133
165
 
134
166
  | Upstream project | Capabilities incorporated into `pi-one-ui` | Reference baseline |
135
167
  | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------- |
136
- | [pi-zentui](https://github.com/lmilojevicc/pi-zentui) | Starship-style Footer, Opencode-style Editor, layouts, and shell capabilities | v0.21.0, commit `5341b38` |
168
+ | [pi-zentui](https://github.com/lmilojevicc/pi-zentui) | Starship-style Footer, Editor layouts, and shell interaction capabilities | v0.21.0, commit `5341b38` |
137
169
  | [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` |
138
170
 
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.
140
-
141
- The upstream projects provided the original foundation. Continued development focuses on turning these capabilities into one coherent product with clear seams and sustainable maintenance.
171
+ Production code lives in `extensions/`. `pi-one-ui` has unified the composition entry point, configuration storage, lifecycle management, layout ownership, overlay orchestration, and input routing. The project now evolves independently and no longer tracks upstream changes directly.
142
172
 
143
173
  See [ARCHITECTURE.md](./ARCHITECTURE.md) for detailed module boundaries, event flow, and ownership conventions.
144
174
 
package/README.md CHANGED
@@ -6,43 +6,44 @@
6
6
 
7
7
  简体中文 | [English](./README.en.md)
8
8
 
9
- `pi-one-ui` 是一个面向 [Pi](https://pi.dev) 的统一 TUI 扩展包。项目的初衷是希望打造一个简单美观的 TUI 界面,最初通过源码级融合,将:
9
+ `pi-one-ui` 是面向 [Pi](https://pi.dev) 的统一 TUI 扩展包,旨在打造简洁、美观且高效的终端交互界面。项目最初通过源码级融合,将:
10
10
 
11
- - [pi-zentui](https://github.com/lmilojevicc/pi-zentui)`pi-zentui` 的终端外壳能力
11
+ - [pi-zentui](https://github.com/lmilojevicc/pi-zentui) 的终端外壳与布局能力
12
12
  - [pi-cc-extensions](https://github.com/minuque/pi-cc-extensions) 的对话内容渲染及生产力功能
13
13
 
14
- 整合到同一个可安装、可配置的 Pi package 中,并在此基础上持续进行模块重构、职责收敛和独立优化。
14
+ 整合为开箱即用、统一可配置的单一扩展包,并在此基础上持续进行模块重构、职责收敛和体验优化。
15
15
 
16
16
  ## 特性
17
17
 
18
18
  ### 统一的界面布局
19
19
 
20
- `pi-one-ui` 将 Pi 的交互界面划分为以下布局:
20
+ `pi-one-ui` 将 Pi 的交互界面划分为以下布局层级:
21
21
 
22
22
  ```text
23
23
  Header → Context → WorkingLine → Editor → Footer
24
24
  ```
25
25
 
26
26
  - **Header**:启动信息、Logo 和快捷键提示。
27
- - **Context**:对话内容区,包含用户消息、Assistant 消息、Thinking、Tool、Diff、Markdown 和 Summary。
28
- - **WorkingLine**:工作状态、spinner、token/thought/elapsed、实时输出速率和回合摘要。
29
- - **Editor**:输入编辑器、completion、metadata,以及 Minimalist 样式(可切换 Pi 原生)。
30
- - **Footer**:目录、Git、runtime、token、cost 和扩展状态等信息。
31
- - **Overlay**:设置面板、Context Inspector 等临时浮层由统一的 OverlayManager 管理。
27
+ - **Context**:对话内容区,包含用户消息、Assistant 消息、Thinking 思考过程、Tool 执行、Diff 对比、Markdown 及回合摘要。
28
+ - **WorkingLine**:工作状态指示、Spinner、Token/思考时长统计、实时吞吐速率及回合摘要。
29
+ - **Editor**:输入编辑器、补全建议、元数据展示及 Minimalist 极简样式(支持一键切换 Pi 原生)。
30
+ - **Footer**:工作目录、Git 状态、运行时信息、Token/费用统计及扩展状态等。
31
+ - **Overlay**:设置面板、Context Inspector 等临时浮层,统一由 OverlayManager 调度管理。
32
32
 
33
33
  ### 内置功能
34
34
 
35
35
  | 功能 | 说明 | 入口 |
36
36
  | --------------------- | ---------------------------------------------------------------------- | ----------------- |
37
- | 统一设置面板 | 按 Header、Context、WorkingLine、Editor、Footer 和 Features 组织设置 | `/oneui` |
38
- | Context Inspector | 查看上下文占用,并预览 System prompt、Memory、Skills、Tools 和消息内容 | `/context` |
39
- | Session reference | 搜索并注入历史 Pi session 或 SubAgent 的有效上下文 | `@` 补全 |
40
- | Subagent autocomplete | 提供 SubAgent 名称补全和委派提示 | `@` 补全 |
41
- | Tool / Diff renderer | 工具调用、结果、折叠内容和 Edit/Write diff 的统一展示 | 自动生效 |
42
- | Subagent live renderer | 保留 pi-subagents 专用进度卡,并避免纳入通用工具分组 | 自动生效 |
43
- | Markdown enhancement | 支持 Mermaid、提示框和 URL 链接化等增强渲染 | 自动生效 |
44
- | Built-in themes | 提供 CC Dark 和 CC Light 主题 | `/theme` |
37
+ | 统一设置面板 | 集中管理 Header、Context、WorkingLine、Editor、Footer 等组件及功能设置 | `/oneui` |
38
+ | Context Inspector | 查看上下文占用,并预览 System prompt、Memory、Skills、Tools 及消息内容 | `/context` |
39
+ | Session reference | 搜索并引用注入历史 Pi 会话或 Subagent 的有效上下文 | `@` 补全 |
40
+ | Subagent autocomplete | 提供 Subagent 名称补全与委派提示 | `@` 补全 |
41
+ | Tool / Diff renderer | 工具调用、执行结果、折叠内容与 Edit/Write Diff 的统一美化渲染 | 自动生效 |
42
+ | Subagent live renderer | 保留 subagents 专用进度卡片,避免混入通用工具分组 | 自动生效 |
43
+ | Markdown enhancement | 支持 Mermaid 图表、提示框与 URL 链接化等增强渲染 | 自动生效 |
44
+ | Built-in themes | 内置 CC Dark 和 CC Light 主题 | `/theme` |
45
45
  | Compatibility aliases | 可选提供常用命令别名 | `/clear`、`/exit` |
46
+ | Effort command | 交互式或直接切换当前模型的 Thinking 思考档位 | `/effort` |
46
47
 
47
48
  ## 快速开始
48
49
 
@@ -75,16 +76,38 @@ pi install git:github.com/kerolt/pi-one-ui
75
76
  /oneui
76
77
  ```
77
78
 
79
+ ### 升级到 0.7.0
80
+
81
+ 本次新增 Editor 工作目录显示开关,并修复修改 Editor 配置后关闭 `/oneui` 导致输入不可见的问题。现有配置无需迁移,工作目录仍默认显示。
82
+
83
+ 未固定版本的 npm 安装可执行:
84
+
85
+ ```bash
86
+ pi update npm:pi-one-ui
87
+ ```
88
+
89
+ 若安装时固定了版本,执行 `pi install npm:pi-one-ui@0.7.0` 更新版本指定。更新安装包后,完整退出并重启 Pi。
90
+
91
+ 如需隐藏 Editor 目录,设置 `components.editor.styles.minimalist.showCwd: false`;Footer 中的目录显示独立配置。完整示例见 [配置指南](./docs/configuration.md#隐藏-editor-目录在-footer-左侧显示)。
92
+
78
93
  ## 配置
79
94
 
80
- 配置文件位于:
95
+ ### 配置方式
96
+
97
+ `pi-one-ui` 统一使用 Canonical v1 格式的配置文件:
81
98
 
82
99
  ```text
83
100
  ~/.pi/agent/pi-one-ui.json
84
101
  ```
85
102
 
103
+ 提供两种配置途径:
104
+
105
+ 1. **交互式设置面板(推荐)**:在 Pi 会话中运行 `/oneui`,即可在可视化面板中即时调整常用组件开关、样式和边框模式。修改即刻生效并自动持久化。
106
+ 2. **手动编辑配置文件**:高级用户可直接编辑 JSON 配置文件以启用更多细粒度选项。修改保存后,在 Pi 中执行 `/reload` 即可生效。文件不存在时将直接使用内置默认值。
86
107
 
87
- 推荐通过 `/oneui` 设置面板修改配置。面板采用更靠近顶部的居中布局;切换 Editor 开关或边框模式时会保持打开并在 Editor 替换后恢复焦点,持久化失败时则恢复列表中的有效旧值。当前配置仍使用 v1 结构,例如:
108
+ ### 基础配置示例
109
+
110
+ 以下为一个典型的 v1 配置文件结构:
88
111
 
89
112
  ```json
90
113
  {
@@ -94,54 +117,60 @@ pi install git:github.com/kerolt/pi-one-ui
94
117
  "style": "on",
95
118
  "borderColorMode": "static"
96
119
  },
97
- "userMessages": {
98
- "enabled": true,
99
- "style": "framed"
120
+ "footer": {
121
+ "style": "starship"
100
122
  },
101
123
  "workingLine": {
102
124
  "enabled": true
103
125
  },
104
- "footer": {
105
- "style": "starship"
126
+ "userMessages": {
127
+ "enabled": true,
128
+ "style": "framed"
106
129
  }
107
130
  },
108
131
  "renderer": {
109
132
  "mode": "on",
110
133
  "diffViewMode": "auto"
134
+ },
135
+ "panel": {
136
+ "anchor": "top-center",
137
+ "width": "85%",
138
+ "maxHeight": "90%",
139
+ "margin": { "top": 6, "right": 1, "bottom": 1, "left": 1 }
111
140
  }
112
141
  }
113
142
  ```
114
143
 
115
- Editor 只保留 `minimalist` 一种装饰样式,通过 `style` 开关控制:`on` 启用 Minimalist 装饰,`off` 恢复 Pi 原生编辑器(边框默认跟随主题与 effort 变色;若显式配置了 `colors.editorBorder`,off 模式下也会按 theme 语义应用该颜色,覆盖原生 effort 变色)。旧配置的 `enabled: false` 会迁移为 `style: "off"`,`opencode`/`minimalist` 会迁移为 `style: "on"`,`styles.opencode` 嵌套配置与 `opencode-copy-friendly`、`accent-rail` 一并失效。颜色统一按 theme 语义渲染:`colors.*` 配置值优先作为主题 token 解析(ANSI 色名如 `red` 会映射为语义色 `error`),未配置时优先主题专有 token(`cwd`/`editorModel`/`editorBorder`,可指向 vars 变量),主题未定义则回落 Pi 原生默认;需要固定终端色时可直接写 hex、256 色索引或 `fg:`/`bg:` 前缀。`borderColorMode` 支持 `static`(固定 `colors.editorBorder`)与 `adaptive`(边框优先用 `colors.editorThinking*` 分档配置,未配置则随 Pi 原生 effort 档位变化)。历史配置中的 `colorSource` 字段(`theme`/`terminal`)已移除并忽略,不主动改写用户文件。详细的颜色字段清单、取值语法与自定义方式见 [docs/editor-colors.md](./docs/editor-colors.md)。上下文占用相关信息由 Footer 统一展示。
116
-
117
- WorkingLine 的 token segment 会在一次模型响应持续至少 500ms 后追加实时输出速率,例如 `⚡12 tok/s`。速率按当前响应独立计算,在下一次 `turn_start` 时重置;关闭 token segment 时也会一并隐藏。
144
+ ### 深度配置与文档指引
118
145
 
119
- 不同布局和渲染器的可用选项会随版本变化,建议优先使用 `/oneui` 面板进行配置。
146
+ 各项组件开关、模板变量与颜色字段的完整规范拆分收录于独立文档中,便于按需查阅:
120
147
 
121
- ### Canonical 配置约定
122
-
123
- `pi-one-ui` 只读取和写入:
124
-
125
- ```text
126
- ~/.pi/agent/pi-one-ui.json
127
- ```
128
-
129
- 不会自动读取、合并或迁移其他历史配置文件,也不会解析旧版扁平字段和旧 style 名称。配置文件不存在时,运行时直接使用内置默认值;首次通过 `/oneui` 修改设置时才创建文件。所有持久化修改统一写入当前 v1 的 `components` 和 `renderer` 结构。
148
+ - **组件开关与排版定制**:详见 [Editor 与 Footer 配置指南 (docs/configuration.md)](./docs/configuration.md)
149
+ - **Editor**:支持 `style`(`on` 极简装饰 / `off` 原生)、`borderColorMode`(固定色 / 思考档位自适应)、`modelLabel` 及 Minimalist 装饰细节(目录显示与格式、会话名、耗时、费用、Git 状态等)。`components.editor.styles.minimalist.showCwd`(0.7.0 起,默认 `true`)可单独隐藏工作目录,不影响 Footer;`pathDisplay` 继续控制目录格式。
150
+ - **Footer**:支持 Starship 风格排版,提供丰富的模板变量(`$cwd`、`$git_branch`、`$tokens`、`$cost` 等),支持通过 `format` 自定义或通过 `segments` 控制各段开关,并可自由配置上下文占用率的展示形式(gauge / text)。
151
+ - **WorkingLine**:内置实时输出速率检测(单次响应持续 >=500ms 自动追加如 `⚡12 tok/s`,按回合独立重置)。
152
+ - **设置面板(`/oneui`)定制**:通过顶层 `panel` 字段控制浮层位置与尺寸,全部字段可省略(缺省值见上文示例)。
153
+ - `anchor`:锚点,支持 `center`、`top-left`、`top-right`、`bottom-left`、`bottom-right`、`top-center`、`bottom-center`、`left-center`、`right-center`。
154
+ - `width` / `maxHeight`:列数 / 行数,或 `"85%"` 形式的百分比字符串。
155
+ - `margin`:距终端边缘的外边距,可以是四边统一数字,也可以是按 `top`/`right`/`bottom`/`left` 分别配置的对象。
156
+ - 修改保存后下次打开 `/oneui` 即生效,无需 `/reload`。
157
+ - **颜色体系与主题定制**:详见 [Editor 颜色配置说明 (docs/editor-colors.md)](./docs/editor-colors.md)
158
+ - 所有颜色统一按 Theme 语义解释,优先解析为当前主题语义 Token(随主题自动切换),ANSI 色名自动映射为语义色(如 `red` 对应 `error`);如需固定色彩,可直接指定 Hex、256 色索引或 `fg:`/`bg:` 前缀。
159
+ - 支持完整的 Thinking 思考档位(Low 至 Max)自适应边框与标签分级配色。
160
+ - **历史版本迁移**:旧版升级带来的字段收敛(如 `opencode` 样式统一合并入 `minimalist`、`colorSource` 双模式移除等)参见 [docs/configuration.md 变更与迁移节](./docs/configuration.md#6-变更与迁移)。
130
161
 
131
162
  ## 上游来源与项目演进
132
163
 
133
- `pi-one-ui` 以以下两个开源项目的源码为初始基础,并对它们进行源码级融合。在此再次感谢两个上游项目及其贡献者,他们为 `pi-one-ui` 提供了最初的实现基础。
164
+ `pi-one-ui` 最初以两个开源项目的源码为基础进行整合。由衷感谢两个上游项目及其贡献者的出色工作:
134
165
 
135
- | 上游项目 | 融入 `pi-one-ui` 的主要能力 | 参照baseline |
166
+ | 上游项目 | 融入 `pi-one-ui` 的主要能力 | 参照 Baseline |
136
167
  | --------------------------------------------------------------- | -------------------------------------------------------------------------- | ------------------------- |
137
- | [pi-zentui](https://github.com/lmilojevicc/pi-zentui) | Starship 风格 Footer、Opencode 风格 Editor、布局和 shell 能力 | v0.21.0,commit `5341b38` |
138
- | [pi-cc-extensions](https://github.com/minuque/pi-cc-extensions) | Claude Code 风格 Context renderer、Tool/Diff、Context Inspector 和引用功能 | v0.8.67,commit `dba37e5` |
139
-
140
- 融合后的生产代码位于 `extensions/`。项目已经在原始实现之上统一入口、配置存储、生命周期、Layout ownership、Overlay 和输入路由,并会继续独立演进;当前实现不再等同于任一上游项目,也不会自动跟随上游同步。
168
+ | [pi-zentui](https://github.com/lmilojevicc/pi-zentui) | Starship 风格 Footer、Editor 基础布局与 Shell 交互能力 | v0.21.0,commit `5341b38` |
169
+ | [pi-cc-extensions](https://github.com/minuque/pi-cc-extensions) | Claude Code 风格 Context 渲染器、Tool/Diff 视图、Context Inspector 与会话引用 | v0.8.67,commit `dba37e5` |
141
170
 
142
- 感谢两个上游项目及其贡献者。它们为 `pi-one-ui` 提供了最初的实现基础,而本项目后续的工作重点是将这些能力收敛为一个边界清晰、可持续维护的统一产品。
171
+ 融合后的生产代码位于 `extensions/`。`pi-one-ui` 在原始实现之上完成了入口统一、配置存储规范化、生命周期治理、Layout Ownership 收敛、Overlay 统一调度与输入路由解耦,并持续独立演进。当前实现已完全独立于上游,不依赖也不自动同步上游分支。
143
172
 
144
- 更详细的模块边界、事件流和 ownership 约定参见 [ARCHITECTURE.md](./ARCHITECTURE.md)。
173
+ 更详细的模块边界、事件流与 Ownership 约定参见 [ARCHITECTURE.md](./ARCHITECTURE.md)。
145
174
 
146
175
  ## 本地开发
147
176
 
@@ -0,0 +1,117 @@
1
+ import type {
2
+ OverlayAnchor,
3
+ OverlayMargin,
4
+ SizeValue,
5
+ } from "@earendil-works/pi-tui";
6
+ import { configStore } from "./store.ts";
7
+
8
+ /**
9
+ * Overlay placement for the /oneui settings panel. Mirrors the Pi
10
+ * `OverlayOptions` subset the panel supports; persisted under the
11
+ * top-level `panel` key in `pi-one-ui.json`.
12
+ */
13
+ export type PanelOverlayConfig = {
14
+ anchor: OverlayAnchor;
15
+ width: SizeValue;
16
+ maxHeight: SizeValue;
17
+ margin: OverlayMargin | number;
18
+ };
19
+
20
+ /** Defaults preserve the historically hardcoded /oneui panel placement. */
21
+ export const DEFAULT_PANEL_OVERLAY: PanelOverlayConfig = {
22
+ anchor: "top-center",
23
+ width: "85%",
24
+ maxHeight: "90%",
25
+ margin: { top: 6, right: 1, bottom: 1, left: 1 },
26
+ };
27
+
28
+ const PANEL_ANCHORS: readonly OverlayAnchor[] = [
29
+ "center",
30
+ "top-left",
31
+ "top-right",
32
+ "bottom-left",
33
+ "bottom-right",
34
+ "top-center",
35
+ "bottom-center",
36
+ "left-center",
37
+ "right-center",
38
+ ];
39
+
40
+ function isRecord(value: unknown): value is Record<string, unknown> {
41
+ return value !== null && typeof value === "object" && !Array.isArray(value);
42
+ }
43
+
44
+ function parseAnchor(value: unknown): OverlayAnchor {
45
+ return PANEL_ANCHORS.some((anchor) => anchor === value)
46
+ ? (value as OverlayAnchor)
47
+ : DEFAULT_PANEL_OVERLAY.anchor;
48
+ }
49
+
50
+ /** Accepts a positive column/row count or a "N%" string within 0..100. */
51
+ function parseSizeValue(value: unknown, fallback: SizeValue): SizeValue {
52
+ if (typeof value === "number" && Number.isFinite(value) && value > 0) {
53
+ return Math.floor(value);
54
+ }
55
+ if (typeof value === "string") {
56
+ const match = /^(\d+(?:\.\d+)?)%$/.exec(value.trim());
57
+ if (match) {
58
+ const percent = Number(match[1]);
59
+ if (percent > 0 && percent <= 100) {
60
+ return value.trim() as SizeValue;
61
+ }
62
+ }
63
+ }
64
+ return fallback;
65
+ }
66
+
67
+ function parseMarginEdge(value: unknown): number | undefined {
68
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0
69
+ ? value
70
+ : undefined;
71
+ }
72
+
73
+ /** Accepts one non-negative integer for all edges or a per-edge object. */
74
+ function parseMargin(value: unknown): OverlayMargin | number {
75
+ const fallback = DEFAULT_PANEL_OVERLAY.margin;
76
+ if (typeof value === "number") {
77
+ return parseMarginEdge(value) ?? fallback;
78
+ }
79
+ if (!isRecord(value)) {
80
+ return fallback;
81
+ }
82
+ const defaults = isRecord(fallback) ? (fallback as OverlayMargin) : {};
83
+ const margin: OverlayMargin = {};
84
+ for (const edge of ["top", "right", "bottom", "left"] as const) {
85
+ margin[edge] = parseMarginEdge(value[edge]) ?? defaults[edge];
86
+ }
87
+ return margin;
88
+ }
89
+
90
+ /**
91
+ * Normalizes the raw `panel` config section, replacing invalid fields with
92
+ * defaults so a broken entry never blocks the /oneui panel from opening.
93
+ */
94
+ export function normalizePanelOverlay(input: unknown): PanelOverlayConfig {
95
+ const source = isRecord(input) ? input : {};
96
+ return {
97
+ anchor: parseAnchor(source.anchor),
98
+ width: parseSizeValue(source.width, DEFAULT_PANEL_OVERLAY.width),
99
+ maxHeight: parseSizeValue(
100
+ source.maxHeight,
101
+ DEFAULT_PANEL_OVERLAY.maxHeight,
102
+ ),
103
+ margin: parseMargin(source.margin),
104
+ };
105
+ }
106
+
107
+ /**
108
+ * Loads the panel overlay placement from the shared store. Read fresh on
109
+ * every /oneui open so JSON edits apply without `/reload`.
110
+ */
111
+ export function loadPanelOverlayConfig(): PanelOverlayConfig {
112
+ try {
113
+ return normalizePanelOverlay(configStore.read().panel);
114
+ } catch {
115
+ return normalizePanelOverlay(undefined);
116
+ }
117
+ }
@@ -62,6 +62,7 @@ export type Config = {
62
62
  enableContextCommand: boolean;
63
63
  enableAgentSummary: boolean;
64
64
  enableAliases: boolean;
65
+ enableEffortCommand: boolean;
65
66
  };
66
67
 
67
68
  function rendererConfigFrom(record: ConfigRecord): ConfigRecord {
@@ -166,6 +167,7 @@ export const DEFAULT_CONFIG: Config = {
166
167
  enableContextCommand: true,
167
168
  enableAgentSummary: true,
168
169
  enableAliases: true,
170
+ enableEffortCommand: true,
169
171
  };
170
172
 
171
173
  function pickEnum<T extends string>(
@@ -296,6 +298,7 @@ export function normalizeConfig(input: unknown): Config {
296
298
  enableContextCommand: source.enableContextCommand !== false,
297
299
  enableAgentSummary: source.enableAgentSummary !== false,
298
300
  enableAliases: source.enableAliases !== false,
301
+ enableEffortCommand: source.enableEffortCommand !== false,
299
302
  };
300
303
  }
301
304
 
@@ -350,6 +353,7 @@ export function formatConfigStatus(source: Config = config): string {
350
353
  `context=${source.enableContextCommand ? "on" : "off"}`,
351
354
  `agentSummary=${source.enableAgentSummary ? "on" : "off"}`,
352
355
  `aliases=${source.enableAliases ? "on" : "off"}`,
356
+ `effort=${source.enableEffortCommand ? "on" : "off"}`,
353
357
  ].join(" · ");
354
358
  }
355
359
 
@@ -97,6 +97,8 @@ export type FooterSegmentsConfig = {
97
97
 
98
98
  export type MinimalistEditorStyleConfig = {
99
99
  pathDisplay: MinimalistPathDisplayMode;
100
+ /** Controls the Editor directory label independently of its format and the Footer. */
101
+ showCwd: boolean;
100
102
  showSessionName: boolean;
101
103
  showTimer: boolean;
102
104
  showCost: boolean;
@@ -395,6 +397,7 @@ const defaultFooterSegments: FooterSegmentsConfig = {
395
397
 
396
398
  const defaultMinimalistStyle: MinimalistEditorStyleConfig = {
397
399
  pathDisplay: "compact",
400
+ showCwd: true,
398
401
  showSessionName: true,
399
402
  showTimer: true,
400
403
  showCost: true,
@@ -1001,6 +1004,10 @@ function resolveComponents(config: ConfigRecord): ComponentsConfig {
1001
1004
  minimalist.pathDisplay === "full"
1002
1005
  ? minimalist.pathDisplay
1003
1006
  : defaultMinimalistStyle.pathDisplay,
1007
+ showCwd: parseBoolean(
1008
+ minimalist.showCwd,
1009
+ defaultMinimalistStyle.showCwd,
1010
+ ),
1004
1011
  showSessionName: parseBoolean(
1005
1012
  minimalist.showSessionName,
1006
1013
  defaultMinimalistStyle.showSessionName,
@@ -1386,6 +1393,9 @@ function applyMinimalistStylePatch(
1386
1393
  patch: Partial<MinimalistEditorStyleConfig>,
1387
1394
  ): void {
1388
1395
  if (patch.pathDisplay !== undefined) style.pathDisplay = patch.pathDisplay;
1396
+ if (patch.showCwd !== undefined) {
1397
+ style.showCwd = patch.showCwd;
1398
+ }
1389
1399
  if (patch.showSessionName !== undefined)
1390
1400
  style.showSessionName = patch.showSessionName;
1391
1401
  if (patch.showTimer !== undefined) style.showTimer = patch.showTimer;
@@ -1,10 +1,13 @@
1
1
  import {
2
2
  type ExtensionCommandContext,
3
3
  type ExtensionContext,
4
+ type ExtensionUIContext,
4
5
  getSettingsListTheme,
5
6
  } from "@earendil-works/pi-coding-agent";
6
7
  import {
8
+ type Component,
7
9
  matchesKey,
10
+ type OverlayHandle,
8
11
  type SettingItem,
9
12
  SettingsList,
10
13
  truncateToWidth,
@@ -13,6 +16,7 @@ import {
13
16
  renderEditorSettingsPreview,
14
17
  renderUserMessageSettingsPreview,
15
18
  } from "./commands/settings-previews.ts";
19
+ import { loadPanelOverlayConfig } from "./config/panel.ts";
16
20
  import {
17
21
  type CompactStyleMode,
18
22
  type Config as ContextConfig,
@@ -303,6 +307,13 @@ function featureItems(config: ContextConfig): SettingItem[] {
303
307
  currentValue: onOff(config.enableAliases),
304
308
  values: ["on", "off"],
305
309
  },
310
+ {
311
+ id: "enableEffortCommand",
312
+ label: "Effort command",
313
+ description: "Register the /effort thinking-level command.",
314
+ currentValue: onOff(config.enableEffortCommand),
315
+ values: ["on", "off"],
316
+ },
306
317
  ];
307
318
  }
308
319
 
@@ -547,6 +558,7 @@ function updateSetting(
547
558
  id === "enableContextCommand" ||
548
559
  id === "enableAgentSummary" ||
549
560
  id === "enableAliases" ||
561
+ id === "enableEffortCommand" ||
550
562
  id === "showStartupHeader"
551
563
  ) {
552
564
  const patch = { [id]: isOn(value) } as Partial<ContextConfig>;
@@ -598,10 +610,24 @@ export async function showOneUiPanel(
598
610
 
599
611
  unifiedPanelOpen = true;
600
612
  try {
601
- let panelHandle: { focus: () => void } | undefined;
613
+ // Read fresh on every open so pi-one-ui.json edits apply without /reload.
614
+ const panelOverlay = loadPanelOverlayConfig();
615
+ let panelHandle: Pick<OverlayHandle, "focus" | "unfocus"> | undefined;
602
616
  await overlayManager.run(() =>
603
617
  ctx.ui.custom(
604
618
  (tui, theme, _keybindings, done) => {
619
+ // Pi's concrete renderers expose focus inspection beyond the narrow TUI port.
620
+ const focusTui = tui as typeof tui & {
621
+ getFocusedComponent?: () => Component | null;
622
+ isOverlayFocused?: () => boolean;
623
+ };
624
+ const originalFocus = focusTui.getFocusedComponent?.();
625
+ let editorFocus:
626
+ | {
627
+ component: Component;
628
+ factory: ReturnType<ExtensionUIContext["getEditorComponent"]>;
629
+ }
630
+ | undefined;
605
631
  let activeIndex = 0;
606
632
  let list: SettingsList;
607
633
  const createList = () => {
@@ -610,6 +636,16 @@ export async function showOneUiPanel(
610
636
  10,
611
637
  getSettingsListTheme(),
612
638
  (id, value) => {
639
+ const updatesEditor =
640
+ id === "editorStyle" || id === "editorBorderColorMode";
641
+ if (updatesEditor && originalFocus !== undefined) {
642
+ // Suspend automatic overlay focus restoration while Pi may replace
643
+ // and roll back an editor, keeping the final instance observable.
644
+ panelHandle?.unfocus?.({
645
+ target: editorFocus?.component ?? originalFocus,
646
+ });
647
+ }
648
+ const previousFocus = focusTui.getFocusedComponent?.();
613
649
  try {
614
650
  updateSetting(id, value, ctx, deps);
615
651
  list.updateValue(id, value);
@@ -618,13 +654,50 @@ export async function showOneUiPanel(
618
654
  createList();
619
655
  list.selectItem(id);
620
656
  } finally {
621
- if (id === "editorStyle") {
657
+ if (updatesEditor) {
658
+ // Replacements (including rollback) focus the new instance, but the
659
+ // overlay still retains its old preFocus. Capture before refocusing.
660
+ const nextFocus = focusTui.getFocusedComponent?.();
661
+ if (
662
+ nextFocus &&
663
+ nextFocus !== previousFocus &&
664
+ !focusTui.isOverlayFocused?.()
665
+ ) {
666
+ try {
667
+ editorFocus = {
668
+ component: nextFocus,
669
+ factory: ctx.ui.getEditorComponent(),
670
+ };
671
+ } catch {
672
+ editorFocus = undefined;
673
+ }
674
+ }
622
675
  panelHandle?.focus();
623
676
  }
624
677
  tui.requestRender();
625
678
  }
626
679
  },
627
- () => done(undefined),
680
+ () => {
681
+ done(undefined);
682
+ // Only correct this panel's stale return target; other overlays and
683
+ // later editor owners keep their focus. Stale session contexts may throw.
684
+ if (
685
+ !editorFocus ||
686
+ tui.hasOverlay() ||
687
+ focusTui.getFocusedComponent?.() !== originalFocus
688
+ ) {
689
+ return;
690
+ }
691
+ try {
692
+ if (ctx.ui.getEditorComponent() !== editorFocus.factory) {
693
+ return;
694
+ }
695
+ } catch {
696
+ return;
697
+ }
698
+ tui.setFocus(editorFocus.component);
699
+ tui.requestRender();
700
+ },
628
701
  );
629
702
  };
630
703
  createList();
@@ -680,17 +753,12 @@ export async function showOneUiPanel(
680
753
  {
681
754
  overlay: true,
682
755
  overlayOptions: {
683
- anchor: "top-center",
684
- width: "85%",
685
- maxHeight: "90%",
686
- margin: {
687
- top: 6,
688
- right: 1,
689
- bottom: 1,
690
- left: 1,
691
- },
756
+ anchor: panelOverlay.anchor,
757
+ width: panelOverlay.width,
758
+ maxHeight: panelOverlay.maxHeight,
759
+ margin: panelOverlay.margin,
692
760
  },
693
- onHandle: (handle: { focus: () => void }) => {
761
+ onHandle: (handle: OverlayHandle) => {
694
762
  panelHandle = handle;
695
763
  },
696
764
  },
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Effort Command Feature
3
+ *
4
+ * Registers the /effort command for selecting the active thinking level:
5
+ * /effort → interactive level picker
6
+ * /effort high → apply a level directly (with autocomplete)
7
+ */
8
+
9
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
10
+
11
+ const EFFORT_LEVELS = [
12
+ "off",
13
+ "minimal",
14
+ "low",
15
+ "medium",
16
+ "high",
17
+ "xhigh",
18
+ "max",
19
+ ] as const;
20
+ type EffortLevel = (typeof EFFORT_LEVELS)[number];
21
+
22
+ /** Reports whether a command argument is a supported thinking-effort level. */
23
+ function isEffortLevel(value: string): value is EffortLevel {
24
+ return EFFORT_LEVELS.some((level) => level === value);
25
+ }
26
+
27
+ /** Registers the /effort command for selecting the active thinking level. */
28
+ export default function effortCommand(pi: ExtensionAPI): void {
29
+ pi.registerCommand("effort", {
30
+ description:
31
+ "Set thinking effort: off, minimal, low, medium, high, xhigh, or max",
32
+ getArgumentCompletions: (prefix) => {
33
+ const normalizedPrefix = prefix.toLowerCase();
34
+ const matches = EFFORT_LEVELS.filter((level) =>
35
+ level.startsWith(normalizedPrefix),
36
+ ).map((level) => ({
37
+ value: level,
38
+ label: level,
39
+ }));
40
+ return matches.length > 0 ? matches : null;
41
+ },
42
+ handler: async (args, ctx) => {
43
+ let requested = args.trim().toLowerCase();
44
+ if (!requested) {
45
+ if (!ctx.hasUI) {
46
+ return;
47
+ }
48
+ const selected = await ctx.ui.select(
49
+ `Thinking effort (current: ${pi.getThinkingLevel()})`,
50
+ [...EFFORT_LEVELS],
51
+ );
52
+ if (!selected) {
53
+ return;
54
+ }
55
+ requested = selected;
56
+ }
57
+
58
+ if (!isEffortLevel(requested)) {
59
+ ctx.ui.notify(
60
+ `Unknown effort "${requested}". Expected: ${EFFORT_LEVELS.join(", ")}`,
61
+ "error",
62
+ );
63
+ return;
64
+ }
65
+
66
+ pi.setThinkingLevel(requested);
67
+ // The active model may clamp unsupported levels; surface the applied value.
68
+ const applied = pi.getThinkingLevel();
69
+ if (applied !== requested) {
70
+ ctx.ui.notify(
71
+ `Requested ${requested}; active model applied ${applied}`,
72
+ "warning",
73
+ );
74
+ return;
75
+ }
76
+ ctx.ui.notify(`Thinking effort: ${applied}`, "info");
77
+ },
78
+ });
79
+ }
@@ -16,6 +16,7 @@ import { type ConfigRecord, configStore } from "../../app/config/store.ts";
16
16
  // shell
17
17
  import piAliases from "../../features/aliases.ts";
18
18
  import context from "../../features/context-inspector/index.ts";
19
+ import effortCommand from "../../features/effort-command.ts";
19
20
  import { installFlushDockedBash } from "../../features/flush-docked-bash.ts";
20
21
  import sessionReference from "../../features/session-reference/index.ts";
21
22
  // feature
@@ -154,6 +155,9 @@ export default function (
154
155
  ): void {
155
156
  // shell chrome
156
157
  if (config.enableAliases) piAliases(pi);
158
+ if (config.enableEffortCommand) {
159
+ effortCommand(pi);
160
+ }
157
161
  installFlushDockedBash();
158
162
  // The thinking controller is queried directly by the context render stack.
159
163
  markdownEnhance(pi);
@@ -262,6 +262,9 @@ function renderBottomRight(
262
262
  uiTheme: Theme,
263
263
  config: ZentuiConfig,
264
264
  ): string {
265
+ if (config.components.editor.styles.minimalist.showCwd === false) {
266
+ return "";
267
+ }
265
268
  const cwd = sanitizeEditorMetadataText(minimalistCwdLabel(metadata, config));
266
269
  return cwd
267
270
  ? renderSourceColor(uiTheme, config.colors.cwd, "cwd", "bold cyan", cwd)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-one-ui",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "A single, customizable Pi UI package with layout-oriented Context and Shell rendering for Pi.",
5
5
  "type": "module",
6
6
  "license": "MIT",