pi-files-widget-overlay 0.3.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 +198 -0
- package/LICENSE +22 -0
- package/README.md +102 -0
- package/demo.png +0 -0
- package/package.json +38 -0
- package/publish-pi-files-widget-overlay.sh +228 -0
- package/src/activity.ts +10 -0
- package/src/browser.ts +1244 -0
- package/src/comment.ts +6 -0
- package/src/constants.ts +31 -0
- package/src/file-tree.ts +321 -0
- package/src/file-viewer.ts +181 -0
- package/src/git.ts +129 -0
- package/src/index.ts +147 -0
- package/src/input-utils.ts +96 -0
- package/src/types.ts +31 -0
- package/src/utils.ts +59 -0
- package/src/viewer.ts +729 -0
- package/tsconfig.json +13 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this extension will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [0.3.0] - 2026-09-10
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- Highlight and select every wrapped visual row of a logical line; comments retain logical source-line ranges.
|
|
9
|
+
- Make `c` and `C` share changed-only state while preserving collapsed and expanded changed-path views.
|
|
10
|
+
- Preserve logical cursor and selection groups across width changes and page navigation.
|
|
11
|
+
- Clear agent-modified file markers before a session switch.
|
|
12
|
+
- Keep Diff searches and comments anchored to logical Diff lines across word-wrap and width changes.
|
|
13
|
+
- Reset rendered Markdown selection to the first raw source line before creating a source-aligned comment.
|
|
14
|
+
- Schedule Git line counts by expanded directory instead of queueing every tracked file at startup.
|
|
15
|
+
- Keep confirmed file-viewer searches available to `n` and `N`.
|
|
16
|
+
- Track observed `edit.file` activity alongside `write.path` using normalized paths.
|
|
17
|
+
- Show non-blocking directory-scan and Git-metadata errors in the browser; verify Git metadata paths from repository subdirectories.
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
- Add Vitest coverage for wrapped-row grouping, logical-line navigation, selection, and comments.
|
|
21
|
+
- Add `C` to toggle the expanded changed view.
|
|
22
|
+
- Add `w` to toggle word wrap in the file viewer; wrapping is disabled by default.
|
|
23
|
+
- Show hidden project files such as `.pi/` and `.github/` while keeping `.git/` and common generated directories hidden.
|
|
24
|
+
- Add anonymous Git and non-Git browser performance benchmarks with a recorded baseline.
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
- Forked `files-widget` as `pi-files-widget-overlay`; retain upstream MIT attribution and add tallshort copyright.
|
|
28
|
+
- Replace Delta's split line-number diff renderer with a compact unified view: explicit `+`/`-` markers and one relevant line number.
|
|
29
|
+
- Highlight the full width of the current line and selection; align the viewer and file-browser default overlay heights.
|
|
30
|
+
- Remove the Delta runtime dependency.
|
|
31
|
+
- Replace the README demo video with a static screenshot and add Pi Packages Gallery image metadata.
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
- `/readfiles` now supports browsing outside the current working directory. Press `u` to re-root to the parent, `.` to jump back to where you started, or pass an explicit starting path (`/readfiles <path>` or `/readfiles ~/somewhere`). The browser header shows the current root so you always know where you are, and comments on files outside the project use absolute paths so the agent can still find them.
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
- Git status, diff stats, and untracked-file discovery now work when the browser root is a subdirectory of the git repository (e.g. after `u`, `.`, or `/readfiles <subdir>`, or when pi runs from a repo subdirectory). Previously repo-root-relative git paths were mixed with root-relative node keys, producing phantom tree entries, missing statuses, and unopenable nested paths.
|
|
38
|
+
- Re-rooting the browser while a background directory scan or line-count batch is in flight no longer lets the stale batch mutate the new root's tree, node index, or scan state.
|
|
39
|
+
- Use `where` instead of `which` on Windows to detect `bat`, `delta`, and `glow`, so the dependency check works when running from PowerShell or cmd.exe.
|
|
40
|
+
|
|
41
|
+
## [0.1.21] - 2026-05-07
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
- Declare `@earendil-works` Pi development dependencies used by runtime imports.
|
|
45
|
+
- Update Pi extension imports and peer dependencies to the new `@earendil-works` namespace.
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
## [0.1.20] - 2026-04-24
|
|
49
|
+
|
|
50
|
+
### Removed
|
|
51
|
+
- Remove the external `/readfiles-review` and `/readfiles-diff` commands so files-widget stays focused on the `/readfiles` browser/viewer.
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
## [0.1.18] - 2026-04-19
|
|
55
|
+
|
|
56
|
+
### Changed
|
|
57
|
+
- Show symlinks with a `↗` marker in the `/readfiles` tree.
|
|
58
|
+
|
|
59
|
+
### Fixed
|
|
60
|
+
- Let `/readfiles` navigate into directory symlinks in both non-git folders and git repos instead of rendering them as inert files or empty directories.
|
|
61
|
+
- Guard symlink directory scanning against ancestor cycles so links like `foo -> .` or `foo -> ..` don't recurse forever.
|
|
62
|
+
- Treat git-tracked and untracked directory symlinks as lazily scannable directories rather than plain files.
|
|
63
|
+
|
|
64
|
+
### Thanks
|
|
65
|
+
- Thanks to @xapids for reporting the original macOS symlink navigation issue ([#9](https://github.com/tmustier/pi-extensions/issues/9)).
|
|
66
|
+
|
|
67
|
+
## [0.1.17] - 2026-04-19
|
|
68
|
+
|
|
69
|
+
### Changed
|
|
70
|
+
- Make the inline comment editor multiline with wrapped footer rendering, `Enter` for a new line, and `Ctrl+Enter`/`Ctrl+D` to send.
|
|
71
|
+
- Add an `m` toggle for rendered vs raw Markdown in the viewer, and fall back to raw mode before line-based search or selection.
|
|
72
|
+
- Show a sent/queued confirmation toast after returning an inline comment to the agent.
|
|
73
|
+
|
|
74
|
+
### Thanks
|
|
75
|
+
- Thanks to avg8888 in the Pi Discord for surfacing the comment editor and Markdown review issues fixed in this release.
|
|
76
|
+
|
|
77
|
+
## [0.1.16] - 2026-04-19
|
|
78
|
+
|
|
79
|
+
### Fixed
|
|
80
|
+
- Let `/readfiles` browser search accept `j` and `k` as search text instead of hijacking them for navigation.
|
|
81
|
+
- Fix viewer scrolling so the last lines of a file remain reachable.
|
|
82
|
+
- Restore `G` / `Shift+G` navigation to jump to the bottom of the viewer.
|
|
83
|
+
- Refresh an open viewer when the file changes on disk while `/readfiles` is open.
|
|
84
|
+
- Accept pasted, multi-character, and chunked bracketed-paste input in browser search and the inline comment prompt.
|
|
85
|
+
- Keep viewer search results in sync after live refreshes.
|
|
86
|
+
- Pause live refresh while a line selection or inline comment is active so comments stay anchored to what the user selected.
|
|
87
|
+
|
|
88
|
+
## [0.1.14] - 2026-02-03
|
|
89
|
+
|
|
90
|
+
### Added
|
|
91
|
+
- Add preview video metadata for the extension listing.
|
|
92
|
+
|
|
93
|
+
## [0.1.13] - 2026-02-02
|
|
94
|
+
|
|
95
|
+
### Changed
|
|
96
|
+
- **BREAKING:** Renamed `/files` command to `/readfiles` to avoid conflict with Pi's new built-in `/files` command (Pi v0.50.2+)
|
|
97
|
+
|
|
98
|
+
## [0.1.11] - 2026-01-26
|
|
99
|
+
|
|
100
|
+
### Changed
|
|
101
|
+
- Require `bat`, `delta`, and `glow` before opening `/files`
|
|
102
|
+
- Add a postinstall reminder for required system tools
|
|
103
|
+
- Document install commands next to the Pi install steps
|
|
104
|
+
|
|
105
|
+
## [0.1.10] - 2026-01-26
|
|
106
|
+
|
|
107
|
+
### Fixed
|
|
108
|
+
- Treat git-reported directory entries as directories to avoid viewer errors
|
|
109
|
+
- Guard the viewer against opening directories directly
|
|
110
|
+
- Wrap delta diff output without breaking gutters and avoid truncation
|
|
111
|
+
- Add a safe fallback when `bat` fails to render with wrapping
|
|
112
|
+
|
|
113
|
+
## [0.1.9] - 2026-01-26
|
|
114
|
+
|
|
115
|
+
### Changed
|
|
116
|
+
- Bind render requests to avoid undefined context with the latest pi-tui
|
|
117
|
+
|
|
118
|
+
## [0.1.8] - 2026-01-26
|
|
119
|
+
|
|
120
|
+
### Changed
|
|
121
|
+
- Compute line counts asynchronously with loading indicators
|
|
122
|
+
- Build git repo trees from git file lists to avoid filesystem scans
|
|
123
|
+
- Add progressive filesystem scanning with safe mode for large folders
|
|
124
|
+
- Reduce refresh work to git metadata updates
|
|
125
|
+
|
|
126
|
+
## [0.1.7] - 2026-01-26
|
|
127
|
+
|
|
128
|
+
### Changed
|
|
129
|
+
- Cache line counts and skip large files to avoid freezes in big folders
|
|
130
|
+
- Avoid recomputing tree stats on every render
|
|
131
|
+
- Preserve line counts for open files across refreshes
|
|
132
|
+
|
|
133
|
+
## [0.1.6] - 2026-01-24
|
|
134
|
+
|
|
135
|
+
### Added
|
|
136
|
+
- Clearer install instructions and dependency notes in README
|
|
137
|
+
|
|
138
|
+
## [0.1.5] - 2026-01-24
|
|
139
|
+
|
|
140
|
+
### Added
|
|
141
|
+
- Demo recording embedded in README
|
|
142
|
+
|
|
143
|
+
### Changed
|
|
144
|
+
- Comment sending now queues with follow-up delivery in streaming sessions
|
|
145
|
+
- Split viewer logic into `viewer.ts` and shared helpers
|
|
146
|
+
- Reduced browser render duplication with node format helpers
|
|
147
|
+
|
|
148
|
+
## [0.1.4] - 2026-01-24
|
|
149
|
+
|
|
150
|
+
### Changed
|
|
151
|
+
- Split viewer logic into `viewer.ts` and shared helpers
|
|
152
|
+
- Reduced browser render duplication with node format helpers
|
|
153
|
+
|
|
154
|
+
## [0.1.3] - 2026-01-24
|
|
155
|
+
|
|
156
|
+
### Changed
|
|
157
|
+
- `c` in viewer now opens an inline comment prompt and sends a follow-up message
|
|
158
|
+
|
|
159
|
+
## [0.1.2] - 2026-01-24
|
|
160
|
+
|
|
161
|
+
### Changed
|
|
162
|
+
- `c` in viewer now appends selection to editor input instead of sending immediately
|
|
163
|
+
|
|
164
|
+
## [0.1.1] - 2026-01-24
|
|
165
|
+
|
|
166
|
+
### Added
|
|
167
|
+
- README with install steps, dependencies, and keybindings
|
|
168
|
+
|
|
169
|
+
### Changed
|
|
170
|
+
- Refactored into modular files (browser, git, tree, viewer, utils)
|
|
171
|
+
|
|
172
|
+
## [0.1.0] - 2026-01-24
|
|
173
|
+
|
|
174
|
+
### Added
|
|
175
|
+
- `/files` command opens full-screen file browser
|
|
176
|
+
- File tree with j/k navigation, Enter to open, h/l to collapse/expand
|
|
177
|
+
- File viewer with syntax highlighting via `bat`
|
|
178
|
+
- Markdown rendering via `glow`
|
|
179
|
+
- Git diff view via `delta` with line numbers
|
|
180
|
+
- Git status indicators (M, A, D, ?) on files
|
|
181
|
+
- Agent-modified file tracking (🤖 indicator)
|
|
182
|
+
- Changed files filter (`c` to toggle)
|
|
183
|
+
- Jump to next/prev changed file (`]`/`[`)
|
|
184
|
+
- Search in file tree (`/` then type)
|
|
185
|
+
- Search in file viewer (`/` then type, `n`/`N` for next/prev match)
|
|
186
|
+
- Select mode (`v`) to select lines and comment (`c`) to send to agent
|
|
187
|
+
- Line counts and diff stats (+/-) on files and collapsed folders
|
|
188
|
+
- Auto-refresh git status every 3 seconds (preserves expansion state)
|
|
189
|
+
- PageUp/PageDown support in browser and viewer
|
|
190
|
+
- Height adjustment (`+`/`-`)
|
|
191
|
+
- Works in non-git directories (git features gracefully disabled)
|
|
192
|
+
|
|
193
|
+
### Dependencies
|
|
194
|
+
- `bat` - syntax highlighting (recommended)
|
|
195
|
+
- `glow` - markdown rendering (recommended)
|
|
196
|
+
- `delta` - diff formatting (recommended)
|
|
197
|
+
|
|
198
|
+
Install with: `brew install bat git-delta glow`
|
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Thomas Mustier
|
|
4
|
+
Copyright (c) 2026 tallshort
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# pi-files-widget-overlay
|
|
2
|
+
|
|
3
|
+
In-terminal floating-overlay file browser and diff viewer for Pi. Navigate files, view diffs, select code, and send comments to the agent without leaving the terminal and without interrupting your agent.
|
|
4
|
+
|
|
5
|
+
## Origin
|
|
6
|
+
|
|
7
|
+
Forked from [tmustier/pi-extensions — files-widget](https://github.com/tmustier/pi-extensions/tree/main/files-widget), distributed under the MIT License. Modifications and overlay-focused maintenance are by tallshort.
|
|
8
|
+
|
|
9
|
+
Directory symlinks are shown with a `↗` marker and can be expanded like normal folders.
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
**Quick install (Pi package manager):**
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pi install npm:pi-files-widget-overlay
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Local development:** add the repository path to `~/.pi/agent/settings.json`:
|
|
21
|
+
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"extensions": [
|
|
25
|
+
"~/pi-files-widget-overlay"
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
## Dependencies
|
|
30
|
+
|
|
31
|
+
- Pi built-in syntax highlighter: code colors follow the active Pi theme
|
|
32
|
+
- Pi built-in Markdown renderer: rendered Markdown follows the active Pi theme
|
|
33
|
+
|
|
34
|
+
The `/readfiles` browser has no `bat`, `glow`, or `delta` runtime dependency. Code, Markdown, and unified diffs use Pi's theme-aware renderers; Diff mode uses `git` when available.
|
|
35
|
+
|
|
36
|
+
## Project layout
|
|
37
|
+
|
|
38
|
+
- `src/`: extension runtime and `/readfiles` entry point
|
|
39
|
+
- `test/`: browser and viewer regression tests
|
|
40
|
+
- `docs/`: design notes and anonymous benchmark baselines
|
|
41
|
+
- `benchmarks/`: locally run benchmark harnesses; excluded from the published package
|
|
42
|
+
|
|
43
|
+
## Development
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm install
|
|
47
|
+
npm test
|
|
48
|
+
npm run typecheck
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Commands
|
|
52
|
+
|
|
53
|
+
- `/readfiles` - open the file browser as a floating overlay in the current directory
|
|
54
|
+
- `/readfiles <path>` - open the floating browser rooted at `<path>` (absolute, relative, or `~`-prefixed)
|
|
55
|
+
|
|
56
|
+
The overlay is centered at 95% of terminal width with a one-cell margin. Its framed header separates the browser from the agent transcript; `q` or `Esc` closes it and returns focus to Pi.
|
|
57
|
+
Diff viewing is built into the file viewer: open a changed tracked file and press `d` to toggle the git diff view.
|
|
58
|
+
|
|
59
|
+
## Browser Keybindings
|
|
60
|
+
|
|
61
|
+
- `j/k` or `↑/↓`: move
|
|
62
|
+
- `Enter`: open file / expand folder
|
|
63
|
+
- `h/l` or `←/→`: collapse/expand folder
|
|
64
|
+
- `PgUp/PgDn`: page up/down
|
|
65
|
+
- `c`: toggle changed-only view
|
|
66
|
+
- `C`: toggle the expanded changed view; enabling it expands every directory containing changes
|
|
67
|
+
- `]` / `[`: next/prev changed file
|
|
68
|
+
- `/`: search (type to filter, `Esc` to exit)
|
|
69
|
+
- `u`: go up one directory (re-root to parent)
|
|
70
|
+
- `.`: jump back to the starting directory
|
|
71
|
+
- `+` / `-`: increase/decrease browser height
|
|
72
|
+
- `q`: close
|
|
73
|
+
|
|
74
|
+
## Viewer Keybindings
|
|
75
|
+
|
|
76
|
+
- `j/k` or `↑/↓`: move the line cursor (the viewport follows it)
|
|
77
|
+
- `PgUp/PgDn`: page up/down
|
|
78
|
+
- `g/G`: top/bottom
|
|
79
|
+
- `d`: toggle diff (tracked files only)
|
|
80
|
+
- `m`: toggle rendered/raw view for Markdown files
|
|
81
|
+
- `w`: toggle word wrap (disabled by default)
|
|
82
|
+
- `/`: search (type to search)
|
|
83
|
+
- `n` / `N`: next/prev match
|
|
84
|
+
- `v`: select mode (line selection)
|
|
85
|
+
- `c`: comment on selected lines (inline prompt)
|
|
86
|
+
- `Enter`: new line in the comment editor
|
|
87
|
+
- `Ctrl+Enter` or `Ctrl+D`: send the comment (`Alt+Enter` also works when supported)
|
|
88
|
+
- `]` / `[`: next/prev changed file
|
|
89
|
+
- `+` / `-`: increase/decrease viewer height
|
|
90
|
+
- `q`, `Esc`, or `←`: back to browser
|
|
91
|
+
|
|
92
|
+
## Notes
|
|
93
|
+
|
|
94
|
+
- The overlay maximum height is 95% of the terminal; browser and viewer panels start at 85%, and `+` / `-` adjust within that available range.
|
|
95
|
+
- Hidden project files and directories such as `.pi/` and `.github/` are visible; `.git/` and common dependency/build caches remain hidden.
|
|
96
|
+
- Untracked files show as `[UNTRACKED]` and open in normal view.
|
|
97
|
+
- Searching in rendered Markdown switches to raw mode first, and selecting from rendered Markdown first switches you back to raw so line-based matches and comments stay aligned with the source file.
|
|
98
|
+
- When you browse outside the current project directory, inline comments on those files use absolute paths so the agent can still locate them. Files inside the project continue to use project-relative paths.
|
|
99
|
+
- Folder LOCs are shown only when the folder is collapsed (expanded folders would duplicate counts).
|
|
100
|
+
- Line counts load asynchronously; the header shows activity while counts are computed.
|
|
101
|
+
- Large non-git folders load progressively and may show `[partial]` while loading in safe mode.
|
|
102
|
+
- Git status refreshes every 3 seconds while `/readfiles` is open.
|
package/demo.png
ADDED
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-files-widget-overlay",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "In-terminal file browser, viewer, and diff overlay for Pi.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "tallshort",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"pi-package"
|
|
9
|
+
],
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/tallshort/pi-files-widget-overlay.git"
|
|
13
|
+
},
|
|
14
|
+
"bugs": "https://github.com/tallshort/pi-files-widget-overlay/issues",
|
|
15
|
+
"homepage": "https://github.com/tallshort/pi-files-widget-overlay#readme",
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
18
|
+
"@earendil-works/pi-tui": "*"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"typecheck": "tsc --noEmit",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"benchmark:readfiles": "vite-node benchmarks/readfiles.ts"
|
|
24
|
+
},
|
|
25
|
+
"pi": {
|
|
26
|
+
"extensions": [
|
|
27
|
+
"src/index.ts"
|
|
28
|
+
],
|
|
29
|
+
"image": "https://raw.githubusercontent.com/tallshort/pi-files-widget-overlay/main/demo.png"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@earendil-works/pi-coding-agent": "^0.80.3",
|
|
33
|
+
"@types/node": "^22.0.0",
|
|
34
|
+
"@earendil-works/pi-tui": "^0.80.3",
|
|
35
|
+
"typescript": "^5.7.3",
|
|
36
|
+
"vitest": "^3.0.0"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# A wizard walks a human through a manual procedure, step by step.
|
|
4
|
+
# Generated by the /wizard skill.
|
|
5
|
+
#
|
|
6
|
+
# Everything above the "STAGES" marker is the wizard library: do not hand-edit
|
|
7
|
+
# it. Author the per-step stages below the marker.
|
|
8
|
+
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
# ──────────────────────────────────────────────────────────────────────────
|
|
12
|
+
# Wizard library: delightful, consistent UX, identical across every wizard.
|
|
13
|
+
# ──────────────────────────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
if [[ -t 1 ]] && command -v tput >/dev/null 2>&1 && [[ "$(tput colors 2>/dev/null || echo 0)" -ge 8 ]]; then
|
|
16
|
+
BOLD=$(tput bold); DIM=$(tput dim); RESET=$(tput sgr0)
|
|
17
|
+
BLUE=$(tput setaf 4); GREEN=$(tput setaf 2); YELLOW=$(tput setaf 3); RED=$(tput setaf 1)
|
|
18
|
+
else
|
|
19
|
+
BOLD=""; DIM=""; RESET=""; BLUE=""; GREEN=""; YELLOW=""; RED=""
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
# Author sets this at the top of the stages section.
|
|
23
|
+
TOTAL_STAGES=0
|
|
24
|
+
|
|
25
|
+
_STAGE_INDEX=0
|
|
26
|
+
ENV_FILE="${ENV_FILE:-.env}"
|
|
27
|
+
WRITTEN_ENV=() # KEYs written to ENV_FILE this run
|
|
28
|
+
WRITTEN_SECRET=() # secret NAMEs set this run
|
|
29
|
+
SKIPPED=() # things we couldn't do (e.g. gh missing)
|
|
30
|
+
|
|
31
|
+
# _clear wipes the terminal so only the current step is on screen. No-op when
|
|
32
|
+
# output isn't a terminal, so piped logs stay readable.
|
|
33
|
+
_clear() {
|
|
34
|
+
[[ -t 1 ]] || return 0
|
|
35
|
+
if command -v tput >/dev/null 2>&1; then tput clear; else printf '\033[2J\033[3J\033[H'; fi
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
# banner "Title" shows the opening frame: what this wizard does.
|
|
39
|
+
banner() {
|
|
40
|
+
_clear
|
|
41
|
+
printf '\n%s%s %s%s\n' "$BOLD" "$BLUE" "$1" "$RESET"
|
|
42
|
+
printf '%s %s stages%s\n\n' "$DIM" "$TOTAL_STAGES" "$RESET"
|
|
43
|
+
printf '%s You drive the browser; this wizard tells you exactly what to do and\n' "$DIM"
|
|
44
|
+
printf ' captures the values you copy back. Stop any time with Ctrl-C and re-run\n'
|
|
45
|
+
printf ' later, since it remembers values already saved.%s\n' "$RESET"
|
|
46
|
+
pause "Ready to start?"
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# stage "Name" clears the screen, then announces a stage and shows progress.
|
|
50
|
+
# Clearing keeps only the current step on screen.
|
|
51
|
+
stage() {
|
|
52
|
+
_clear
|
|
53
|
+
_STAGE_INDEX=$((_STAGE_INDEX + 1))
|
|
54
|
+
printf '\n%s%s▸ Stage %s/%s · %s%s\n' \
|
|
55
|
+
"$BOLD" "$BLUE" "$_STAGE_INDEX" "$TOTAL_STAGES" "$1" "$RESET"
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
# say "..." prints a plain instruction line.
|
|
59
|
+
say() { printf ' %s\n' "$1"; }
|
|
60
|
+
# step "..." is a numbered-feeling action the human takes in the browser.
|
|
61
|
+
step() { printf ' %s•%s %s\n' "$BLUE" "$RESET" "$1"; }
|
|
62
|
+
note() { printf ' %s%s%s\n' "$DIM" "$1" "$RESET"; }
|
|
63
|
+
warn() { printf ' %s⚠ %s%s\n' "$YELLOW" "$1" "$RESET"; }
|
|
64
|
+
|
|
65
|
+
# open_url URL opens it in the human's browser, cross-platform incl. WSL.
|
|
66
|
+
open_url() {
|
|
67
|
+
local url="$1"
|
|
68
|
+
printf ' %s↗ opening%s %s\n' "$GREEN" "$RESET" "$url"
|
|
69
|
+
{ if command -v wslview >/dev/null 2>&1; then wslview "$url"
|
|
70
|
+
elif command -v explorer.exe >/dev/null 2>&1; then explorer.exe "$url"
|
|
71
|
+
elif command -v xdg-open >/dev/null 2>&1; then xdg-open "$url"
|
|
72
|
+
elif command -v open >/dev/null 2>&1; then open "$url"
|
|
73
|
+
else warn "couldn't open a browser; visit it manually: $url"; fi
|
|
74
|
+
} >/dev/null 2>&1 || warn "couldn't open a browser, so visit it manually: $url"
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
# pause "msg" waits for the human to confirm they've done the manual part.
|
|
78
|
+
pause() {
|
|
79
|
+
printf ' %s%s%s ' "$DIM" "${1:-Press Enter to continue}" "$RESET"
|
|
80
|
+
read -r _ || true
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# confirm "question" is a y/N gate; returns success on yes.
|
|
84
|
+
confirm() {
|
|
85
|
+
local reply=""
|
|
86
|
+
printf ' %s? %s [y/N] ' "$YELLOW" "$1"
|
|
87
|
+
read -r reply || true
|
|
88
|
+
[[ "$reply" =~ ^[Yy] ]]
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
# _existing KEY: current value of KEY in ENV_FILE, if any.
|
|
92
|
+
_existing() {
|
|
93
|
+
[[ -f "$ENV_FILE" ]] || return 1
|
|
94
|
+
local line; line=$(grep -E "^${1}=" "$ENV_FILE" | tail -n1) || return 1
|
|
95
|
+
printf '%s' "${line#*=}"
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
# ask KEY "Prompt" reads a value into $KEY. Offers the existing .env value as
|
|
99
|
+
# a default on re-runs (Enter keeps it). Visible input (non-secret).
|
|
100
|
+
ask() {
|
|
101
|
+
local key="$1" prompt="$2" current input
|
|
102
|
+
current=$(_existing "$key" || true)
|
|
103
|
+
if [[ -n "$current" ]]; then
|
|
104
|
+
printf ' %s%s%s %s[Enter keeps current]%s ' "$BOLD" "$prompt" "$RESET" "$DIM" "$RESET"
|
|
105
|
+
else
|
|
106
|
+
printf ' %s%s%s ' "$BOLD" "$prompt" "$RESET"
|
|
107
|
+
fi
|
|
108
|
+
read -r input || true
|
|
109
|
+
[[ -z "$input" && -n "$current" ]] && input="$current"
|
|
110
|
+
printf -v "$key" '%s' "$input"
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
# ask_secret KEY "Prompt" is like ask, but input is hidden.
|
|
114
|
+
ask_secret() {
|
|
115
|
+
local key="$1" prompt="$2" current input
|
|
116
|
+
current=$(_existing "$key" || true)
|
|
117
|
+
if [[ -n "$current" ]]; then
|
|
118
|
+
printf ' %s%s%s %s[Enter keeps current]%s ' "$BOLD" "$prompt" "$RESET" "$DIM" "$RESET"
|
|
119
|
+
else
|
|
120
|
+
printf ' %s%s%s ' "$BOLD" "$prompt" "$RESET"
|
|
121
|
+
fi
|
|
122
|
+
read -rs input || true
|
|
123
|
+
printf '\n'
|
|
124
|
+
[[ -z "$input" && -n "$current" ]] && input="$current"
|
|
125
|
+
printf -v "$key" '%s' "$input"
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
# write_env KEY VALUE upserts KEY=VALUE into ENV_FILE (creates it; replaces
|
|
129
|
+
# any existing line). Idempotent.
|
|
130
|
+
write_env() {
|
|
131
|
+
local key="$1" value="$2" tmp
|
|
132
|
+
touch "$ENV_FILE"
|
|
133
|
+
tmp=$(mktemp)
|
|
134
|
+
grep -vE "^${key}=" "$ENV_FILE" > "$tmp" || true
|
|
135
|
+
printf '%s=%s\n' "$key" "$value" >> "$tmp"
|
|
136
|
+
mv "$tmp" "$ENV_FILE"
|
|
137
|
+
WRITTEN_ENV+=("$key")
|
|
138
|
+
printf ' %s✓ wrote%s %s → %s\n' "$GREEN" "$RESET" "$key" "$ENV_FILE"
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
# set_secret NAME VALUE sets a GitHub Actions repo secret via gh. Falls back
|
|
142
|
+
# to a warning (and records it) if gh is unavailable or unauthenticated.
|
|
143
|
+
set_secret() {
|
|
144
|
+
local name="$1" value="$2"
|
|
145
|
+
if command -v gh >/dev/null 2>&1 && gh auth status >/dev/null 2>&1; then
|
|
146
|
+
if printf '%s' "$value" | gh secret set "$name" >/dev/null 2>&1; then
|
|
147
|
+
WRITTEN_SECRET+=("$name")
|
|
148
|
+
printf ' %s✓ set%s GitHub secret %s\n' "$GREEN" "$RESET" "$name"
|
|
149
|
+
return
|
|
150
|
+
fi
|
|
151
|
+
fi
|
|
152
|
+
SKIPPED+=("GitHub secret $name (set it manually: gh secret set $name)")
|
|
153
|
+
warn "skipped GitHub secret $name: gh not ready; set it later"
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
# set_var NAME VALUE sets a GitHub Actions repo variable (non-secret).
|
|
157
|
+
set_var() {
|
|
158
|
+
local name="$1" value="$2"
|
|
159
|
+
if command -v gh >/dev/null 2>&1 && gh auth status >/dev/null 2>&1; then
|
|
160
|
+
if gh variable set "$name" --body "$value" >/dev/null 2>&1; then
|
|
161
|
+
printf ' %s✓ set%s GitHub variable %s\n' "$GREEN" "$RESET" "$name"
|
|
162
|
+
return
|
|
163
|
+
fi
|
|
164
|
+
fi
|
|
165
|
+
SKIPPED+=("GitHub variable $name")
|
|
166
|
+
warn "skipped GitHub variable $name, gh not ready; set it later"
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
# finish clears, then shows a closing summary of everything configured.
|
|
170
|
+
finish() {
|
|
171
|
+
_clear
|
|
172
|
+
printf '\n%s%s ✓ Setup complete%s\n' "$BOLD" "$GREEN" "$RESET"
|
|
173
|
+
(( ${#WRITTEN_ENV[@]} )) && note "wrote ${#WRITTEN_ENV[@]} value(s) to $ENV_FILE: ${WRITTEN_ENV[*]}"
|
|
174
|
+
(( ${#WRITTEN_SECRET[@]} )) && note "set ${#WRITTEN_SECRET[@]} GitHub secret(s): ${WRITTEN_SECRET[*]}"
|
|
175
|
+
if (( ${#SKIPPED[@]} )); then
|
|
176
|
+
printf '\n'; warn "still to do by hand:"
|
|
177
|
+
for s in "${SKIPPED[@]}"; do note " - $s"; done
|
|
178
|
+
fi
|
|
179
|
+
printf '\n'
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
# ──────────────────────────────────────────────────────────────────────────
|
|
183
|
+
# STAGES: author this section. One stage() per step the human takes.
|
|
184
|
+
# Replace the example below. Set TOTAL_STAGES to match the stages you write.
|
|
185
|
+
# ──────────────────────────────────────────────────────────────────────────
|
|
186
|
+
|
|
187
|
+
TOTAL_STAGES=5
|
|
188
|
+
|
|
189
|
+
banner "Publish pi-files-widget-overlay"
|
|
190
|
+
|
|
191
|
+
stage "Create the GitHub repository"
|
|
192
|
+
open_url "https://github.com/new"
|
|
193
|
+
step "Owner: tallshort. Repository name: pi-files-widget-overlay."
|
|
194
|
+
step "Choose Public, and leave README, .gitignore, and license initialization unchecked."
|
|
195
|
+
step "Create the repository; it must be empty because this checkout already has history."
|
|
196
|
+
pause "Press Enter after the repository exists."
|
|
197
|
+
|
|
198
|
+
stage "Push the existing main branch"
|
|
199
|
+
say "This checkout already uses: https://github.com/tallshort/pi-files-widget-overlay.git"
|
|
200
|
+
step "Run: git ls-remote origin"
|
|
201
|
+
step "Run: git push -u origin main"
|
|
202
|
+
pause "Press Enter after the push succeeds."
|
|
203
|
+
|
|
204
|
+
stage "Verify the GitHub project"
|
|
205
|
+
open_url "https://github.com/tallshort/pi-files-widget-overlay"
|
|
206
|
+
step "Confirm the default branch is main and the repository shows src/, test/, docs/, README.md, and package.json."
|
|
207
|
+
pause "Press Enter after verification."
|
|
208
|
+
|
|
209
|
+
stage "Prepare the v0.3.0 Git release"
|
|
210
|
+
step "From the checkout run: npm test && npm run typecheck && npm pack --dry-run"
|
|
211
|
+
step "Review git status --short; it must be empty before tagging."
|
|
212
|
+
step "Run: git tag -a v0.3.0 -m 'Release 0.3.0'"
|
|
213
|
+
step "Run: git push origin main --tags"
|
|
214
|
+
pause "Press Enter after the tag is visible on GitHub."
|
|
215
|
+
|
|
216
|
+
stage "Publish to npm"
|
|
217
|
+
say "package.json already links the package page to the GitHub repository through its repository field."
|
|
218
|
+
step "Run: npm login"
|
|
219
|
+
step "Run: npm whoami"
|
|
220
|
+
step "Optional availability check: npm view pi-files-widget-overlay version"
|
|
221
|
+
if confirm "Publish version 0.3.0 to npm now?"; then
|
|
222
|
+
step "Run: npm publish"
|
|
223
|
+
step "Verify: npm view pi-files-widget-overlay version"
|
|
224
|
+
else
|
|
225
|
+
note "Skipped npm publish. Re-run this wizard when you are ready."
|
|
226
|
+
fi
|
|
227
|
+
|
|
228
|
+
finish
|
package/src/activity.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
|
|
3
|
+
export function getObservedToolActivityPath(toolName: string, input: unknown, cwd: string): string | undefined {
|
|
4
|
+
if (toolName !== "write" && toolName !== "edit") return undefined;
|
|
5
|
+
if (!input || typeof input !== "object") return undefined;
|
|
6
|
+
|
|
7
|
+
const field = toolName === "write" ? "path" : "file";
|
|
8
|
+
const path = (input as Record<string, unknown>)[field];
|
|
9
|
+
return typeof path === "string" && path.trim() ? resolve(cwd, path) : undefined;
|
|
10
|
+
}
|