@narumitw/pi-sync 0.29.1 → 0.30.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/README.md +38 -15
- package/package.json +1 -1
- package/src/command.ts +1 -1
- package/src/config-file.ts +545 -0
- package/src/config.ts +130 -19
- package/src/file-selection.ts +0 -1
- package/src/manager-ui.ts +125 -98
- package/src/paths.ts +6 -1
- package/src/settings-management.ts +24 -9
- package/src/settings-ui.ts +199 -0
- package/src/sync.ts +21 -16
- package/src/target-switch.ts +119 -0
- package/src/types.ts +2 -0
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ The extension uses immutable snapshot bundles, a `latest.json` publication point
|
|
|
10
10
|
|
|
11
11
|
- Opens a goal-oriented `/sync` manager showing the current target, storage, auto-sync, session scope, and relevant next actions.
|
|
12
12
|
- Supports multiple named **sync targets** and reusable R2/S3 **storage profiles**.
|
|
13
|
-
-
|
|
13
|
+
- Asks to review a pull after switching targets by default, with settings to start that review automatically or switch only.
|
|
14
14
|
- Previews concrete local or remote file changes before push, pull, force resolution, or rollback.
|
|
15
15
|
- Uses transactional synced-content drafts with explicit Save, Discard, and Continue editing choices.
|
|
16
16
|
- Keeps direct `help`, `use`, `init`, `config`, `files`, `status`, `diff`, `doctor`, `push`, `pull`, `sync`, `history`, `rollback`, and `unlock` routes for compatibility and automation.
|
|
@@ -79,36 +79,49 @@ A configured manager shows:
|
|
|
79
79
|
```text
|
|
80
80
|
Current target: home
|
|
81
81
|
Storage: Cloudflare R2 · personal-pi
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
Synced content: 9 built-in groups · 0 extra files · Sessions: Off
|
|
83
|
+
Auto-sync: On
|
|
84
|
+
Last applied snapshot: snapshot-id (or Never synced)
|
|
85
|
+
Remote changes: Not checked
|
|
84
86
|
```
|
|
85
87
|
|
|
86
88
|
Its primary actions are:
|
|
87
89
|
|
|
88
|
-
- **Sync now** — conservatively decide whether to push, pull, or do nothing
|
|
89
|
-
- **
|
|
90
|
+
- **Sync now (recommended)** — conservatively decide whether to push, pull, or do nothing
|
|
91
|
+
- **Pull from remote** — check the remote snapshot, preview exact local writes/deletes, then confirm
|
|
92
|
+
- **Push to remote** — scan and preview exact remote publication changes, then confirm
|
|
93
|
+
- **Switch target** — preview the target change, then follow the configured pull behavior
|
|
90
94
|
- **Status & changes** — perform a cancellable read-only remote check
|
|
91
|
-
- **Settings** — control automatic sync and synced content
|
|
92
|
-
- **
|
|
93
|
-
- **History & recovery** — browse snapshots, preview rollback, diagnose setup, or recover a stale lock
|
|
94
|
-
- **Help**
|
|
95
|
+
- **Settings** — control post-switch pulling, automatic sync, and synced content
|
|
96
|
+
- **More…** — open one shallow level containing target/storage management, history/recovery, Help, and Back
|
|
95
97
|
|
|
96
|
-
|
|
98
|
+
The menu does not query remote storage merely to open. It shows the last locally applied snapshot and marks remote changes as unchecked until an operation runs. When no synced content is selected, transfer actions are hidden and Settings becomes the first action. During an active or recoverable lock, mutation actions remain unavailable.
|
|
99
|
+
|
|
100
|
+
Push and pull keep their existing concrete previews and confirmation prompts. Pull creates a local backup before applying; push scans locally managed content for likely secrets before publication. Escape cancels a pre-commit check without changing local or remote files. Once publication or apply begins, cancellation is disabled. Conflicts never force automatically; inspect **Status & changes** and use an explicit direct route only after reviewing the conflict.
|
|
101
|
+
|
|
102
|
+
Escape exits the main menu. **More…** and secondary menus provide Back; dirty synced-content drafts provide Save, Discard, and Continue editing. Cancellation before publication has no side effects.
|
|
97
103
|
|
|
98
104
|
## ⚙️ Settings
|
|
99
105
|
|
|
100
106
|
The private user settings file is:
|
|
101
107
|
|
|
102
108
|
```text
|
|
103
|
-
${PI_CODING_AGENT_DIR:-~/.pi/agent}/pi-sync.
|
|
109
|
+
${PI_CODING_AGENT_DIR:-~/.pi/agent}/pi-sync.json
|
|
104
110
|
```
|
|
105
111
|
|
|
112
|
+
On first read, an existing `pi-sync.local.json` is migrated byte-for-byte to `pi-sync.json`
|
|
113
|
+
with private POSIX `0600` permissions. The private legacy file is retained as a recovery copy and may
|
|
114
|
+
be deleted after verifying the new file. If both files exist, `pi-sync.json` takes precedence and the
|
|
115
|
+
legacy file remains untouched. Malformed, invalid, symlinked, changed, or otherwise unsafe legacy
|
|
116
|
+
files are never overwritten automatically.
|
|
117
|
+
|
|
106
118
|
A version 2 example:
|
|
107
119
|
|
|
108
120
|
```json
|
|
109
121
|
{
|
|
110
122
|
"version": 2,
|
|
111
123
|
"activeTarget": "home",
|
|
124
|
+
"targetSwitchAction": "ask",
|
|
112
125
|
"profiles": {
|
|
113
126
|
"r2": {
|
|
114
127
|
"kind": "r2",
|
|
@@ -155,15 +168,22 @@ A version 2 example:
|
|
|
155
168
|
- A **storage profile** owns connection/authentication fields: `kind`, `endpoint`, `region`, `accessKeyId`, `secretAccessKey`, and optional `sessionToken`.
|
|
156
169
|
- A **sync target** references a storage profile and owns `bucket`, `prefix`, `namespace`, `autoSync`, and its synced-content policy.
|
|
157
170
|
- `activeTarget` is used by bare commands and automatic sync.
|
|
171
|
+
- `targetSwitchAction` controls what happens after a target switch: `ask` (default), `pull`, or `switch-only`.
|
|
158
172
|
- `namespace` is the old flat `profile` concept. The remote layout and snapshot wire field remain named `profiles`/`profile` for compatibility.
|
|
159
173
|
|
|
160
174
|
When adding another target with the same storage profile, pi-sync recommends reusing the current target's bucket and prefix while deriving a separate namespace from the new target name. For example, `home` and `work` may both use profile `r2`, bucket `pi-sync`, and prefix `pi-sync`, producing `pi-sync/profiles/home/` and `pi-sync/profiles/work/`.
|
|
161
175
|
|
|
162
176
|
Two targets may intentionally overlap local files, but only one is automatic. pi-sync rejects duplicate effective target remote identities—including deprecated bucket/prefix/namespace environment overrides—to prevent independent local states from controlling the same remote pointer. Removing a target/profile removes local configuration only; it never deletes buckets or snapshots. A referenced profile cannot be removed, and users must switch away before removing one of several current targets.
|
|
163
177
|
|
|
178
|
+
### Target switching
|
|
179
|
+
|
|
180
|
+
The default `targetSwitchAction: "ask"` changes `activeTarget` atomically, then asks in TUI mode whether to review a pull for that target. Choosing not to review leaves local files unchanged. Accepting starts the normal pull flow, which fetches the remote snapshot and shows the exact writes and deletions before apply. In print, JSON, or RPC mode, `ask` switches without pulling and directs interactive users to `/sync pull` where notifications are available.
|
|
181
|
+
|
|
182
|
+
Set `targetSwitchAction` to `"pull"` to start that reviewed pull automatically after a confirmed target switch. The exact pull summary and apply confirmation remain enabled, conflict detection still stops unsafe merges, a local backup is created before apply, and pi-sync never adds `--force`; Pi may separately ask whether to reload changed resources after a successful pull. Because that confirmation requires observable UI, `/sync use` rejects `"pull"` in print and JSON modes before changing `activeTarget`; use TUI or RPC mode instead. Set it to `"switch-only"` to retain the previous no-pull behavior. Selecting an already-current target is a no-op. If a pull fails or its concrete review is declined, the new target remains active and pi-sync reports that synced files were not changed before `/sync pull` is retried.
|
|
183
|
+
|
|
164
184
|
### Synced content
|
|
165
185
|
|
|
166
|
-
The **Settings → Choose synced content** screen edits a draft. Enter or Space toggles,
|
|
186
|
+
The **Settings → Choose synced content** screen edits a draft. Arrow keys navigate, Enter or Space toggles, and Escape opens the Save/Discard/Continue decision. A single Save atomically updates the target while preserving unknown fields and POSIX `0600` permissions. Saving settings never starts network sync.
|
|
167
187
|
|
|
168
188
|
Omitting `syncFiles` preserves the legacy default of every built-in item. An empty array is valid and means the target manages nothing; **Sync now** reports that state instead of publishing an empty sync. Unknown built-in names fail validation.
|
|
169
189
|
|
|
@@ -200,7 +220,7 @@ Environment-overridden fields are read-only in interactive settings. Cloudflare
|
|
|
200
220
|
|
|
201
221
|
### Legacy flat settings
|
|
202
222
|
|
|
203
|
-
Existing flat
|
|
223
|
+
Existing flat settings continue to work unchanged as a synthetic `default` target/profile, including settings migrated from the legacy `pi-sync.local.json` filename. The old flat `profile` remains the remote namespace.
|
|
204
224
|
|
|
205
225
|
Adding a second target offers an explicit migration preview. On confirmation pi-sync:
|
|
206
226
|
|
|
@@ -254,7 +274,7 @@ For the current target, startup auto-sync uses conservative decisions:
|
|
|
254
274
|
- first-sync mismatch or both changed → stop and require review
|
|
255
275
|
- no selected content → report/skip
|
|
256
276
|
|
|
257
|
-
Switching targets changes
|
|
277
|
+
Switching targets first changes `activeTarget`, then follows `targetSwitchAction`: ask before reviewing a pull in TUI by default, start a reviewed pull automatically when configured, or stop after switching. Pulls remain pinned to the selected target and retain exact summaries, locking, backups, and conflict safeguards. The next startup uses the new target's `autoSync` regardless of the switch action.
|
|
258
278
|
|
|
259
279
|
Remote layout remains compatible:
|
|
260
280
|
|
|
@@ -284,7 +304,7 @@ Sessions can contain prompts, model output, tool results, file paths, images, an
|
|
|
284
304
|
|
|
285
305
|
## 🛡️ Safety notes
|
|
286
306
|
|
|
287
|
-
- Credentials stay local and are
|
|
307
|
+
- Credentials stay local; canonical, legacy, temporary, and migration-recovery settings files are always excluded from snapshots.
|
|
288
308
|
- Push refuses common secret patterns in locally managed files.
|
|
289
309
|
- Pull/rollback reject unsafe paths, duplicate paths, checksum mismatches, symlink parents, and file/directory replacement hazards before mutation.
|
|
290
310
|
- Unmanaged local/remote files remain preserved.
|
|
@@ -312,7 +332,10 @@ extensions/pi-sync/
|
|
|
312
332
|
│ ├── sync.ts # Command and lifecycle orchestration
|
|
313
333
|
│ ├── manager-ui.ts # Goal-oriented menus and setup/management flows
|
|
314
334
|
│ ├── file-selection.ts # Transactional synced-content editor
|
|
335
|
+
│ ├── config-file.ts # Private settings I/O and legacy filename migration
|
|
315
336
|
│ ├── settings-management.ts # Profiles, targets, migration, and atomic saves
|
|
337
|
+
│ ├── settings-ui.ts # SettingsList interaction and serialized saves
|
|
338
|
+
│ ├── target-switch.ts # Post-switch prompt, policy, and target handoff
|
|
316
339
|
│ ├── snapshot-transaction.ts # Local apply journal, rollback, and recovery
|
|
317
340
|
│ └── *.ts # Config, policy, snapshot, S3, lock, and format modules
|
|
318
341
|
├── test/
|
package/package.json
CHANGED
package/src/command.ts
CHANGED
|
@@ -230,6 +230,6 @@ export function usage() {
|
|
|
230
230
|
return [
|
|
231
231
|
"Usage: /sync <command>",
|
|
232
232
|
`Commands: ${commands}`,
|
|
233
|
-
"Settings: use /sync init or edit profiles and targets in ~/.pi/agent/pi-sync.
|
|
233
|
+
"Settings: use /sync init or edit profiles and targets in ~/.pi/agent/pi-sync.json (or $PI_CODING_AGENT_DIR/pi-sync.json). Existing PI_SYNC_* overrides still work but are deprecated for future major-version removal.",
|
|
234
234
|
].join("\n");
|
|
235
235
|
}
|