pi-cc-extensions 0.8.16 → 0.8.18
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.en.md +174 -174
- package/README.md +115 -115
- package/extensions/ask-user-question/state/questionnaire-session.ts +19 -2
- package/extensions/ask-user-question/view/dialog-builder.ts +16 -1
- package/extensions/claude-code-style.ts +74 -26
- package/extensions/closable-dialog.ts +57 -0
- package/extensions/context.ts +24 -3
- package/package.json +69 -69
package/README.en.md
CHANGED
|
@@ -1,174 +1,174 @@
|
|
|
1
|
-
<p align="center">
|
|
2
|
-
<img src="./assets/readme/hero.svg" width="100%" alt="pi-cc-extensions: a productivity extension suite for Pi">
|
|
3
|
-
</p>
|
|
4
|
-
|
|
5
|
-
<p align="center">
|
|
6
|
-
<a href="https://pi.dev/packages?name=pi-cc-extensions"><img alt="Pi package catalog" src="https://img.shields.io/badge/Pi-package-58B7FF?style=flat-square"></a>
|
|
7
|
-
<a href="https://www.npmjs.com/package/pi-cc-extensions"><img alt="npm version" src="https://img.shields.io/npm/v/pi-cc-extensions?style=flat-square&color=66E3C4"></a>
|
|
8
|
-
<a href="#compatibility"><img alt="Node.js 22.19 or newer" src="https://img.shields.io/badge/Node.js-%E2%89%A522.19-66E3C4?style=flat-square"></a>
|
|
9
|
-
<a href="./extensions"><img alt="TypeScript extensions" src="https://img.shields.io/badge/TypeScript-extensions-3178C6?style=flat-square"></a>
|
|
10
|
-
</p>
|
|
11
|
-
|
|
12
|
-
<p align="center">
|
|
13
|
-
Claude Code-style output, structured questionnaires, context inspection, and Agent / Session references.
|
|
14
|
-
</p>
|
|
15
|
-
|
|
16
|
-
<p align="center">
|
|
17
|
-
<a href="./README.md">简体中文</a> · <strong>English</strong>
|
|
18
|
-
</p>
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## Preview
|
|
23
|
-
|
|
24
|
-
<table>
|
|
25
|
-
<tr>
|
|
26
|
-
<td colspan="2" align="center">
|
|
27
|
-
<img src="./assets/readme/welcome.webp" width="100%" alt="Pi welcome screen">
|
|
28
|
-
<br>
|
|
29
|
-
<sub><b>Welcome screen</b><br><code>npm:pi-startup-header</code> with <code>npm:pi-zentui</code></sub>
|
|
30
|
-
</td>
|
|
31
|
-
</tr>
|
|
32
|
-
<tr>
|
|
33
|
-
<td width="50%" align="center">
|
|
34
|
-
<img src="./assets/readme/fixed-editor-navigation.webp" width="100%" alt="Tool results, back-to-bottom control, and Ctrl+End in the fixed editor">
|
|
35
|
-
<br>
|
|
36
|
-
<sub><b>Fixed-editor workflow</b><br>Tool summaries, expand/collapse, and keyboard navigation</sub>
|
|
37
|
-
</td>
|
|
38
|
-
<td width="50%" align="center">
|
|
39
|
-
<img src="./assets/readme/session-reference.webp" width="100%" alt="Selecting a previous Session through at-sign completion">
|
|
40
|
-
<br>
|
|
41
|
-
<sub><b>Session references</b><br>Find and inject previous context through completion</sub>
|
|
42
|
-
</td>
|
|
43
|
-
</tr>
|
|
44
|
-
<tr>
|
|
45
|
-
<td width="50%" align="center">
|
|
46
|
-
<img src="./assets/readme/context-usage.webp" width="100%" alt="Context window usage breakdown">
|
|
47
|
-
<br>
|
|
48
|
-
<sub><b>Context usage</b><br>Inspect usage by category</sub>
|
|
49
|
-
</td>
|
|
50
|
-
<td width="50%" align="center">
|
|
51
|
-
<img src="./assets/readme/context-preview.webp" width="100%" alt="Previewing injected context">
|
|
52
|
-
<br>
|
|
53
|
-
<sub><b>Context preview</b><br>Inspect the content injected into the model</sub>
|
|
54
|
-
</td>
|
|
55
|
-
</tr>
|
|
56
|
-
</table>
|
|
57
|
-
|
|
58
|
-
## Quick start
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
pi install npm:pi-cc-extensions
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Run `/reload` after installation, then try:
|
|
65
|
-
|
|
66
|
-
```text
|
|
67
|
-
/ccstyle # Configure output and fixed-editor interaction
|
|
68
|
-
/context # Inspect context usage
|
|
69
|
-
@ # Complete Agents, Sessions, and files
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
The `ask_user_question` tool is registered automatically.
|
|
73
|
-
|
|
74
|
-
## Features
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
| Feature | Description | Entry point |
|
|
78
|
-
| --------------------------- | -------------------------------------------------------------------------------------------------- | --------------------- |
|
|
79
|
-
| Claude Code-style output | Tool summaries, expand/collapse, rich edit/write diffs, and`on` / `off` / `compact` modes | `/ccstyle` |
|
|
80
|
-
| Fixed-editor interaction | Five-row wheel scrolling, tool clicks, collapse anchoring, back-to-bottom control, and`Ctrl+End` | `/ccstyle` |
|
|
81
|
-
| Structured questionnaires | Single choice, multiple choice, custom answers, Markdown previews, and RPC / ACP fallback | `ask_user_question` |
|
|
82
|
-
| Context inspection | Usage breakdown and previews for the system prompt, tools, skills, and messages | `/context` |
|
|
83
|
-
| Session references | Search and inject effective context from previous Sessions or existing SubAgents | `@session:` |
|
|
84
|
-
| Theme | Includes the GitHub Dark Default theme | `/theme` |
|
|
85
|
-
|
|
86
|
-
### Output modes
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
| Mode | Behavior |
|
|
90
|
-
| ----------- | ----------------------------------------------------------------------- |
|
|
91
|
-
| `on` | Claude Code-style tool output with rich diffs for`edit` and `write` |
|
|
92
|
-
| `off` | Native Pi renderers |
|
|
93
|
-
| `compact` | One-line previews, merged repeated calls, duration, and run summaries |
|
|
94
|
-
|
|
95
|
-
```text
|
|
96
|
-
/ccstyle on
|
|
97
|
-
/ccstyle off
|
|
98
|
-
/ccstyle compact
|
|
99
|
-
/ccstyle status
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
Configuration is stored in `~/.pi/agent/claude-code-style.json`:
|
|
103
|
-
|
|
104
|
-
```json
|
|
105
|
-
{
|
|
106
|
-
"mode": "on",
|
|
107
|
-
"excludeRenderers": [],
|
|
108
|
-
"fixedEditorFeatures": true
|
|
109
|
-
}
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
- `excludeRenderers` uses exact tool names. `Agent` always keeps its dedicated renderer.
|
|
113
|
-
- `fixedEditorFeatures: true` enables fixed-editor mouse scrolling, clicks, viewport mapping, and the back-to-bottom indicator.
|
|
114
|
-
- Set it to `false` to disable terminal mouse reporting and restore native terminal wheel scrolling. `Ctrl+End` remains available.
|
|
115
|
-
- Run `/reload` after editing the file manually.
|
|
116
|
-
|
|
117
|
-
### Structured questionnaires
|
|
118
|
-
|
|
119
|
-
Supports 1–4 questions, 2–4 options per question, single and multiple selection, custom answers, and optional Markdown previews. The TUI preserves transcript space; RPC / ACP environments fall back to native dialogs.
|
|
120
|
-
|
|
121
|
-
Questionnaire configuration is stored at `~/.config/rpiv-ask-user-question/config.json`. See [`extensions/ask-user-question/README.md`](./extensions/ask-user-question/README.md) for shortcuts and detailed behavior.
|
|
122
|
-
|
|
123
|
-
### `@` references
|
|
124
|
-
|
|
125
|
-
- Enter `@session:` to reference a previous Session.
|
|
126
|
-
- Enter `@agent-name` to delegate to a custom Agent.
|
|
127
|
-
- Compatible with `@bacnh85/pi-fff` and `@tintinweb/pi-subagents`.
|
|
128
|
-
- Session context is deduplicated and size-limited before injection.
|
|
129
|
-
|
|
130
|
-
## Other installation methods
|
|
131
|
-
|
|
132
|
-
```bash
|
|
133
|
-
# GitHub
|
|
134
|
-
pi install git:github.com/minuque/pi-cc-extensions
|
|
135
|
-
|
|
136
|
-
# Local repository
|
|
137
|
-
pi install /absolute/path/to/pi-cc-extensions
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
## Local development
|
|
141
|
-
|
|
142
|
-
```bash
|
|
143
|
-
npm test
|
|
144
|
-
npm run typecheck
|
|
145
|
-
pi -e .
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
Run `/reload` after changing extensions. Changes under `extensions/ask-user-question/`, or reinstalling its dependencies, require a full Pi restart.
|
|
149
|
-
|
|
150
|
-
## Compatibility
|
|
151
|
-
|
|
152
|
-
- Node.js `>=22.19.0`
|
|
153
|
-
- Loaded through `pi.extensions` and `pi.themes` in the root `package.json`
|
|
154
|
-
- If a Pi, TUI, or `pi-zentui` update causes display issues, try `/reload` first
|
|
155
|
-
|
|
156
|
-
## Recommended companions
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
| Extension | Purpose |
|
|
160
|
-
| ------------------------------- | -------------------------------------------------------------- |
|
|
161
|
-
| `npm:pi-zentui` | Fixed editor, status line, and Git status |
|
|
162
|
-
| `npm:@tintinweb/pi-subagents` | Parallel SubAgents, background tasks, and worktree isolation |
|
|
163
|
-
| `npm:pi-mcp-adapter` | On-demand MCP tool discovery with lower context usage |
|
|
164
|
-
| `npm:pi-theme-picker` | Theme search and live preview |
|
|
165
|
-
| `npm:@ayulab/pi-rewind` | Checkpoint-based code or conversation rollback |
|
|
166
|
-
| `npm:pi-compact-thinking` | Compact rendering for hidden thinking blocks |
|
|
167
|
-
|
|
168
|
-
## Credits
|
|
169
|
-
|
|
170
|
-
- Compact transcript behavior is based on [`avhagedorn/pi-compact-transcript`](https://github.com/avhagedorn/pi-compact-transcript) v0.6.2 (MIT).
|
|
171
|
-
- Structured questionnaires are based on [`@juicesharp/rpiv-ask-user-question`](https://github.com/juicesharp/rpiv-mono/tree/main/packages/rpiv-ask-user-question) v2.1.0 (MIT).
|
|
172
|
-
- Rich diffs are adapted from [`MasuRii/pi-tool-display`](https://github.com/MasuRii/pi-tool-display) (MIT). See [`extensions/tool-diff/ATTRIBUTION.md`](./extensions/tool-diff/ATTRIBUTION.md).
|
|
173
|
-
- Startup header based on [`EnderLiquid/pi-startup-header`](https://github.com/EnderLiquid/pi-startup-header) (MIT).
|
|
174
|
-
- Command aliases based on [`xRyul/pi-aliases`](https://github.com/xRyul/pi-aliases) (MIT).
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="./assets/readme/hero.svg" width="100%" alt="pi-cc-extensions: a productivity extension suite for Pi">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://pi.dev/packages?name=pi-cc-extensions"><img alt="Pi package catalog" src="https://img.shields.io/badge/Pi-package-58B7FF?style=flat-square"></a>
|
|
7
|
+
<a href="https://www.npmjs.com/package/pi-cc-extensions"><img alt="npm version" src="https://img.shields.io/npm/v/pi-cc-extensions?style=flat-square&color=66E3C4"></a>
|
|
8
|
+
<a href="#compatibility"><img alt="Node.js 22.19 or newer" src="https://img.shields.io/badge/Node.js-%E2%89%A522.19-66E3C4?style=flat-square"></a>
|
|
9
|
+
<a href="./extensions"><img alt="TypeScript extensions" src="https://img.shields.io/badge/TypeScript-extensions-3178C6?style=flat-square"></a>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
Claude Code-style output, structured questionnaires, context inspection, and Agent / Session references.
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<a href="./README.md">简体中文</a> · <strong>English</strong>
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Preview
|
|
23
|
+
|
|
24
|
+
<table>
|
|
25
|
+
<tr>
|
|
26
|
+
<td colspan="2" align="center">
|
|
27
|
+
<img src="./assets/readme/welcome.webp" width="100%" alt="Pi welcome screen">
|
|
28
|
+
<br>
|
|
29
|
+
<sub><b>Welcome screen</b><br><code>npm:pi-startup-header</code> with <code>npm:pi-zentui</code></sub>
|
|
30
|
+
</td>
|
|
31
|
+
</tr>
|
|
32
|
+
<tr>
|
|
33
|
+
<td width="50%" align="center">
|
|
34
|
+
<img src="./assets/readme/fixed-editor-navigation.webp" width="100%" alt="Tool results, back-to-bottom control, and Ctrl+End in the fixed editor">
|
|
35
|
+
<br>
|
|
36
|
+
<sub><b>Fixed-editor workflow</b><br>Tool summaries, expand/collapse, and keyboard navigation</sub>
|
|
37
|
+
</td>
|
|
38
|
+
<td width="50%" align="center">
|
|
39
|
+
<img src="./assets/readme/session-reference.webp" width="100%" alt="Selecting a previous Session through at-sign completion">
|
|
40
|
+
<br>
|
|
41
|
+
<sub><b>Session references</b><br>Find and inject previous context through completion</sub>
|
|
42
|
+
</td>
|
|
43
|
+
</tr>
|
|
44
|
+
<tr>
|
|
45
|
+
<td width="50%" align="center">
|
|
46
|
+
<img src="./assets/readme/context-usage.webp" width="100%" alt="Context window usage breakdown">
|
|
47
|
+
<br>
|
|
48
|
+
<sub><b>Context usage</b><br>Inspect usage by category</sub>
|
|
49
|
+
</td>
|
|
50
|
+
<td width="50%" align="center">
|
|
51
|
+
<img src="./assets/readme/context-preview.webp" width="100%" alt="Previewing injected context">
|
|
52
|
+
<br>
|
|
53
|
+
<sub><b>Context preview</b><br>Inspect the content injected into the model</sub>
|
|
54
|
+
</td>
|
|
55
|
+
</tr>
|
|
56
|
+
</table>
|
|
57
|
+
|
|
58
|
+
## Quick start
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pi install npm:pi-cc-extensions
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Run `/reload` after installation, then try:
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
/ccstyle # Configure output and fixed-editor interaction
|
|
68
|
+
/context # Inspect context usage
|
|
69
|
+
@ # Complete Agents, Sessions, and files
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The `ask_user_question` tool is registered automatically.
|
|
73
|
+
|
|
74
|
+
## Features
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
| Feature | Description | Entry point |
|
|
78
|
+
| --------------------------- | -------------------------------------------------------------------------------------------------- | --------------------- |
|
|
79
|
+
| Claude Code-style output | Tool summaries, expand/collapse, rich edit/write diffs, and`on` / `off` / `compact` modes | `/ccstyle` |
|
|
80
|
+
| Fixed-editor interaction | Five-row wheel scrolling, tool clicks, collapse anchoring, back-to-bottom control, and`Ctrl+End` | `/ccstyle` |
|
|
81
|
+
| Structured questionnaires | Single choice, multiple choice, custom answers, Markdown previews, and RPC / ACP fallback | `ask_user_question` |
|
|
82
|
+
| Context inspection | Usage breakdown and previews for the system prompt, tools, skills, and messages | `/context` |
|
|
83
|
+
| Session references | Search and inject effective context from previous Sessions or existing SubAgents | `@session:` |
|
|
84
|
+
| Theme | Includes the GitHub Dark Default theme | `/theme` |
|
|
85
|
+
|
|
86
|
+
### Output modes
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
| Mode | Behavior |
|
|
90
|
+
| ----------- | ----------------------------------------------------------------------- |
|
|
91
|
+
| `on` | Claude Code-style tool output with rich diffs for`edit` and `write` |
|
|
92
|
+
| `off` | Native Pi renderers |
|
|
93
|
+
| `compact` | One-line previews, merged repeated calls, duration, and run summaries |
|
|
94
|
+
|
|
95
|
+
```text
|
|
96
|
+
/ccstyle on
|
|
97
|
+
/ccstyle off
|
|
98
|
+
/ccstyle compact
|
|
99
|
+
/ccstyle status
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Configuration is stored in `~/.pi/agent/claude-code-style.json`:
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"mode": "on",
|
|
107
|
+
"excludeRenderers": [],
|
|
108
|
+
"fixedEditorFeatures": true
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
- `excludeRenderers` uses exact tool names. `Agent` always keeps its dedicated renderer.
|
|
113
|
+
- `fixedEditorFeatures: true` enables fixed-editor mouse scrolling, clicks, viewport mapping, and the back-to-bottom indicator.
|
|
114
|
+
- Set it to `false` to disable terminal mouse reporting and restore native terminal wheel scrolling. `Ctrl+End` remains available.
|
|
115
|
+
- Run `/reload` after editing the file manually.
|
|
116
|
+
|
|
117
|
+
### Structured questionnaires
|
|
118
|
+
|
|
119
|
+
Supports 1–4 questions, 2–4 options per question, single and multiple selection, custom answers, and optional Markdown previews. The TUI preserves transcript space; RPC / ACP environments fall back to native dialogs.
|
|
120
|
+
|
|
121
|
+
Questionnaire configuration is stored at `~/.config/rpiv-ask-user-question/config.json`. See [`extensions/ask-user-question/README.md`](./extensions/ask-user-question/README.md) for shortcuts and detailed behavior.
|
|
122
|
+
|
|
123
|
+
### `@` references
|
|
124
|
+
|
|
125
|
+
- Enter `@session:` to reference a previous Session.
|
|
126
|
+
- Enter `@agent-name` to delegate to a custom Agent.
|
|
127
|
+
- Compatible with `@bacnh85/pi-fff` and `@tintinweb/pi-subagents`.
|
|
128
|
+
- Session context is deduplicated and size-limited before injection.
|
|
129
|
+
|
|
130
|
+
## Other installation methods
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# GitHub
|
|
134
|
+
pi install git:github.com/minuque/pi-cc-extensions
|
|
135
|
+
|
|
136
|
+
# Local repository
|
|
137
|
+
pi install /absolute/path/to/pi-cc-extensions
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Local development
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
npm test
|
|
144
|
+
npm run typecheck
|
|
145
|
+
pi -e .
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Run `/reload` after changing extensions. Changes under `extensions/ask-user-question/`, or reinstalling its dependencies, require a full Pi restart.
|
|
149
|
+
|
|
150
|
+
## Compatibility
|
|
151
|
+
|
|
152
|
+
- Node.js `>=22.19.0`
|
|
153
|
+
- Loaded through `pi.extensions` and `pi.themes` in the root `package.json`
|
|
154
|
+
- If a Pi, TUI, or `pi-zentui` update causes display issues, try `/reload` first
|
|
155
|
+
|
|
156
|
+
## Recommended companions
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
| Extension | Purpose |
|
|
160
|
+
| ------------------------------- | -------------------------------------------------------------- |
|
|
161
|
+
| `npm:pi-zentui` | Fixed editor, status line, and Git status |
|
|
162
|
+
| `npm:@tintinweb/pi-subagents` | Parallel SubAgents, background tasks, and worktree isolation |
|
|
163
|
+
| `npm:pi-mcp-adapter` | On-demand MCP tool discovery with lower context usage |
|
|
164
|
+
| `npm:pi-theme-picker` | Theme search and live preview |
|
|
165
|
+
| `npm:@ayulab/pi-rewind` | Checkpoint-based code or conversation rollback |
|
|
166
|
+
| `npm:pi-compact-thinking` | Compact rendering for hidden thinking blocks |
|
|
167
|
+
|
|
168
|
+
## Credits
|
|
169
|
+
|
|
170
|
+
- Compact transcript behavior is based on [`avhagedorn/pi-compact-transcript`](https://github.com/avhagedorn/pi-compact-transcript) v0.6.2 (MIT).
|
|
171
|
+
- Structured questionnaires are based on [`@juicesharp/rpiv-ask-user-question`](https://github.com/juicesharp/rpiv-mono/tree/main/packages/rpiv-ask-user-question) v2.1.0 (MIT).
|
|
172
|
+
- Rich diffs are adapted from [`MasuRii/pi-tool-display`](https://github.com/MasuRii/pi-tool-display) (MIT). See [`extensions/tool-diff/ATTRIBUTION.md`](./extensions/tool-diff/ATTRIBUTION.md).
|
|
173
|
+
- Startup header based on [`EnderLiquid/pi-startup-header`](https://github.com/EnderLiquid/pi-startup-header) (MIT).
|
|
174
|
+
- Command aliases based on [`xRyul/pi-aliases`](https://github.com/xRyul/pi-aliases) (MIT).
|
package/README.md
CHANGED
|
@@ -1,115 +1,115 @@
|
|
|
1
|
-
<p align="center">
|
|
2
|
-
<img src="./assets/readme/hero.svg" width="100%" alt="pi-cc-extensions:Pi 终端效率扩展套件">
|
|
3
|
-
</p>
|
|
4
|
-
|
|
5
|
-
<p align="center">
|
|
6
|
-
<a href="https://pi.dev/packages?name=pi-cc-extensions"><img alt="Pi package catalog" src="https://img.shields.io/badge/Pi-package-58B7FF?style=flat-square"></a>
|
|
7
|
-
<a href="https://www.npmjs.com/package/pi-cc-extensions"><img alt="npm version" src="https://img.shields.io/npm/v/pi-cc-extensions?style=flat-square&color=66E3C4"></a>
|
|
8
|
-
<a href="#兼容性"><img alt="Node.js 22.19 or newer" src="https://img.shields.io/badge/Node.js-%E2%89%A522.19-66E3C4?style=flat-square"></a>
|
|
9
|
-
<a href="./extensions"><img alt="TypeScript extensions" src="https://img.shields.io/badge/TypeScript-extensions-3178C6?style=flat-square"></a>
|
|
10
|
-
</p>
|
|
11
|
-
|
|
12
|
-
<p align="center">
|
|
13
|
-
Claude Code 风格界面、结构化问卷、上下文检查,以及 Agent / Session 引用。
|
|
14
|
-
</p>
|
|
15
|
-
|
|
16
|
-
<p align="center">
|
|
17
|
-
<strong>简体中文</strong> · <a href="./README.en.md">English</a>
|
|
18
|
-
</p>
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## 界面预览
|
|
23
|
-
|
|
24
|
-
<table>
|
|
25
|
-
<tr>
|
|
26
|
-
<td colspan="2" align="center">
|
|
27
|
-
<img src="./assets/readme/welcome.webp" width="100%" alt="Pi 启动后的欢迎界面">
|
|
28
|
-
<br>
|
|
29
|
-
<sub><b>欢迎界面</b><br> @ <code>npm:pi-startup-header</code> 与 <code>npm:pi-zentui</code></sub>
|
|
30
|
-
</td>
|
|
31
|
-
</tr>
|
|
32
|
-
<tr>
|
|
33
|
-
<td width="50%" align="center">
|
|
34
|
-
<img src="./assets/readme/fixed-editor-navigation.webp" width="100%" alt="Pi fixed-editor 中的工具结果、回到底部按钮与 Ctrl+End 快捷键">
|
|
35
|
-
<br>
|
|
36
|
-
<sub><b>固定编辑器工作流</b><br>工具结果摘要、折叠展开与键盘导航</sub>
|
|
37
|
-
</td>
|
|
38
|
-
<td width="50%" align="center">
|
|
39
|
-
<img src="./assets/readme/session-reference.webp" width="100%" alt="在 Pi 中通过 @ 补全选择历史 Session">
|
|
40
|
-
<br>
|
|
41
|
-
<sub><b>历史 Session 引用</b><br>通过 @ 补全快速找到并引用历史会话</sub>
|
|
42
|
-
</td>
|
|
43
|
-
</tr>
|
|
44
|
-
<tr>
|
|
45
|
-
<td width="50%" align="center">
|
|
46
|
-
<img src="./assets/readme/context-usage.webp" width="100%" alt="Pi 上下文窗口用量查看器">
|
|
47
|
-
<br>
|
|
48
|
-
<sub><b>上下文用量</b><br>查看 System prompt、Tools、Skills 等占用分布</sub>
|
|
49
|
-
</td>
|
|
50
|
-
<td width="50%" align="center">
|
|
51
|
-
<img src="./assets/readme/context-preview.webp" width="100%" alt="Pi 中展开查看 System Prompt 内容">
|
|
52
|
-
<br>
|
|
53
|
-
<sub><b>上下文预览</b><br>按类别展开查看实际注入的上下文内容</sub>
|
|
54
|
-
</td>
|
|
55
|
-
</tr>
|
|
56
|
-
</table>
|
|
57
|
-
|
|
58
|
-
## 快速开始
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
pi install npm:pi-cc-extensions
|
|
62
|
-
|
|
63
|
-
# GitHub
|
|
64
|
-
pi install git:github.com/minuque/pi-cc-extensions
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
安装后执行 `/reload`
|
|
68
|
-
|
|
69
|
-
## 功能
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
| 功能 | 说明 | 入口 |
|
|
73
|
-
| ------------------------------ | --------------------------------------------------------------------------------- | --------------------- |
|
|
74
|
-
| Claude Code 风格输出 | 工具摘要、折叠展开、rich edit/write diff,以及`on` / `off` / `compact` 三种模式 | `/ccstyle` |
|
|
75
|
-
| Fixed editor 交互 | 每刻度 5 行滚动、工具点击、收起位置补偿、回到底部按钮与`Ctrl+End` | `/ccstyle` |
|
|
76
|
-
| Ask User Question 结构化问卷 | 单选、多选、自定义回答、Markdown 预览及 RPC / ACP 降级 | `ask_user_question` |
|
|
77
|
-
| 上下文检查 | 查看上下文占用,并预览 System prompt、Tools、Skills 和消息内容 | `/context` |
|
|
78
|
-
| Session 引用 | 搜索并注入历史 Session 或现有 SubAgent 的有效上下文 | `@session:` |
|
|
79
|
-
| 主题 | 随包提供内置 GitHub Dark Default 主题 | `/theme` |
|
|
80
|
-
|
|
81
|
-
## 本地开发
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
npm test
|
|
85
|
-
npm run typecheck
|
|
86
|
-
pi -e .
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
修改扩展后执行 `/reload`。修改 `extensions/ask-user-question/` 或重装其依赖后,需要完整重启 Pi。
|
|
90
|
-
|
|
91
|
-
## 兼容性
|
|
92
|
-
|
|
93
|
-
- Node.js `>=22.19.0`
|
|
94
|
-
- 通过根目录 `package.json` 的 `pi.extensions` 和 `pi.themes` 加载
|
|
95
|
-
- `pi-zentui`、Pi 或 TUI 内部实现升级后若显示异常,先执行 `/reload`
|
|
96
|
-
|
|
97
|
-
## 推荐搭配
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
| 扩展 | 用途 |
|
|
101
|
-
| ------------------------------- | ------------------------------------- |
|
|
102
|
-
| `npm:pi-zentui` | Fixed editor、状态栏和 Git 状态 |
|
|
103
|
-
| `npm:@tintinweb/pi-subagents` | 并行 SubAgent、后台任务与工作树隔离 |
|
|
104
|
-
| `npm:pi-mcp-adapter` | 按需发现 MCP 工具,减少上下文占用 |
|
|
105
|
-
| `npm:pi-theme-picker` | 主题搜索和实时预览 |
|
|
106
|
-
| `npm:@ayulab/pi-rewind` | 基于 checkpoint 回退代码或对话 |
|
|
107
|
-
| `npm:pi-compact-thinking` | 紧凑显示隐藏的 thinking 块 |
|
|
108
|
-
|
|
109
|
-
## 致谢
|
|
110
|
-
|
|
111
|
-
- Compact transcript 基于 [`avhagedorn/pi-compact-transcript`](https://github.com/avhagedorn/pi-compact-transcript) v0.6.2(MIT)。
|
|
112
|
-
- 结构化问卷基于 [`@juicesharp/rpiv-ask-user-question`](https://github.com/juicesharp/rpiv-mono/tree/main/packages/rpiv-ask-user-question) v2.1.0(MIT)。
|
|
113
|
-
- Rich diff 改编自 [`MasuRii/pi-tool-display`](https://github.com/MasuRii/pi-tool-display)(MIT);详见 [`extensions/tool-diff/ATTRIBUTION.md`](./extensions/tool-diff/ATTRIBUTION.md)。
|
|
114
|
-
- 启动头基于 [`EnderLiquid/pi-startup-header`](https://github.com/EnderLiquid/pi-startup-header)(MIT)。
|
|
115
|
-
- 命令别名基于 [`xRyul/pi-aliases`](https://github.com/xRyul/pi-aliases)(MIT)。
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="./assets/readme/hero.svg" width="100%" alt="pi-cc-extensions:Pi 终端效率扩展套件">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://pi.dev/packages?name=pi-cc-extensions"><img alt="Pi package catalog" src="https://img.shields.io/badge/Pi-package-58B7FF?style=flat-square"></a>
|
|
7
|
+
<a href="https://www.npmjs.com/package/pi-cc-extensions"><img alt="npm version" src="https://img.shields.io/npm/v/pi-cc-extensions?style=flat-square&color=66E3C4"></a>
|
|
8
|
+
<a href="#兼容性"><img alt="Node.js 22.19 or newer" src="https://img.shields.io/badge/Node.js-%E2%89%A522.19-66E3C4?style=flat-square"></a>
|
|
9
|
+
<a href="./extensions"><img alt="TypeScript extensions" src="https://img.shields.io/badge/TypeScript-extensions-3178C6?style=flat-square"></a>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
Claude Code 风格界面、结构化问卷、上下文检查,以及 Agent / Session 引用。
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<strong>简体中文</strong> · <a href="./README.en.md">English</a>
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 界面预览
|
|
23
|
+
|
|
24
|
+
<table>
|
|
25
|
+
<tr>
|
|
26
|
+
<td colspan="2" align="center">
|
|
27
|
+
<img src="./assets/readme/welcome.webp" width="100%" alt="Pi 启动后的欢迎界面">
|
|
28
|
+
<br>
|
|
29
|
+
<sub><b>欢迎界面</b><br> @ <code>npm:pi-startup-header</code> 与 <code>npm:pi-zentui</code></sub>
|
|
30
|
+
</td>
|
|
31
|
+
</tr>
|
|
32
|
+
<tr>
|
|
33
|
+
<td width="50%" align="center">
|
|
34
|
+
<img src="./assets/readme/fixed-editor-navigation.webp" width="100%" alt="Pi fixed-editor 中的工具结果、回到底部按钮与 Ctrl+End 快捷键">
|
|
35
|
+
<br>
|
|
36
|
+
<sub><b>固定编辑器工作流</b><br>工具结果摘要、折叠展开与键盘导航</sub>
|
|
37
|
+
</td>
|
|
38
|
+
<td width="50%" align="center">
|
|
39
|
+
<img src="./assets/readme/session-reference.webp" width="100%" alt="在 Pi 中通过 @ 补全选择历史 Session">
|
|
40
|
+
<br>
|
|
41
|
+
<sub><b>历史 Session 引用</b><br>通过 @ 补全快速找到并引用历史会话</sub>
|
|
42
|
+
</td>
|
|
43
|
+
</tr>
|
|
44
|
+
<tr>
|
|
45
|
+
<td width="50%" align="center">
|
|
46
|
+
<img src="./assets/readme/context-usage.webp" width="100%" alt="Pi 上下文窗口用量查看器">
|
|
47
|
+
<br>
|
|
48
|
+
<sub><b>上下文用量</b><br>查看 System prompt、Tools、Skills 等占用分布</sub>
|
|
49
|
+
</td>
|
|
50
|
+
<td width="50%" align="center">
|
|
51
|
+
<img src="./assets/readme/context-preview.webp" width="100%" alt="Pi 中展开查看 System Prompt 内容">
|
|
52
|
+
<br>
|
|
53
|
+
<sub><b>上下文预览</b><br>按类别展开查看实际注入的上下文内容</sub>
|
|
54
|
+
</td>
|
|
55
|
+
</tr>
|
|
56
|
+
</table>
|
|
57
|
+
|
|
58
|
+
## 快速开始
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pi install npm:pi-cc-extensions
|
|
62
|
+
|
|
63
|
+
# GitHub
|
|
64
|
+
pi install git:github.com/minuque/pi-cc-extensions
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
安装后执行 `/reload`
|
|
68
|
+
|
|
69
|
+
## 功能
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
| 功能 | 说明 | 入口 |
|
|
73
|
+
| ------------------------------ | --------------------------------------------------------------------------------- | --------------------- |
|
|
74
|
+
| Claude Code 风格输出 | 工具摘要、折叠展开、rich edit/write diff,以及`on` / `off` / `compact` 三种模式 | `/ccstyle` |
|
|
75
|
+
| Fixed editor 交互 | 每刻度 5 行滚动、工具点击、收起位置补偿、回到底部按钮与`Ctrl+End` | `/ccstyle` |
|
|
76
|
+
| Ask User Question 结构化问卷 | 单选、多选、自定义回答、Markdown 预览及 RPC / ACP 降级 | `ask_user_question` |
|
|
77
|
+
| 上下文检查 | 查看上下文占用,并预览 System prompt、Tools、Skills 和消息内容 | `/context` |
|
|
78
|
+
| Session 引用 | 搜索并注入历史 Session 或现有 SubAgent 的有效上下文 | `@session:` |
|
|
79
|
+
| 主题 | 随包提供内置 GitHub Dark Default 主题 | `/theme` |
|
|
80
|
+
|
|
81
|
+
## 本地开发
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npm test
|
|
85
|
+
npm run typecheck
|
|
86
|
+
pi -e .
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
修改扩展后执行 `/reload`。修改 `extensions/ask-user-question/` 或重装其依赖后,需要完整重启 Pi。
|
|
90
|
+
|
|
91
|
+
## 兼容性
|
|
92
|
+
|
|
93
|
+
- Node.js `>=22.19.0`
|
|
94
|
+
- 通过根目录 `package.json` 的 `pi.extensions` 和 `pi.themes` 加载
|
|
95
|
+
- `pi-zentui`、Pi 或 TUI 内部实现升级后若显示异常,先执行 `/reload`
|
|
96
|
+
|
|
97
|
+
## 推荐搭配
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
| 扩展 | 用途 |
|
|
101
|
+
| ------------------------------- | ------------------------------------- |
|
|
102
|
+
| `npm:pi-zentui` | Fixed editor、状态栏和 Git 状态 |
|
|
103
|
+
| `npm:@tintinweb/pi-subagents` | 并行 SubAgent、后台任务与工作树隔离 |
|
|
104
|
+
| `npm:pi-mcp-adapter` | 按需发现 MCP 工具,减少上下文占用 |
|
|
105
|
+
| `npm:pi-theme-picker` | 主题搜索和实时预览 |
|
|
106
|
+
| `npm:@ayulab/pi-rewind` | 基于 checkpoint 回退代码或对话 |
|
|
107
|
+
| `npm:pi-compact-thinking` | 紧凑显示隐藏的 thinking 块 |
|
|
108
|
+
|
|
109
|
+
## 致谢
|
|
110
|
+
|
|
111
|
+
- Compact transcript 基于 [`avhagedorn/pi-compact-transcript`](https://github.com/avhagedorn/pi-compact-transcript) v0.6.2(MIT)。
|
|
112
|
+
- 结构化问卷基于 [`@juicesharp/rpiv-ask-user-question`](https://github.com/juicesharp/rpiv-mono/tree/main/packages/rpiv-ask-user-question) v2.1.0(MIT)。
|
|
113
|
+
- Rich diff 改编自 [`MasuRii/pi-tool-display`](https://github.com/MasuRii/pi-tool-display)(MIT);详见 [`extensions/tool-diff/ATTRIBUTION.md`](./extensions/tool-diff/ATTRIBUTION.md)。
|
|
114
|
+
- 启动头基于 [`EnderLiquid/pi-startup-header`](https://github.com/EnderLiquid/pi-startup-header)(MIT)。
|
|
115
|
+
- 命令别名基于 [`xRyul/pi-aliases`](https://github.com/xRyul/pi-aliases)(MIT)。
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { bottomDialogBounds, isDialogCloseClick } from "../../closable-dialog.ts";
|
|
2
3
|
import { getKeybindings, type Input } from "@earendil-works/pi-tui";
|
|
3
4
|
import type { QuestionData, QuestionnaireResult, QuestionParams } from "../tool/types.js";
|
|
4
5
|
import type { WrappingSelectItem } from "../view/components/wrapping-select.js";
|
|
@@ -93,10 +94,26 @@ export class QuestionnaireSession {
|
|
|
93
94
|
// so the transcript regains space while Ctrl+] can still expand the questionnaire.
|
|
94
95
|
const collapsedRender = (_width: number): string[] => [theme.fg("dim", ` ${COLLAPSED_HINT} `)];
|
|
95
96
|
|
|
97
|
+
let lastWidth = 0;
|
|
98
|
+
let lastHeight = 0;
|
|
96
99
|
this.component = {
|
|
97
|
-
render: (width) =>
|
|
100
|
+
render: (width) => {
|
|
101
|
+
const lines = this.state.collapsed ? collapsedRender(width) : built.render(width);
|
|
102
|
+
lastWidth = width;
|
|
103
|
+
lastHeight = lines.length;
|
|
104
|
+
return lines;
|
|
105
|
+
},
|
|
98
106
|
invalidate: built.invalidate,
|
|
99
|
-
handleInput: (data) =>
|
|
107
|
+
handleInput: (data) => {
|
|
108
|
+
if (
|
|
109
|
+
!this.state.collapsed &&
|
|
110
|
+
isDialogCloseClick(data, bottomDialogBounds(this.tui.terminal, lastWidth, lastHeight))
|
|
111
|
+
) {
|
|
112
|
+
this.dispatch("\x1b");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
this.dispatch(data);
|
|
116
|
+
},
|
|
100
117
|
};
|
|
101
118
|
|
|
102
119
|
this.viewAdapter.apply(this.state);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DynamicBorder, type Theme } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { renderDialogHeader, renderDialogTopBorder } from "../../closable-dialog.ts";
|
|
2
3
|
import { type Component, Container, type Input, Spacer } from "@earendil-works/pi-tui";
|
|
3
4
|
import type { QuestionnaireState } from "../state/state.js";
|
|
4
5
|
import type { QuestionData } from "../tool/types.js";
|
|
@@ -133,10 +134,24 @@ export class DialogView implements StatefulView<DialogProps> {
|
|
|
133
134
|
// Render only the active tab's natural content; blank height equalization would
|
|
134
135
|
// unnecessarily consume transcript rows above this full-width editor component.
|
|
135
136
|
const natural = this.buildContainerFromStrategy(strategy, headingRowCache).render(width);
|
|
137
|
+
if (natural.length > 0) {
|
|
138
|
+
natural[0] = renderDialogTopBorder(width, (text) => this.config.theme.fg("accent", text));
|
|
139
|
+
natural.splice(
|
|
140
|
+
1,
|
|
141
|
+
0,
|
|
142
|
+
renderDialogHeader(
|
|
143
|
+
" Questions",
|
|
144
|
+
width,
|
|
145
|
+
(text) => this.config.theme.fg("accent", text),
|
|
146
|
+
(text) => this.config.theme.fg("toolTitle", text),
|
|
147
|
+
(text) => this.config.theme.fg("muted", text),
|
|
148
|
+
),
|
|
149
|
+
);
|
|
150
|
+
}
|
|
136
151
|
|
|
137
152
|
// Fixed region sizes (deterministic from structure).
|
|
138
153
|
// TabBar.render() returns [tabLine, ""] — always 2 rows.
|
|
139
|
-
const topFixed =
|
|
154
|
+
const topFixed = 2 + (this.config.isMulti && this.config.tabBar ? 2 : 0) + 1;
|
|
140
155
|
const bottomFixed = 1 + strategy.footerRowCount;
|
|
141
156
|
const middleRows = natural.length - topFixed - bottomFixed;
|
|
142
157
|
|
|
@@ -29,6 +29,12 @@ import {
|
|
|
29
29
|
wrapTextWithAnsi,
|
|
30
30
|
} from "@earendil-works/pi-tui";
|
|
31
31
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
32
|
+
import {
|
|
33
|
+
bottomDialogBounds,
|
|
34
|
+
isDialogCloseClick,
|
|
35
|
+
renderDialogHeader,
|
|
36
|
+
renderDialogTopBorder,
|
|
37
|
+
} from "./closable-dialog.ts";
|
|
32
38
|
import { homedir } from "node:os";
|
|
33
39
|
import { join } from "node:path";
|
|
34
40
|
|
|
@@ -1974,6 +1980,8 @@ async function showCcstylePanel(ctx: any, compactStyle: CompactStyleHooks): Prom
|
|
|
1974
1980
|
];
|
|
1975
1981
|
|
|
1976
1982
|
let activeSection = 0;
|
|
1983
|
+
let lastWidth = 0;
|
|
1984
|
+
let lastHeight = 0;
|
|
1977
1985
|
const settingsTheme = getSettingsListTheme();
|
|
1978
1986
|
const lists = sections.map(
|
|
1979
1987
|
(section) =>
|
|
@@ -2010,8 +2018,15 @@ async function showCcstylePanel(ctx: any, compactStyle: CompactStyleHooks): Prom
|
|
|
2010
2018
|
while (listBody.length > 0 && listBody[listBody.length - 1] === "") listBody.pop();
|
|
2011
2019
|
|
|
2012
2020
|
// Frame: top rule · tabs · mid rule · settings · mid rule · footer · bottom rule
|
|
2013
|
-
|
|
2014
|
-
|
|
2021
|
+
const lines = [
|
|
2022
|
+
renderDialogTopBorder(safeWidth, (text) => theme.fg("border", text)),
|
|
2023
|
+
renderDialogHeader(
|
|
2024
|
+
" CC Style",
|
|
2025
|
+
safeWidth,
|
|
2026
|
+
(text) => theme.fg("border", text),
|
|
2027
|
+
(text) => theme.fg("toolTitle", text),
|
|
2028
|
+
(text) => theme.fg("muted", text),
|
|
2029
|
+
),
|
|
2015
2030
|
renderSectionTabBar(theme, sections, activeSection, safeWidth),
|
|
2016
2031
|
rule,
|
|
2017
2032
|
...listBody,
|
|
@@ -2025,11 +2040,22 @@ async function showCcstylePanel(ctx: any, compactStyle: CompactStyleHooks): Prom
|
|
|
2025
2040
|
),
|
|
2026
2041
|
rule,
|
|
2027
2042
|
];
|
|
2043
|
+
lastWidth = safeWidth;
|
|
2044
|
+
lastHeight = lines.length;
|
|
2045
|
+
return lines;
|
|
2028
2046
|
},
|
|
2029
2047
|
invalidate() {
|
|
2030
2048
|
for (const list of lists) list.invalidate();
|
|
2031
2049
|
},
|
|
2032
2050
|
handleInput(data: string) {
|
|
2051
|
+
if (
|
|
2052
|
+
!excludeSubmenuOpen &&
|
|
2053
|
+
tui.terminal &&
|
|
2054
|
+
isDialogCloseClick(data, bottomDialogBounds(tui.terminal, lastWidth, lastHeight))
|
|
2055
|
+
) {
|
|
2056
|
+
done();
|
|
2057
|
+
return;
|
|
2058
|
+
}
|
|
2033
2059
|
if (!excludeSubmenuOpen && isForwardTabKey(data)) {
|
|
2034
2060
|
switchSection(1);
|
|
2035
2061
|
tui.requestRender();
|
|
@@ -2056,28 +2082,39 @@ function renderDefault(tool: any, slot: "renderCall" | "renderResult", args: any
|
|
|
2056
2082
|
return new Text(fallback, 0, 0);
|
|
2057
2083
|
}
|
|
2058
2084
|
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2085
|
+
function singleLine(text: string) {
|
|
2086
|
+
return {
|
|
2087
|
+
render: (width: number) => [truncateToWidth(text, width, "…")],
|
|
2088
|
+
invalidate() {},
|
|
2089
|
+
};
|
|
2090
|
+
}
|
|
2091
|
+
|
|
2092
|
+
/** Return the most useful scalar argument without semantically truncating it. */
|
|
2093
|
+
function toolCallArgument(args: any): { key: string; value: string } | undefined {
|
|
2094
|
+
if (!args) return undefined;
|
|
2065
2095
|
const keys = Object.keys(args);
|
|
2066
|
-
if (keys.length === 0) return
|
|
2067
|
-
// Prefer "query" or "question" args, then fall back to the first stringable value
|
|
2096
|
+
if (keys.length === 0) return undefined;
|
|
2068
2097
|
const preferred = ["query", "question", "command", "pattern", "name", "path", "url", "message"];
|
|
2069
|
-
|
|
2070
|
-
const val = args[
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2098
|
+
const key = preferred.find((candidate) => {
|
|
2099
|
+
const val = args[candidate];
|
|
2100
|
+
return val !== undefined && val !== null && typeof val !== "object";
|
|
2101
|
+
});
|
|
2102
|
+
const selected = key ?? keys[0];
|
|
2103
|
+
const value = args[selected];
|
|
2104
|
+
return value !== undefined && value !== null && typeof value !== "object"
|
|
2105
|
+
? { key: selected, value: oneLine(value, Infinity) }
|
|
2106
|
+
: undefined;
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
function tailToWidth(text: string, width: number): string {
|
|
2110
|
+
if (visibleWidth(text) <= width) return text;
|
|
2111
|
+
if (width <= 1) return "…";
|
|
2112
|
+
let tail = "";
|
|
2113
|
+
for (const char of Array.from(text).reverse()) {
|
|
2114
|
+
if (visibleWidth(`…${char}${tail}`) > width) break;
|
|
2115
|
+
tail = char + tail;
|
|
2079
2116
|
}
|
|
2080
|
-
return
|
|
2117
|
+
return `…${tail}`;
|
|
2081
2118
|
}
|
|
2082
2119
|
|
|
2083
2120
|
export function shouldRenderRichDiff(
|
|
@@ -2117,8 +2154,21 @@ function createCcstyleTool(
|
|
|
2117
2154
|
? `${BRIGHT_GREEN}${rawIcon}${ANSI_RESET}`
|
|
2118
2155
|
: theme.fg(toolIconColor(context), rawIcon);
|
|
2119
2156
|
|
|
2120
|
-
const
|
|
2121
|
-
return
|
|
2157
|
+
const argument = toolCallArgument(args);
|
|
2158
|
+
return {
|
|
2159
|
+
render(width: number) {
|
|
2160
|
+
const argumentWidth = Math.max(1, width - visibleWidth(`${rawIcon} ${label}()`));
|
|
2161
|
+
const shown = argument
|
|
2162
|
+
? argument.key === "path"
|
|
2163
|
+
? tailToWidth(argument.value, argumentWidth)
|
|
2164
|
+
: truncateToWidth(argument.value, argumentWidth, "…")
|
|
2165
|
+
: undefined;
|
|
2166
|
+
const call = shown === undefined ? label : `${label}(${shown})`;
|
|
2167
|
+
const callWidth = Math.max(0, width - visibleWidth(icon) - 1);
|
|
2168
|
+
return [`${icon} ${theme.fg("toolTitle", truncateToWidth(call, callWidth, "…"))}`];
|
|
2169
|
+
},
|
|
2170
|
+
invalidate() {},
|
|
2171
|
+
};
|
|
2122
2172
|
},
|
|
2123
2173
|
renderResult(result: any, options: any, theme: any, context: any) {
|
|
2124
2174
|
if (config.mode !== "on") {
|
|
@@ -2168,10 +2218,8 @@ function createCcstyleTool(
|
|
|
2168
2218
|
);
|
|
2169
2219
|
}
|
|
2170
2220
|
if (context?.state) context.state.ccstyleIoView = undefined;
|
|
2171
|
-
return
|
|
2221
|
+
return singleLine(
|
|
2172
2222
|
theme.fg(isError ? "error" : "muted", renderCollapsedToolResult(rendered, hint)),
|
|
2173
|
-
0,
|
|
2174
|
-
0,
|
|
2175
2223
|
);
|
|
2176
2224
|
},
|
|
2177
2225
|
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
2
|
+
|
|
3
|
+
export type DialogBounds = { left: number; top: number; width: number };
|
|
4
|
+
|
|
5
|
+
export function renderDialogTopBorder(width: number, color: (text: string) => string): string {
|
|
6
|
+
const safeWidth = Math.max(4, Math.floor(width));
|
|
7
|
+
return color(`╭${"─".repeat(safeWidth - 2)}╮`);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** Render title and a larger [ × ] target on the row below the top border. */
|
|
11
|
+
export function renderDialogHeader(
|
|
12
|
+
title: string,
|
|
13
|
+
width: number,
|
|
14
|
+
color: (text: string) => string,
|
|
15
|
+
titleColor: (text: string) => string,
|
|
16
|
+
closeColor: (text: string) => string,
|
|
17
|
+
): string {
|
|
18
|
+
const safeWidth = Math.max(8, Math.floor(width));
|
|
19
|
+
const innerWidth = safeWidth - 2;
|
|
20
|
+
const button = "[ × ]";
|
|
21
|
+
const titleWidth = Math.max(0, innerWidth - visibleWidth(button) - 2);
|
|
22
|
+
const shownTitle = truncateToWidth(title, titleWidth, "…");
|
|
23
|
+
const gap = " ".repeat(Math.max(1, innerWidth - visibleWidth(shownTitle) - visibleWidth(button)));
|
|
24
|
+
return `${color("│")}${titleColor(shownTitle)}${gap}${closeColor(button)}${color("│")}`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Match a left-button press anywhere on the [ × ] target. */
|
|
28
|
+
export function isDialogCloseClick(data: string, bounds: DialogBounds): boolean {
|
|
29
|
+
const match = data.match(/^\x1b\[<(\d+);(\d+);(\d+)([Mm])$/);
|
|
30
|
+
if (!match || match[4] !== "M") return false;
|
|
31
|
+
const code = Number(match[1]);
|
|
32
|
+
if ((code & 3) !== 0 || (code & 32) !== 0) return false;
|
|
33
|
+
const col = Number(match[2]);
|
|
34
|
+
const firstButtonCol = bounds.left + bounds.width - 7;
|
|
35
|
+
const lastButtonCol = bounds.left + bounds.width - 3;
|
|
36
|
+
return col >= firstButtonCol && col <= lastButtonCol && Number(match[3]) === bounds.top + 1;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function centeredDialogBounds(
|
|
40
|
+
terminal: { columns: number; rows: number },
|
|
41
|
+
width: number,
|
|
42
|
+
height: number,
|
|
43
|
+
): DialogBounds {
|
|
44
|
+
return {
|
|
45
|
+
left: Math.floor((terminal.columns - width) / 2) + 1,
|
|
46
|
+
top: Math.floor((terminal.rows - height) / 2) + 1,
|
|
47
|
+
width,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function bottomDialogBounds(
|
|
52
|
+
terminal: { rows: number },
|
|
53
|
+
width: number,
|
|
54
|
+
height: number,
|
|
55
|
+
): DialogBounds {
|
|
56
|
+
return { left: 1, top: Math.max(1, terminal.rows - height + 1), width };
|
|
57
|
+
}
|
package/extensions/context.ts
CHANGED
|
@@ -10,6 +10,12 @@ import {
|
|
|
10
10
|
visibleWidth,
|
|
11
11
|
wrapTextWithAnsi,
|
|
12
12
|
} from "@earendil-works/pi-tui";
|
|
13
|
+
import {
|
|
14
|
+
centeredDialogBounds,
|
|
15
|
+
isDialogCloseClick,
|
|
16
|
+
renderDialogHeader,
|
|
17
|
+
renderDialogTopBorder,
|
|
18
|
+
} from "./closable-dialog.ts";
|
|
13
19
|
|
|
14
20
|
export type ContextPart = {
|
|
15
21
|
label: string;
|
|
@@ -65,6 +71,8 @@ export async function showTextPreview(
|
|
|
65
71
|
let scrollOffset = 0;
|
|
66
72
|
let pageSize = 1;
|
|
67
73
|
let totalLines = 1;
|
|
74
|
+
let lastWidth = 0;
|
|
75
|
+
let lastHeight = 0;
|
|
68
76
|
const wrappedContent = createWrappedTextCache(content);
|
|
69
77
|
|
|
70
78
|
const scrollTo = (nextOffset: number): void => {
|
|
@@ -77,6 +85,10 @@ export async function showTextPreview(
|
|
|
77
85
|
wrappedContent.invalidate();
|
|
78
86
|
},
|
|
79
87
|
handleInput(data: string) {
|
|
88
|
+
if (isDialogCloseClick(data, centeredDialogBounds(tui.terminal, lastWidth, lastHeight))) {
|
|
89
|
+
done(undefined);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
80
92
|
if (matchesKey(data, Key.escape) || matchesKey(data, Key.ctrl("c"))) {
|
|
81
93
|
done(undefined);
|
|
82
94
|
return;
|
|
@@ -138,15 +150,24 @@ export async function showTextPreview(
|
|
|
138
150
|
const end = Math.min(totalLines, scrollOffset + pageSize);
|
|
139
151
|
const status = `${start}-${end} / ${totalLines} lines · ↑↓ PgUp/PgDn Home/End · Esc close`;
|
|
140
152
|
|
|
141
|
-
|
|
142
|
-
border
|
|
143
|
-
|
|
153
|
+
const lines = [
|
|
154
|
+
renderDialogTopBorder(width, border),
|
|
155
|
+
renderDialogHeader(
|
|
156
|
+
` ${title}`,
|
|
157
|
+
width,
|
|
158
|
+
border,
|
|
159
|
+
(text) => theme.bold(theme.fg("accent", text)),
|
|
160
|
+
(text) => theme.fg("muted", text),
|
|
161
|
+
),
|
|
144
162
|
`${border("├")}${border("─".repeat(inner))}${border("┤")}`,
|
|
145
163
|
...bodyRows,
|
|
146
164
|
`${border("├")}${border("─".repeat(inner))}${border("┤")}`,
|
|
147
165
|
`${border("│")}${padLine(theme.fg("dim", ` ${status}`))}${border("│")}`,
|
|
148
166
|
border(`╰${"─".repeat(inner)}╯`),
|
|
149
167
|
];
|
|
168
|
+
lastWidth = width;
|
|
169
|
+
lastHeight = lines.length;
|
|
170
|
+
return lines;
|
|
150
171
|
},
|
|
151
172
|
};
|
|
152
173
|
},
|
package/package.json
CHANGED
|
@@ -1,69 +1,69 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "pi-cc-extensions",
|
|
3
|
-
"version": "0.8.
|
|
4
|
-
"description": "A Pi productivity suite with Claude Code-style UI, structured questionnaires, context inspection, and agent/session references",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"keywords": [
|
|
7
|
-
"pi-package",
|
|
8
|
-
"pi-extension",
|
|
9
|
-
"pi-coding-agent",
|
|
10
|
-
"claude-code",
|
|
11
|
-
"questionnaire"
|
|
12
|
-
],
|
|
13
|
-
"homepage": "https://github.com/minuque/pi-cc-extensions#readme",
|
|
14
|
-
"repository": {
|
|
15
|
-
"type": "git",
|
|
16
|
-
"url": "git+https://github.com/minuque/pi-cc-extensions.git"
|
|
17
|
-
},
|
|
18
|
-
"bugs": {
|
|
19
|
-
"url": "https://github.com/minuque/pi-cc-extensions/issues"
|
|
20
|
-
},
|
|
21
|
-
"files": [
|
|
22
|
-
"extensions",
|
|
23
|
-
"assets/readme",
|
|
24
|
-
"themes",
|
|
25
|
-
"README.md",
|
|
26
|
-
"README.en.md"
|
|
27
|
-
],
|
|
28
|
-
"pi": {
|
|
29
|
-
"extensions": [
|
|
30
|
-
"./extensions/pi-aliases.ts",
|
|
31
|
-
"./extensions/pi-startup-header.ts",
|
|
32
|
-
"./extensions/claude-code-style.ts",
|
|
33
|
-
"./extensions/context.ts",
|
|
34
|
-
"./extensions/session-reference.ts",
|
|
35
|
-
"./extensions/agent-autocomplete.ts",
|
|
36
|
-
"./extensions/ask-user-question/index.ts"
|
|
37
|
-
],
|
|
38
|
-
"themes": [
|
|
39
|
-
"./themes/github-dark-default.json"
|
|
40
|
-
],
|
|
41
|
-
"image": "https://raw.githubusercontent.com/minuque/pi-cc-extensions/main/assets/readme/welcome.webp"
|
|
42
|
-
},
|
|
43
|
-
"scripts": {
|
|
44
|
-
"test": "node --test tests/**/*.test.ts",
|
|
45
|
-
"typecheck": "node scripts/typecheck.mjs",
|
|
46
|
-
"format": "biome format --write .",
|
|
47
|
-
"format:check": "biome format .",
|
|
48
|
-
"preversion": "npm run format:check && npm run typecheck && npm test",
|
|
49
|
-
"release": "npm version patch && npm publish",
|
|
50
|
-
"release:minor": "npm version minor && npm publish",
|
|
51
|
-
"release:major": "npm version major && npm publish"
|
|
52
|
-
},
|
|
53
|
-
"dependencies": {
|
|
54
|
-
"@juicesharp/rpiv-config": "^2.1.0",
|
|
55
|
-
"typebox": "^1.1.24"
|
|
56
|
-
},
|
|
57
|
-
"peerDependencies": {
|
|
58
|
-
"@earendil-works/pi-ai": "*",
|
|
59
|
-
"@earendil-works/pi-coding-agent": "*",
|
|
60
|
-
"@earendil-works/pi-tui": "*"
|
|
61
|
-
},
|
|
62
|
-
"engines": {
|
|
63
|
-
"node": ">=22.19.0"
|
|
64
|
-
},
|
|
65
|
-
"devDependencies": {
|
|
66
|
-
"@biomejs/biome": "2.5.5",
|
|
67
|
-
"@types/node": "^26.1.1"
|
|
68
|
-
}
|
|
69
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-cc-extensions",
|
|
3
|
+
"version": "0.8.18",
|
|
4
|
+
"description": "A Pi productivity suite with Claude Code-style UI, structured questionnaires, context inspection, and agent/session references",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"pi-package",
|
|
8
|
+
"pi-extension",
|
|
9
|
+
"pi-coding-agent",
|
|
10
|
+
"claude-code",
|
|
11
|
+
"questionnaire"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://github.com/minuque/pi-cc-extensions#readme",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/minuque/pi-cc-extensions.git"
|
|
17
|
+
},
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/minuque/pi-cc-extensions/issues"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"extensions",
|
|
23
|
+
"assets/readme",
|
|
24
|
+
"themes",
|
|
25
|
+
"README.md",
|
|
26
|
+
"README.en.md"
|
|
27
|
+
],
|
|
28
|
+
"pi": {
|
|
29
|
+
"extensions": [
|
|
30
|
+
"./extensions/pi-aliases.ts",
|
|
31
|
+
"./extensions/pi-startup-header.ts",
|
|
32
|
+
"./extensions/claude-code-style.ts",
|
|
33
|
+
"./extensions/context.ts",
|
|
34
|
+
"./extensions/session-reference.ts",
|
|
35
|
+
"./extensions/agent-autocomplete.ts",
|
|
36
|
+
"./extensions/ask-user-question/index.ts"
|
|
37
|
+
],
|
|
38
|
+
"themes": [
|
|
39
|
+
"./themes/github-dark-default.json"
|
|
40
|
+
],
|
|
41
|
+
"image": "https://raw.githubusercontent.com/minuque/pi-cc-extensions/main/assets/readme/welcome.webp"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"test": "node --test tests/**/*.test.ts",
|
|
45
|
+
"typecheck": "node scripts/typecheck.mjs",
|
|
46
|
+
"format": "biome format --write .",
|
|
47
|
+
"format:check": "biome format .",
|
|
48
|
+
"preversion": "npm run format:check && npm run typecheck && npm test",
|
|
49
|
+
"release": "npm version patch && npm publish",
|
|
50
|
+
"release:minor": "npm version minor && npm publish",
|
|
51
|
+
"release:major": "npm version major && npm publish"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@juicesharp/rpiv-config": "^2.1.0",
|
|
55
|
+
"typebox": "^1.1.24"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"@earendil-works/pi-ai": "*",
|
|
59
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
60
|
+
"@earendil-works/pi-tui": "*"
|
|
61
|
+
},
|
|
62
|
+
"engines": {
|
|
63
|
+
"node": ">=22.19.0"
|
|
64
|
+
},
|
|
65
|
+
"devDependencies": {
|
|
66
|
+
"@biomejs/biome": "2.5.5",
|
|
67
|
+
"@types/node": "^26.1.1"
|
|
68
|
+
}
|
|
69
|
+
}
|