@narumitw/pi-sync 0.54.2 → 0.56.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 +40 -15
- package/dist/chunks/agent-candidate-3JN6DJKT.ts +26 -0
- package/dist/chunks/agent-plan-QCUJWBP4.ts +99 -0
- package/dist/chunks/agent-plan-QCUJWBP4.ts.map +7 -0
- package/dist/chunks/agent-runner-E2JU2VZ6.ts +182 -0
- package/dist/chunks/agent-runner-E2JU2VZ6.ts.map +7 -0
- package/dist/chunks/agent-store-A3F6IYWZ.ts +152 -0
- package/dist/chunks/agent-store-A3F6IYWZ.ts.map +7 -0
- package/dist/chunks/chunk-5Q5SSKNG.ts +128 -0
- package/dist/chunks/chunk-5Q5SSKNG.ts.map +7 -0
- package/dist/chunks/chunk-5XZOC7FD.ts +215 -0
- package/dist/chunks/chunk-5XZOC7FD.ts.map +7 -0
- package/dist/chunks/{chunk-IJ6VV6FN.ts → chunk-AAEEHR7H.ts} +31 -87
- package/dist/chunks/chunk-AAEEHR7H.ts.map +7 -0
- package/dist/chunks/{chunk-CHSIAC4N.ts → chunk-B4QZBDBT.ts} +2 -2
- package/dist/chunks/{chunk-CL7BZRRQ.ts → chunk-CRKTAPSL.ts} +8 -8
- package/dist/chunks/chunk-DT7M4VQS.ts +69 -0
- package/dist/chunks/chunk-DT7M4VQS.ts.map +7 -0
- package/dist/chunks/chunk-ED3TYIVW.ts +229 -0
- package/dist/chunks/chunk-ED3TYIVW.ts.map +7 -0
- package/dist/chunks/{chunk-VHXBCEVF.ts → chunk-EUMINX7L.ts} +6 -6
- package/dist/chunks/chunk-FQOSHGJ7.ts +215 -0
- package/dist/chunks/chunk-FQOSHGJ7.ts.map +7 -0
- package/dist/chunks/chunk-GNH73BJ5.ts +153 -0
- package/dist/chunks/chunk-GNH73BJ5.ts.map +7 -0
- package/dist/chunks/{chunk-UQ3ALBIB.ts → chunk-GP5DU62N.ts} +8 -9
- package/dist/chunks/chunk-GP5DU62N.ts.map +7 -0
- package/dist/chunks/{chunk-5RZPINUQ.ts → chunk-GSNPASKB.ts} +2 -2
- package/dist/chunks/{chunk-QE7NZZWT.ts → chunk-IWZH5KYS.ts} +23 -7
- package/dist/chunks/chunk-IWZH5KYS.ts.map +7 -0
- package/dist/chunks/{chunk-5ZWQ33XL.ts → chunk-JJTARUSO.ts} +15 -14
- package/dist/chunks/chunk-JJTARUSO.ts.map +7 -0
- package/dist/chunks/{chunk-2DI6PDZV.ts → chunk-NLWS55B6.ts} +15 -2
- package/dist/chunks/chunk-NLWS55B6.ts.map +7 -0
- package/dist/chunks/{chunk-SDZCTCYQ.ts → chunk-OEWQVWLC.ts} +4 -4
- package/dist/chunks/{chunk-MYPSMJHJ.ts → chunk-OTZRCKYP.ts} +380 -510
- package/dist/chunks/chunk-OTZRCKYP.ts.map +7 -0
- package/dist/chunks/{chunk-WFKUKVCP.ts → chunk-OWBAZA6J.ts} +24 -12
- package/dist/chunks/chunk-OWBAZA6J.ts.map +7 -0
- package/dist/chunks/chunk-PRUEIIK7.ts +24 -0
- package/dist/chunks/chunk-PRUEIIK7.ts.map +7 -0
- package/dist/chunks/chunk-QGK445K7.ts +21 -0
- package/dist/chunks/chunk-QGK445K7.ts.map +7 -0
- package/dist/chunks/{chunk-3B4Z2SKV.ts → chunk-QO333NM4.ts} +49 -21
- package/dist/chunks/chunk-QO333NM4.ts.map +7 -0
- package/dist/chunks/{chunk-4SBTAVFL.ts → chunk-QSHMOL3I.ts} +22 -24
- package/dist/chunks/chunk-QSHMOL3I.ts.map +7 -0
- package/dist/chunks/chunk-S2FMH5FT.ts +97 -0
- package/dist/chunks/chunk-S2FMH5FT.ts.map +7 -0
- package/dist/chunks/{chunk-BVVP33U5.ts → chunk-SWRVXVFD.ts} +12 -9
- package/dist/chunks/chunk-SWRVXVFD.ts.map +7 -0
- package/dist/chunks/{chunk-ZX2Q6THB.ts → chunk-UBV24CG4.ts} +4 -5
- package/dist/chunks/chunk-UBV24CG4.ts.map +7 -0
- package/dist/chunks/chunk-UOHR7LRO.ts +70 -0
- package/dist/chunks/chunk-UOHR7LRO.ts.map +7 -0
- package/dist/chunks/{chunk-4QVPTIZB.ts → chunk-UPNVIUBN.ts} +3 -3
- package/dist/chunks/chunk-UZPMDLTL.ts +54 -0
- package/dist/chunks/chunk-UZPMDLTL.ts.map +7 -0
- package/dist/chunks/chunk-VJN7KU4J.ts +350 -0
- package/dist/chunks/chunk-VJN7KU4J.ts.map +7 -0
- package/dist/chunks/chunk-YHT4YTYG.ts +31 -0
- package/dist/chunks/chunk-YHT4YTYG.ts.map +7 -0
- package/dist/chunks/{chunk-V6VZ5TLG.ts → chunk-YK52VDXG.ts} +6 -5
- package/dist/chunks/chunk-YK52VDXG.ts.map +7 -0
- package/dist/chunks/config-KGIYTTXQ.ts +37 -0
- package/dist/chunks/{conflict-artifacts-BB2FZMIE.ts → conflict-artifacts-FXFIIBCB.ts} +8 -7
- package/dist/chunks/{conflict-review-4PLVLMRO.ts → conflict-review-6WIEQLXW.ts} +31 -24
- package/dist/chunks/{conflict-review-4PLVLMRO.ts.map → conflict-review-6WIEQLXW.ts.map} +1 -1
- package/dist/chunks/continuous-record-LFRVXQBD.ts +30 -0
- package/dist/chunks/continuous-sync-AWAAOXK2.ts +545 -0
- package/dist/chunks/continuous-sync-AWAAOXK2.ts.map +7 -0
- package/dist/chunks/{file-selection-WZX7HAY2.ts → file-selection-3JJYOVNR.ts} +5 -5
- package/dist/chunks/{git-backend-FD7AVSK6.ts → git-backend-KYDZ673X.ts} +28 -32
- package/dist/chunks/git-backend-KYDZ673X.ts.map +7 -0
- package/dist/chunks/{manager-result-dispatcher-6MQKFCWB.ts → manager-result-dispatcher-AGBBVDDS.ts} +10 -9
- package/dist/chunks/{manager-ui-IURS4WXY.ts → manager-ui-KRAW3NE2.ts} +464 -164
- package/dist/chunks/manager-ui-KRAW3NE2.ts.map +7 -0
- package/dist/chunks/{merge-baseline-store-EVQAAML6.ts → merge-baseline-store-RFCAH7KL.ts} +7 -5
- package/dist/chunks/{remote-selection-ui-6LJJ4IMQ.ts → remote-selection-ui-5725JDNC.ts} +9 -8
- package/dist/chunks/remote-selection-ui-5725JDNC.ts.map +7 -0
- package/dist/chunks/{s3-backend-AQGV6LFT.ts → s3-backend-Y7WSCLJI.ts} +38 -38
- package/dist/chunks/s3-backend-Y7WSCLJI.ts.map +7 -0
- package/dist/chunks/{setup-switch-KTUWL6DE.ts → setup-switch-E7PHKI6J.ts} +7 -6
- package/dist/chunks/setup-switch-E7PHKI6J.ts.map +7 -0
- package/dist/chunks/{setup-wizard-GSDPDFC4.ts → setup-wizard-65DROCIJ.ts} +14 -13
- package/dist/chunks/setup-wizard-65DROCIJ.ts.map +7 -0
- package/dist/chunks/{sync-inspection-K45QVLHB.ts → sync-inspection-XFJOAMJD.ts} +9 -8
- package/dist/chunks/sync-inspection-XFJOAMJD.ts.map +7 -0
- package/dist/chunks/{sync-operations-47OUX76C.ts → sync-operations-HDUDT5PD.ts} +188 -73
- package/dist/chunks/sync-operations-HDUDT5PD.ts.map +7 -0
- package/dist/chunks/{webdav-backend-TBILVEQK.ts → webdav-backend-6K26F6LT.ts} +39 -48
- package/dist/chunks/webdav-backend-6K26F6LT.ts.map +7 -0
- package/dist/index.ts +246 -131
- package/dist/index.ts.map +3 -3
- package/docs/agent-mode-verification.md +99 -0
- package/docs/continuous-sync-verification.md +87 -0
- package/docs/settings.md +131 -11
- package/docs/tui-contract.md +61 -0
- package/package.json +3 -2
- package/src/backends/git/git-backend.ts +1 -4
- package/src/backends/git/git-runner.ts +1 -5
- package/src/backends/s3/s3-backend.ts +3 -25
- package/src/backends/s3/s3-client.ts +14 -2
- package/src/backends/snapshot-pointer.ts +27 -0
- package/src/backends/webdav/webdav-backend.ts +3 -29
- package/src/backends/webdav/webdav-client.ts +11 -7
- package/src/commands/command-execution.ts +7 -3
- package/src/commands/command-handler.ts +15 -3
- package/src/commands/command-types.ts +10 -0
- package/src/commands/command.ts +4 -1
- package/src/settings/config.ts +20 -10
- package/src/settings/settings-store.ts +1 -34
- package/src/settings/settings-types.ts +10 -0
- package/src/settings/settings-validation.ts +4 -1
- package/src/snapshot/snapshot-codec.ts +1 -5
- package/src/state/lock.ts +13 -10
- package/src/state/merge-baseline-store.ts +19 -1
- package/src/state/state-directory.ts +8 -1
- package/src/sync/agent-candidate.ts +251 -0
- package/src/sync/agent-plan.ts +87 -0
- package/src/sync/agent-policy.ts +13 -0
- package/src/sync/agent-request.ts +17 -0
- package/src/sync/agent-runner.ts +188 -0
- package/src/sync/agent-store.ts +151 -0
- package/src/sync/agent-sync.ts +91 -0
- package/src/sync/apply-review.ts +63 -0
- package/src/sync/automatic-sync.ts +46 -33
- package/src/sync/continuous-errors.ts +85 -0
- package/src/sync/continuous-lease.ts +221 -0
- package/src/sync/continuous-record.ts +179 -0
- package/src/sync/continuous-storage.ts +55 -0
- package/src/sync/continuous-sync.ts +516 -0
- package/src/sync/continuous-watch.ts +59 -0
- package/src/sync/merged-sync.ts +268 -112
- package/src/sync/remote-snapshot.ts +2 -3
- package/src/sync/settings-merge.ts +19 -3
- package/src/sync/setup-switch.ts +1 -5
- package/src/sync/startup-check.ts +51 -29
- package/src/sync/startup-timings.ts +90 -0
- package/src/sync/sync-inspection.ts +16 -5
- package/src/sync/sync-mutations.ts +55 -28
- package/src/sync/sync-queries.ts +19 -3
- package/src/sync/text-merge.ts +3 -3
- package/src/sync-extension.ts +75 -19
- package/src/ui/agent-mode-setting.ts +91 -0
- package/src/ui/manager-state.ts +12 -6
- package/src/ui/manager-ui.ts +57 -7
- package/src/ui/merge-review.ts +3 -3
- package/src/ui/merged-sync-summary.ts +2 -18
- package/src/ui/remote-selection-ui.ts +5 -5
- package/src/ui/settings-frame.ts +55 -0
- package/src/ui/settings-ui.ts +223 -43
- package/src/ui/setup/s3-credentials-ui.ts +1 -5
- package/src/ui/setup/setup-name-ui.ts +2 -5
- package/src/ui/setup/setup-prompts.ts +4 -3
- package/src/ui/setup/setup-switcher.ts +2 -0
- package/src/ui/sync-behavior.ts +15 -0
- package/src/ui/sync-format.ts +69 -38
- package/src/ui/sync-setups-ui.ts +3 -5
- package/src/ui/transfer-changes.ts +33 -0
- package/src/ui/transfer-review.ts +27 -0
- package/dist/chunks/chunk-2DI6PDZV.ts.map +0 -7
- package/dist/chunks/chunk-3B4Z2SKV.ts.map +0 -7
- package/dist/chunks/chunk-4SBTAVFL.ts.map +0 -7
- package/dist/chunks/chunk-5ZWQ33XL.ts.map +0 -7
- package/dist/chunks/chunk-BVVP33U5.ts.map +0 -7
- package/dist/chunks/chunk-IJ6VV6FN.ts.map +0 -7
- package/dist/chunks/chunk-MYPSMJHJ.ts.map +0 -7
- package/dist/chunks/chunk-ORQRHEEO.ts +0 -362
- package/dist/chunks/chunk-ORQRHEEO.ts.map +0 -7
- package/dist/chunks/chunk-QE7NZZWT.ts.map +0 -7
- package/dist/chunks/chunk-UQ3ALBIB.ts.map +0 -7
- package/dist/chunks/chunk-V6VZ5TLG.ts.map +0 -7
- package/dist/chunks/chunk-WFKUKVCP.ts.map +0 -7
- package/dist/chunks/chunk-ZX2Q6THB.ts.map +0 -7
- package/dist/chunks/git-backend-FD7AVSK6.ts.map +0 -7
- package/dist/chunks/manager-ui-IURS4WXY.ts.map +0 -7
- package/dist/chunks/s3-backend-AQGV6LFT.ts.map +0 -7
- package/dist/chunks/setup-wizard-GSDPDFC4.ts.map +0 -7
- package/dist/chunks/sync-operations-47OUX76C.ts.map +0 -7
- package/dist/chunks/webdav-backend-TBILVEQK.ts.map +0 -7
- /package/dist/chunks/{conflict-artifacts-BB2FZMIE.ts.map → agent-candidate-3JN6DJKT.ts.map} +0 -0
- /package/dist/chunks/{chunk-CHSIAC4N.ts.map → chunk-B4QZBDBT.ts.map} +0 -0
- /package/dist/chunks/{chunk-CL7BZRRQ.ts.map → chunk-CRKTAPSL.ts.map} +0 -0
- /package/dist/chunks/{chunk-VHXBCEVF.ts.map → chunk-EUMINX7L.ts.map} +0 -0
- /package/dist/chunks/{chunk-5RZPINUQ.ts.map → chunk-GSNPASKB.ts.map} +0 -0
- /package/dist/chunks/{chunk-SDZCTCYQ.ts.map → chunk-OEWQVWLC.ts.map} +0 -0
- /package/dist/chunks/{chunk-4QVPTIZB.ts.map → chunk-UPNVIUBN.ts.map} +0 -0
- /package/dist/chunks/{manager-result-dispatcher-6MQKFCWB.ts.map → config-KGIYTTXQ.ts.map} +0 -0
- /package/dist/chunks/{merge-baseline-store-EVQAAML6.ts.map → conflict-artifacts-FXFIIBCB.ts.map} +0 -0
- /package/dist/chunks/{remote-selection-ui-6LJJ4IMQ.ts.map → continuous-record-LFRVXQBD.ts.map} +0 -0
- /package/dist/chunks/{file-selection-WZX7HAY2.ts.map → file-selection-3JJYOVNR.ts.map} +0 -0
- /package/dist/chunks/{setup-switch-KTUWL6DE.ts.map → manager-result-dispatcher-AGBBVDDS.ts.map} +0 -0
- /package/dist/chunks/{sync-inspection-K45QVLHB.ts.map → merge-baseline-store-RFCAH7KL.ts.map} +0 -0
|
@@ -1,7 +1,9 @@
|
|
|
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
3
|
import {
|
|
4
|
-
|
|
4
|
+
confirmMergeReview
|
|
5
|
+
} from "./chunk-5XZOC7FD.ts";
|
|
6
|
+
import {
|
|
5
7
|
applyS3CredentialUpdate,
|
|
6
8
|
chooseS3CredentialUpdate,
|
|
7
9
|
chooseS3Credentials,
|
|
@@ -20,56 +22,58 @@ import {
|
|
|
20
22
|
showEditS3Target,
|
|
21
23
|
showEditWebDavStorageProfile,
|
|
22
24
|
showEditWebDavTarget
|
|
23
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-QSHMOL3I.ts";
|
|
24
26
|
import {
|
|
25
27
|
dispatchManagerResult
|
|
26
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-EUMINX7L.ts";
|
|
27
29
|
import {
|
|
28
30
|
runCancellableOperation
|
|
29
|
-
} from "./chunk-
|
|
30
|
-
import "./chunk-
|
|
31
|
-
import "./chunk-SDZCTCYQ.ts";
|
|
31
|
+
} from "./chunk-JJTARUSO.ts";
|
|
32
|
+
import "./chunk-YK52VDXG.ts";
|
|
32
33
|
import {
|
|
33
34
|
SETUP_SWITCH_ACTION_OPTIONS,
|
|
34
35
|
saveOnSwitch,
|
|
35
36
|
setupSwitchActionFromLabel,
|
|
36
37
|
setupSwitchActionLabel,
|
|
37
38
|
useSyncSetup
|
|
38
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-GP5DU62N.ts";
|
|
40
|
+
import "./chunk-OEWQVWLC.ts";
|
|
41
|
+
import {
|
|
42
|
+
addStorageConnection,
|
|
43
|
+
removeStorageConnection,
|
|
44
|
+
removeSyncSetup,
|
|
45
|
+
updateStorageConnection,
|
|
46
|
+
updateSyncSetup
|
|
47
|
+
} from "./chunk-B4QZBDBT.ts";
|
|
39
48
|
import {
|
|
40
49
|
observationMatchesConfig,
|
|
41
50
|
observationSummary,
|
|
42
51
|
syncAttentionMatchesConfig
|
|
43
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-GSNPASKB.ts";
|
|
44
53
|
import {
|
|
45
|
-
captureMutationOwner
|
|
46
|
-
|
|
47
|
-
isLockGuardHeld,
|
|
48
|
-
isStaleLock
|
|
49
|
-
} from "./chunk-IJ6VV6FN.ts";
|
|
50
|
-
import "./chunk-PWMWOJP4.ts";
|
|
54
|
+
captureMutationOwner
|
|
55
|
+
} from "./chunk-UOHR7LRO.ts";
|
|
51
56
|
import {
|
|
52
57
|
automaticSyncSummary
|
|
53
58
|
} from "./chunk-ECYCNZOE.ts";
|
|
54
59
|
import {
|
|
55
60
|
configureSyncStatus
|
|
56
61
|
} from "./chunk-K3RIEL6J.ts";
|
|
57
|
-
import
|
|
62
|
+
import {
|
|
63
|
+
AUTOMATIC_SYNC_DESCRIPTION,
|
|
64
|
+
STARTUP_TRANSFER_DESCRIPTION,
|
|
65
|
+
startupTransferSummary
|
|
66
|
+
} from "./chunk-NLWS55B6.ts";
|
|
58
67
|
import {
|
|
59
68
|
safeTerminalText
|
|
60
69
|
} from "./chunk-AMJRUXFT.ts";
|
|
70
|
+
import "./chunk-UBV24CG4.ts";
|
|
61
71
|
import {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
} from "./chunk-4QVPTIZB.ts";
|
|
65
|
-
import "./chunk-BVVP33U5.ts";
|
|
72
|
+
syncErrorGuidance
|
|
73
|
+
} from "./chunk-G4RUXRWZ.ts";
|
|
66
74
|
import {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
removeSyncSetup,
|
|
70
|
-
updateStorageConnection,
|
|
71
|
-
updateSyncSetup
|
|
72
|
-
} from "./chunk-CHSIAC4N.ts";
|
|
75
|
+
errorMessage
|
|
76
|
+
} from "./chunk-7D5SF7P3.ts";
|
|
73
77
|
import {
|
|
74
78
|
activeLocalConfigPath,
|
|
75
79
|
isCloudflareR2Endpoint,
|
|
@@ -80,27 +84,35 @@ import {
|
|
|
80
84
|
normalizeS3Endpoint,
|
|
81
85
|
ownRecord,
|
|
82
86
|
readLocalConfigObject,
|
|
87
|
+
requireSettings,
|
|
88
|
+
syncCheckConfigFingerprint,
|
|
83
89
|
syncConfigReviewIdentity,
|
|
84
90
|
updateLocalConfig
|
|
85
|
-
} from "./chunk-
|
|
86
|
-
import "./chunk-2JZFHNLM.ts";
|
|
87
|
-
import "./chunk-T2SJD3N7.ts";
|
|
88
|
-
import "./chunk-ZX2Q6THB.ts";
|
|
89
|
-
import {
|
|
90
|
-
syncErrorGuidance
|
|
91
|
-
} from "./chunk-G4RUXRWZ.ts";
|
|
92
|
-
import {
|
|
93
|
-
errorMessage
|
|
94
|
-
} from "./chunk-7D5SF7P3.ts";
|
|
91
|
+
} from "./chunk-QO333NM4.ts";
|
|
95
92
|
import {
|
|
96
93
|
normalizeLocalFields,
|
|
97
94
|
sameLocalFields
|
|
98
95
|
} from "./chunk-A6HU4ERM.ts";
|
|
96
|
+
import {
|
|
97
|
+
inspectLock,
|
|
98
|
+
isLockGuardHeld,
|
|
99
|
+
isStaleLock
|
|
100
|
+
} from "./chunk-AAEEHR7H.ts";
|
|
101
|
+
import {
|
|
102
|
+
throwIfAborted
|
|
103
|
+
} from "./chunk-PWMWOJP4.ts";
|
|
99
104
|
import {
|
|
100
105
|
compareSyncInclude,
|
|
101
106
|
syncIncludeSelection
|
|
102
107
|
} from "./chunk-QOFMXPM5.ts";
|
|
103
108
|
import "./chunk-ZW5ZLGBI.ts";
|
|
109
|
+
import {
|
|
110
|
+
readStateForConfig,
|
|
111
|
+
syncStateFingerprint
|
|
112
|
+
} from "./chunk-UPNVIUBN.ts";
|
|
113
|
+
import "./chunk-SWRVXVFD.ts";
|
|
114
|
+
import "./chunk-2JZFHNLM.ts";
|
|
115
|
+
import "./chunk-T2SJD3N7.ts";
|
|
104
116
|
import "./chunk-HUZ5CR4W.ts";
|
|
105
117
|
|
|
106
118
|
// src/ui/manager-ui.ts
|
|
@@ -172,7 +184,7 @@ function blockedSyncMenuItem(label, manager) {
|
|
|
172
184
|
};
|
|
173
185
|
}
|
|
174
186
|
async function showManagerAttention(ctx, attention, runRoute, signal, onSelectionResolved) {
|
|
175
|
-
const { showRemoteSelectionReview } = await import("./remote-selection-ui-
|
|
187
|
+
const { showRemoteSelectionReview } = await import("./remote-selection-ui-5725JDNC.ts");
|
|
176
188
|
if (signal?.aborted) return "close";
|
|
177
189
|
const review = await showRemoteSelectionReview(ctx, attention.decision.setupName, signal, void 0, {
|
|
178
190
|
decision: attention.decision,
|
|
@@ -254,10 +266,6 @@ async function countValidSyncSetups(setups, signal) {
|
|
|
254
266
|
}
|
|
255
267
|
return count;
|
|
256
268
|
}
|
|
257
|
-
function throwIfAborted(signal) {
|
|
258
|
-
if (!signal?.aborted) return;
|
|
259
|
-
throw signal.reason instanceof Error ? signal.reason : new DOMException("The operation was aborted", "AbortError");
|
|
260
|
-
}
|
|
261
269
|
async function showSyncSetups(ctx, actions, signal) {
|
|
262
270
|
let selectedName;
|
|
263
271
|
let exit = false;
|
|
@@ -395,6 +403,8 @@ async function loadSetupMenuState(selectedName, signal) {
|
|
|
395
403
|
`Sessions: ${selection.sessions ? "On \u2014 privacy-sensitive" : "Off"}`,
|
|
396
404
|
`Automatic sync: ${config.automatic ? "On" : "Off"}`,
|
|
397
405
|
`Automatic transfer at startup: ${config.automaticTransfer ? "On \u2014 may upload, replace, or delete selected files; no reload" : "Off"}`,
|
|
406
|
+
`Agent mode: ${config.agentMode ? "On (experimental; autonomous merged sync)" : "Off"}`,
|
|
407
|
+
`Continuous sync: ${config.continuous ? config.agentMode ? "On (experimental; recurring requests and transfers)" : "Saved On; paused until Agent mode is enabled" : "Off"}`,
|
|
398
408
|
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."
|
|
399
409
|
];
|
|
400
410
|
} catch (error) {
|
|
@@ -453,6 +463,8 @@ var MAIN_MENU_ACTIONS = [
|
|
|
453
463
|
"Sync now",
|
|
454
464
|
"Pull from remote\u2026",
|
|
455
465
|
"Push to remote\u2026",
|
|
466
|
+
"View differences",
|
|
467
|
+
"Check remote status",
|
|
456
468
|
"Settings",
|
|
457
469
|
"History",
|
|
458
470
|
"Diagnostics"
|
|
@@ -514,7 +526,7 @@ async function describeManagerState(signal, attention, inspectOperation = inspec
|
|
|
514
526
|
const noSyncedContent = config.include.length === 0;
|
|
515
527
|
const syncState = changesBlocked ? void 0 : await readStateForConfig(config).catch(() => void 0);
|
|
516
528
|
const currentObservation = observation && observationMatchesConfig(observation, config) && syncState && syncStateFingerprint(syncState) === observation.inspection.stateIdentity ? observation : void 0;
|
|
517
|
-
const lastAppliedSnapshot = changesBlocked ? "Unavailable while operations are locked" : syncState?.lastAppliedSnapshot ? safeTerminalText(syncState.lastAppliedSnapshot) : syncState ? "Never synced" : "Unavailable";
|
|
529
|
+
const lastAppliedSnapshot = changesBlocked ? "Unavailable while operations are locked" : syncState?.lastAppliedSnapshot ? `${truncateToWidth(safeTerminalText(syncState.lastAppliedSnapshot), 20, "\u2026")} (application time unavailable; full ID in History)` : syncState ? "Never synced" : "Unavailable";
|
|
518
530
|
const canSwitch = await countValidSyncSetups(configuredTargets, signal) > 1;
|
|
519
531
|
const mainActions = [...MAIN_MENU_ACTIONS];
|
|
520
532
|
if (canSwitch) mainActions.push("Switch sync setup");
|
|
@@ -524,10 +536,7 @@ async function describeManagerState(signal, attention, inspectOperation = inspec
|
|
|
524
536
|
"",
|
|
525
537
|
`Current sync setup: ${safeTerminalText(config.setupName)}`,
|
|
526
538
|
`Storage: ${backendStorageDescription(config)}`,
|
|
527
|
-
|
|
528
|
-
`Automatic sync: ${automaticSyncSummary(config.automatic)}`,
|
|
529
|
-
`Automatic transfer at startup: ${config.automaticTransfer ? "On \u2014 upload/replace/delete at idle; no reload" : "Off"}`,
|
|
530
|
-
`Last applied: ${lastAppliedSnapshot}`,
|
|
539
|
+
"CURRENT STATE",
|
|
531
540
|
...syncState?.unresolved?.length ? [
|
|
532
541
|
`Unresolved: ${syncState.unresolved.length} dependency groups \xB7 choose Review unresolved conflicts`,
|
|
533
542
|
`Last observed: ${safeTerminalText(syncState.lastObservedSnapshot ?? "unknown")}`
|
|
@@ -540,9 +549,15 @@ async function describeManagerState(signal, attention, inspectOperation = inspec
|
|
|
540
549
|
`Startup check (${safeTerminalText(currentObservation.checkedAt)}): ${observationSummary(currentObservation)}`,
|
|
541
550
|
"Check-time observation only; synchronization rechecks current content."
|
|
542
551
|
] : ["Remote status: Not checked"],
|
|
552
|
+
`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"}`,
|
|
553
|
+
`Automatic sync: ${automaticSyncSummary(config.automatic)}`,
|
|
554
|
+
`Startup transfer: ${startupTransferSummary(config)}`,
|
|
555
|
+
`Agent mode: ${config.agentMode ? "On (experimental; autonomous merged sync)" : "Off"}`,
|
|
556
|
+
...config.continuous ? await (await import("./continuous-record-LFRVXQBD.ts")).continuousStatusLines(config) : [],
|
|
557
|
+
`Last applied: ${lastAppliedSnapshot}`,
|
|
543
558
|
...noSyncedContent ? ["", "No included content is selected. Choose included content in Settings before syncing."] : [],
|
|
544
559
|
"",
|
|
545
|
-
"
|
|
560
|
+
"ACTIONS \xB7 transfer, inspect, or manage"
|
|
546
561
|
];
|
|
547
562
|
return {
|
|
548
563
|
title: (changesBlocked ? ["Manage sync", ...operationStatusLines(operation)] : ordinaryTitle).join("\n"),
|
|
@@ -630,8 +645,112 @@ function backendStorageDescription(config) {
|
|
|
630
645
|
// src/ui/settings-ui.ts
|
|
631
646
|
import { defineMenu as defineMenu4, runMenu as runMenu4 } from "@narumitw/pi-tui-kit";
|
|
632
647
|
|
|
633
|
-
// src/ui/
|
|
648
|
+
// src/ui/agent-mode-setting.ts
|
|
634
649
|
import { isDeepStrictEqual } from "node:util";
|
|
650
|
+
var AGENT_MODE_DESCRIPTION = "This setup, experimental: one autonomous merged sync next startup and on Sync now. Sends eligible conflict text to the selected Pi model; may incur costs and replace/delete selected local and remote content without transfer prompts. No automatic reload. Unsupported conflicts pause.";
|
|
651
|
+
var CONTINUOUS_DESCRIPTION = "This setup, experimental: recurring sync while Pi is open. Requires Agent mode. Watches selected files, checks the remote every 60\u201366 seconds, and retries temporary failures. Local changes and retries can cause extra requests between polls. May disclose conflict text and incur model/storage costs. No automatic reload.";
|
|
652
|
+
function saveContinuousMode(ctx, setupName, enabled, signal) {
|
|
653
|
+
return saveAgentMode(ctx, setupName, enabled, signal, "continuous");
|
|
654
|
+
}
|
|
655
|
+
async function saveAgentMode(ctx, setupName, enabled, signal, preference = "agentMode") {
|
|
656
|
+
const validate = captureMutationOwner(ctx, signal);
|
|
657
|
+
const settings = await requireSettings();
|
|
658
|
+
validate();
|
|
659
|
+
const setup = settings.syncSetups[setupName];
|
|
660
|
+
if (!setup || settings.activeSyncSetup !== setupName) throw new Error("Current sync setup changed; reopen Settings.");
|
|
661
|
+
const continuous = preference === "continuous";
|
|
662
|
+
const label = continuous ? "Continuous sync" : "Agent mode";
|
|
663
|
+
if (enabled && continuous && !setup.sync.agentMode) throw new Error("Enable Agent mode before Continuous sync.");
|
|
664
|
+
if (Boolean(setup.sync[preference]) === enabled) return true;
|
|
665
|
+
if (enabled) {
|
|
666
|
+
const summary = [
|
|
667
|
+
`Setup: ${safeTerminalText(setupName)}`,
|
|
668
|
+
`Storage connection: ${safeTerminalText(setup.storage.connection)}`,
|
|
669
|
+
`Storage path: ${safeTerminalText(setup.storage.path)}`,
|
|
670
|
+
...setup.storage.bucket ? [`Bucket: ${safeTerminalText(String(setup.storage.bucket))}`] : [],
|
|
671
|
+
...setup.storage.branch ? [`Branch: ${safeTerminalText(String(setup.storage.branch))}`] : [],
|
|
672
|
+
`Included paths: ${setup.sync.include.map(safeTerminalText).join(", ")}`,
|
|
673
|
+
continuous ? CONTINUOUS_DESCRIPTION : AGENT_MODE_DESCRIPTION,
|
|
674
|
+
...continuous ? [
|
|
675
|
+
"Upgrade all Pi processes sharing this agent directory before enabling Continuous sync. Monitoring starts after the /sync command or manager closes. An elected idle local session uses its selected Pi model; another session can use a different provider/model. Each computer is a separate replica.",
|
|
676
|
+
"Automatic requests are limited to two per candidate and two per replica binding in a rolling 15-minute window, across restarts. Network/storage checks and requests may incur costs. Retries start at five seconds and grow to five minutes. These are request bounds, not a currency cap."
|
|
677
|
+
] : setup.sync.continuous ? ["The saved Continuous sync preference will resume monitoring after the /sync command or manager closes."] : [],
|
|
678
|
+
"Only bounded Markdown/plain-text conflicts and atomic global settings choices are eligible. Model errors can change intended behavior. Session histories, code, deletion conflicts and path collisions are not model-resolved.",
|
|
679
|
+
"The existing baseline, selection, secret-scan and publication checks remain. Pi Sync cannot exclude arbitrary concurrent local writers. Disabling does not undo completed transfers or provider charges. No transfer starts from Settings."
|
|
680
|
+
].join("\n\n");
|
|
681
|
+
if (!await confirmMergeReview(
|
|
682
|
+
ctx,
|
|
683
|
+
`Enable experimental ${label}?`,
|
|
684
|
+
summary,
|
|
685
|
+
signal,
|
|
686
|
+
() => !signal?.aborted,
|
|
687
|
+
`Enable ${label}`,
|
|
688
|
+
summary.split("\n")
|
|
689
|
+
))
|
|
690
|
+
return false;
|
|
691
|
+
validate();
|
|
692
|
+
}
|
|
693
|
+
await updateLocalConfig((current) => {
|
|
694
|
+
validate();
|
|
695
|
+
if (current.activeSyncSetup !== setupName || !isDeepStrictEqual(current.syncSetups[setupName], setup) || !isDeepStrictEqual(
|
|
696
|
+
current.storageConnections[setup.storage.connection],
|
|
697
|
+
settings.storageConnections[setup.storage.connection]
|
|
698
|
+
))
|
|
699
|
+
throw new Error("Sync setup or connection changed during Agent mode review; reopen Settings.");
|
|
700
|
+
return {
|
|
701
|
+
...current,
|
|
702
|
+
syncSetups: { ...current.syncSetups, [setupName]: { ...setup, sync: { ...setup.sync, [preference]: enabled } } }
|
|
703
|
+
};
|
|
704
|
+
}, signal);
|
|
705
|
+
return true;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// src/ui/settings-frame.ts
|
|
709
|
+
import { stripVTControlCharacters } from "node:util";
|
|
710
|
+
function boundedSettingsUI(ctx) {
|
|
711
|
+
return {
|
|
712
|
+
...ctx.ui,
|
|
713
|
+
custom: (factory, options) => ctx.ui.custom((tui, ...args) => {
|
|
714
|
+
const terminal = new Proxy(tui.terminal, {
|
|
715
|
+
get: (target, key) => key === "rows" ? Math.max(8, target.rows) : Reflect.get(target, key)
|
|
716
|
+
});
|
|
717
|
+
const screenTui = new Proxy(tui, {
|
|
718
|
+
get(target, key) {
|
|
719
|
+
if (key === "terminal") return terminal;
|
|
720
|
+
const value = Reflect.get(target, key);
|
|
721
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
722
|
+
}
|
|
723
|
+
});
|
|
724
|
+
const guard = (component2) => {
|
|
725
|
+
const render = component2.render.bind(component2);
|
|
726
|
+
const handleMouse = component2.handleMouse?.bind(component2);
|
|
727
|
+
let sourceRow = 0;
|
|
728
|
+
const compact = () => tui.terminal.rows < 8;
|
|
729
|
+
component2.render = (width) => {
|
|
730
|
+
if (width <= 0) return [];
|
|
731
|
+
const lines = render(width);
|
|
732
|
+
if (!compact()) return lines;
|
|
733
|
+
const active = lines.findIndex((line) => stripVTControlCharacters(line).startsWith("\u2192"));
|
|
734
|
+
const search = lines.findIndex((line) => stripVTControlCharacters(line).startsWith(">"));
|
|
735
|
+
sourceRow = active < 0 ? Math.max(0, search) : active;
|
|
736
|
+
return lines.slice(sourceRow, sourceRow + 1);
|
|
737
|
+
};
|
|
738
|
+
if (handleMouse)
|
|
739
|
+
component2.handleMouse = (event) => {
|
|
740
|
+
if (event.width <= 0 || compact() && event.y !== 0) return void 0;
|
|
741
|
+
component2.render(event.width);
|
|
742
|
+
return handleMouse(compact() ? { ...event, y: event.y + sourceRow } : event);
|
|
743
|
+
};
|
|
744
|
+
return component2;
|
|
745
|
+
};
|
|
746
|
+
const component = factory(screenTui, ...args);
|
|
747
|
+
return component instanceof Promise ? component.then(guard) : guard(component);
|
|
748
|
+
}, options)
|
|
749
|
+
};
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
// src/ui/storage-connections-ui.ts
|
|
753
|
+
import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
|
|
635
754
|
import { defineMenu as defineMenu2, runMenu as runMenu2 } from "@narumitw/pi-tui-kit";
|
|
636
755
|
async function showStorageConnections(ctx, signal) {
|
|
637
756
|
let selectedName;
|
|
@@ -826,7 +945,7 @@ async function editStorageConnection(ctx, name, profile, usedBy, signal) {
|
|
|
826
945
|
(saveSignal) => updateStorageConnection(
|
|
827
946
|
name,
|
|
828
947
|
(current) => {
|
|
829
|
-
if (current.type !== "s3" || !
|
|
948
|
+
if (current.type !== "s3" || !isDeepStrictEqual2(current, profile)) {
|
|
830
949
|
throw new Error("Storage connection changed while it was open; reopen it.");
|
|
831
950
|
}
|
|
832
951
|
return {
|
|
@@ -1038,6 +1157,8 @@ async function showSetupSwitcher(ctx, runRoute, selectedName, signal) {
|
|
|
1038
1157
|
`Included content: ${config.include.length} paths`,
|
|
1039
1158
|
`Automatic sync: ${automaticSyncSummary(config.automatic)} \xB7 Sessions: ${config.include.includes("sessions") ? "On" : "Off"}`,
|
|
1040
1159
|
`Automatic transfer at startup: ${config.automaticTransfer ? "On \u2014 may upload, replace, or delete selected files; no reload" : "Off"}`,
|
|
1160
|
+
`Agent mode: ${config.agentMode ? "On (experimental; autonomous merged sync)" : "Off"}`,
|
|
1161
|
+
`Continuous sync: ${config.continuous ? config.agentMode ? "On (experimental; recurring requests and transfers)" : "Saved On; paused until Agent mode is enabled" : "Off"}`,
|
|
1041
1162
|
"",
|
|
1042
1163
|
switchEffect
|
|
1043
1164
|
].join("\n"),
|
|
@@ -1227,118 +1348,172 @@ async function showSyncSettings(ctx, runRoute, signal) {
|
|
|
1227
1348
|
const initial = await loadConfig();
|
|
1228
1349
|
if (signal?.aborted) return "back";
|
|
1229
1350
|
const setupName = initial.setupName;
|
|
1351
|
+
const groups = {
|
|
1352
|
+
content: { label: "Sync content", ids: ["include", "remoteInclude", "localFields"] },
|
|
1353
|
+
behavior: {
|
|
1354
|
+
label: "Sync behavior",
|
|
1355
|
+
ids: ["automatic", "automaticTransfer", "agentMode", "continuous", "onSwitch"]
|
|
1356
|
+
},
|
|
1357
|
+
storage: { label: "Storage & setups", ids: ["storageLocation", "setups", "connections"] },
|
|
1358
|
+
advanced: { label: "Advanced", ids: ["mergeSettings", "contentPolicy", "skipSecretScan", "showStatus", "debug"] },
|
|
1359
|
+
all: { label: "All settings (search)", ids: [] }
|
|
1360
|
+
};
|
|
1361
|
+
let saveStatus = "Simple choices save immediately. Back does not undo saved changes.";
|
|
1362
|
+
const settingsScreen = (state, group) => ({
|
|
1363
|
+
kind: "settings",
|
|
1364
|
+
title: `Pi Sync Settings \xB7 ${groups[group].label}`,
|
|
1365
|
+
lines: [
|
|
1366
|
+
`Setup: ${safeTerminalText(state.setupName)} \xB7 Connection: ${safeTerminalText(state.connectionName)}`,
|
|
1367
|
+
saveStatus
|
|
1368
|
+
],
|
|
1369
|
+
items: [
|
|
1370
|
+
{
|
|
1371
|
+
id: "include",
|
|
1372
|
+
label: "Included paths",
|
|
1373
|
+
description: "This setup: choose paths in a draft, then review and Save or Discard. No transfer is started.",
|
|
1374
|
+
currentValue: `${state.include.length} paths \xB7 Edit`,
|
|
1375
|
+
action: "include"
|
|
1376
|
+
},
|
|
1377
|
+
{
|
|
1378
|
+
id: "remoteInclude",
|
|
1379
|
+
label: "Compare included paths",
|
|
1380
|
+
description: "This setup: compare included-path policies, not file contents. Review before saving either list; no files transfer unless you explicitly Continue.",
|
|
1381
|
+
currentValue: "Review",
|
|
1382
|
+
action: "remote-include"
|
|
1383
|
+
},
|
|
1384
|
+
{
|
|
1385
|
+
id: "localFields",
|
|
1386
|
+
label: "Machine-local fields",
|
|
1387
|
+
description: "This setup: settings.json root fields excluded from future portable snapshots, not project overrides. Policy changes require reviewed directional migration; old history remains.",
|
|
1388
|
+
currentValue: `${state.localFields?.length ?? 0} fields \xB7 Edit`,
|
|
1389
|
+
action: "local-fields"
|
|
1390
|
+
},
|
|
1391
|
+
{
|
|
1392
|
+
id: "storageLocation",
|
|
1393
|
+
label: "Storage location",
|
|
1394
|
+
description: "This setup: review and save bucket, branch, or path changes. Remote history is not moved.",
|
|
1395
|
+
currentValue: state.backend.type === "s3" ? `${safeTerminalText(state.backend.destination.bucket)} \xB7 ${safeTerminalText(state.backend.destination.prefix)}` : state.backend.type === "git" ? `${safeTerminalText(state.backend.destination.branch)} \xB7 ${safeTerminalText(state.backend.destination.directory)}` : safeTerminalText(state.backend.destination.path),
|
|
1396
|
+
action: "storage-location"
|
|
1397
|
+
},
|
|
1398
|
+
{
|
|
1399
|
+
id: "setups",
|
|
1400
|
+
label: "Manage sync setups",
|
|
1401
|
+
description: "This device: add, switch, edit, or remove sync setups. Each edit identifies its owner before saving.",
|
|
1402
|
+
currentValue: "Open",
|
|
1403
|
+
action: "setups"
|
|
1404
|
+
},
|
|
1405
|
+
{
|
|
1406
|
+
id: "connections",
|
|
1407
|
+
label: "Manage storage connections",
|
|
1408
|
+
description: "Shared connections on this device: review affected setups before saving server or credential changes.",
|
|
1409
|
+
currentValue: "Open",
|
|
1410
|
+
action: "connections"
|
|
1411
|
+
},
|
|
1412
|
+
{
|
|
1413
|
+
id: "automatic",
|
|
1414
|
+
label: "Automatic sync",
|
|
1415
|
+
description: AUTOMATIC_SYNC_DESCRIPTION,
|
|
1416
|
+
currentValue: state.automatic ? "On" : "Off",
|
|
1417
|
+
values: ["On", "Off"],
|
|
1418
|
+
action: "automatic"
|
|
1419
|
+
},
|
|
1420
|
+
{
|
|
1421
|
+
id: "automaticTransfer",
|
|
1422
|
+
label: "Startup transfer",
|
|
1423
|
+
description: `${STARTUP_TRANSFER_DESCRIPTION} Saved preference and requirements: ${startupTransferSummary(state)}.`,
|
|
1424
|
+
currentValue: state.automaticTransfer ? "On" : "Off",
|
|
1425
|
+
values: ["On", "Off"],
|
|
1426
|
+
action: "automatic-transfer"
|
|
1427
|
+
},
|
|
1428
|
+
{
|
|
1429
|
+
id: "agentMode",
|
|
1430
|
+
label: "Agent mode (experimental)",
|
|
1431
|
+
description: AGENT_MODE_DESCRIPTION,
|
|
1432
|
+
currentValue: state.agentMode ? "On" : "Off",
|
|
1433
|
+
values: ["On", "Off"],
|
|
1434
|
+
action: "agent-mode"
|
|
1435
|
+
},
|
|
1436
|
+
{
|
|
1437
|
+
id: "continuous",
|
|
1438
|
+
label: "Continuous sync (experimental)",
|
|
1439
|
+
description: `${CONTINUOUS_DESCRIPTION}${state.continuous && !state.agentMode ? " Saved On, but paused until Agent mode is enabled." : ""}`,
|
|
1440
|
+
currentValue: state.continuous ? "On" : "Off",
|
|
1441
|
+
values: ["On", "Off"],
|
|
1442
|
+
action: "continuous"
|
|
1443
|
+
},
|
|
1444
|
+
{
|
|
1445
|
+
id: "onSwitch",
|
|
1446
|
+
label: "On setup switch",
|
|
1447
|
+
description: "All setups on this device: ask before a pull review, open it automatically, or switch without pulling. Applies to subsequent switches.",
|
|
1448
|
+
currentValue: setupSwitchActionLabel(state.onSwitch),
|
|
1449
|
+
values: SETUP_SWITCH_ACTION_OPTIONS.map(({ label }) => label),
|
|
1450
|
+
action: "on-switch"
|
|
1451
|
+
},
|
|
1452
|
+
{
|
|
1453
|
+
id: "mergeSettings",
|
|
1454
|
+
label: "Merge settings fields",
|
|
1455
|
+
description: "This setup, experimental opt-in: merge independent global settings.json root fields with a verified private ancestor. Arrays and nested objects remain atomic. Applies to subsequent sync; no reload.",
|
|
1456
|
+
currentValue: state.mergeSettings ? "On" : "Off",
|
|
1457
|
+
values: ["On", "Off"],
|
|
1458
|
+
action: "merge-settings"
|
|
1459
|
+
},
|
|
1460
|
+
{
|
|
1461
|
+
id: "contentPolicy",
|
|
1462
|
+
label: "Content merge / partial progress",
|
|
1463
|
+
description: "This setup, experimental opt-in: review the version-5 upgrade before saving. Merge bounded text and prefix-only sessions; partial progress keeps withheld versions and baselines. Applies to subsequent sync; disabling does not clear recovery evidence.",
|
|
1464
|
+
currentValue: state.mergeContent ? state.partialSync ? "Merge + partial" : "Merge only" : state.partialSync ? "Partial only" : "Off",
|
|
1465
|
+
values: ["Off", "Merge only", "Merge + partial", "Partial only"],
|
|
1466
|
+
action: "content-policy"
|
|
1467
|
+
},
|
|
1468
|
+
{
|
|
1469
|
+
id: "skipSecretScan",
|
|
1470
|
+
label: "Skip secret scan",
|
|
1471
|
+
description: "All setups on this device: skip possible-secret checks on subsequent pushes, including automatic pushes. Other safety checks remain. Diagnostics still scans.",
|
|
1472
|
+
currentValue: state.skipSecretScan ? "On" : "Off",
|
|
1473
|
+
values: ["On", "Off"],
|
|
1474
|
+
action: "skip-secret-scan"
|
|
1475
|
+
},
|
|
1476
|
+
{
|
|
1477
|
+
id: "showStatus",
|
|
1478
|
+
label: "Show sync status",
|
|
1479
|
+
description: "All setups on this device: saved and applied immediately to Pi status. Review widgets and notifications remain available.",
|
|
1480
|
+
currentValue: state.showStatus ? "On" : "Off",
|
|
1481
|
+
values: ["On", "Off"],
|
|
1482
|
+
action: "show-status"
|
|
1483
|
+
},
|
|
1484
|
+
{
|
|
1485
|
+
id: "debug",
|
|
1486
|
+
label: "Debug startup timings",
|
|
1487
|
+
description: "All setups on this device: show startup durations in TUI/RPC notifications. Applies next session start; no credentials or file contents.",
|
|
1488
|
+
currentValue: state.debug ? "On" : "Off",
|
|
1489
|
+
values: ["On", "Off"],
|
|
1490
|
+
action: "debug"
|
|
1491
|
+
}
|
|
1492
|
+
].filter((item) => group === "all" || groups[group].ids.includes(item.id))
|
|
1493
|
+
});
|
|
1230
1494
|
const menu = defineMenu4({
|
|
1231
|
-
start: "
|
|
1495
|
+
start: "categories",
|
|
1232
1496
|
screens: {
|
|
1233
|
-
|
|
1234
|
-
kind: "
|
|
1497
|
+
categories: ({ state }) => ({
|
|
1498
|
+
kind: "actions",
|
|
1235
1499
|
title: "Pi Sync Settings",
|
|
1236
1500
|
lines: [
|
|
1237
|
-
`
|
|
1501
|
+
`Setup: ${safeTerminalText(state.setupName)} \xB7 Connection: ${safeTerminalText(state.connectionName)}`,
|
|
1502
|
+
"Choose a task, or search all settings. Scope is shown in each setting's description.",
|
|
1503
|
+
saveStatus
|
|
1238
1504
|
],
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
label: "Compare synced content",
|
|
1252
|
-
description: "Review this device and remote content lists before choosing either one.",
|
|
1253
|
-
currentValue: "Review",
|
|
1254
|
-
action: "remote-include"
|
|
1255
|
-
},
|
|
1256
|
-
{
|
|
1257
|
-
id: "localFields",
|
|
1258
|
-
label: "Machine-local settings fields",
|
|
1259
|
-
description: "Root field names omitted from future portable snapshots. Policy changes require directional migration; old history remains.",
|
|
1260
|
-
currentValue: `${state.localFields?.length ?? 0} fields \xB7 Edit`,
|
|
1261
|
-
action: "local-fields"
|
|
1262
|
-
},
|
|
1263
|
-
{
|
|
1264
|
-
id: "storageLocation",
|
|
1265
|
-
label: "Storage location",
|
|
1266
|
-
description: "Destination: edit this setup's bucket, branch, or path; remote history is not moved.",
|
|
1267
|
-
currentValue: state.backend.type === "s3" ? `${safeTerminalText(state.backend.destination.bucket)} \xB7 ${safeTerminalText(state.backend.destination.prefix)}` : state.backend.type === "git" ? `${safeTerminalText(state.backend.destination.branch)} \xB7 ${safeTerminalText(state.backend.destination.directory)}` : safeTerminalText(state.backend.destination.path),
|
|
1268
|
-
action: "storage-location"
|
|
1269
|
-
},
|
|
1270
|
-
{
|
|
1271
|
-
id: "setups",
|
|
1272
|
-
label: "Manage sync setups",
|
|
1273
|
-
description: "Destination: add, switch, edit, or remove sync setups.",
|
|
1274
|
-
currentValue: "Open",
|
|
1275
|
-
action: "setups"
|
|
1276
|
-
},
|
|
1277
|
-
{
|
|
1278
|
-
id: "connections",
|
|
1279
|
-
label: "Manage storage connections",
|
|
1280
|
-
description: "Destination: manage shared server addresses and credentials; edits may affect multiple setups.",
|
|
1281
|
-
currentValue: "Open",
|
|
1282
|
-
action: "connections"
|
|
1283
|
-
},
|
|
1284
|
-
{
|
|
1285
|
-
id: "automatic",
|
|
1286
|
-
label: "Automatic sync",
|
|
1287
|
-
description: AUTOMATIC_SYNC_DESCRIPTION,
|
|
1288
|
-
currentValue: state.automatic ? "On" : "Off",
|
|
1289
|
-
values: ["On", "Off"],
|
|
1290
|
-
action: "automatic"
|
|
1291
|
-
},
|
|
1292
|
-
{
|
|
1293
|
-
id: "automaticTransfer",
|
|
1294
|
-
label: "Automatic transfer at startup",
|
|
1295
|
-
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.",
|
|
1296
|
-
currentValue: state.automaticTransfer ? "On" : "Off",
|
|
1297
|
-
values: ["On", "Off"],
|
|
1298
|
-
action: "automatic-transfer"
|
|
1299
|
-
},
|
|
1300
|
-
{
|
|
1301
|
-
id: "onSwitch",
|
|
1302
|
-
label: "After switching setup (all setups)",
|
|
1303
|
-
description: "All setups: ask before a pull review, open it automatically, or switch without pulling.",
|
|
1304
|
-
currentValue: setupSwitchActionLabel(state.onSwitch),
|
|
1305
|
-
values: SETUP_SWITCH_ACTION_OPTIONS.map(({ label }) => label),
|
|
1306
|
-
action: "on-switch"
|
|
1307
|
-
},
|
|
1308
|
-
{
|
|
1309
|
-
id: "mergeSettings",
|
|
1310
|
-
label: "Settings field merge (experimental)",
|
|
1311
|
-
description: "Combine independent global settings.json fields using a verified private ancestor; arrays and nested objects remain atomic. No reload.",
|
|
1312
|
-
currentValue: state.mergeSettings ? "On" : "Off",
|
|
1313
|
-
values: ["On", "Off"],
|
|
1314
|
-
action: "merge-settings"
|
|
1315
|
-
},
|
|
1316
|
-
{
|
|
1317
|
-
id: "contentPolicy",
|
|
1318
|
-
label: "Content / partial sync (experimental)",
|
|
1319
|
-
description: "Version-5 opt-in: bounded text and prefix-only sessions; partial progress keeps full withheld versions and old baseline hashes.",
|
|
1320
|
-
currentValue: state.mergeContent ? state.partialSync ? "Content & partial" : "Content only" : state.partialSync ? "Partial only" : "Off",
|
|
1321
|
-
values: ["Off", "Content only", "Content & partial", "Partial only"],
|
|
1322
|
-
action: "content-policy"
|
|
1323
|
-
},
|
|
1324
|
-
{
|
|
1325
|
-
id: "skipSecretScan",
|
|
1326
|
-
label: "Skip secret scan (all setups)",
|
|
1327
|
-
description: "All setups: allow pushes without checking managed local files for possible secrets.",
|
|
1328
|
-
currentValue: state.skipSecretScan ? "On" : "Off",
|
|
1329
|
-
values: ["On", "Off"],
|
|
1330
|
-
action: "skip-secret-scan"
|
|
1331
|
-
},
|
|
1332
|
-
{
|
|
1333
|
-
id: "showStatus",
|
|
1334
|
-
label: "Show status (all setups)",
|
|
1335
|
-
description: "All setups: show sync progress and attention in Pi status.",
|
|
1336
|
-
currentValue: state.showStatus ? "On" : "Off",
|
|
1337
|
-
values: ["On", "Off"],
|
|
1338
|
-
action: "show-status"
|
|
1339
|
-
}
|
|
1340
|
-
]
|
|
1341
|
-
})
|
|
1505
|
+
items: Object.entries(groups).map(([id, group]) => ({
|
|
1506
|
+
id,
|
|
1507
|
+
label: group.label,
|
|
1508
|
+
to: id
|
|
1509
|
+
})),
|
|
1510
|
+
hint: "back"
|
|
1511
|
+
}),
|
|
1512
|
+
content: ({ state }) => settingsScreen(state, "content"),
|
|
1513
|
+
behavior: ({ state }) => settingsScreen(state, "behavior"),
|
|
1514
|
+
storage: ({ state }) => settingsScreen(state, "storage"),
|
|
1515
|
+
advanced: ({ state }) => settingsScreen(state, "advanced"),
|
|
1516
|
+
all: ({ state }) => settingsScreen(state, "all")
|
|
1342
1517
|
},
|
|
1343
1518
|
actions: {
|
|
1344
1519
|
"storage-location": async ({ signal: actionSignal }) => {
|
|
@@ -1362,8 +1537,8 @@ async function showSyncSettings(ctx, runRoute, signal) {
|
|
|
1362
1537
|
try {
|
|
1363
1538
|
const previous = await loadConfig(setupName);
|
|
1364
1539
|
validate();
|
|
1365
|
-
const mergeContent = value === "
|
|
1366
|
-
const partialSync = value === "Partial only" || value === "
|
|
1540
|
+
const mergeContent = value === "Merge only" || value === "Merge + partial";
|
|
1541
|
+
const partialSync = value === "Partial only" || value === "Merge + partial";
|
|
1367
1542
|
if (!await ctx.ui.confirm(
|
|
1368
1543
|
"Save experimental content policy?",
|
|
1369
1544
|
"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.",
|
|
@@ -1371,6 +1546,7 @@ async function showSyncSettings(ctx, runRoute, signal) {
|
|
|
1371
1546
|
))
|
|
1372
1547
|
return { kind: "rejected" };
|
|
1373
1548
|
validate();
|
|
1549
|
+
ctx.ui.notify("Saving reviewed Pi Sync policy\u2026", "info");
|
|
1374
1550
|
await updateLocalConfig((current) => {
|
|
1375
1551
|
validate();
|
|
1376
1552
|
const setup = current.syncSetups[setupName];
|
|
@@ -1386,6 +1562,8 @@ async function showSyncSettings(ctx, runRoute, signal) {
|
|
|
1386
1562
|
};
|
|
1387
1563
|
}, mutationSignal);
|
|
1388
1564
|
validate();
|
|
1565
|
+
saveStatus = "Saved reviewed policy for this setup. Applies to subsequent sync operations; recovery evidence is retained.";
|
|
1566
|
+
ctx.ui.notify(saveStatus, "info");
|
|
1389
1567
|
return { kind: "stay" };
|
|
1390
1568
|
} catch (error) {
|
|
1391
1569
|
if (!mutationSignal.aborted) notifySaveFailure(ctx, error);
|
|
@@ -1436,6 +1614,7 @@ async function showSyncSettings(ctx, runRoute, signal) {
|
|
|
1436
1614
|
);
|
|
1437
1615
|
validate();
|
|
1438
1616
|
if (!confirmed) return { kind: "rejected" };
|
|
1617
|
+
ctx.ui.notify("Saving reviewed Pi Sync policy\u2026", "info");
|
|
1439
1618
|
await updateLocalConfig((current) => {
|
|
1440
1619
|
validate();
|
|
1441
1620
|
const setup = current.syncSetups[setupName];
|
|
@@ -1451,6 +1630,8 @@ async function showSyncSettings(ctx, runRoute, signal) {
|
|
|
1451
1630
|
};
|
|
1452
1631
|
}, mutationSignal);
|
|
1453
1632
|
validate();
|
|
1633
|
+
saveStatus = "Saved reviewed policy for this setup. Applies to subsequent sync operations; recovery evidence is retained.";
|
|
1634
|
+
ctx.ui.notify(saveStatus, "info");
|
|
1454
1635
|
return { kind: "stay" };
|
|
1455
1636
|
} catch (error) {
|
|
1456
1637
|
if (!mutationSignal.aborted) notifySaveFailure(ctx, error);
|
|
@@ -1478,6 +1659,56 @@ async function showSyncSettings(ctx, runRoute, signal) {
|
|
|
1478
1659
|
return { kind: "rejected" };
|
|
1479
1660
|
}
|
|
1480
1661
|
},
|
|
1662
|
+
"agent-mode": async ({ value, signal: actionSignal }) => {
|
|
1663
|
+
const mutationSignal = signal ? AbortSignal.any([signal, actionSignal]) : actionSignal;
|
|
1664
|
+
const validate = captureMutationOwner(ctx, mutationSignal);
|
|
1665
|
+
try {
|
|
1666
|
+
const saved = await saveAgentMode(ctx, setupName, value === "On", mutationSignal);
|
|
1667
|
+
if (!saved) return { kind: "rejected" };
|
|
1668
|
+
try {
|
|
1669
|
+
validate();
|
|
1670
|
+
ctx.ui.notify(
|
|
1671
|
+
"Agent mode saved. Applies to subsequent sync and the next session start; no transfer started.",
|
|
1672
|
+
"info"
|
|
1673
|
+
);
|
|
1674
|
+
} catch {
|
|
1675
|
+
}
|
|
1676
|
+
return { kind: "stay" };
|
|
1677
|
+
} catch (error) {
|
|
1678
|
+
try {
|
|
1679
|
+
validate();
|
|
1680
|
+
} catch {
|
|
1681
|
+
return { kind: "rejected" };
|
|
1682
|
+
}
|
|
1683
|
+
notifySaveFailure(ctx, error);
|
|
1684
|
+
return { kind: "rejected" };
|
|
1685
|
+
}
|
|
1686
|
+
},
|
|
1687
|
+
continuous: async ({ value, signal: actionSignal }) => {
|
|
1688
|
+
const mutationSignal = signal ? AbortSignal.any([signal, actionSignal]) : actionSignal;
|
|
1689
|
+
const validate = captureMutationOwner(ctx, mutationSignal);
|
|
1690
|
+
try {
|
|
1691
|
+
const saved = await saveContinuousMode(ctx, setupName, value === "On", mutationSignal);
|
|
1692
|
+
if (!saved) return { kind: "rejected" };
|
|
1693
|
+
try {
|
|
1694
|
+
validate();
|
|
1695
|
+
ctx.ui.notify(
|
|
1696
|
+
value === "On" ? "Continuous sync enabled. Monitoring starts after the /sync command or manager closes; completed work is not undone." : "Continuous sync disabled. Completed work is not undone.",
|
|
1697
|
+
"info"
|
|
1698
|
+
);
|
|
1699
|
+
} catch {
|
|
1700
|
+
}
|
|
1701
|
+
return { kind: "stay" };
|
|
1702
|
+
} catch (error) {
|
|
1703
|
+
try {
|
|
1704
|
+
validate();
|
|
1705
|
+
} catch {
|
|
1706
|
+
return { kind: "rejected" };
|
|
1707
|
+
}
|
|
1708
|
+
notifySaveFailure(ctx, error);
|
|
1709
|
+
return { kind: "rejected" };
|
|
1710
|
+
}
|
|
1711
|
+
},
|
|
1481
1712
|
"automatic-transfer": async ({ value, signal: actionSignal }) => {
|
|
1482
1713
|
const automaticTransfer = value === "On";
|
|
1483
1714
|
const mutationSignal = signal ? AbortSignal.any([signal, actionSignal]) : actionSignal;
|
|
@@ -1529,6 +1760,18 @@ async function showSyncSettings(ctx, runRoute, signal) {
|
|
|
1529
1760
|
return { kind: "rejected" };
|
|
1530
1761
|
}
|
|
1531
1762
|
},
|
|
1763
|
+
debug: async ({ value, signal: actionSignal }) => {
|
|
1764
|
+
const debug = value === "On";
|
|
1765
|
+
const mutationSignal = signal ? AbortSignal.any([signal, actionSignal]) : actionSignal;
|
|
1766
|
+
try {
|
|
1767
|
+
await updateLocalConfig((settings) => ({ ...settings, debug }), mutationSignal);
|
|
1768
|
+
if (mutationSignal.aborted) return { kind: "rejected" };
|
|
1769
|
+
return { kind: "stay" };
|
|
1770
|
+
} catch (error) {
|
|
1771
|
+
if (!mutationSignal.aborted) notifySaveFailure(ctx, error);
|
|
1772
|
+
return { kind: "rejected" };
|
|
1773
|
+
}
|
|
1774
|
+
},
|
|
1532
1775
|
"on-switch": async ({ value, signal: actionSignal }) => {
|
|
1533
1776
|
const action = value ? setupSwitchActionFromLabel(value) : void 0;
|
|
1534
1777
|
if (!action) return { kind: "rejected" };
|
|
@@ -1553,7 +1796,7 @@ async function showSyncSettings(ctx, runRoute, signal) {
|
|
|
1553
1796
|
},
|
|
1554
1797
|
"remote-include": async ({ signal: actionSignal }) => {
|
|
1555
1798
|
const reviewSignal = signal ? AbortSignal.any([signal, actionSignal]) : actionSignal;
|
|
1556
|
-
const { showRemoteSelectionReview } = await import("./remote-selection-ui-
|
|
1799
|
+
const { showRemoteSelectionReview } = await import("./remote-selection-ui-5725JDNC.ts");
|
|
1557
1800
|
if (reviewSignal.aborted) return { kind: "rejected" };
|
|
1558
1801
|
const review = await showRemoteSelectionReview(ctx, setupName, reviewSignal, void 0, {
|
|
1559
1802
|
origin: "settings",
|
|
@@ -1568,6 +1811,28 @@ async function showSyncSettings(ctx, runRoute, signal) {
|
|
|
1568
1811
|
}
|
|
1569
1812
|
}
|
|
1570
1813
|
});
|
|
1814
|
+
for (const id of [
|
|
1815
|
+
"automatic",
|
|
1816
|
+
"automatic-transfer",
|
|
1817
|
+
"merge-settings",
|
|
1818
|
+
"skip-secret-scan",
|
|
1819
|
+
"show-status",
|
|
1820
|
+
"debug",
|
|
1821
|
+
"on-switch"
|
|
1822
|
+
]) {
|
|
1823
|
+
const save = menu.actions[id];
|
|
1824
|
+
menu.actions[id] = async (action) => {
|
|
1825
|
+
const validate = captureMutationOwner(ctx, action.signal);
|
|
1826
|
+
validate();
|
|
1827
|
+
ctx.ui.notify("Saving Pi Sync setting\u2026", "info");
|
|
1828
|
+
const result = await save(action);
|
|
1829
|
+
if (action.signal.aborted || signal?.aborted) return { kind: "rejected" };
|
|
1830
|
+
validate();
|
|
1831
|
+
saveStatus = result?.kind === "rejected" ? "Save failed or rejected. Previous value retained; retry is available." : id === "automatic-transfer" || id === "automatic" || id === "debug" ? "Saved. Enabling startup work applies next session start; completed transfers are not undone." : "Saved. Applies to subsequent operations; status visibility applies immediately.";
|
|
1832
|
+
ctx.ui.notify(saveStatus, result?.kind === "rejected" ? "warning" : "info");
|
|
1833
|
+
return result;
|
|
1834
|
+
};
|
|
1835
|
+
}
|
|
1571
1836
|
async function resumeSettings(editorSignal) {
|
|
1572
1837
|
if (editorSignal.aborted) return { kind: "close" };
|
|
1573
1838
|
try {
|
|
@@ -1578,7 +1843,7 @@ async function showSyncSettings(ctx, runRoute, signal) {
|
|
|
1578
1843
|
return { kind: "close" };
|
|
1579
1844
|
}
|
|
1580
1845
|
}
|
|
1581
|
-
await runMenu4(ctx, menu, {
|
|
1846
|
+
await runMenu4({ ...ctx, ui: boundedSettingsUI(ctx) }, menu, {
|
|
1582
1847
|
getState: () => loadConfig(setupName),
|
|
1583
1848
|
signal,
|
|
1584
1849
|
isCurrent: () => !signal?.aborted
|
|
@@ -1626,7 +1891,7 @@ async function showSyncManager(ctx, runRoute, sessionSignal, options = {}) {
|
|
|
1626
1891
|
if (!attention) {
|
|
1627
1892
|
const observation = options.getObservation?.();
|
|
1628
1893
|
if (!observation) return { kind: "stay" };
|
|
1629
|
-
const { showRemoteSelectionReview } = await import("./remote-selection-ui-
|
|
1894
|
+
const { showRemoteSelectionReview } = await import("./remote-selection-ui-5725JDNC.ts");
|
|
1630
1895
|
if (sessionSignal?.aborted) return { kind: "close" };
|
|
1631
1896
|
const config = await loadConfig();
|
|
1632
1897
|
if (sessionSignal?.aborted) return { kind: "close" };
|
|
@@ -1717,12 +1982,45 @@ async function showSyncManager(ctx, runRoute, sessionSignal, options = {}) {
|
|
|
1717
1982
|
});
|
|
1718
1983
|
return { kind: result.kind === "closed" ? "close" : "stay" };
|
|
1719
1984
|
},
|
|
1720
|
-
|
|
1721
|
-
const result = await runCancellableOperation(ctx, "
|
|
1985
|
+
diff: async () => {
|
|
1986
|
+
const result = await runCancellableOperation(ctx, "Comparing local and remote\u2026", "diff", runRoute, {
|
|
1987
|
+
signal: sessionSignal
|
|
1988
|
+
});
|
|
1989
|
+
return { kind: result.kind === "closed" ? "close" : "stay" };
|
|
1990
|
+
},
|
|
1991
|
+
status: async () => {
|
|
1992
|
+
const result = await runCancellableOperation(ctx, "Checking remote status\u2026", "status", runRoute, {
|
|
1722
1993
|
signal: sessionSignal
|
|
1723
1994
|
});
|
|
1724
1995
|
return { kind: result.kind === "closed" ? "close" : "stay" };
|
|
1725
1996
|
},
|
|
1997
|
+
doctor: async ({ signal: actionSignal }) => {
|
|
1998
|
+
const signal = sessionSignal ? AbortSignal.any([sessionSignal, actionSignal]) : actionSignal;
|
|
1999
|
+
const validate = captureMutationOwner(ctx, signal);
|
|
2000
|
+
const config = await loadConfig();
|
|
2001
|
+
validate();
|
|
2002
|
+
const confirmed = await ctx.ui.confirm(
|
|
2003
|
+
"Run diagnostics?",
|
|
2004
|
+
`Setup: ${safeTerminalText(config.setupName)}
|
|
2005
|
+
Storage: ${backendStorageDescription(config)}
|
|
2006
|
+
S3/R2 reads the latest pointer without writing. Git reads remote snapshots and checks its cache. WebDAV probes conditional writes and cleanup, and can repair a missing history entry. Possible-secret checks still run. This is not the read-only Check remote status action.`,
|
|
2007
|
+
{ signal }
|
|
2008
|
+
);
|
|
2009
|
+
if (signal.aborted) return { kind: "close" };
|
|
2010
|
+
validate();
|
|
2011
|
+
if (!confirmed) return { kind: "stay" };
|
|
2012
|
+
const latest = await loadConfig();
|
|
2013
|
+
validate();
|
|
2014
|
+
if (syncCheckConfigFingerprint(config) !== syncCheckConfigFingerprint(latest)) {
|
|
2015
|
+
ctx.ui.notify("Setup changed during diagnostics review; reopen Diagnostics.", "warning");
|
|
2016
|
+
return { kind: "stay" };
|
|
2017
|
+
}
|
|
2018
|
+
const result = await runCancellableOperation(ctx, "Checking setup access\u2026", "doctor", runRoute, {
|
|
2019
|
+
signal,
|
|
2020
|
+
target: config.setupName
|
|
2021
|
+
});
|
|
2022
|
+
return { kind: result.kind === "closed" ? "close" : "stay" };
|
|
2023
|
+
},
|
|
1726
2024
|
recover: async ({ state, signal: actionSignal }) => {
|
|
1727
2025
|
const result = await recoverSyncAccess(ctx, state.manager, runRoute, sessionSignal, actionSignal);
|
|
1728
2026
|
return { kind: result === "close" ? "close" : "stay" };
|
|
@@ -1769,6 +2067,8 @@ function syncMainMenuItem(label) {
|
|
|
1769
2067
|
"Sync now": "sync",
|
|
1770
2068
|
"Pull from remote\u2026": "pull",
|
|
1771
2069
|
"Push to remote\u2026": "push",
|
|
2070
|
+
"View differences": "diff",
|
|
2071
|
+
"Check remote status": "status",
|
|
1772
2072
|
"Switch sync setup": "switch",
|
|
1773
2073
|
Settings: "settings",
|
|
1774
2074
|
History: "history",
|
|
@@ -1788,10 +2088,10 @@ function syncMainMenuItem(label) {
|
|
|
1788
2088
|
id: action,
|
|
1789
2089
|
label,
|
|
1790
2090
|
action,
|
|
1791
|
-
|
|
2091
|
+
description: action === "doctor" ? "Manage: review backend checks before running." : action === "settings" || action === "history" || action === "switch" ? "Manage" : action === "sync" ? "Transfer: choose a safe direction or review conflicts." : action === "pull" ? "Transfer: remote \u2192 local; review writes and removals." : action === "push" ? "Transfer: local \u2192 remote active snapshot; review publication." : action === "status" || action === "diff" ? "Inspect: read current local and remote state without transferring files." : void 0
|
|
1792
2092
|
};
|
|
1793
2093
|
}
|
|
1794
2094
|
export {
|
|
1795
2095
|
showSyncManager
|
|
1796
2096
|
};
|
|
1797
|
-
//# sourceMappingURL=manager-ui-
|
|
2097
|
+
//# sourceMappingURL=manager-ui-KRAW3NE2.ts.map
|