@wuyaos/pi-sync 1.1.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/LICENSE +21 -0
- package/PROMO.md +95 -0
- package/README.md +205 -0
- package/README.zh-CN.md +205 -0
- package/docs/sync-menu.png +0 -0
- package/extensions/_shared/box-drawing.ts +58 -0
- package/extensions/_shared/enhanced-select.ts +477 -0
- package/extensions/_shared/fetch-utils.ts +46 -0
- package/extensions/_shared/json-io.ts +120 -0
- package/extensions/_shared/spawn.ts +91 -0
- package/extensions/sync/archive.ts +264 -0
- package/extensions/sync/config.ts +93 -0
- package/extensions/sync/index.ts +59 -0
- package/extensions/sync/menus.ts +258 -0
- package/extensions/sync/restore.ts +140 -0
- package/extensions/sync/session-sync.ts +231 -0
- package/extensions/sync/webdav.ts +91 -0
- package/package.json +36 -0
- package/pi-bootstrap.ps1 +113 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BevalZ
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/PROMO.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# pi-sync promotion drafts
|
|
2
|
+
|
|
3
|
+
Repo: https://github.com/wuyaos/pi-packages
|
|
4
|
+
Install: `pi install git:github.com/wuyaos/pi-packages`
|
|
5
|
+
Release: https://github.com/wuyaos/pi-packages/releases/tag/v1.0.1
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## English (short)
|
|
10
|
+
|
|
11
|
+
**pi-sync** — WebDAV backup/restore for the [Pi coding agent](https://github.com/earendil-works/pi-coding-agent).
|
|
12
|
+
|
|
13
|
+
Open `/sync`, then **Upload Backup** on one machine and **Download Backup** on another.
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pi install git:github.com/wuyaos/pi-packages
|
|
17
|
+
/sync # main machine → Upload Backup (Backup to cloud)
|
|
18
|
+
/sync # new machine → Download Backup (Restore from cloud)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Works with any WebDAV (Nextcloud, 坚果云, TeraCLOUD, self-hosted). Restore keeps local `.bak` copies. MIT.
|
|
22
|
+
|
|
23
|
+
👉 https://github.com/wuyaos/pi-packages
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## English (Discord / forum)
|
|
28
|
+
|
|
29
|
+
Hey Pi users — I open-sourced **pi-sync**, a small package that syncs your Pi agent home over WebDAV.
|
|
30
|
+
|
|
31
|
+
Problem: multi-machine setups mean re-copying `models.json`, skills, and extensions by hand.
|
|
32
|
+
Solution: `/sync push` on the main box, `/sync pull` on the next one.
|
|
33
|
+
|
|
34
|
+
- Install: `pi install git:github.com/wuyaos/pi-packages`
|
|
35
|
+
- Interactive menu: Upload Backup · Download Backup · Configure Sync Settings
|
|
36
|
+
- Optional Windows bootstrap script for brand-new machines
|
|
37
|
+
- Backup zips tagged by platform (`windows11`, `macos`, …)
|
|
38
|
+
- Restore confirms and keeps timestamped local backups
|
|
39
|
+
|
|
40
|
+
Feedback / issues welcome: https://github.com/wuyaos/pi-packages
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 中文(短)
|
|
45
|
+
|
|
46
|
+
**pi-sync**:给 [Pi coding agent](https://github.com/earendil-works/pi-coding-agent) 用的 WebDAV 配置同步插件。
|
|
47
|
+
|
|
48
|
+
多机之间一键备份 / 恢复 models、settings、skills、extensions。
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pi install git:github.com/wuyaos/pi-packages
|
|
52
|
+
/sync # 主力机 → Upload Backup (Backup to cloud)
|
|
53
|
+
/sync # 新机器 → Download Backup (Restore from cloud)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
支持任意 WebDAV(坚果云 / Nextcloud / 自建)。恢复前会做本地备份。MIT 开源。
|
|
57
|
+
|
|
58
|
+
👉 https://github.com/wuyaos/pi-packages
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 中文(朋友圈 / 社区)
|
|
63
|
+
|
|
64
|
+
换电脑重装 Pi 配置太烦?我做了个小工具 **pi-sync** 并开源了。
|
|
65
|
+
|
|
66
|
+
- 主力机 `/sync` → **Upload Backup** 把配置打成 zip 传到 WebDAV
|
|
67
|
+
- 新机器 `/sync` → **Download Backup** 选择备份并还原
|
|
68
|
+
- 覆盖 models / settings / skills / extensions
|
|
69
|
+
- 恢复前自动留本地备份,密码建议用应用专用密码 + 环境变量
|
|
70
|
+
|
|
71
|
+
安装一行:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pi install git:github.com/wuyaos/pi-packages
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
仓库:https://github.com/wuyaos/pi-packages
|
|
78
|
+
Release:https://github.com/wuyaos/pi-packages/releases/tag/v1.0.1
|
|
79
|
+
|
|
80
|
+
欢迎试用和提 issue。
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Tweet / X (EN)
|
|
85
|
+
|
|
86
|
+
Multi-machine Pi setup? I open-sourced pi-sync:
|
|
87
|
+
|
|
88
|
+
`/sync` → Upload Backup → WebDAV
|
|
89
|
+
`/sync` → Download Backup → new machine
|
|
90
|
+
|
|
91
|
+
models · settings · skills · extensions
|
|
92
|
+
|
|
93
|
+
`pi install git:github.com/wuyaos/pi-packages`
|
|
94
|
+
|
|
95
|
+
https://github.com/wuyaos/pi-packages
|
package/README.md
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# pi-sync
|
|
2
|
+
|
|
3
|
+
**English** | [简体中文](./README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
[](https://github.com/earendil-works/pi-coding-agent)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
[](https://github.com/wuyaos/pi-packages/releases)
|
|
8
|
+
|
|
9
|
+
WebDAV-based config sync for [Pi](https://github.com/earendil-works/pi-coding-agent) — backup and restore **models**, **settings**, **skills**, **extensions**, and **session projects** across machines.
|
|
10
|
+
|
|
11
|
+
Run `/sync`, pick an action from the menu. One machine uploads; another downloads and restores.
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
14
|
+
<img src="docs/sync-menu.png" alt="Pi WebDAV Synchronization menu" width="720" />
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p align="center"><sub><b>Pi WebDAV Synchronization</b> — interactive menu after <code>/sync</code></sub></p>
|
|
18
|
+
|
|
19
|
+
## Why
|
|
20
|
+
|
|
21
|
+
If you run Pi on multiple PCs / WSL / servers, reinstalling models, skills, and extensions by hand is painful. `pi-sync` packages your agent home into a timestamped zip, uploads it to any WebDAV folder, and restores it with local safety backups.
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
Requires [Pi coding agent](https://github.com/earendil-works/pi-coding-agent) and a WebDAV endpoint (TeraCLOUD, 坚果云 / Jianguoyun, Nextcloud, ownCloud, self-hosted, …).
|
|
26
|
+
|
|
27
|
+
`pi-sync` is part of the [wuyaos/pi-packages](https://github.com/wuyaos/pi-packages) monorepo. Installing the whole repo loads every sub-package:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pi install git:github.com/wuyaos/pi-packages
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
To load **only** `pi-sync`, use the object form in `~/.pi/agent/settings.json`:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"packages": [
|
|
38
|
+
{
|
|
39
|
+
"source": "git:github.com/wuyaos/pi-packages",
|
|
40
|
+
"extensions": ["pi-sync/extensions/*.ts"],
|
|
41
|
+
"themes": []
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Then restart Pi or run `/reload`.
|
|
48
|
+
|
|
49
|
+
## Usage
|
|
50
|
+
|
|
51
|
+
Type **`/sync`** in Pi. There are no CLI subcommands — everything goes through the interactive menu:
|
|
52
|
+
|
|
53
|
+
| Menu item | What it does |
|
|
54
|
+
|-----------|----------------|
|
|
55
|
+
| ☁️ **Upload Backup (Backup to cloud)** | Zip current config and upload to WebDAV |
|
|
56
|
+
| 📥 **Download Backup (Restore from cloud)** | List remote backups, download one, restore with confirmation |
|
|
57
|
+
| ⚙️ **Configure Sync Settings** | WebDAV URL / user / password, and what to include |
|
|
58
|
+
| ❌ **Cancel** | Leave the menu |
|
|
59
|
+
|
|
60
|
+
Keyboard hints (as shown in the TUI): `↵` select · `↑↓` navigate · `Esc` cancel.
|
|
61
|
+
|
|
62
|
+
### First-time setup
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# 1. Install
|
|
66
|
+
pi install git:github.com/wuyaos/pi-packages
|
|
67
|
+
|
|
68
|
+
# 2. Open the menu (first run starts the setup wizard if WebDAV is empty)
|
|
69
|
+
/sync
|
|
70
|
+
|
|
71
|
+
# 3. If needed: Configure Sync Settings
|
|
72
|
+
# enter URL / user / password
|
|
73
|
+
# tip: set password to $PI_WEBDAV_PASS and export that env var
|
|
74
|
+
|
|
75
|
+
# 4. On your main machine → Upload Backup (Backup to cloud)
|
|
76
|
+
# 5. On a new machine (after install + configure) → Download Backup (Restore from cloud)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### What gets synced
|
|
80
|
+
|
|
81
|
+
| Component | Default | Notes |
|
|
82
|
+
|-----------|---------|-------|
|
|
83
|
+
| Config | ON | `models.json`, `settings.json`, `auth.json` |
|
|
84
|
+
| Skills | ON | entire `~/.pi/agent/skills` |
|
|
85
|
+
| Extensions | ON | `~/.pi/agent/extensions` (the sync plugin itself is excluded from the zip) |
|
|
86
|
+
| Sessions | OFF | per-project session history under `~/.pi/agent/sessions/`; pick which projects to include under **Configure Sync Settings → Session Projects** |
|
|
87
|
+
|
|
88
|
+
Toggle any of these under **Configure Sync Settings**.
|
|
89
|
+
|
|
90
|
+
### Sessions (optional)
|
|
91
|
+
|
|
92
|
+
Session history is organized by project cwd under `~/.pi/agent/sessions/<projectDir>/`. The **Session Projects** submenu lists every project directory found on this machine and lets you check the ones you want to back up.
|
|
93
|
+
|
|
94
|
+
- Turn on **Backup Sessions** in **Configure Sync Settings**.
|
|
95
|
+
- Open **Session Projects** and toggle projects on/off (use **Select All** / **Reset list** for convenience).
|
|
96
|
+
- List mode (toggleable):
|
|
97
|
+
- **Whitelist**: only checked projects are backed up; an empty list backs up **nothing**.
|
|
98
|
+
- **Blacklist**: checked projects are skipped; an empty list backs up **everything**.
|
|
99
|
+
- On restore, session files are *merged* into the local `~/.pi/agent/sessions/` — session file names are unique (timestamp + uuid), so restoring never overwrites or deletes your local sessions.
|
|
100
|
+
|
|
101
|
+
> Note: project directory names encode the project path, so a backup made on one machine only restores into the same project path on another machine.
|
|
102
|
+
|
|
103
|
+
### Backup filename
|
|
104
|
+
|
|
105
|
+
Archives look like:
|
|
106
|
+
|
|
107
|
+
```text
|
|
108
|
+
pi_sync_backup_2026-7-14_20260714120000_windows11.zip
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The trailing platform tag (`windows11` / `windows10` / `macos` / `linux`) shows which host created the backup.
|
|
112
|
+
|
|
113
|
+
### Safety on restore
|
|
114
|
+
|
|
115
|
+
- Existing config files get a timestamped `.bak` copy before overwrite
|
|
116
|
+
- Existing skills / extensions folders are renamed to `*-backup-<timestamp>` before replace/merge
|
|
117
|
+
- Restore shows a plan and asks for confirmation
|
|
118
|
+
- After a successful restore you can reload the agent runtime to apply skills/extensions
|
|
119
|
+
|
|
120
|
+
## Bootstrap (new Windows machine, no Pi yet)
|
|
121
|
+
|
|
122
|
+
If Pi is not installed yet, you can still pull the latest zip with the helper script:
|
|
123
|
+
|
|
124
|
+
```powershell
|
|
125
|
+
# Prefer env vars so secrets never land in shell history
|
|
126
|
+
$env:PI_WEBDAV_URL = "https://your-webdav.example/dav/Pi"
|
|
127
|
+
$env:PI_WEBDAV_USER = "your-user"
|
|
128
|
+
$env:PI_WEBDAV_PASS = "your-app-password"
|
|
129
|
+
.\pi-bootstrap.ps1
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Or one-liner placeholders (replace before running):
|
|
133
|
+
|
|
134
|
+
```powershell
|
|
135
|
+
$url="https://your-webdav.example/dav/Pi"; $user="your-user"; $pass="your-app-password"
|
|
136
|
+
$pair="$user`:$pass"; $auth=[Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes($pair))
|
|
137
|
+
$resp=Invoke-RestMethod -Uri $url -Method PROPFIND -Headers @{Authorization="Basic $auth";Depth="1"} -ContentType "application/xml"
|
|
138
|
+
$files=([regex]'<d:href>([^<]+)</d:href>').Matches($resp) | %{$_.Groups[1].Value} | ?{$_ -match "pi_sync_backup_.*\.zip$"} | Sort-Object -Descending
|
|
139
|
+
$latest=$files[0]; $name=Split-Path $latest -Leaf
|
|
140
|
+
Invoke-WebRequest -Uri "$url/$name" -Headers @{Authorization="Basic $auth"} -OutFile "$env:TEMP\$name"
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Then install Pi and use **Download Backup** from `/sync` for future updates.
|
|
144
|
+
|
|
145
|
+
## Security
|
|
146
|
+
|
|
147
|
+
- WebDAV credentials are stored locally in `~/.pi/agent/sync_config.json`
|
|
148
|
+
- Prefer **app-specific passwords** (not your main account password)
|
|
149
|
+
- Prefer env-var references: set password to `$PI_WEBDAV_PASS` in the UI, then export that variable in your shell profile
|
|
150
|
+
- Backups may include `auth.json` / API keys if those options are enabled — treat the WebDAV folder as sensitive
|
|
151
|
+
- Never commit real WebDAV URLs with credentials into git
|
|
152
|
+
|
|
153
|
+
## Troubleshooting
|
|
154
|
+
|
|
155
|
+
| Symptom | Fix |
|
|
156
|
+
|---------|-----|
|
|
157
|
+
| HTTP 401 / 403 | Check user/password; use app password; confirm URL includes the correct DAV path |
|
|
158
|
+
| PROPFIND fails / empty list | Server may block PROPFIND; try another WebDAV provider; ensure Depth:1 is allowed |
|
|
159
|
+
| tar / zip errors | Need a working `tar` on PATH (Windows 10+ has one; Git Bash / WSL also fine) |
|
|
160
|
+
| Restore overwrote something | Look for `*.bak-*` files and `skills-backup-*` / `extensions-backup-*` folders next to the agent dir |
|
|
161
|
+
| Plugin missing after restore | Re-run `pi install git:github.com/wuyaos/pi-packages` — the sync package excludes itself from the archive |
|
|
162
|
+
|
|
163
|
+
## Structure
|
|
164
|
+
|
|
165
|
+
```text
|
|
166
|
+
pi-sync/
|
|
167
|
+
package.json
|
|
168
|
+
LICENSE
|
|
169
|
+
README.md
|
|
170
|
+
README.zh-CN.md
|
|
171
|
+
pi-bootstrap.ps1
|
|
172
|
+
docs/
|
|
173
|
+
sync-menu.png # /sync menu screenshot
|
|
174
|
+
extensions/
|
|
175
|
+
sync/
|
|
176
|
+
index.ts # /sync command
|
|
177
|
+
_shared/
|
|
178
|
+
json-io.ts
|
|
179
|
+
enhanced-select.ts
|
|
180
|
+
spawn.ts
|
|
181
|
+
fetch-utils.ts
|
|
182
|
+
box-drawing.ts
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Changelog
|
|
186
|
+
|
|
187
|
+
### v1.0.1
|
|
188
|
+
|
|
189
|
+
- Tag backup zip names with host platform (`windows11` / `macos` / `linux` / …)
|
|
190
|
+
- Remove example credentials from bootstrap script comments
|
|
191
|
+
- Add MIT `LICENSE` and expand README (security, restore safety, troubleshooting, menu screenshot)
|
|
192
|
+
|
|
193
|
+
### v1.0.0
|
|
194
|
+
|
|
195
|
+
- Initial public release: interactive `/sync` menu over WebDAV
|
|
196
|
+
- Upload Backup · Download Backup · Configure Sync Settings
|
|
197
|
+
- Windows bootstrap helper script
|
|
198
|
+
|
|
199
|
+
## License
|
|
200
|
+
|
|
201
|
+
MIT — see [LICENSE](./LICENSE).
|
|
202
|
+
|
|
203
|
+
## Acknowledgements
|
|
204
|
+
|
|
205
|
+
This open-source project is linked and recognized by the [LINUX DO](https://linux.do) community.
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# pi-sync
|
|
2
|
+
|
|
3
|
+
[English](./README.md) | **简体中文**
|
|
4
|
+
|
|
5
|
+
[](https://github.com/earendil-works/pi-coding-agent)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
[](https://github.com/wuyaos/pi-packages/releases)
|
|
8
|
+
|
|
9
|
+
面向 [Pi](https://github.com/earendil-works/pi-coding-agent) 的 WebDAV 配置同步工具 —— 跨机器备份与恢复 **models**、**settings**、**skills**、**extensions** 以及选定的 **session 项目**。
|
|
10
|
+
|
|
11
|
+
在 Pi 里输入 `/sync`,从菜单选择操作。一台机器上传,另一台下载并恢复。
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
14
|
+
<img src="docs/sync-menu.png" alt="Pi WebDAV Synchronization 菜单" width="720" />
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p align="center"><sub><b>Pi WebDAV Synchronization</b> —— 输入 <code>/sync</code> 后的交互菜单</sub></p>
|
|
18
|
+
|
|
19
|
+
## 为什么需要它
|
|
20
|
+
|
|
21
|
+
如果你在多台 PC / WSL / 服务器上使用 Pi,手工重装 models、skills、extensions 很痛苦。`pi-sync` 会把 agent 主目录打包成带时间戳的 zip,上传到任意 WebDAV 目录,并在恢复时保留本地安全备份。
|
|
22
|
+
|
|
23
|
+
## 安装
|
|
24
|
+
|
|
25
|
+
需要 [Pi coding agent](https://github.com/earendil-works/pi-coding-agent),以及可用的 WebDAV(TeraCLOUD、坚果云、Nextcloud、ownCloud、自建等)。
|
|
26
|
+
|
|
27
|
+
`pi-sync` 是 [wuyaos/pi-packages](https://github.com/wuyaos/pi-packages) monorepo 的子包。直接安装整个仓库会加载所有子包:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pi install git:github.com/wuyaos/pi-packages
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
只想加载 **pi-sync** 时,在 `~/.pi/agent/settings.json` 用 object 形式筛选:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"packages": [
|
|
38
|
+
{
|
|
39
|
+
"source": "git:github.com/wuyaos/pi-packages",
|
|
40
|
+
"extensions": ["pi-sync/extensions/*.ts"],
|
|
41
|
+
"themes": []
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
然后重启 Pi,或执行 `/reload`。
|
|
48
|
+
|
|
49
|
+
## 用法
|
|
50
|
+
|
|
51
|
+
在 Pi 中输入 **`/sync`**。没有命令行子命令 —— 全部通过交互菜单完成:
|
|
52
|
+
|
|
53
|
+
| 菜单项 | 作用 |
|
|
54
|
+
|--------|------|
|
|
55
|
+
| ☁️ **Upload Backup (Backup to cloud)** | 打包当前配置并上传到 WebDAV |
|
|
56
|
+
| 📥 **Download Backup (Restore from cloud)** | 列出云端备份,下载并在确认后恢复 |
|
|
57
|
+
| ⚙️ **Configure Sync Settings** | 配置 WebDAV 地址 / 用户 / 密码,以及同步范围 |
|
|
58
|
+
| ❌ **Cancel** | 退出菜单 |
|
|
59
|
+
|
|
60
|
+
TUI 提示:`↵` 选择 · `↑↓` 导航 · `Esc` 取消。
|
|
61
|
+
|
|
62
|
+
### 首次配置
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# 1. 安装
|
|
66
|
+
pi install git:github.com/wuyaos/pi-packages
|
|
67
|
+
|
|
68
|
+
# 2. 打开菜单(若尚未配置 WebDAV,会先进入设置向导)
|
|
69
|
+
/sync
|
|
70
|
+
|
|
71
|
+
# 3. 如需修改:Configure Sync Settings
|
|
72
|
+
# 填写 URL / 用户名 / 密码
|
|
73
|
+
# 建议:密码填 $PI_WEBDAV_PASS,并在 shell 中 export 该环境变量
|
|
74
|
+
|
|
75
|
+
# 4. 主力机 → Upload Backup (Backup to cloud)
|
|
76
|
+
# 5. 新机器(安装并配置后)→ Download Backup (Restore from cloud)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 会同步哪些内容
|
|
80
|
+
|
|
81
|
+
| 组件 | 默认 | 说明 |
|
|
82
|
+
|------|------|------|
|
|
83
|
+
| Config | 开 | `models.json`、`settings.json`、`auth.json` |
|
|
84
|
+
| Skills | 开 | 整个 `~/.pi/agent/skills` |
|
|
85
|
+
| Extensions | 开 | `~/.pi/agent/extensions`(zip 中会排除 sync 插件自身) |
|
|
86
|
+
| Sessions | 关 | `~/.pi/agent/sessions/` 下按项目分目录的会话历史;在 **Configure Sync Settings → Session Projects** 中勾选要同步的项目 |
|
|
87
|
+
|
|
88
|
+
可在 **Configure Sync Settings** 中分别开关。
|
|
89
|
+
|
|
90
|
+
### Sessions(可选)
|
|
91
|
+
|
|
92
|
+
会话历史按项目 cwd 存放在 `~/.pi/agent/sessions/<projectDir>/`。**Session Projects** 子菜单会列出本机所有项目目录,勾选你想备份的那些。
|
|
93
|
+
|
|
94
|
+
- 在 **Configure Sync Settings** 中打开 **Backup Sessions**。
|
|
95
|
+
- 打开 **Session Projects** 逐个勾选项目(可用 **Select All** / **Reset list** 快捷全选/清空)。
|
|
96
|
+
- 列表模式(可切换):
|
|
97
|
+
- **白名单模式**:只备份勾选的项目,空列表 = 全部不备份。
|
|
98
|
+
- **黑名单模式**:跳过勾选的项目,空列表 = 全部备份。
|
|
99
|
+
- 恢复时会以 *合并* 方式写入本地 `~/.pi/agent/sessions/`——会话文件名为唯一的时间戳+uuid,不会覆盖或删除本地已有会话。
|
|
100
|
+
|
|
101
|
+
> 注意:项目目录名由项目路径编码而来,备份在 A 机器上制作,恢复到 B 机器时只会落到相同项目路径对应的项目目录中。
|
|
102
|
+
|
|
103
|
+
### 备份文件名
|
|
104
|
+
|
|
105
|
+
归档文件形如:
|
|
106
|
+
|
|
107
|
+
```text
|
|
108
|
+
pi_sync_backup_2026-7-14_20260714120000_windows11.zip
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
末尾的平台标签(`windows11` / `windows10` / `macos` / `linux`)标明该备份由哪类主机生成。
|
|
112
|
+
|
|
113
|
+
### 恢复时的安全机制
|
|
114
|
+
|
|
115
|
+
- 覆盖前,已有配置文件会生成带时间戳的 `.bak` 副本
|
|
116
|
+
- 已有 skills / extensions 目录会先改名为 `*-backup-<timestamp>`,再替换/合并
|
|
117
|
+
- 恢复前会展示计划,并要求确认
|
|
118
|
+
- 恢复成功后可选择 reload agent runtime,以应用 skills / extensions
|
|
119
|
+
|
|
120
|
+
## 新机引导(Windows,尚未安装 Pi)
|
|
121
|
+
|
|
122
|
+
若还没装 Pi,也可先用辅助脚本拉取最新 zip:
|
|
123
|
+
|
|
124
|
+
```powershell
|
|
125
|
+
# 优先用环境变量,避免密钥进入 shell 历史
|
|
126
|
+
$env:PI_WEBDAV_URL = "https://your-webdav.example/dav/Pi"
|
|
127
|
+
$env:PI_WEBDAV_USER = "your-user"
|
|
128
|
+
$env:PI_WEBDAV_PASS = "your-app-password"
|
|
129
|
+
.\pi-bootstrap.ps1
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
或使用占位符一行命令(运行前请替换):
|
|
133
|
+
|
|
134
|
+
```powershell
|
|
135
|
+
$url="https://your-webdav.example/dav/Pi"; $user="your-user"; $pass="your-app-password"
|
|
136
|
+
$pair="$user`:$pass"; $auth=[Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes($pair))
|
|
137
|
+
$resp=Invoke-RestMethod -Uri $url -Method PROPFIND -Headers @{Authorization="Basic $auth";Depth="1"} -ContentType "application/xml"
|
|
138
|
+
$files=([regex]'<d:href>([^<]+)</d:href>').Matches($resp) | %{$_.Groups[1].Value} | ?{$_ -match "pi_sync_backup_.*\.zip$"} | Sort-Object -Descending
|
|
139
|
+
$latest=$files[0]; $name=Split-Path $latest -Leaf
|
|
140
|
+
Invoke-WebRequest -Uri "$url/$name" -Headers @{Authorization="Basic $auth"} -OutFile "$env:TEMP\$name"
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
之后安装 Pi,后续更新用 `/sync` → **Download Backup** 即可。
|
|
144
|
+
|
|
145
|
+
## 安全建议
|
|
146
|
+
|
|
147
|
+
- WebDAV 凭证保存在本机 `~/.pi/agent/sync_config.json`
|
|
148
|
+
- 优先使用**应用专用密码**(不要用主账号密码)
|
|
149
|
+
- 更推荐环境变量引用:界面里密码填 `$PI_WEBDAV_PASS`,再在 shell profile 中 export
|
|
150
|
+
- 若开启相关选项,备份可能包含 `auth.json` / API key —— 请把 WebDAV 目录当敏感数据对待
|
|
151
|
+
- 切勿把真实 WebDAV 地址与凭证提交进 git
|
|
152
|
+
|
|
153
|
+
## 故障排查
|
|
154
|
+
|
|
155
|
+
| 现象 | 处理 |
|
|
156
|
+
|------|------|
|
|
157
|
+
| HTTP 401 / 403 | 检查用户名密码;改用应用专用密码;确认 URL 含正确 DAV 路径 |
|
|
158
|
+
| PROPFIND 失败 / 列表为空 | 服务端可能禁用 PROPFIND;换 WebDAV 提供商;确认允许 Depth:1 |
|
|
159
|
+
| tar / zip 报错 | PATH 中需要可用的 `tar`(Windows 10+ 自带;Git Bash / WSL 亦可) |
|
|
160
|
+
| 恢复覆盖了本地内容 | 在 agent 目录旁查找 `*.bak-*` 与 `skills-backup-*` / `extensions-backup-*` |
|
|
161
|
+
| 恢复后插件不见了 | 重新执行 `pi install git:github.com/wuyaos/pi-packages` —— 归档会排除 sync 包自身 |
|
|
162
|
+
|
|
163
|
+
## 目录结构
|
|
164
|
+
|
|
165
|
+
```text
|
|
166
|
+
pi-sync/
|
|
167
|
+
package.json
|
|
168
|
+
LICENSE
|
|
169
|
+
README.md
|
|
170
|
+
README.zh-CN.md
|
|
171
|
+
pi-bootstrap.ps1
|
|
172
|
+
docs/
|
|
173
|
+
sync-menu.png # /sync 菜单截图
|
|
174
|
+
extensions/
|
|
175
|
+
sync/
|
|
176
|
+
index.ts # /sync 命令
|
|
177
|
+
_shared/
|
|
178
|
+
json-io.ts
|
|
179
|
+
enhanced-select.ts
|
|
180
|
+
spawn.ts
|
|
181
|
+
fetch-utils.ts
|
|
182
|
+
box-drawing.ts
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## 更新日志
|
|
186
|
+
|
|
187
|
+
### v1.0.1
|
|
188
|
+
|
|
189
|
+
- 备份 zip 文件名增加主机平台标签(`windows11` / `macos` / `linux` 等)
|
|
190
|
+
- 从 bootstrap 脚本示例中移除真实凭证
|
|
191
|
+
- 增加 MIT `LICENSE`,扩充 README(安全、恢复保护、故障排查、菜单截图)
|
|
192
|
+
|
|
193
|
+
### v1.0.0
|
|
194
|
+
|
|
195
|
+
- 首次公开发布:基于 WebDAV 的交互式 `/sync` 菜单
|
|
196
|
+
- Upload Backup · Download Backup · Configure Sync Settings
|
|
197
|
+
- Windows 新机引导脚本
|
|
198
|
+
|
|
199
|
+
## 许可证
|
|
200
|
+
|
|
201
|
+
MIT — 见 [LICENSE](./LICENSE)。
|
|
202
|
+
|
|
203
|
+
## 致谢
|
|
204
|
+
|
|
205
|
+
本开源项目已链接并获 [LINUX DO](https://linux.do) 社区认可。
|
|
Binary file
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared box-drawing utilities for TUI dashboards.
|
|
3
|
+
*
|
|
4
|
+
* Reusable across extensions (cost-tracker, session-manager, etc.).
|
|
5
|
+
* Import: import { … } from "../_shared/box-drawing"
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
9
|
+
|
|
10
|
+
// ── Unicode box-drawing characters ─────────────────────────────────────
|
|
11
|
+
|
|
12
|
+
export const H = "─";
|
|
13
|
+
export const V = "│";
|
|
14
|
+
export const TL = "╭";
|
|
15
|
+
export const TR = "╮";
|
|
16
|
+
export const BL = "╰";
|
|
17
|
+
export const BR = "╯";
|
|
18
|
+
export const LT = "├";
|
|
19
|
+
export const RT = "┤";
|
|
20
|
+
|
|
21
|
+
// ── Border helpers ─────────────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
/** Top border with optional title (title rendered by caller, not inserted here). */
|
|
24
|
+
export function topBorder(w: number, title: string, th: any): string {
|
|
25
|
+
const titleVis = visibleWidth(title);
|
|
26
|
+
const left = 2;
|
|
27
|
+
const right = w - 2 - left - titleVis;
|
|
28
|
+
return th.fg("accent", TL + H.repeat(left)) + title + th.fg("accent", H.repeat(Math.max(0, right)) + TR);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Simple top border without title. */
|
|
32
|
+
export function topBorderPlain(w: number, th: any): string {
|
|
33
|
+
return th.fg("accent", TL + H.repeat(w - 2) + TR);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Bottom border. */
|
|
37
|
+
export function bottomBorder(w: number, th: any): string {
|
|
38
|
+
return th.fg("borderMuted", BL + H.repeat(w - 2) + BR);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Mid horizontal divider. */
|
|
42
|
+
export function midBorder(w: number, th: any): string {
|
|
43
|
+
return th.fg("borderMuted", LT + H.repeat(w - 2) + RT);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Pad text to a fixed visible width, truncating if too long. */
|
|
47
|
+
export function sidePad(text: string, width: number): string {
|
|
48
|
+
const vis = visibleWidth(text);
|
|
49
|
+
if (vis >= width) return truncateToWidth(text, width);
|
|
50
|
+
return text + " ".repeat(width - vis);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Render a single content line inside a box: `│ content │`. */
|
|
54
|
+
export function lineInBox(content: string, boxWidth: number, th: any): string {
|
|
55
|
+
const contentW = boxWidth - 4;
|
|
56
|
+
if (contentW <= 0) return th.fg("borderMuted", V) + V;
|
|
57
|
+
return th.fg("borderMuted", V) + " " + sidePad(content, contentW) + " " + th.fg("borderMuted", V);
|
|
58
|
+
}
|