@narumitw/pi-sync 0.51.0 → 0.52.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 +30 -5
- package/dist/chunks/{chunk-7KHKWL3Q.ts → chunk-2CBF6SMT.ts} +8 -7
- package/dist/chunks/chunk-2CBF6SMT.ts.map +7 -0
- package/dist/chunks/{chunk-YFADF5ZQ.ts → chunk-2DI6PDZV.ts} +5 -1
- package/dist/chunks/chunk-2DI6PDZV.ts.map +7 -0
- package/dist/chunks/chunk-2GUXI2XT.ts +1702 -0
- package/dist/chunks/chunk-2GUXI2XT.ts.map +7 -0
- package/dist/chunks/{chunk-4MPIH46N.ts → chunk-3B4Z2SKV.ts} +40 -6
- package/dist/chunks/chunk-3B4Z2SKV.ts.map +7 -0
- package/dist/chunks/{chunk-YPXGU5OR.ts → chunk-4QVPTIZB.ts} +16 -6
- package/dist/chunks/{chunk-YPXGU5OR.ts.map → chunk-4QVPTIZB.ts.map} +2 -2
- package/dist/chunks/{chunk-UA7RXOIT.ts → chunk-4SBTAVFL.ts} +6 -6
- package/dist/chunks/{chunk-6546TS54.ts → chunk-5RZPINUQ.ts} +7 -4
- package/dist/chunks/{chunk-6546TS54.ts.map → chunk-5RZPINUQ.ts.map} +2 -2
- package/dist/chunks/chunk-76NB4R7U.ts +107 -0
- package/dist/chunks/chunk-76NB4R7U.ts.map +7 -0
- package/dist/chunks/{chunk-DM4X4FIA.ts → chunk-7D6RDCVC.ts} +8 -10
- package/dist/chunks/{chunk-DM4X4FIA.ts.map → chunk-7D6RDCVC.ts.map} +2 -2
- package/dist/chunks/chunk-A6HU4ERM.ts +124 -0
- package/dist/chunks/chunk-A6HU4ERM.ts.map +7 -0
- package/dist/chunks/chunk-AMJRUXFT.ts +17 -0
- package/dist/chunks/chunk-AMJRUXFT.ts.map +7 -0
- package/dist/chunks/chunk-ANWNQIR7.ts +1013 -0
- package/dist/chunks/chunk-ANWNQIR7.ts.map +7 -0
- package/dist/chunks/{chunk-T56RNRZJ.ts → chunk-BDB4IDM3.ts} +19 -10
- package/dist/chunks/chunk-BDB4IDM3.ts.map +7 -0
- package/dist/chunks/{chunk-2RZSQWBH.ts → chunk-CHSIAC4N.ts} +5 -5
- package/dist/chunks/{chunk-2RZSQWBH.ts.map → chunk-CHSIAC4N.ts.map} +2 -2
- package/dist/chunks/chunk-HUZ5CR4W.ts +110 -0
- package/dist/chunks/chunk-HUZ5CR4W.ts.map +7 -0
- package/dist/chunks/{chunk-QLSN7AGX.ts → chunk-IJ6VV6FN.ts} +81 -19
- package/dist/chunks/chunk-IJ6VV6FN.ts.map +7 -0
- package/dist/chunks/chunk-ORQRHEEO.ts +362 -0
- package/dist/chunks/chunk-ORQRHEEO.ts.map +7 -0
- package/dist/chunks/chunk-QE7NZZWT.ts +380 -0
- package/dist/chunks/chunk-QE7NZZWT.ts.map +7 -0
- package/dist/chunks/{chunk-HGJH56KR.ts → chunk-QHSQCK7L.ts} +4 -4
- package/dist/chunks/chunk-QOFMXPM5.ts +735 -0
- package/dist/chunks/chunk-QOFMXPM5.ts.map +7 -0
- package/dist/chunks/{chunk-DZUSTGQV.ts → chunk-UQ3ALBIB.ts} +4 -4
- package/dist/chunks/{chunk-Q32CQWPM.ts → chunk-V6VZ5TLG.ts} +13 -6
- package/dist/chunks/chunk-V6VZ5TLG.ts.map +7 -0
- package/dist/chunks/{chunk-E42GXD6D.ts → chunk-WKPX2SIC.ts} +4 -4
- package/dist/chunks/chunk-ZW5ZLGBI.ts +154 -0
- package/dist/chunks/chunk-ZW5ZLGBI.ts.map +7 -0
- package/dist/chunks/{chunk-6NT3YFGY.ts → chunk-ZX2Q6THB.ts} +8 -3
- package/dist/chunks/{chunk-6NT3YFGY.ts.map → chunk-ZX2Q6THB.ts.map} +2 -2
- package/dist/chunks/conflict-artifacts-BB2FZMIE.ts +27 -0
- package/dist/chunks/conflict-review-T3PB7ZSD.ts +175 -0
- package/dist/chunks/conflict-review-T3PB7ZSD.ts.map +7 -0
- package/dist/chunks/{file-selection-RAVHRYFG.ts → file-selection-WZX7HAY2.ts} +8 -7
- package/dist/chunks/{file-selection-RAVHRYFG.ts.map → file-selection-WZX7HAY2.ts.map} +1 -1
- package/dist/chunks/{git-backend-IAANDL3K.ts → git-backend-HLGKUQJT.ts} +19 -7
- package/dist/chunks/git-backend-HLGKUQJT.ts.map +7 -0
- package/dist/chunks/local-fields-6DGYOOIK.ts +22 -0
- package/dist/chunks/manager-result-dispatcher-VIDT3QBU.ts +23 -0
- package/dist/chunks/{manager-ui-763NEKJY.ts → manager-ui-HSMHS3OK.ts} +236 -57
- package/dist/chunks/manager-ui-HSMHS3OK.ts.map +7 -0
- package/dist/chunks/merge-baseline-store-EVQAAML6.ts +22 -0
- package/dist/chunks/remote-selection-ui-SMF5CLFO.ts +22 -0
- package/dist/chunks/{s3-backend-XGXUOPUN.ts → s3-backend-DJ2NT3SZ.ts} +16 -9
- package/dist/chunks/s3-backend-DJ2NT3SZ.ts.map +7 -0
- package/dist/chunks/{setup-switch-5G2VNJHL.ts → setup-switch-KTUWL6DE.ts} +9 -6
- package/dist/chunks/{setup-wizard-YIEWGX32.ts → setup-wizard-GSDPDFC4.ts} +10 -7
- package/dist/chunks/{setup-wizard-YIEWGX32.ts.map → setup-wizard-GSDPDFC4.ts.map} +1 -1
- package/dist/chunks/{snapshot-JL5DFSXI.ts → snapshot-THS5EY2L.ts} +6 -9
- package/dist/chunks/snapshot-THS5EY2L.ts.map +7 -0
- package/dist/chunks/{sync-inspection-P3ENJLNF.ts → sync-inspection-VBJF2FWC.ts} +10 -10
- package/dist/chunks/sync-inspection-VBJF2FWC.ts.map +7 -0
- package/dist/chunks/{sync-operations-AR76EB6C.ts → sync-operations-27VQUDH2.ts} +309 -508
- package/dist/chunks/sync-operations-27VQUDH2.ts.map +7 -0
- package/dist/chunks/{sync-state-VHJUZ4YG.ts → sync-state-CFL4RRRB.ts} +6 -6
- package/dist/chunks/sync-state-CFL4RRRB.ts.map +7 -0
- package/dist/chunks/{webdav-backend-3EGUONAT.ts → webdav-backend-ETQGSI6I.ts} +13 -7
- package/dist/chunks/webdav-backend-ETQGSI6I.ts.map +7 -0
- package/dist/index.ts +142 -43
- package/dist/index.ts.map +2 -2
- package/docs/content-merge-audit.md +156 -0
- package/docs/merge-implementation-audit.md +312 -0
- package/docs/settings-merge-audit.md +153 -0
- package/docs/settings.md +36 -0
- package/package.json +6 -6
- package/src/backends/git/git-backend.ts +2 -0
- package/src/backends/git/git-storage.ts +8 -3
- package/src/backends/s3/s3-backend.ts +2 -1
- package/src/backends/webdav/webdav-backend.ts +2 -1
- package/src/commands/command-execution.ts +10 -0
- package/src/commands/command.ts +4 -0
- package/src/settings/config.ts +12 -0
- package/src/settings/settings-management.ts +2 -2
- package/src/settings/settings-types.ts +14 -1
- package/src/settings/settings-validation.ts +24 -3
- package/src/snapshot/session-paths.ts +34 -7
- package/src/snapshot/snapshot-apply.ts +81 -32
- package/src/snapshot/snapshot-case-replacement.ts +80 -0
- package/src/snapshot/snapshot-codec.ts +6 -1
- package/src/snapshot/snapshot-root-transition.ts +154 -0
- package/src/snapshot/snapshot-transaction-plan.ts +72 -0
- package/src/snapshot/snapshot-transaction.ts +844 -102
- package/src/snapshot/snapshot-types.ts +5 -0
- package/src/state/json-file.ts +32 -5
- package/src/state/merge-baseline-store.ts +182 -0
- package/src/state/mutation-directory-sync.ts +34 -0
- package/src/state/state-types.ts +4 -0
- package/src/state/sync-state-store.ts +14 -1
- package/src/sync/automatic-sync.ts +11 -3
- package/src/sync/conflict-artifact-ownership.ts +63 -0
- package/src/sync/conflict-artifacts.ts +195 -0
- package/src/sync/conflict-groups.ts +68 -0
- package/src/sync/conflict-preview.ts +56 -0
- package/src/sync/conflict-resolution.ts +93 -0
- package/src/sync/conflict-retention.ts +72 -0
- package/src/sync/conflict-review.ts +95 -0
- package/src/sync/content-conflicts.ts +73 -0
- package/src/sync/field-migration.ts +39 -0
- package/src/sync/file-merge-planner.ts +143 -0
- package/src/sync/json-document.ts +184 -0
- package/src/sync/local-fields.ts +134 -0
- package/src/sync/merge-apply.ts +380 -0
- package/src/sync/merge-journal.ts +219 -0
- package/src/sync/merged-sync.ts +723 -0
- package/src/sync/partial-progress.ts +54 -0
- package/src/sync/remote-snapshot.ts +6 -0
- package/src/sync/session-merge.ts +194 -0
- package/src/sync/settings-conflicts.ts +52 -0
- package/src/sync/settings-merge.ts +57 -0
- package/src/sync/startup-check.ts +90 -5
- package/src/sync/sync-inspection.ts +1 -0
- package/src/sync/sync-local.ts +61 -0
- package/src/sync/sync-mutations.ts +256 -114
- package/src/sync/sync-queries.ts +6 -2
- package/src/sync/sync-state.ts +14 -5
- package/src/sync/text-merge.ts +133 -0
- package/src/sync-extension.ts +8 -0
- package/src/ui/manager-state.ts +12 -1
- package/src/ui/manager-ui.ts +10 -0
- package/src/ui/merge-review.ts +28 -0
- package/src/ui/remote-selection-ui.ts +1 -0
- package/src/ui/settings-ui.ts +183 -2
- package/src/ui/setup/setup-actions.ts +2 -2
- package/src/ui/setup/setup-switcher.ts +2 -1
- package/src/ui/storage-connections-ui.ts +11 -7
- package/src/ui/sync-attention.ts +3 -0
- package/src/ui/sync-format.ts +16 -12
- package/src/ui/sync-setups-ui.ts +1 -0
- package/src/ui/terminal-text.ts +9 -2
- package/dist/chunks/chunk-4AIHXRKE.ts +0 -197
- package/dist/chunks/chunk-4AIHXRKE.ts.map +0 -7
- package/dist/chunks/chunk-4MPIH46N.ts.map +0 -7
- package/dist/chunks/chunk-7KHKWL3Q.ts.map +0 -7
- package/dist/chunks/chunk-EEJPYTWE.ts +0 -348
- package/dist/chunks/chunk-EEJPYTWE.ts.map +0 -7
- package/dist/chunks/chunk-IVXEDPAD.ts +0 -370
- package/dist/chunks/chunk-IVXEDPAD.ts.map +0 -7
- package/dist/chunks/chunk-MSSW6F3R.ts +0 -12
- package/dist/chunks/chunk-MSSW6F3R.ts.map +0 -7
- package/dist/chunks/chunk-OVDTF5CH.ts +0 -90
- package/dist/chunks/chunk-OVDTF5CH.ts.map +0 -7
- package/dist/chunks/chunk-Q32CQWPM.ts.map +0 -7
- package/dist/chunks/chunk-QLSN7AGX.ts.map +0 -7
- package/dist/chunks/chunk-SWUXA3MH.ts +0 -18
- package/dist/chunks/chunk-SWUXA3MH.ts.map +0 -7
- package/dist/chunks/chunk-T56RNRZJ.ts.map +0 -7
- package/dist/chunks/chunk-YFADF5ZQ.ts.map +0 -7
- package/dist/chunks/git-backend-IAANDL3K.ts.map +0 -7
- package/dist/chunks/manager-result-dispatcher-OTUMQM26.ts +0 -23
- package/dist/chunks/manager-ui-763NEKJY.ts.map +0 -7
- package/dist/chunks/remote-selection-ui-TZTJF32Y.ts +0 -22
- package/dist/chunks/s3-backend-XGXUOPUN.ts.map +0 -7
- package/dist/chunks/sync-operations-AR76EB6C.ts.map +0 -7
- package/dist/chunks/webdav-backend-3EGUONAT.ts.map +0 -7
- /package/dist/chunks/{chunk-UA7RXOIT.ts.map → chunk-4SBTAVFL.ts.map} +0 -0
- /package/dist/chunks/{chunk-HGJH56KR.ts.map → chunk-QHSQCK7L.ts.map} +0 -0
- /package/dist/chunks/{chunk-DZUSTGQV.ts.map → chunk-UQ3ALBIB.ts.map} +0 -0
- /package/dist/chunks/{chunk-E42GXD6D.ts.map → chunk-WKPX2SIC.ts.map} +0 -0
- /package/dist/chunks/{manager-result-dispatcher-OTUMQM26.ts.map → conflict-artifacts-BB2FZMIE.ts.map} +0 -0
- /package/dist/chunks/{remote-selection-ui-TZTJF32Y.ts.map → local-fields-6DGYOOIK.ts.map} +0 -0
- /package/dist/chunks/{setup-switch-5G2VNJHL.ts.map → manager-result-dispatcher-VIDT3QBU.ts.map} +0 -0
- /package/dist/chunks/{snapshot-JL5DFSXI.ts.map → merge-baseline-store-EVQAAML6.ts.map} +0 -0
- /package/dist/chunks/{sync-inspection-P3ENJLNF.ts.map → remote-selection-ui-SMF5CLFO.ts.map} +0 -0
- /package/dist/chunks/{sync-state-VHJUZ4YG.ts.map → setup-switch-KTUWL6DE.ts.map} +0 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// @generated by scripts/build-runtime.mjs; do not edit.
|
|
2
|
+
// @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
|
|
3
|
+
import {
|
|
4
|
+
dispatchManagerResult
|
|
5
|
+
} from "./chunk-WKPX2SIC.ts";
|
|
6
|
+
import "./chunk-2CBF6SMT.ts";
|
|
7
|
+
import "./chunk-V6VZ5TLG.ts";
|
|
8
|
+
import "./chunk-QHSQCK7L.ts";
|
|
9
|
+
import "./chunk-K3RIEL6J.ts";
|
|
10
|
+
import "./chunk-AMJRUXFT.ts";
|
|
11
|
+
import "./chunk-CHSIAC4N.ts";
|
|
12
|
+
import "./chunk-3B4Z2SKV.ts";
|
|
13
|
+
import "./chunk-2JZFHNLM.ts";
|
|
14
|
+
import "./chunk-T2SJD3N7.ts";
|
|
15
|
+
import "./chunk-7D5SF7P3.ts";
|
|
16
|
+
import "./chunk-A6HU4ERM.ts";
|
|
17
|
+
import "./chunk-QOFMXPM5.ts";
|
|
18
|
+
import "./chunk-ZW5ZLGBI.ts";
|
|
19
|
+
import "./chunk-HUZ5CR4W.ts";
|
|
20
|
+
export {
|
|
21
|
+
dispatchManagerResult
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=manager-result-dispatcher-VIDT3QBU.ts.map
|
|
@@ -1,37 +1,5 @@
|
|
|
1
1
|
// @generated by scripts/build-runtime.mjs; do not edit.
|
|
2
2
|
// @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
|
|
3
|
-
import {
|
|
4
|
-
dispatchManagerResult
|
|
5
|
-
} from "./chunk-E42GXD6D.ts";
|
|
6
|
-
import {
|
|
7
|
-
runCancellableOperation
|
|
8
|
-
} from "./chunk-7KHKWL3Q.ts";
|
|
9
|
-
import {
|
|
10
|
-
SETUP_SWITCH_ACTION_OPTIONS,
|
|
11
|
-
saveOnSwitch,
|
|
12
|
-
setupSwitchActionFromLabel,
|
|
13
|
-
setupSwitchActionLabel,
|
|
14
|
-
useSyncSetup
|
|
15
|
-
} from "./chunk-DZUSTGQV.ts";
|
|
16
|
-
import "./chunk-Q32CQWPM.ts";
|
|
17
|
-
import "./chunk-HGJH56KR.ts";
|
|
18
|
-
import {
|
|
19
|
-
observationMatchesConfig,
|
|
20
|
-
observationSummary,
|
|
21
|
-
syncAttentionMatchesConfig
|
|
22
|
-
} from "./chunk-6546TS54.ts";
|
|
23
|
-
import {
|
|
24
|
-
inspectLock,
|
|
25
|
-
isLockGuardHeld,
|
|
26
|
-
isStaleLock
|
|
27
|
-
} from "./chunk-QLSN7AGX.ts";
|
|
28
|
-
import {
|
|
29
|
-
configureSyncStatus
|
|
30
|
-
} from "./chunk-K3RIEL6J.ts";
|
|
31
|
-
import {
|
|
32
|
-
readStateForConfig,
|
|
33
|
-
syncStateFingerprint
|
|
34
|
-
} from "./chunk-YPXGU5OR.ts";
|
|
35
3
|
import {
|
|
36
4
|
AUTOMATIC_SYNC_DESCRIPTION,
|
|
37
5
|
applyS3CredentialUpdate,
|
|
@@ -52,21 +20,56 @@ import {
|
|
|
52
20
|
showEditS3Target,
|
|
53
21
|
showEditWebDavStorageProfile,
|
|
54
22
|
showEditWebDavTarget
|
|
55
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-4SBTAVFL.ts";
|
|
24
|
+
import {
|
|
25
|
+
dispatchManagerResult
|
|
26
|
+
} from "./chunk-WKPX2SIC.ts";
|
|
27
|
+
import {
|
|
28
|
+
runCancellableOperation
|
|
29
|
+
} from "./chunk-2CBF6SMT.ts";
|
|
30
|
+
import "./chunk-V6VZ5TLG.ts";
|
|
31
|
+
import "./chunk-QHSQCK7L.ts";
|
|
32
|
+
import {
|
|
33
|
+
SETUP_SWITCH_ACTION_OPTIONS,
|
|
34
|
+
saveOnSwitch,
|
|
35
|
+
setupSwitchActionFromLabel,
|
|
36
|
+
setupSwitchActionLabel,
|
|
37
|
+
useSyncSetup
|
|
38
|
+
} from "./chunk-UQ3ALBIB.ts";
|
|
39
|
+
import {
|
|
40
|
+
observationMatchesConfig,
|
|
41
|
+
observationSummary,
|
|
42
|
+
syncAttentionMatchesConfig
|
|
43
|
+
} from "./chunk-5RZPINUQ.ts";
|
|
44
|
+
import {
|
|
45
|
+
captureMutationOwner,
|
|
46
|
+
inspectLock,
|
|
47
|
+
isLockGuardHeld,
|
|
48
|
+
isStaleLock
|
|
49
|
+
} from "./chunk-IJ6VV6FN.ts";
|
|
50
|
+
import "./chunk-PWMWOJP4.ts";
|
|
56
51
|
import {
|
|
57
52
|
automaticSyncSummary
|
|
58
53
|
} from "./chunk-ECYCNZOE.ts";
|
|
59
|
-
import
|
|
54
|
+
import {
|
|
55
|
+
configureSyncStatus
|
|
56
|
+
} from "./chunk-K3RIEL6J.ts";
|
|
57
|
+
import "./chunk-2DI6PDZV.ts";
|
|
60
58
|
import {
|
|
61
59
|
safeTerminalText
|
|
62
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-AMJRUXFT.ts";
|
|
61
|
+
import {
|
|
62
|
+
readStateForConfig,
|
|
63
|
+
syncStateFingerprint
|
|
64
|
+
} from "./chunk-4QVPTIZB.ts";
|
|
65
|
+
import "./chunk-BVVP33U5.ts";
|
|
63
66
|
import {
|
|
64
67
|
addStorageConnection,
|
|
65
68
|
removeStorageConnection,
|
|
66
69
|
removeSyncSetup,
|
|
67
70
|
updateStorageConnection,
|
|
68
71
|
updateSyncSetup
|
|
69
|
-
} from "./chunk-
|
|
72
|
+
} from "./chunk-CHSIAC4N.ts";
|
|
70
73
|
import {
|
|
71
74
|
activeLocalConfigPath,
|
|
72
75
|
isCloudflareR2Endpoint,
|
|
@@ -79,23 +82,26 @@ import {
|
|
|
79
82
|
readLocalConfigObject,
|
|
80
83
|
syncConfigReviewIdentity,
|
|
81
84
|
updateLocalConfig
|
|
82
|
-
} from "./chunk-
|
|
85
|
+
} from "./chunk-3B4Z2SKV.ts";
|
|
83
86
|
import "./chunk-2JZFHNLM.ts";
|
|
84
|
-
import "./chunk-BVVP33U5.ts";
|
|
85
87
|
import "./chunk-T2SJD3N7.ts";
|
|
88
|
+
import "./chunk-ZX2Q6THB.ts";
|
|
86
89
|
import {
|
|
87
90
|
syncErrorGuidance
|
|
88
91
|
} from "./chunk-G4RUXRWZ.ts";
|
|
89
92
|
import {
|
|
90
93
|
errorMessage
|
|
91
94
|
} from "./chunk-7D5SF7P3.ts";
|
|
92
|
-
import
|
|
93
|
-
|
|
94
|
-
|
|
95
|
+
import {
|
|
96
|
+
normalizeLocalFields,
|
|
97
|
+
sameLocalFields
|
|
98
|
+
} from "./chunk-A6HU4ERM.ts";
|
|
95
99
|
import {
|
|
96
100
|
compareSyncInclude,
|
|
97
101
|
syncIncludeSelection
|
|
98
|
-
} from "./chunk-
|
|
102
|
+
} from "./chunk-QOFMXPM5.ts";
|
|
103
|
+
import "./chunk-ZW5ZLGBI.ts";
|
|
104
|
+
import "./chunk-HUZ5CR4W.ts";
|
|
99
105
|
|
|
100
106
|
// src/ui/manager-ui.ts
|
|
101
107
|
import { defineMenu as defineMenu5, runMenu as runMenu5 } from "@narumitw/pi-tui-kit";
|
|
@@ -166,7 +172,7 @@ function blockedSyncMenuItem(label, manager) {
|
|
|
166
172
|
};
|
|
167
173
|
}
|
|
168
174
|
async function showManagerAttention(ctx, attention, runRoute, signal, onSelectionResolved) {
|
|
169
|
-
const { showRemoteSelectionReview } = await import("./remote-selection-ui-
|
|
175
|
+
const { showRemoteSelectionReview } = await import("./remote-selection-ui-SMF5CLFO.ts");
|
|
170
176
|
if (signal?.aborted) return "close";
|
|
171
177
|
const review = await showRemoteSelectionReview(ctx, attention.decision.setupName, signal, void 0, {
|
|
172
178
|
decision: attention.decision,
|
|
@@ -388,6 +394,7 @@ async function loadSetupMenuState(selectedName, signal) {
|
|
|
388
394
|
`Included content: ${selection.builtIns.length} built-in groups \xB7 ${selection.custom.length} extra paths`,
|
|
389
395
|
`Sessions: ${selection.sessions ? "On \u2014 privacy-sensitive" : "Off"}`,
|
|
390
396
|
`Automatic sync: ${config.automatic ? "On" : "Off"}`,
|
|
397
|
+
`Automatic transfer at startup: ${config.automaticTransfer ? "On \u2014 may upload, replace, or delete selected files; no reload" : "Off"}`,
|
|
391
398
|
isCurrent ? "Edit included content and automatic sync in /sync \u2192 Settings." : "To edit included content or automatic sync, make this setup current, then open /sync \u2192 Settings."
|
|
392
399
|
];
|
|
393
400
|
} catch (error) {
|
|
@@ -474,7 +481,7 @@ async function describeManagerState(signal, attention, inspectOperation = inspec
|
|
|
474
481
|
};
|
|
475
482
|
}
|
|
476
483
|
const configuredTargets = ownRecord(raw.syncSetups);
|
|
477
|
-
if (raw.version === 3 && configuredTargets && Object.keys(configuredTargets).length === 0) {
|
|
484
|
+
if ((raw.version === 3 || raw.version === 4 || raw.version === 5) && configuredTargets && Object.keys(configuredTargets).length === 0) {
|
|
478
485
|
return {
|
|
479
486
|
title: [
|
|
480
487
|
"Manage sync",
|
|
@@ -516,7 +523,12 @@ async function describeManagerState(signal, attention, inspectOperation = inspec
|
|
|
516
523
|
`Storage: ${backendStorageDescription(config)}`,
|
|
517
524
|
`Included: ${selection.builtIns.length} built-in group${selection.builtIns.length === 1 ? "" : "s"} \xB7 ${selection.custom.length} extra path${selection.custom.length === 1 ? "" : "s"} \xB7 Sessions ${selection.sessions ? "on" : "off"}`,
|
|
518
525
|
`Automatic sync: ${automaticSyncSummary(config.automatic)}`,
|
|
526
|
+
`Automatic transfer at startup: ${config.automaticTransfer ? "On \u2014 upload/replace/delete at idle; no reload" : "Off"}`,
|
|
519
527
|
`Last applied: ${lastAppliedSnapshot}`,
|
|
528
|
+
...syncState?.unresolved?.length ? [
|
|
529
|
+
`Unresolved: ${syncState.unresolved.length} dependency groups \xB7 review History & recovery`,
|
|
530
|
+
`Last observed: ${safeTerminalText(syncState.lastObservedSnapshot ?? "unknown")}`
|
|
531
|
+
] : [],
|
|
520
532
|
...currentAttention ? [
|
|
521
533
|
currentAttention.decision.setupName === config.setupName ? "Sync status: Review needed" : `Sync status: Review needed for setup ${safeTerminalText(currentAttention.decision.setupName)}`,
|
|
522
534
|
attentionComparison?.remoteOnly.length === 0 && attentionComparison.localOnly.length === 0 ? "Only the synced-content order differs." : `Remote-only paths: ${attentionComparison?.remoteOnly.length ?? 0} \xB7 Device-only paths: ${attentionComparison?.localOnly.length ?? 0}`,
|
|
@@ -663,11 +675,143 @@ async function showSyncSettings(ctx, runRoute, signal) {
|
|
|
663
675
|
description: "Review this device and remote content lists before choosing either one.",
|
|
664
676
|
currentValue: "Review",
|
|
665
677
|
action: "remote-include"
|
|
678
|
+
},
|
|
679
|
+
{
|
|
680
|
+
id: "automaticTransfer",
|
|
681
|
+
label: "Automatic transfer at startup",
|
|
682
|
+
description: "May upload, replace, or delete selected files once at idle startup in TUI/RPC. Requires a baseline and conditional/lease publication; never reloads resources. Turning off cancels pending work.",
|
|
683
|
+
currentValue: state.automaticTransfer ? "On" : "Off",
|
|
684
|
+
values: ["On", "Off"],
|
|
685
|
+
action: "automatic-transfer"
|
|
686
|
+
},
|
|
687
|
+
{
|
|
688
|
+
id: "mergeSettings",
|
|
689
|
+
label: "Settings field merge (experimental)",
|
|
690
|
+
description: "Combine independent global settings.json fields using a verified private ancestor; arrays and nested objects remain atomic. No reload.",
|
|
691
|
+
currentValue: state.mergeSettings ? "On" : "Off",
|
|
692
|
+
values: ["On", "Off"],
|
|
693
|
+
action: "merge-settings"
|
|
694
|
+
},
|
|
695
|
+
{
|
|
696
|
+
id: "localFields",
|
|
697
|
+
label: "Machine-local settings fields",
|
|
698
|
+
description: "Root field names omitted from future portable snapshots. Policy changes require directional migration; old history remains.",
|
|
699
|
+
currentValue: `${state.localFields?.length ?? 0} fields \xB7 Edit`,
|
|
700
|
+
action: "local-fields"
|
|
701
|
+
},
|
|
702
|
+
{
|
|
703
|
+
id: "contentPolicy",
|
|
704
|
+
label: "Content / partial sync (experimental)",
|
|
705
|
+
description: "Version-5 opt-in: bounded text and prefix-only sessions; partial progress keeps full withheld versions and old baseline hashes.",
|
|
706
|
+
currentValue: state.mergeContent ? state.partialSync ? "Content & partial" : "Content only" : state.partialSync ? "Partial only" : "Off",
|
|
707
|
+
values: ["Off", "Content only", "Content & partial", "Partial only"],
|
|
708
|
+
action: "content-policy"
|
|
666
709
|
}
|
|
667
710
|
]
|
|
668
711
|
})
|
|
669
712
|
},
|
|
670
713
|
actions: {
|
|
714
|
+
"content-policy": async ({ value, signal: actionSignal }) => {
|
|
715
|
+
const mutationSignal = signal ? AbortSignal.any([signal, actionSignal]) : actionSignal;
|
|
716
|
+
const validate = captureMutationOwner(ctx, mutationSignal);
|
|
717
|
+
try {
|
|
718
|
+
const previous = await loadConfig(setupName);
|
|
719
|
+
validate();
|
|
720
|
+
const mergeContent = value === "Content only" || value === "Content & partial";
|
|
721
|
+
const partialSync = value === "Partial only" || value === "Content & partial";
|
|
722
|
+
if (!await ctx.ui.confirm(
|
|
723
|
+
"Save experimental content policy?",
|
|
724
|
+
"This explicitly upgrades settings to version 5; partial snapshots use version 3 and older clients must refuse them. Text/session merge is conservative. Partial sync preserves withheld versions and old baselines. Disabling does not clear unresolved groups or recovery evidence. Review a directional migration first if portable policy changes.",
|
|
725
|
+
{ signal: mutationSignal }
|
|
726
|
+
))
|
|
727
|
+
return { kind: "rejected" };
|
|
728
|
+
validate();
|
|
729
|
+
await updateLocalConfig((current) => {
|
|
730
|
+
validate();
|
|
731
|
+
const setup = current.syncSetups[setupName];
|
|
732
|
+
if (!setup || Boolean(setup.sync.mergeContent) !== Boolean(previous.mergeContent) || Boolean(setup.sync.partialSync) !== Boolean(previous.partialSync))
|
|
733
|
+
throw new Error("Content policy changed during review.");
|
|
734
|
+
return {
|
|
735
|
+
...current,
|
|
736
|
+
version: 5,
|
|
737
|
+
syncSetups: {
|
|
738
|
+
...current.syncSetups,
|
|
739
|
+
[setupName]: { ...setup, sync: { ...setup.sync, mergeContent, partialSync } }
|
|
740
|
+
}
|
|
741
|
+
};
|
|
742
|
+
}, mutationSignal);
|
|
743
|
+
validate();
|
|
744
|
+
return { kind: "stay" };
|
|
745
|
+
} catch (error) {
|
|
746
|
+
if (!mutationSignal.aborted) notifySaveFailure(ctx, error);
|
|
747
|
+
return { kind: "rejected" };
|
|
748
|
+
}
|
|
749
|
+
},
|
|
750
|
+
"merge-settings": async ({ value, signal: actionSignal }) => {
|
|
751
|
+
const mutationSignal = signal ? AbortSignal.any([signal, actionSignal]) : actionSignal;
|
|
752
|
+
const validate = captureMutationOwner(ctx, mutationSignal);
|
|
753
|
+
try {
|
|
754
|
+
validate();
|
|
755
|
+
await updateSyncSetup(
|
|
756
|
+
setupName,
|
|
757
|
+
(setup) => ({ ...setup, sync: { ...setup.sync, mergeSettings: value === "On" } }),
|
|
758
|
+
{ signal: mutationSignal }
|
|
759
|
+
);
|
|
760
|
+
validate();
|
|
761
|
+
return { kind: "stay" };
|
|
762
|
+
} catch (error) {
|
|
763
|
+
if (!mutationSignal.aborted) notifySaveFailure(ctx, error);
|
|
764
|
+
return { kind: "rejected" };
|
|
765
|
+
}
|
|
766
|
+
},
|
|
767
|
+
"local-fields": async ({ signal: actionSignal }) => {
|
|
768
|
+
const mutationSignal = signal ? AbortSignal.any([signal, actionSignal]) : actionSignal;
|
|
769
|
+
const validate = captureMutationOwner(ctx, mutationSignal);
|
|
770
|
+
try {
|
|
771
|
+
const previous = await loadConfig(setupName);
|
|
772
|
+
validate();
|
|
773
|
+
const input = await ctx.ui.input(
|
|
774
|
+
"Machine-local settings.json root fields (JSON string array)",
|
|
775
|
+
JSON.stringify(previous.localFields ?? []),
|
|
776
|
+
{ signal: mutationSignal }
|
|
777
|
+
);
|
|
778
|
+
validate();
|
|
779
|
+
if (input === void 0) return { kind: "rejected" };
|
|
780
|
+
let fields;
|
|
781
|
+
try {
|
|
782
|
+
fields = normalizeLocalFields(JSON.parse(input));
|
|
783
|
+
} catch {
|
|
784
|
+
throw new Error("Invalid localFields JSON array; no policy was changed.");
|
|
785
|
+
}
|
|
786
|
+
if (sameLocalFields(previous.localFields, fields)) return { kind: "stay" };
|
|
787
|
+
const confirmed = await ctx.ui.confirm(
|
|
788
|
+
"Save portable field policy?",
|
|
789
|
+
"This opts into settings/snapshot version 4/2; older clients must refuse them. Future snapshots omit these fields, but old remote history is NOT erased. Review an explicit force push/pull migration before further sync. Removed rules can expose or replace local-only values.",
|
|
790
|
+
{ signal: mutationSignal }
|
|
791
|
+
);
|
|
792
|
+
validate();
|
|
793
|
+
if (!confirmed) return { kind: "rejected" };
|
|
794
|
+
await updateLocalConfig((current) => {
|
|
795
|
+
validate();
|
|
796
|
+
const setup = current.syncSetups[setupName];
|
|
797
|
+
if (!setup || !sameLocalFields(setup.sync.localFields, previous.localFields))
|
|
798
|
+
throw new Error("Field policy changed while under review; reopen settings.");
|
|
799
|
+
return {
|
|
800
|
+
...current,
|
|
801
|
+
version: current.version === 5 ? 5 : 4,
|
|
802
|
+
syncSetups: {
|
|
803
|
+
...current.syncSetups,
|
|
804
|
+
[setupName]: { ...setup, sync: { ...setup.sync, localFields: fields } }
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
}, mutationSignal);
|
|
808
|
+
validate();
|
|
809
|
+
return { kind: "stay" };
|
|
810
|
+
} catch (error) {
|
|
811
|
+
if (!mutationSignal.aborted) notifySaveFailure(ctx, error);
|
|
812
|
+
return { kind: "rejected" };
|
|
813
|
+
}
|
|
814
|
+
},
|
|
671
815
|
automatic: async ({ value, signal: actionSignal }) => {
|
|
672
816
|
const automatic = value === "On";
|
|
673
817
|
const mutationSignal = signal ? AbortSignal.any([signal, actionSignal]) : actionSignal;
|
|
@@ -689,6 +833,24 @@ async function showSyncSettings(ctx, runRoute, signal) {
|
|
|
689
833
|
return { kind: "rejected" };
|
|
690
834
|
}
|
|
691
835
|
},
|
|
836
|
+
"automatic-transfer": async ({ value, signal: actionSignal }) => {
|
|
837
|
+
const automaticTransfer = value === "On";
|
|
838
|
+
const mutationSignal = signal ? AbortSignal.any([signal, actionSignal]) : actionSignal;
|
|
839
|
+
try {
|
|
840
|
+
await updateSyncSetup(setupName, (setup) => ({ ...setup, sync: { ...setup.sync, automaticTransfer } }), {
|
|
841
|
+
signal: mutationSignal
|
|
842
|
+
});
|
|
843
|
+
if (mutationSignal.aborted) return { kind: "rejected" };
|
|
844
|
+
ctx.ui.notify(
|
|
845
|
+
`Automatic startup transfer ${automaticTransfer ? "enabled for the next session start" : "disabled"}. Completed transfers are not undone.`,
|
|
846
|
+
"info"
|
|
847
|
+
);
|
|
848
|
+
return { kind: "stay" };
|
|
849
|
+
} catch (error) {
|
|
850
|
+
if (!mutationSignal.aborted) notifySaveFailure(ctx, error);
|
|
851
|
+
return { kind: "rejected" };
|
|
852
|
+
}
|
|
853
|
+
},
|
|
692
854
|
"skip-secret-scan": async ({ value, signal: actionSignal }) => {
|
|
693
855
|
const skipSecretScan = value === "On";
|
|
694
856
|
const mutationSignal = signal ? AbortSignal.any([signal, actionSignal]) : actionSignal;
|
|
@@ -746,7 +908,7 @@ async function showSyncSettings(ctx, runRoute, signal) {
|
|
|
746
908
|
},
|
|
747
909
|
"remote-include": async ({ signal: actionSignal }) => {
|
|
748
910
|
const reviewSignal = signal ? AbortSignal.any([signal, actionSignal]) : actionSignal;
|
|
749
|
-
const { showRemoteSelectionReview } = await import("./remote-selection-ui-
|
|
911
|
+
const { showRemoteSelectionReview } = await import("./remote-selection-ui-SMF5CLFO.ts");
|
|
750
912
|
if (reviewSignal.aborted) return { kind: "rejected" };
|
|
751
913
|
const review = await showRemoteSelectionReview(ctx, setupName, reviewSignal, void 0, {
|
|
752
914
|
origin: "settings",
|
|
@@ -768,7 +930,10 @@ async function showSyncSettings(ctx, runRoute, signal) {
|
|
|
768
930
|
});
|
|
769
931
|
}
|
|
770
932
|
function notifySaveFailure(ctx, error) {
|
|
771
|
-
ctx.ui.notify(
|
|
933
|
+
ctx.ui.notify(
|
|
934
|
+
`Pi Sync settings save failed: ${safeTerminalText(error instanceof Error ? error.message : String(error))}`,
|
|
935
|
+
"error"
|
|
936
|
+
);
|
|
772
937
|
}
|
|
773
938
|
|
|
774
939
|
// src/ui/storage-connections-ui.ts
|
|
@@ -786,8 +951,8 @@ async function showStorageConnections(ctx, signal) {
|
|
|
786
951
|
return {
|
|
787
952
|
kind: "actions",
|
|
788
953
|
title: "Storage connections",
|
|
789
|
-
lines: state.
|
|
790
|
-
items: state.
|
|
954
|
+
lines: state.supportedVersion ? ["Server addresses and sign-in details, reusable across sync setups."] : ["Create supported pi-sync settings before managing storage connections."],
|
|
955
|
+
items: state.supportedVersion ? [
|
|
791
956
|
{ id: "add", label: "Add storage connection", action: "add" },
|
|
792
957
|
...names.map((name, index) => {
|
|
793
958
|
const id = `connection:${index}`;
|
|
@@ -882,11 +1047,15 @@ async function loadStorageMenuState(selectedName, signal) {
|
|
|
882
1047
|
const profiles = ownRecord(raw?.storageConnections) ?? {};
|
|
883
1048
|
const profile = selectedName ? ownRecord(profiles[selectedName]) : void 0;
|
|
884
1049
|
if (!selectedName || !profile) {
|
|
885
|
-
return {
|
|
1050
|
+
return {
|
|
1051
|
+
supportedVersion: raw?.version === 3 || raw?.version === 4 || raw?.version === 5,
|
|
1052
|
+
profiles,
|
|
1053
|
+
selected: void 0
|
|
1054
|
+
};
|
|
886
1055
|
}
|
|
887
1056
|
const usedBy = referencingSetups(raw, selectedName);
|
|
888
1057
|
return {
|
|
889
|
-
|
|
1058
|
+
supportedVersion: raw?.version === 3 || raw?.version === 4 || raw?.version === 5,
|
|
890
1059
|
profiles,
|
|
891
1060
|
selected: {
|
|
892
1061
|
name: selectedName,
|
|
@@ -911,7 +1080,7 @@ function notifyConnectionError(ctx, name, error, signal) {
|
|
|
911
1080
|
async function editStorageConnection(ctx, name, profile, usedBy, signal) {
|
|
912
1081
|
if (ctx.mode !== "tui") {
|
|
913
1082
|
ctx.ui.notify(
|
|
914
|
-
"Editing storage connections requires TUI mode for safe credential handling. Edit the private
|
|
1083
|
+
"Editing storage connections requires TUI mode for safe credential handling. Edit the private pi-sync settings file instead.",
|
|
915
1084
|
"warning"
|
|
916
1085
|
);
|
|
917
1086
|
return;
|
|
@@ -984,7 +1153,7 @@ async function editStorageConnection(ctx, name, profile, usedBy, signal) {
|
|
|
984
1153
|
async function showAddStorageConnection(ctx, signal) {
|
|
985
1154
|
if (ctx.mode !== "tui") {
|
|
986
1155
|
ctx.ui.notify(
|
|
987
|
-
"Adding storage connections requires TUI mode for safe credential handling. Edit the private
|
|
1156
|
+
"Adding storage connections requires TUI mode for safe credential handling. Edit the private pi-sync settings file instead.",
|
|
988
1157
|
"warning"
|
|
989
1158
|
);
|
|
990
1159
|
return false;
|
|
@@ -1129,7 +1298,7 @@ async function selectSetupForSwitch(ctx, raw, targets, active, signal) {
|
|
|
1129
1298
|
async function showSetupSwitcher(ctx, runRoute, selectedName, signal) {
|
|
1130
1299
|
const raw = await readLocalConfigObject();
|
|
1131
1300
|
if (signal?.aborted) return false;
|
|
1132
|
-
if (raw?.version !== 3) {
|
|
1301
|
+
if (raw?.version !== 3 && raw?.version !== 4 && raw?.version !== 5) {
|
|
1133
1302
|
ctx.ui.notify("Add a second sync setup before switching setups.", "info");
|
|
1134
1303
|
return false;
|
|
1135
1304
|
}
|
|
@@ -1174,6 +1343,7 @@ async function showSetupSwitcher(ctx, runRoute, selectedName, signal) {
|
|
|
1174
1343
|
`Storage: ${backendStorageDescription(config)}`,
|
|
1175
1344
|
`Included content: ${config.include.length} paths`,
|
|
1176
1345
|
`Automatic sync: ${automaticSyncSummary(config.automatic)} \xB7 Sessions: ${config.include.includes("sessions") ? "On" : "Off"}`,
|
|
1346
|
+
`Automatic transfer at startup: ${config.automaticTransfer ? "On \u2014 may upload, replace, or delete selected files; no reload" : "Off"}`,
|
|
1177
1347
|
"",
|
|
1178
1348
|
switchEffect
|
|
1179
1349
|
].join("\n"),
|
|
@@ -1248,7 +1418,7 @@ async function showAddTarget(ctx, signal) {
|
|
|
1248
1418
|
let raw = await readLocalConfigObject();
|
|
1249
1419
|
if (signal?.aborted) return;
|
|
1250
1420
|
if (!raw) return void ctx.ui.notify("Set up the first sync setup before adding another.", "info");
|
|
1251
|
-
if (raw.version !== 3) {
|
|
1421
|
+
if (raw.version !== 3 && raw.version !== 4 && raw.version !== 5) {
|
|
1252
1422
|
ctx.ui.notify("Version 1 and version 2 settings are unsupported and are never migrated.", "error");
|
|
1253
1423
|
return;
|
|
1254
1424
|
}
|
|
@@ -1295,7 +1465,7 @@ async function showEditTarget(ctx, name, signal) {
|
|
|
1295
1465
|
const partial = await loadPartialConfig(name);
|
|
1296
1466
|
if (signal?.aborted) return;
|
|
1297
1467
|
if (!partial.setupName) {
|
|
1298
|
-
ctx.ui.notify("Create
|
|
1468
|
+
ctx.ui.notify("Create supported pi-sync settings before editing a named sync setup.", "info");
|
|
1299
1469
|
return;
|
|
1300
1470
|
}
|
|
1301
1471
|
if (partial.storageKind === "webdav") {
|
|
@@ -1374,6 +1544,7 @@ async function showSyncManager(ctx, runRoute, sessionSignal, options = {}) {
|
|
|
1374
1544
|
title: "History & recovery",
|
|
1375
1545
|
items: [
|
|
1376
1546
|
{ id: "history", label: "Browse history", action: "history" },
|
|
1547
|
+
{ id: "conflicts", label: "Review unresolved conflicts", action: "conflicts" },
|
|
1377
1548
|
{
|
|
1378
1549
|
id: "doctor",
|
|
1379
1550
|
label: "Check setup",
|
|
@@ -1392,7 +1563,7 @@ async function showSyncManager(ctx, runRoute, sessionSignal, options = {}) {
|
|
|
1392
1563
|
if (!attention) {
|
|
1393
1564
|
const observation = options.getObservation?.();
|
|
1394
1565
|
if (!observation) return { kind: "stay" };
|
|
1395
|
-
const { showRemoteSelectionReview } = await import("./remote-selection-ui-
|
|
1566
|
+
const { showRemoteSelectionReview } = await import("./remote-selection-ui-SMF5CLFO.ts");
|
|
1396
1567
|
if (sessionSignal?.aborted) return { kind: "close" };
|
|
1397
1568
|
const config = await loadConfig();
|
|
1398
1569
|
if (sessionSignal?.aborted) return { kind: "close" };
|
|
@@ -1508,6 +1679,14 @@ async function showSyncManager(ctx, runRoute, sessionSignal, options = {}) {
|
|
|
1508
1679
|
await runRoute("init");
|
|
1509
1680
|
return { kind: "stay" };
|
|
1510
1681
|
},
|
|
1682
|
+
conflicts: async () => {
|
|
1683
|
+
const result = await runCancellableOperation(ctx, "Reviewing private conflicts\u2026", "conflicts", runRoute, {
|
|
1684
|
+
commitAware: true,
|
|
1685
|
+
signal: sessionSignal
|
|
1686
|
+
});
|
|
1687
|
+
const disposition = await dispatchManagerResult(ctx, result, "sync", runRoute, sessionSignal);
|
|
1688
|
+
return disposition.kind === "close" ? { kind: "close" } : { kind: "stay" };
|
|
1689
|
+
},
|
|
1511
1690
|
back: async () => ({ kind: "back" })
|
|
1512
1691
|
}
|
|
1513
1692
|
});
|
|
@@ -1550,4 +1729,4 @@ function syncMainMenuItem(label) {
|
|
|
1550
1729
|
export {
|
|
1551
1730
|
showSyncManager
|
|
1552
1731
|
};
|
|
1553
|
-
//# sourceMappingURL=manager-ui-
|
|
1732
|
+
//# sourceMappingURL=manager-ui-HSMHS3OK.ts.map
|