pi-extmgr 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -393
- package/package.json +2 -2
- package/src/ui/remote.ts +4 -2
- package/src/ui/unified.ts +3 -2
- package/src/utils/format.ts +30 -0
package/README.md
CHANGED
|
@@ -1,430 +1,83 @@
|
|
|
1
|
-
#
|
|
1
|
+
# pi-extmgr
|
|
2
2
|
|
|
3
|
-
<img width="2560" height="369" alt="image" src="https://i.imgur.com/
|
|
4
|
-
|
|
5
|
-
> Enhanced UI/UX for managing Pi extensions and discovering community packages
|
|
3
|
+
<img width="2560" height="369" alt="image" src="https://i.imgur.com/tTD31v8.png" />
|
|
6
4
|
|
|
7
5
|
[](https://github.com/ayagmar/pi-extmgr/actions/workflows/ci.yml)
|
|
8
6
|
[](https://opensource.org/licenses/MIT)
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<!-- Replace with actual demo GIF/Screenshot when available -->
|
|
13
|
-
<!--  -->
|
|
14
|
-
|
|
15
|
-
## ✨ Features
|
|
16
|
-
|
|
17
|
-
### 🎨 Interactive TUI Interface
|
|
18
|
-
|
|
19
|
-
- **Beautiful themed interface** with color-coded status indicators
|
|
20
|
-
- **Unified view** - local extensions and npm/git packages in one screen
|
|
21
|
-
- **Keyboard-driven navigation** - fast and efficient
|
|
22
|
-
- **Real-time previews** with package descriptions
|
|
23
|
-
- **Context-aware help** - press `?` anywhere for shortcuts
|
|
24
|
-
|
|
25
|
-
### 📋 Unified Extension Manager
|
|
26
|
-
|
|
27
|
-
All your extensions in one place:
|
|
28
|
-
|
|
29
|
-
- **Local extensions**: `● enabled` / `○ disabled` with `[G]` global or `[P]` project scope
|
|
30
|
-
- **Installed packages**: `◆` npm / `◇` git icon with name@version and size info
|
|
31
|
-
- **Visual distinction** between toggle-able locals and action-based packages
|
|
32
|
-
- **Smart deduplication** - packages already managed as local extensions are hidden
|
|
33
|
-
- **Theme adaptive UI** - Works consistently in dark and light themes
|
|
34
|
-
|
|
35
|
-
### 🔍 Smart Package Discovery
|
|
36
|
-
|
|
37
|
-
- **Browse community packages** with pagination (20 per page)
|
|
38
|
-
- **Cached search results** - npm metadata cached for 24 hours for fast navigation
|
|
39
|
-
- **Keyword filtering** - automatically shows `pi-package` tagged npm packages
|
|
40
|
-
- **Detailed package info** - view version, author, homepage, and install size
|
|
41
|
-
|
|
42
|
-
### 📦 Flexible Installation
|
|
43
|
-
|
|
44
|
-
- **Multiple source support**: npm, git, local paths
|
|
45
|
-
- **Two install modes**:
|
|
46
|
-
- **Managed** (npm) - Auto-updates with `pi update`, stored in pi's package cache
|
|
47
|
-
- **Standalone** (local) - Full package directory to `~/.pi/agent/extensions/{package}/`
|
|
48
|
-
- **Multi-file extension support** - Local install copies entire package directory, preserving imports
|
|
49
|
-
- **Auto-extract** from npm tarballs for local installs
|
|
50
|
-
- **One-click reload** after installation
|
|
51
|
-
|
|
52
|
-
### ⚡ Quick Extension Management
|
|
53
|
-
|
|
54
|
-
- **Enable/disable extensions** with staging (preview before applying)
|
|
55
|
-
- **Package actions** - update/remove/view details without leaving the manager
|
|
56
|
-
- **Visual change indicators** (`*`) show pending modifications
|
|
57
|
-
- **Bulk operations** - update all packages at once
|
|
58
|
-
- **Scope indicators**: Global (G) vs Project (P) for all items
|
|
59
|
-
|
|
60
|
-
### 📊 Extension Change History
|
|
8
|
+
A better way to manage Pi extensions. Browse, install, enable/disable, and remove extensions from one place.
|
|
61
9
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
- **Automatic logging** - Every toggle, install, update, and remove is recorded
|
|
65
|
-
- **Session persistence** - View change history with `/extensions history`
|
|
66
|
-
- **Statistics** - View totals by action type with `/extensions stats`
|
|
67
|
-
- **Error tracking** - Failed operations are logged with error details
|
|
68
|
-
|
|
69
|
-
### 🎯 Quality of Life
|
|
70
|
-
|
|
71
|
-
- **Tab autocomplete** for all subcommands
|
|
72
|
-
- **Status bar integration** - shows installed package count
|
|
73
|
-
- **Keyboard shortcut**: `Ctrl+Shift+E` opens extension manager
|
|
74
|
-
- **Non-interactive mode** - works in scripts and CI
|
|
75
|
-
- **Parallel data loading** - local extensions and packages fetched simultaneously
|
|
76
|
-
- **Metadata caching** - npm package info cached for 24 hours for faster browsing
|
|
77
|
-
|
|
78
|
-
## 🚀 Installation
|
|
10
|
+
## Install
|
|
79
11
|
|
|
80
12
|
```bash
|
|
81
13
|
pi install npm:pi-extmgr
|
|
82
14
|
```
|
|
83
15
|
|
|
84
|
-
Then reload Pi
|
|
16
|
+
Then reload Pi with `/reload`.
|
|
85
17
|
|
|
86
|
-
|
|
87
|
-
/reload
|
|
88
|
-
```
|
|
18
|
+
## What it does
|
|
89
19
|
|
|
90
|
-
|
|
20
|
+
- **Unified view**: See all your local extensions and installed npm/git packages in one list
|
|
21
|
+
- **Toggle extensions**: Enable/disable local extensions with Space/Enter, save with `S`
|
|
22
|
+
- **Package actions**: Update or remove installed packages with `A`
|
|
23
|
+
- **Browse community**: Search and install from npm (`R` to browse)
|
|
24
|
+
- **History tracking**: See what you've changed with `/extensions history`
|
|
91
25
|
|
|
92
|
-
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
Open the manager:
|
|
93
29
|
|
|
94
30
|
```
|
|
95
|
-
/extensions
|
|
31
|
+
/extensions
|
|
96
32
|
```
|
|
97
33
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
- **Local extensions** first (toggle-able)
|
|
101
|
-
- **Installed packages** second (action-based)
|
|
102
|
-
- Sorted alphabetically within each group
|
|
103
|
-
|
|
104
|
-
#### Keyboard Shortcuts
|
|
105
|
-
|
|
106
|
-
| Key | Action |
|
|
107
|
-
| ------------- | --------------------------------------------------- |
|
|
108
|
-
| `↑↓` | Navigate items |
|
|
109
|
-
| `Space/Enter` | Toggle local extension on/off |
|
|
110
|
-
| `S` | Save changes to local extensions |
|
|
111
|
-
| `A` | Actions on selected package (update/remove/details) |
|
|
112
|
-
| `R` | Browse remote packages |
|
|
113
|
-
| `?` / `H` | Show help |
|
|
114
|
-
| `Esc` | Cancel / Exit |
|
|
115
|
-
|
|
116
|
-
**Staged Changes**: Toggle extensions on/off without immediate effect. Press `S` to apply all changes at once. Pending changes show `*` next to the extension name.
|
|
117
|
-
|
|
118
|
-
#### Package Actions
|
|
119
|
-
|
|
120
|
-
When a package is selected, press `A` to:
|
|
121
|
-
|
|
122
|
-
- **Update package** - fetch latest version
|
|
123
|
-
- **Remove package** - uninstall completely
|
|
124
|
-
- **View details** - see version, source, scope
|
|
125
|
-
- **Back to manager** - return to unified view
|
|
126
|
-
|
|
127
|
-
#### Community Package Browser
|
|
34
|
+
### In the manager
|
|
128
35
|
|
|
129
|
-
|
|
36
|
+
| Key | Action |
|
|
37
|
+
| ------------- | ------------------------------------------------ |
|
|
38
|
+
| `↑↓` | Navigate |
|
|
39
|
+
| `Space/Enter` | Toggle local extension on/off |
|
|
40
|
+
| `S` | Save changes |
|
|
41
|
+
| `A` | Actions on selected package (update/remove/view) |
|
|
42
|
+
| `R` | Browse remote packages |
|
|
43
|
+
| `?` / `H` | Help |
|
|
44
|
+
| `Esc` | Exit |
|
|
130
45
|
|
|
131
|
-
|
|
132
|
-
| ------- | -------------------- |
|
|
133
|
-
| `↑↓` | Navigate packages |
|
|
134
|
-
| `Enter` | View package details |
|
|
135
|
-
| `N` | Next page |
|
|
136
|
-
| `P` | Previous page |
|
|
137
|
-
| `R` | Refresh search |
|
|
138
|
-
| `Esc` | Cancel |
|
|
139
|
-
|
|
140
|
-
### Command Reference
|
|
46
|
+
### Commands
|
|
141
47
|
|
|
142
48
|
```bash
|
|
143
|
-
#
|
|
144
|
-
/extensions
|
|
145
|
-
|
|
146
|
-
#
|
|
147
|
-
/extensions
|
|
148
|
-
/extensions
|
|
149
|
-
|
|
150
|
-
# Package Discovery
|
|
151
|
-
/extensions remote # Browse community packages
|
|
152
|
-
/extensions packages # Alias for remote
|
|
153
|
-
/extensions search <query> # Search npm for packages
|
|
154
|
-
|
|
155
|
-
# Package Management
|
|
156
|
-
/extensions install <source> # Install from npm/git/path
|
|
157
|
-
/extensions remove [source] # Remove package (interactive if no source)
|
|
158
|
-
/extensions uninstall [source]# Alias for remove
|
|
159
|
-
|
|
160
|
-
# History & Stats
|
|
161
|
-
/extensions history # View recent extension changes
|
|
162
|
-
/extensions stats # View extension manager statistics
|
|
163
|
-
/extensions clear-cache # Clear metadata cache
|
|
49
|
+
/extensions # Open the manager
|
|
50
|
+
/extensions search <query> # Search npm
|
|
51
|
+
/extensions install <source> # Install package
|
|
52
|
+
/extensions remove [source] # Remove package
|
|
53
|
+
/extensions history # View change history
|
|
54
|
+
/extensions stats # View statistics
|
|
55
|
+
/extensions clear-cache # Clear metadata cache
|
|
164
56
|
```
|
|
165
57
|
|
|
166
|
-
### Install
|
|
58
|
+
### Install sources
|
|
167
59
|
|
|
168
60
|
```bash
|
|
169
|
-
|
|
170
|
-
/extensions install npm:some-package
|
|
61
|
+
/extensions install npm:package-name
|
|
171
62
|
/extensions install @scope/package
|
|
172
|
-
|
|
173
|
-
# Git repositories
|
|
174
63
|
/extensions install git:https://github.com/user/repo.git
|
|
175
|
-
|
|
176
|
-
# GitHub single-file extensions (.ts files)
|
|
177
|
-
# Automatically converts blob URLs to raw and downloads directly
|
|
178
64
|
/extensions install https://github.com/user/repo/blob/main/extension.ts
|
|
179
|
-
|
|
180
|
-
# Local paths
|
|
181
65
|
/extensions install /path/to/extension.ts
|
|
182
|
-
/extensions install ./
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
### Non-Interactive Mode
|
|
186
|
-
|
|
187
|
-
All commands work in non-interactive environments (CI, scripts):
|
|
188
|
-
|
|
189
|
-
```bash
|
|
190
|
-
# These work without UI
|
|
191
|
-
/extensions list
|
|
192
|
-
/extensions installed
|
|
193
|
-
|
|
194
|
-
# These require arguments in non-interactive mode
|
|
195
|
-
/extensions install npm:package-name
|
|
196
|
-
/extensions remove npm:package-name
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
## 🎮 Keyboard Shortcuts
|
|
200
|
-
|
|
201
|
-
### Global
|
|
202
|
-
|
|
203
|
-
- `Ctrl+Shift+E` - Open Extensions Manager
|
|
204
|
-
|
|
205
|
-
### In Unified Manager
|
|
206
|
-
|
|
207
|
-
| Key | Action |
|
|
208
|
-
| -------------- | ------------------------------- |
|
|
209
|
-
| `↑/↓` or `K/J` | Navigate |
|
|
210
|
-
| `Enter/Space` | Toggle local extension |
|
|
211
|
-
| `S` | Save changes |
|
|
212
|
-
| `A` | Package actions (update/remove) |
|
|
213
|
-
| `R` | Browse remote packages |
|
|
214
|
-
| `?` / `H` | Help |
|
|
215
|
-
| `Esc` | Cancel / Exit |
|
|
216
|
-
|
|
217
|
-
## 🏗️ Extension Discovery
|
|
218
|
-
|
|
219
|
-
pi-extmgr discovers extensions from multiple sources:
|
|
220
|
-
|
|
221
|
-
### Local Extensions
|
|
222
|
-
|
|
223
|
-
```
|
|
224
|
-
~/.pi/agent/extensions/ # Global
|
|
225
|
-
├── my-extension.ts
|
|
226
|
-
├── disabled-extension.ts.disabled
|
|
227
|
-
└── my-extension/
|
|
228
|
-
└── index.ts
|
|
229
|
-
|
|
230
|
-
./.pi/extensions/ # Project
|
|
231
|
-
├── project-tool.ts
|
|
232
|
-
└── local-helper/
|
|
233
|
-
└── index.ts
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
### Installed Packages
|
|
237
|
-
|
|
238
|
-
Managed by `pi install`:
|
|
239
|
-
|
|
240
|
-
- npm packages (`npm:package@version`)
|
|
241
|
-
- git packages (`git:https://...`)
|
|
242
|
-
- Stored in pi's package cache
|
|
243
|
-
|
|
244
|
-
**Naming**: Append `.disabled` to disable a local extension without removing it.
|
|
245
|
-
|
|
246
|
-
## 🔧 Configuration
|
|
247
|
-
|
|
248
|
-
No configuration needed! But you can customize your Pi theme to change the appearance:
|
|
249
|
-
|
|
250
|
-
```typescript
|
|
251
|
-
// In your theme extension
|
|
252
|
-
export default function myTheme(pi: ExtensionAPI) {
|
|
253
|
-
pi.registerTheme({
|
|
254
|
-
name: "my-theme",
|
|
255
|
-
colors: {
|
|
256
|
-
accent: "#00ff00",
|
|
257
|
-
success: "#00aa00",
|
|
258
|
-
error: "#ff0000",
|
|
259
|
-
warning: "#ffaa00",
|
|
260
|
-
// ... other colors
|
|
261
|
-
},
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
## 📝 Example Workflows
|
|
267
|
-
|
|
268
|
-
### Managing All Extensions
|
|
269
|
-
|
|
270
|
-
1. Press `Ctrl+Shift+E` or type `/extensions`
|
|
271
|
-
2. See all local extensions and installed packages in one view
|
|
272
|
-
3. Navigate with `↑↓`
|
|
273
|
-
4. For local extensions: press `Space` to toggle on/off
|
|
274
|
-
5. For packages: press `A` for actions (update/remove)
|
|
275
|
-
6. Press `S` to save any changes to local extensions
|
|
276
|
-
7. Confirm reload to apply changes
|
|
277
|
-
|
|
278
|
-
### Installing a New Extension
|
|
279
|
-
|
|
280
|
-
1. Type `/extensions` to open manager
|
|
281
|
-
2. Press `R` for remote packages
|
|
282
|
-
3. Browse or search for the extension
|
|
283
|
-
4. Press `Enter` on the desired package
|
|
284
|
-
5. Choose install mode:
|
|
285
|
-
- **"Install via npm (managed)"** - Uses pi's package manager. Auto-updates with `pi update`. Best for most users.
|
|
286
|
-
- **"Install locally (standalone)"** - Copies entire package to `~/.pi/agent/extensions/{package}/`. Supports multi-file extensions with imports. Manual updates required.
|
|
287
|
-
6. Confirm installation
|
|
288
|
-
7. Choose to reload Pi to activate
|
|
289
|
-
|
|
290
|
-
**Local Install Directory Structure:**
|
|
291
|
-
|
|
292
|
-
```
|
|
293
|
-
~/.pi/agent/extensions/
|
|
294
|
-
└── pi-some-extension/ # Full package directory
|
|
295
|
-
├── index.ts # Entry point
|
|
296
|
-
├── utils.ts # Helper (imports work!)
|
|
297
|
-
└── package.json # Original package.json preserved
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
### Updating a Package
|
|
301
|
-
|
|
302
|
-
1. Type `/extensions` to open unified manager
|
|
303
|
-
2. Navigate to the installed package
|
|
304
|
-
3. Press `A` for actions
|
|
305
|
-
4. Select "Update package"
|
|
306
|
-
5. Confirm reload if updated
|
|
307
|
-
|
|
308
|
-
### Disabling a Local Extension Temporarily
|
|
309
|
-
|
|
310
|
-
1. Type `/extensions` to open manager
|
|
311
|
-
2. Navigate to the local extension with `↑↓`
|
|
312
|
-
3. Press `Space` to toggle it off
|
|
313
|
-
4. Press `S` to save
|
|
314
|
-
5. Confirm reload
|
|
315
|
-
|
|
316
|
-
The extension remains installed but won't load until re-enabled.
|
|
317
|
-
|
|
318
|
-
### Removing a Package
|
|
319
|
-
|
|
320
|
-
1. Type `/extensions` to open unified manager
|
|
321
|
-
2. Navigate to the installed package with `↑↓`
|
|
322
|
-
3. Press `A` for actions
|
|
323
|
-
4. Select "Remove package"
|
|
324
|
-
5. Confirm removal
|
|
325
|
-
|
|
326
|
-
**Important**: Unlike install/update, removing a package requires a **full restart** of pi (not just `/reload`). The extension files are deleted, but the extension remains loaded in memory until you exit and restart pi.
|
|
327
|
-
|
|
328
|
-
### Updating All Packages
|
|
329
|
-
|
|
330
|
-
1. Type `/extensions` to open unified manager
|
|
331
|
-
2. Navigate to any installed package
|
|
332
|
-
3. Press `A` for actions
|
|
333
|
-
4. Select "Update package"
|
|
334
|
-
5. Or use command: `/extensions install npm:pi-extmgr` then select "[Update all packages]"
|
|
335
|
-
|
|
336
|
-
### Viewing Change History
|
|
337
|
-
|
|
338
|
-
See what you've done in the current session:
|
|
339
|
-
|
|
340
|
-
```
|
|
341
|
-
/extensions history
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
Output shows recent actions like:
|
|
345
|
-
|
|
346
|
-
```
|
|
347
|
-
[12:34:56] ✓ global:my-extension: enabled → disabled
|
|
348
|
-
[12:35:10] ✓ Installed pi-some-package@1.2.3
|
|
349
|
-
[12:36:22] ✓ Updated pi-other-package → @2.0.0
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
### Viewing Statistics
|
|
353
|
-
|
|
354
|
-
Get a summary of your extension management activity:
|
|
355
|
-
|
|
356
|
-
```
|
|
357
|
-
/extensions stats
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
Shows installed package count, total changes, and breakdown by action type.
|
|
361
|
-
|
|
362
|
-
## 🐛 Troubleshooting
|
|
363
|
-
|
|
364
|
-
### Commands not showing after install
|
|
365
|
-
|
|
366
|
-
Make sure to reload Pi:
|
|
367
|
-
|
|
368
|
-
```
|
|
369
|
-
/reload
|
|
66
|
+
/extensions install ./local-folder/
|
|
370
67
|
```
|
|
371
68
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
Check that the file has a `.ts` or `.js` extension and is in one of the discovery paths:
|
|
375
|
-
|
|
376
|
-
- `~/.pi/agent/extensions/` (global)
|
|
377
|
-
- `.pi/extensions/` (project)
|
|
69
|
+
## Tips
|
|
378
70
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
-
|
|
382
|
-
-
|
|
383
|
-
-
|
|
384
|
-
|
|
385
|
-
### Commands still work after removing package
|
|
386
|
-
|
|
387
|
-
This is expected behavior. When you remove a package:
|
|
388
|
-
|
|
389
|
-
1. The files are deleted from disk
|
|
390
|
-
2. The extension remains loaded in pi's memory
|
|
391
|
-
3. Commands continue to work until you **restart pi**\n
|
|
392
|
-
A full restart (Ctrl+C or `/quit`) is required to fully unload removed extensions. `/reload` is only sufficient for install/update operations.
|
|
393
|
-
|
|
394
|
-
### Back to manager closes everything
|
|
395
|
-
|
|
396
|
-
Fixed! Pressing "Back to manager" now correctly returns to the unified view instead of closing.
|
|
397
|
-
|
|
398
|
-
## 🤝 Contributing
|
|
399
|
-
|
|
400
|
-
Contributions welcome! Please ensure:
|
|
401
|
-
|
|
402
|
-
1. Run `pnpm run check` before committing
|
|
403
|
-
2. Husky pre-commit hooks will validate automatically
|
|
404
|
-
3. Follow existing code style
|
|
405
|
-
|
|
406
|
-
```bash
|
|
407
|
-
# Setup
|
|
408
|
-
git clone https://github.com/ayagmar/pi-extmgr.git
|
|
409
|
-
cd pi-extmgr
|
|
410
|
-
pnpm install
|
|
411
|
-
|
|
412
|
-
# Development
|
|
413
|
-
pnpm run typecheck # Type checking
|
|
414
|
-
pnpm run lint # Linting
|
|
415
|
-
pnpm run check # Full validation
|
|
416
|
-
|
|
417
|
-
# Test in Pi
|
|
418
|
-
pi install ./index.ts
|
|
419
|
-
/reload
|
|
420
|
-
```
|
|
71
|
+
- **Staged changes**: Toggle extensions on/off, then press `S` to apply all at once. A `*` shows pending changes.
|
|
72
|
+
- **Two install modes**:
|
|
73
|
+
- **Managed** (npm): Auto-updates with `pi update`, stored in pi's package cache
|
|
74
|
+
- **Local** (standalone): Copies to `~/.pi/agent/extensions/{package}/`, supports multi-file extensions
|
|
75
|
+
- **Remove requires restart**: After removing a package, you need to fully restart Pi (not just `/reload`) for it to be completely unloaded.
|
|
421
76
|
|
|
422
|
-
##
|
|
77
|
+
## Keyboard shortcut
|
|
423
78
|
|
|
424
|
-
|
|
79
|
+
Press `Ctrl+Shift+E` anywhere to open the extension manager.
|
|
425
80
|
|
|
426
|
-
|
|
81
|
+
## License
|
|
427
82
|
|
|
428
|
-
|
|
429
|
-
Made with ❤️ for the Pi community
|
|
430
|
-
</p>
|
|
83
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extmgr",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Enhanced UX for managing local Pi extensions and community packages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"./src/index.ts"
|
|
31
31
|
],
|
|
32
32
|
"video": "https://github.com/ayagmar/pi-extmgr/releases/download/v0.0.2/Screencast_20260207_013142.mp4",
|
|
33
|
-
"image": "https://i.imgur.com/
|
|
33
|
+
"image": "https://i.imgur.com/tTD31v8.png"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@mariozechner/pi-coding-agent": "*",
|
package/src/ui/remote.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import type { ExtensionAPI, ExtensionCommandContext } from "@mariozechner/pi-coding-agent";
|
|
5
5
|
import type { BrowseAction, NpmPackage } from "../types/index.js";
|
|
6
6
|
import { PAGE_SIZE } from "../constants.js";
|
|
7
|
-
import { truncate } from "../utils/format.js";
|
|
7
|
+
import { truncate, dynamicTruncate } from "../utils/format.js";
|
|
8
8
|
import {
|
|
9
9
|
searchNpmPackages,
|
|
10
10
|
getSearchCache,
|
|
@@ -119,9 +119,11 @@ export async function browseRemotePackages(
|
|
|
119
119
|
: `Search: ${truncate(query, 40)}`;
|
|
120
120
|
|
|
121
121
|
// Use simple select instead of custom component to avoid hanging issues
|
|
122
|
+
// Calculate reserved space: name (~25) + version (~10) + separator (3) = ~40 chars
|
|
123
|
+
const reservedSpace = 40;
|
|
122
124
|
const selectItems: string[] = packages.map(
|
|
123
125
|
(p) =>
|
|
124
|
-
`${p.name}${p.version ? ` @${p.version}` : ""} - ${
|
|
126
|
+
`${p.name}${p.version ? ` @${p.version}` : ""} - ${dynamicTruncate(p.description || "No description", reservedSpace)}`
|
|
125
127
|
);
|
|
126
128
|
|
|
127
129
|
// Add navigation options
|
package/src/ui/unified.ts
CHANGED
|
@@ -21,7 +21,7 @@ import { showPackageActions } from "../packages/management.js";
|
|
|
21
21
|
import { showRemote } from "./remote.js";
|
|
22
22
|
import { showHelp } from "./help.js";
|
|
23
23
|
import { discoverExtensions as discoverExt } from "../extensions/discovery.js";
|
|
24
|
-
import { formatEntry as formatExtEntry,
|
|
24
|
+
import { formatEntry as formatExtEntry, dynamicTruncate } from "../utils/format.js";
|
|
25
25
|
import {
|
|
26
26
|
getStatusIcon,
|
|
27
27
|
getPackageIcon,
|
|
@@ -291,8 +291,9 @@ function formatUnifiedItemLabel(
|
|
|
291
291
|
const infoParts: string[] = [];
|
|
292
292
|
|
|
293
293
|
// Show description if available
|
|
294
|
+
// Reserved space: icon (2) + scope (3) + name (~25) + version (~10) + separator (3) = ~43 chars
|
|
294
295
|
if (item.description) {
|
|
295
|
-
infoParts.push(
|
|
296
|
+
infoParts.push(dynamicTruncate(item.description, 43));
|
|
296
297
|
} else if (item.source?.startsWith("npm:")) {
|
|
297
298
|
infoParts.push("npm");
|
|
298
299
|
} else if (item.source?.startsWith("git:")) {
|
package/src/utils/format.ts
CHANGED
|
@@ -8,6 +8,36 @@ export function truncate(text: string, maxLength: number): string {
|
|
|
8
8
|
return text.slice(0, maxLength - 3) + "...";
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Get the terminal width, with a minimum fallback
|
|
13
|
+
*/
|
|
14
|
+
export function getTerminalWidth(minWidth = 80): number {
|
|
15
|
+
return Math.max(minWidth, process.stdout.columns || minWidth);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Calculate available space for description based on fixed-width elements
|
|
20
|
+
*/
|
|
21
|
+
export function getDescriptionWidth(
|
|
22
|
+
totalWidth: number,
|
|
23
|
+
reservedSpace: number,
|
|
24
|
+
minDescWidth = 20
|
|
25
|
+
): number {
|
|
26
|
+
return Math.max(minDescWidth, totalWidth - reservedSpace);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Dynamic truncate that adapts to available terminal width
|
|
31
|
+
* @param text - Text to truncate
|
|
32
|
+
* @param reservedSpace - Space taken by fixed elements (icons, name, version, etc.)
|
|
33
|
+
* @param minWidth - Minimum terminal width to consider
|
|
34
|
+
*/
|
|
35
|
+
export function dynamicTruncate(text: string, reservedSpace: number, minWidth = 80): string {
|
|
36
|
+
const termWidth = getTerminalWidth(minWidth);
|
|
37
|
+
const maxDescWidth = getDescriptionWidth(termWidth, reservedSpace);
|
|
38
|
+
return truncate(text, maxDescWidth);
|
|
39
|
+
}
|
|
40
|
+
|
|
11
41
|
export function formatEntry(entry: ExtensionEntry): string {
|
|
12
42
|
const state = entry.state === "enabled" ? "on " : "off";
|
|
13
43
|
const scope = entry.scope === "global" ? "G" : "P";
|