@narumitw/pi-sync 0.49.14 → 0.49.15

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.
Files changed (56) hide show
  1. package/README.md +98 -238
  2. package/dist/chunks/{chunk-LONPFFNP.ts → chunk-44LPGQTI.ts} +4 -4
  3. package/dist/chunks/{chunk-FR6CVXAL.ts → chunk-5LZALPCD.ts} +4 -4
  4. package/dist/chunks/{chunk-APZVBSM6.ts → chunk-5T442OP3.ts} +18 -6
  5. package/dist/chunks/chunk-5T442OP3.ts.map +7 -0
  6. package/dist/chunks/{chunk-5WJNWFTG.ts → chunk-ARN2672F.ts} +5 -5
  7. package/dist/chunks/{chunk-W64NEHXT.ts → chunk-C7LXZ3UH.ts} +3 -3
  8. package/dist/chunks/{chunk-4F3W4CSC.ts → chunk-DFXBKHGN.ts} +3 -2
  9. package/dist/chunks/chunk-DFXBKHGN.ts.map +7 -0
  10. package/dist/chunks/{chunk-JNOOSPEW.ts → chunk-E4COSV32.ts} +3 -3
  11. package/dist/chunks/{chunk-BHJUISB4.ts → chunk-GLQLN5GV.ts} +3 -3
  12. package/dist/chunks/{chunk-EWX3TPLQ.ts → chunk-HVUSHMVL.ts} +2 -2
  13. package/dist/chunks/{chunk-RGJ6SOYR.ts → chunk-JF6MZCT4.ts} +2 -2
  14. package/dist/chunks/{chunk-LJDSHNS3.ts → chunk-WSOBYHIZ.ts} +2 -2
  15. package/dist/chunks/{chunk-3NDD5QPM.ts → chunk-X7SQ2EQM.ts} +4 -4
  16. package/dist/chunks/{file-selection-4UABOP44.ts → file-selection-RKEHALNQ.ts} +3 -3
  17. package/dist/chunks/manager-result-dispatcher-LWPYJAD5.ts +18 -0
  18. package/dist/chunks/{manager-ui-QO2P4V3Z.ts → manager-ui-NF4RUHBY.ts} +42 -14
  19. package/dist/chunks/manager-ui-NF4RUHBY.ts.map +7 -0
  20. package/dist/chunks/{remote-selection-ui-LHSAGKGA.ts → remote-selection-ui-NUF5P4ZJ.ts} +8 -8
  21. package/dist/chunks/{s3-backend-3QZGO2EF.ts → s3-backend-552LXHE4.ts} +2 -2
  22. package/dist/chunks/{setup-switch-X3W3FALZ.ts → setup-switch-5YDG5YGJ.ts} +6 -6
  23. package/dist/chunks/{snapshot-WBSV4MQG.ts → snapshot-2RYBUDRA.ts} +3 -3
  24. package/dist/chunks/{sync-operations-MPAFVVHA.ts → sync-operations-3LLIHWZO.ts} +15 -13
  25. package/dist/chunks/sync-operations-3LLIHWZO.ts.map +7 -0
  26. package/dist/chunks/{sync-state-36H7ULG2.ts → sync-state-SRN6YRBK.ts} +4 -4
  27. package/dist/index.ts +15 -15
  28. package/docs/settings.md +187 -0
  29. package/package.json +6 -8
  30. package/src/config.ts +16 -3
  31. package/src/settings-management.ts +1 -0
  32. package/src/settings-ui.ts +29 -2
  33. package/src/sync-operations.ts +7 -5
  34. package/src/types.ts +2 -0
  35. package/dist/chunks/chunk-4F3W4CSC.ts.map +0 -7
  36. package/dist/chunks/chunk-APZVBSM6.ts.map +0 -7
  37. package/dist/chunks/manager-result-dispatcher-RNRQA3PW.ts +0 -18
  38. package/dist/chunks/manager-ui-QO2P4V3Z.ts.map +0 -7
  39. package/dist/chunks/sync-operations-MPAFVVHA.ts.map +0 -7
  40. /package/dist/chunks/{chunk-LONPFFNP.ts.map → chunk-44LPGQTI.ts.map} +0 -0
  41. /package/dist/chunks/{chunk-FR6CVXAL.ts.map → chunk-5LZALPCD.ts.map} +0 -0
  42. /package/dist/chunks/{chunk-5WJNWFTG.ts.map → chunk-ARN2672F.ts.map} +0 -0
  43. /package/dist/chunks/{chunk-W64NEHXT.ts.map → chunk-C7LXZ3UH.ts.map} +0 -0
  44. /package/dist/chunks/{chunk-JNOOSPEW.ts.map → chunk-E4COSV32.ts.map} +0 -0
  45. /package/dist/chunks/{chunk-BHJUISB4.ts.map → chunk-GLQLN5GV.ts.map} +0 -0
  46. /package/dist/chunks/{chunk-EWX3TPLQ.ts.map → chunk-HVUSHMVL.ts.map} +0 -0
  47. /package/dist/chunks/{chunk-RGJ6SOYR.ts.map → chunk-JF6MZCT4.ts.map} +0 -0
  48. /package/dist/chunks/{chunk-LJDSHNS3.ts.map → chunk-WSOBYHIZ.ts.map} +0 -0
  49. /package/dist/chunks/{chunk-3NDD5QPM.ts.map → chunk-X7SQ2EQM.ts.map} +0 -0
  50. /package/dist/chunks/{file-selection-4UABOP44.ts.map → file-selection-RKEHALNQ.ts.map} +0 -0
  51. /package/dist/chunks/{manager-result-dispatcher-RNRQA3PW.ts.map → manager-result-dispatcher-LWPYJAD5.ts.map} +0 -0
  52. /package/dist/chunks/{remote-selection-ui-LHSAGKGA.ts.map → remote-selection-ui-NUF5P4ZJ.ts.map} +0 -0
  53. /package/dist/chunks/{s3-backend-3QZGO2EF.ts.map → s3-backend-552LXHE4.ts.map} +0 -0
  54. /package/dist/chunks/{setup-switch-X3W3FALZ.ts.map → setup-switch-5YDG5YGJ.ts.map} +0 -0
  55. /package/dist/chunks/{snapshot-WBSV4MQG.ts.map → snapshot-2RYBUDRA.ts.map} +0 -0
  56. /package/dist/chunks/{sync-state-36H7ULG2.ts.map → sync-state-SRN6YRBK.ts.map} +0 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/config-file.ts", "../../src/config.ts", "../../src/webdav-config.ts", "../../src/config-errors.ts"],
4
+ "sourcesContent": ["import { randomUUID } from \"node:crypto\";\nimport {\n\tmkdir,\n\tmkdirSync,\n\trealpath,\n\trealpathSync,\n\trmdir,\n\trmdirSync,\n\tstat,\n\tstatSync,\n\tutimes,\n\tutimesSync,\n} from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { getAgentDir } from \"@earendil-works/pi-coding-agent\";\nimport lockfile from \"proper-lockfile\";\n\nconst CONFIG_FILE_NAME = \"pi-sync.json\";\nconst LEGACY_CONFIG_FILE_NAME = \"pi-sync.local.json\";\nconst configMigrationNotices = new Map<string, string>();\nconst legacyPresenceNoticed = new Set<string>();\nconst CONFIG_LOCK_STALE_MS = 30_000;\nconst CONFIG_LOCK_UPDATE_MS = 10_000;\nconst LOCKFILE_FS_ADAPTER = {\n\tmkdir,\n\tmkdirSync,\n\trealpath,\n\trealpathSync,\n\trmdir,\n\trmdirSync,\n\tstat,\n\tstatSync,\n\tutimes,\n\tutimesSync,\n};\n\ntype PublishFile = (source: string, destination: string) => Promise<void>;\nlet publishConfigFile: PublishFile = publishFileWithoutReplacement;\nlet beforeConfigPublicationHook: () => Promise<void> = async () => undefined;\nlet afterMissingConfigReadProbeHook: () => Promise<void> = async () => undefined;\nlet afterReplacementInstalledHook: () => Promise<void> = async () => undefined;\nlet afterConfigQuarantinedHook: () => Promise<void> = async () => undefined;\n\nexport type FileIdentity = { dev: number; ino: number };\n\nexport async function withConfigFilePublicationForTest<T>(\n\tpublish: PublishFile,\n\trun: () => Promise<T>,\n): Promise<T> {\n\tconst previous = publishConfigFile;\n\tpublishConfigFile = publish;\n\ttry {\n\t\treturn await run();\n\t} finally {\n\t\tpublishConfigFile = previous;\n\t}\n}\n\nexport async function withConfigPublicationReadyHookForTest<T>(\n\thook: () => Promise<void>,\n\trun: () => Promise<T>,\n): Promise<T> {\n\tconst previous = beforeConfigPublicationHook;\n\tbeforeConfigPublicationHook = hook;\n\ttry {\n\t\treturn await run();\n\t} finally {\n\t\tbeforeConfigPublicationHook = previous;\n\t}\n}\n\nexport async function withMissingConfigReadProbeHookForTest<T>(\n\thook: () => Promise<void>,\n\trun: () => Promise<T>,\n): Promise<T> {\n\tconst previous = afterMissingConfigReadProbeHook;\n\tafterMissingConfigReadProbeHook = hook;\n\ttry {\n\t\treturn await run();\n\t} finally {\n\t\tafterMissingConfigReadProbeHook = previous;\n\t}\n}\n\nexport async function withConfigReplacementInstalledHookForTest<T>(\n\thook: () => Promise<void>,\n\trun: () => Promise<T>,\n): Promise<T> {\n\tconst previous = afterReplacementInstalledHook;\n\tafterReplacementInstalledHook = hook;\n\ttry {\n\t\treturn await run();\n\t} finally {\n\t\tafterReplacementInstalledHook = previous;\n\t}\n}\n\nexport async function withConfigQuarantinedHookForTest<T>(\n\thook: () => Promise<void>,\n\trun: () => Promise<T>,\n): Promise<T> {\n\tconst previous = afterConfigQuarantinedHook;\n\tafterConfigQuarantinedHook = hook;\n\ttry {\n\t\treturn await run();\n\t} finally {\n\t\tafterConfigQuarantinedHook = previous;\n\t}\n}\n\ntype ConfigSnapshot = {\n\tbytes: Buffer;\n\tidentity: FileIdentity;\n\tparsed: Record<string, unknown>;\n};\n\nexport type LocalConfigDocument = ConfigSnapshot & { path: string };\n\nexport function localConfigPath() {\n\treturn path.join(getAgentDir(), CONFIG_FILE_NAME);\n}\n\nexport function legacyLocalConfigPath() {\n\treturn path.join(getAgentDir(), LEGACY_CONFIG_FILE_NAME);\n}\n\nexport async function activeLocalConfigPath() {\n\tconst canonicalPath = localConfigPath();\n\tconst legacyPath = legacyLocalConfigPath();\n\treturn withLocalConfigReadLockIfNeeded(async () => {\n\t\tif (await pathExists(canonicalPath)) return canonicalPath;\n\t\treturn (await pathExists(legacyPath)) ? legacyPath : canonicalPath;\n\t});\n}\n\nexport function consumeLocalConfigMigrationNotice() {\n\tconst configPath = localConfigPath();\n\tconst notice = configMigrationNotices.get(configPath);\n\tconfigMigrationNotices.delete(configPath);\n\treturn notice;\n}\n\nexport async function readActiveLocalConfigDocumentForRepair(): Promise<\n\tLocalConfigDocument | undefined\n> {\n\tconst canonicalPath = localConfigPath();\n\tconst legacyPath = legacyLocalConfigPath();\n\treturn withLocalConfigReadLockIfNeeded(async () => {\n\t\tconst filePath = (await pathExists(canonicalPath)) ? canonicalPath : legacyPath;\n\t\tconst snapshot = await readConfigSnapshotIfExists(filePath);\n\t\treturn snapshot ? { path: filePath, ...snapshot } : undefined;\n\t});\n}\n\nexport async function readMigratingLocalConfigDocument(\n\tvalidateForMigration: (settings: Record<string, unknown>) => void,\n): Promise<LocalConfigDocument | undefined> {\n\treturn withLocalConfigReadLockIfNeeded(async () => {\n\t\tconst configPath = await prepareLocalConfigPath(validateForMigration);\n\t\tconst snapshot = await readConfigSnapshotIfExists(configPath);\n\t\treturn snapshot ? { path: configPath, ...snapshot } : undefined;\n\t});\n}\n\nasync function withLocalConfigReadLockIfNeeded<T>(read: () => Promise<T>): Promise<T> {\n\tif ((await pathExists(localConfigPath())) || (await pathExists(legacyLocalConfigPath()))) {\n\t\treturn withLocalConfigFileLock(read);\n\t}\n\tawait afterMissingConfigReadProbeHook();\n\tif (await pathExists(configMutationLockPath())) return withLocalConfigFileLock(read);\n\treturn read();\n}\n\nexport function updateLocalConfigDocument<T extends Record<string, unknown>>(\n\tdefaultValue: T,\n\tupdate: (current: T) => T,\n\tvalidate: (value: Record<string, unknown>) => void,\n\tsignal?: AbortSignal,\n): Promise<T> {\n\treturn withLocalConfigFileLock(async () => {\n\t\tsignal?.throwIfAborted();\n\t\tconst configPath = await prepareLocalConfigPath(validate);\n\t\tconst snapshot = await readConfigSnapshotIfExists(configPath);\n\t\tconst document = snapshot ? { path: configPath, ...snapshot } : undefined;\n\t\tconst current = document\n\t\t\t? (structuredClone(document.parsed) as T)\n\t\t\t: structuredClone(defaultValue);\n\t\tconst next = update(current);\n\t\tvalidate(next);\n\t\tsignal?.throwIfAborted();\n\t\tif (document && JSON.stringify(document.parsed) === JSON.stringify(next)) return next;\n\t\tif (document) await replaceLocalConfigDocumentUnlocked(document, next);\n\t\telse await installPrivateConfigExclusively(localConfigPath(), serializedConfig(next));\n\t\treturn next;\n\t});\n}\n\nexport function createLocalConfigDocument(value: Record<string, unknown>) {\n\treturn withLocalConfigFileLock(async () => {\n\t\tconst bytes = serializedConfig(value);\n\t\ttry {\n\t\t\tawait installPrivateConfigExclusively(localConfigPath(), bytes);\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"EEXIST\") {\n\t\t\t\tthrow new Error(\"Pi-sync settings were created concurrently; reopen settings and retry.\");\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t});\n}\n\nexport function replaceLocalConfigDocument(\n\tdocument: LocalConfigDocument,\n\tvalue: Record<string, unknown>,\n) {\n\treturn withLocalConfigFileLock(() => replaceLocalConfigDocumentUnlocked(document, value));\n}\n\nasync function replaceLocalConfigDocumentUnlocked(\n\tdocument: LocalConfigDocument,\n\tvalue: Record<string, unknown>,\n) {\n\tconst nextBytes = serializedConfig(value);\n\tconst canonicalPath = localConfigPath();\n\tif (document.path !== canonicalPath) {\n\t\tif (!(await configDocumentStillMatches(document))) throw settingsChangedError();\n\t\tlet installed: FileIdentity;\n\t\ttry {\n\t\t\tinstalled = await installPrivateConfigExclusively(canonicalPath, nextBytes);\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"EEXIST\") {\n\t\t\t\tthrow new Error(\"Canonical settings were created concurrently; no settings were replaced.\");\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tif (!(await configDocumentStillMatches(document))) {\n\t\t\tawait quarantineAndRemoveConfigIfMatchesUnlocked(canonicalPath, installed, nextBytes);\n\t\t\tthrow settingsChangedError();\n\t\t}\n\t\treturn;\n\t}\n\n\tconst quarantinePath = await claimCanonicalConfigDocument(document);\n\tlet installed: FileIdentity;\n\ttry {\n\t\tinstalled = await installPrivateConfigExclusively(canonicalPath, nextBytes);\n\t} catch (error) {\n\t\tawait restoreQuarantinedConfig(canonicalPath, quarantinePath);\n\t\tif ((error as NodeJS.ErrnoException).code === \"EEXIST\") {\n\t\t\tthrow new Error(\"Canonical settings changed concurrently; no settings were replaced.\");\n\t\t}\n\t\tthrow error;\n\t}\n\ttry {\n\t\tawait afterReplacementInstalledHook();\n\t\tif (!(await fileIdentityAndContentsMatch(quarantinePath, document.identity, document.bytes))) {\n\t\t\tthrow settingsChangedError();\n\t\t}\n\t\tif (process.platform !== \"win32\") await fs.chmod(quarantinePath, 0o600);\n\t} catch (error) {\n\t\tawait quarantineAndRemoveConfigIfMatchesUnlocked(canonicalPath, installed, nextBytes);\n\t\tawait restoreQuarantinedConfig(canonicalPath, quarantinePath);\n\t\tthrow error;\n\t}\n\tawait fs.rm(quarantinePath).catch(() => undefined);\n\tawait syncParentDirectory(canonicalPath).catch(() => undefined);\n}\n\nasync function prepareLocalConfigPath(\n\tvalidateForMigration: (settings: Record<string, unknown>) => void,\n) {\n\tconst canonicalPath = localConfigPath();\n\tconst legacyPath = legacyLocalConfigPath();\n\tif (await pathExists(canonicalPath)) {\n\t\tconst legacyStatus = await secureIgnoredLegacyIfPresent(legacyPath);\n\t\tif (legacyStatus !== \"missing\" && !legacyPresenceNoticed.has(canonicalPath)) {\n\t\t\tlegacyPresenceNoticed.add(canonicalPath);\n\t\t\trecordConfigMigrationNotice(\n\t\t\t\tcanonicalPath,\n\t\t\t\tlegacyStatus === \"private\"\n\t\t\t\t\t? `${LEGACY_CONFIG_FILE_NAME} legacy settings were ignored because ${CONFIG_FILE_NAME} takes precedence. Delete ${LEGACY_CONFIG_FILE_NAME} after confirming your settings.`\n\t\t\t\t\t: `${LEGACY_CONFIG_FILE_NAME} legacy settings were ignored because ${CONFIG_FILE_NAME} takes precedence, but pi-sync could not verify them as a private regular file. Secure or delete the legacy path after confirming your settings.`,\n\t\t\t);\n\t\t}\n\t\treturn canonicalPath;\n\t}\n\n\tconst legacy = await readConfigSnapshotIfExists(legacyPath);\n\tif (!legacy) return canonicalPath;\n\tvalidateForMigration(legacy.parsed);\n\n\tlet installedIdentity: FileIdentity;\n\ttry {\n\t\tinstalledIdentity = await installPrivateConfigExclusively(canonicalPath, legacy.bytes);\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"EEXIST\") {\n\t\t\trecordConfigMigrationNotice(\n\t\t\t\tcanonicalPath,\n\t\t\t\t`${LEGACY_CONFIG_FILE_NAME} legacy settings were ignored because ${CONFIG_FILE_NAME} was created concurrently and takes precedence.`,\n\t\t\t);\n\t\t\treturn canonicalPath;\n\t\t}\n\t\trecordConfigMigrationNotice(\n\t\t\tcanonicalPath,\n\t\t\t`Could not migrate ${LEGACY_CONFIG_FILE_NAME} to ${CONFIG_FILE_NAME}; the legacy settings were used for this session and were not changed.`,\n\t\t);\n\t\treturn legacyPath;\n\t}\n\n\tif (!(await configSnapshotStillMatches(legacyPath, legacy))) {\n\t\tconst removed = await quarantineAndRemoveConfigIfMatchesUnlocked(\n\t\t\tcanonicalPath,\n\t\t\tinstalledIdentity,\n\t\t\tlegacy.bytes,\n\t\t);\n\t\trecordConfigMigrationNotice(\n\t\t\tcanonicalPath,\n\t\t\tremoved\n\t\t\t\t? `${LEGACY_CONFIG_FILE_NAME} changed during migration; the stale ${CONFIG_FILE_NAME} copy was removed and the legacy settings were used for this session.`\n\t\t\t\t: `${LEGACY_CONFIG_FILE_NAME} changed during migration, but ${CONFIG_FILE_NAME} was replaced concurrently and takes precedence.`,\n\t\t);\n\t\treturn removed ? legacyPath : canonicalPath;\n\t}\n\n\tlegacyPresenceNoticed.add(canonicalPath);\n\trecordConfigMigrationNotice(\n\t\tcanonicalPath,\n\t\t`pi-sync settings migrated from ${LEGACY_CONFIG_FILE_NAME} to ${CONFIG_FILE_NAME}; the private legacy file was retained as a recovery copy and can be deleted after verification.`,\n\t);\n\treturn canonicalPath;\n}\n\nasync function secureIgnoredLegacyIfPresent(filePath: string) {\n\tlet pathStat: Awaited<ReturnType<typeof fs.lstat>>;\n\ttry {\n\t\tpathStat = await fs.lstat(filePath);\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return \"missing\" as const;\n\t\treturn \"unsafe\" as const;\n\t}\n\tif (pathStat.isSymbolicLink() || !pathStat.isFile()) return \"unsafe\" as const;\n\n\tlet handle: fs.FileHandle | undefined;\n\ttry {\n\t\thandle = await fs.open(filePath, \"r\");\n\t\tconst openedStat = await handle.stat();\n\t\tif (openedStat.dev !== pathStat.dev || openedStat.ino !== pathStat.ino) {\n\t\t\treturn \"unsafe\" as const;\n\t\t}\n\t\tif (process.platform !== \"win32\" && (openedStat.mode & 0o777) !== 0o600) {\n\t\t\tawait handle.chmod(0o600);\n\t\t}\n\t\treturn \"private\" as const;\n\t} catch {\n\t\treturn \"unsafe\" as const;\n\t} finally {\n\t\tawait handle?.close().catch(() => undefined);\n\t}\n}\n\nasync function readConfigSnapshotIfExists(filePath: string): Promise<ConfigSnapshot | undefined> {\n\tlet pathStat: Awaited<ReturnType<typeof fs.lstat>>;\n\ttry {\n\t\tpathStat = await fs.lstat(filePath);\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n\t\tthrow error;\n\t}\n\tif (pathStat.isSymbolicLink()) {\n\t\tthrow new Error(`Refusing to read symlinked pi-sync config: ${filePath}`);\n\t}\n\tif (!pathStat.isFile()) throw new Error(`pi-sync config is not a regular file: ${filePath}`);\n\n\tconst handle = await fs.open(filePath, \"r\");\n\ttry {\n\t\tconst openedStat = await handle.stat();\n\t\tif (openedStat.dev !== pathStat.dev || openedStat.ino !== pathStat.ino) {\n\t\t\tthrow new Error(`pi-sync config changed while opening: ${filePath}`);\n\t\t}\n\t\tif (process.platform !== \"win32\" && (openedStat.mode & 0o777) !== 0o600) {\n\t\t\tawait handle.chmod(0o600);\n\t\t}\n\t\tconst bytes = await handle.readFile();\n\t\treturn {\n\t\t\tbytes,\n\t\t\tidentity: { dev: openedStat.dev, ino: openedStat.ino },\n\t\t\tparsed: parseConfigObject(bytes, filePath),\n\t\t};\n\t} finally {\n\t\tawait handle.close();\n\t}\n}\n\nfunction serializedConfig(value: Record<string, unknown>) {\n\treturn Buffer.from(`${JSON.stringify(value, null, \"\\t\")}\\n`, \"utf8\");\n}\n\nfunction parseConfigObject(bytes: Buffer, filePath: string) {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(bytes.toString(\"utf8\"));\n\t} catch {\n\t\tthrow new SyntaxError(`Invalid JSON in pi-sync config: ${filePath}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`pi-sync config must contain a JSON object: ${filePath}`);\n\t}\n\treturn parsed as Record<string, unknown>;\n}\n\nasync function installPrivateConfigExclusively(filePath: string, bytes: Buffer) {\n\tawait fs.mkdir(path.dirname(filePath), { recursive: true });\n\tconst temporaryPath = path.join(\n\t\tpath.dirname(filePath),\n\t\t`.${path.basename(filePath)}.${process.pid}.${randomUUID()}.migrate`,\n\t);\n\tlet handle: fs.FileHandle | undefined;\n\ttry {\n\t\thandle = await fs.open(temporaryPath, \"wx\", 0o600);\n\t\tawait handle.writeFile(bytes);\n\t\tif (process.platform !== \"win32\") await handle.chmod(0o600);\n\t\tawait handle.sync();\n\t\tawait handle.close();\n\t\thandle = undefined;\n\t\tawait publishConfigFile(temporaryPath, filePath);\n\t\tconst installed = await fs.lstat(filePath);\n\t\tlet publishedHandle: fs.FileHandle | undefined;\n\t\tlet publicationError: unknown;\n\t\ttry {\n\t\t\tif (installed.isSymbolicLink() || !installed.isFile()) {\n\t\t\t\tthrow new Error(`Published pi-sync settings are not a regular file: ${filePath}`);\n\t\t\t}\n\t\t\tpublishedHandle = await fs.open(filePath, \"r+\");\n\t\t\tconst published = await publishedHandle.stat();\n\t\t\tif (published.dev !== installed.dev || published.ino !== installed.ino) {\n\t\t\t\tthrow new Error(`Published pi-sync settings changed while opening: ${filePath}`);\n\t\t\t}\n\t\t\tif (process.platform !== \"win32\") await publishedHandle.chmod(0o600);\n\t\t\tawait publishedHandle.sync();\n\t\t\tawait syncParentDirectory(filePath);\n\t\t} catch (error) {\n\t\t\tpublicationError = error;\n\t\t} finally {\n\t\t\tawait publishedHandle?.close().catch(() => undefined);\n\t\t}\n\t\tif (publicationError) {\n\t\t\tawait quarantineAndRemoveConfigIfMatchesUnlocked(\n\t\t\t\tfilePath,\n\t\t\t\t{ dev: installed.dev, ino: installed.ino },\n\t\t\t\tbytes,\n\t\t\t);\n\t\t\tthrow publicationError;\n\t\t}\n\t\treturn { dev: installed.dev, ino: installed.ino };\n\t} finally {\n\t\tawait handle?.close().catch(() => undefined);\n\t\tawait fs.rm(temporaryPath, { force: true }).catch(() => undefined);\n\t}\n}\n\nasync function configDocumentStillMatches(document: LocalConfigDocument) {\n\treturn fileIdentityAndContentsMatch(document.path, document.identity, document.bytes);\n}\n\nasync function claimCanonicalConfigDocument(document: LocalConfigDocument) {\n\tconst quarantinePath = path.join(\n\t\tpath.dirname(document.path),\n\t\t`.${path.basename(document.path)}.${randomUUID()}.schema-migration-source`,\n\t);\n\ttry {\n\t\tawait fs.rename(document.path, quarantinePath);\n\t\tawait syncParentDirectory(document.path);\n\t} catch (error) {\n\t\tawait restoreQuarantinedConfig(document.path, quarantinePath);\n\t\tthrow error;\n\t}\n\tif (!(await fileIdentityAndContentsMatch(quarantinePath, document.identity, document.bytes))) {\n\t\tawait restoreQuarantinedConfig(document.path, quarantinePath);\n\t\tthrow settingsChangedError();\n\t}\n\tif (await pathExists(document.path)) {\n\t\tawait restoreQuarantinedConfig(document.path, quarantinePath);\n\t\tthrow new Error(\"Canonical settings changed concurrently; no settings were replaced.\");\n\t}\n\treturn quarantinePath;\n}\n\nfunction settingsChangedError() {\n\treturn new Error(\"pi-sync settings changed during migration; no settings were replaced.\");\n}\n\nasync function configSnapshotStillMatches(filePath: string, snapshot: ConfigSnapshot) {\n\treturn fileIdentityAndContentsMatch(filePath, snapshot.identity, snapshot.bytes);\n}\n\nexport function quarantineAndRemoveConfigIfMatches(\n\tfilePath: string,\n\tidentity: FileIdentity,\n\texpectedBytes: Buffer,\n) {\n\treturn withLocalConfigFileLock(() =>\n\t\tquarantineAndRemoveConfigIfMatchesUnlocked(filePath, identity, expectedBytes),\n\t);\n}\n\nasync function quarantineAndRemoveConfigIfMatchesUnlocked(\n\tfilePath: string,\n\tidentity: FileIdentity,\n\texpectedBytes: Buffer,\n) {\n\tconst quarantinePath = path.join(\n\t\tpath.dirname(filePath),\n\t\t`.${path.basename(filePath)}.${randomUUID()}.migration-retired`,\n\t);\n\ttry {\n\t\tawait fs.rename(filePath, quarantinePath);\n\t} catch {\n\t\treturn false;\n\t}\n\tawait afterConfigQuarantinedHook();\n\ttry {\n\t\tawait syncParentDirectory(filePath);\n\t} catch {\n\t\tawait restoreQuarantinedConfig(filePath, quarantinePath);\n\t\treturn false;\n\t}\n\n\tconst matches = await fileIdentityAndContentsMatch(quarantinePath, identity, expectedBytes);\n\tif (!matches) {\n\t\tawait restoreQuarantinedConfig(filePath, quarantinePath);\n\t\treturn false;\n\t}\n\tif (await pathExists(filePath)) {\n\t\tawait fs.rm(quarantinePath, { force: true });\n\t\tawait syncParentDirectory(filePath);\n\t\treturn false;\n\t}\n\tawait fs.rm(quarantinePath);\n\tawait syncParentDirectory(filePath);\n\treturn true;\n}\n\nasync function fileIdentityAndContentsMatch(\n\tfilePath: string,\n\tidentity: FileIdentity,\n\texpectedBytes: Buffer,\n) {\n\ttry {\n\t\tconst current = await fs.lstat(filePath);\n\t\tif (current.isSymbolicLink()) return false;\n\t\tif (current.dev !== identity.dev || current.ino !== identity.ino) return false;\n\t\treturn (await fs.readFile(filePath)).equals(expectedBytes);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function restoreQuarantinedConfig(filePath: string, quarantinePath: string) {\n\ttry {\n\t\tawait renameFileWithoutReplacement(quarantinePath, filePath);\n\t\tif (process.platform !== \"win32\") await fs.chmod(filePath, 0o600);\n\t\tawait syncParentDirectory(filePath);\n\t\treturn;\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code !== \"EEXIST\") return;\n\t}\n\ttry {\n\t\tif (process.platform !== \"win32\") await fs.chmod(quarantinePath, 0o600);\n\t\tawait syncParentDirectory(filePath);\n\t} catch {\n\t\t// Preserve the quarantine rather than risk deleting settings that changed concurrently.\n\t}\n}\n\nfunction configMutationLockPath() {\n\treturn `${localConfigPath()}.mutation-lock`;\n}\n\nexport async function withLocalConfigFileLock<T>(run: () => Promise<T>): Promise<T> {\n\tconst configPath = localConfigPath();\n\tawait fs.mkdir(path.dirname(configPath), { recursive: true });\n\tlet compromisedError: Error | undefined;\n\tconst release = await lockfile.lock(configPath, {\n\t\tfs: LOCKFILE_FS_ADAPTER,\n\t\tlockfilePath: configMutationLockPath(),\n\t\trealpath: false,\n\t\tstale: CONFIG_LOCK_STALE_MS,\n\t\tupdate: CONFIG_LOCK_UPDATE_MS,\n\t\tretries: { retries: 100, factor: 1.2, minTimeout: 10, maxTimeout: 100 },\n\t\tonCompromised: (error) => {\n\t\t\tcompromisedError = error;\n\t\t},\n\t});\n\ttry {\n\t\tconst result = await run();\n\t\tif (compromisedError) throw compromisedError;\n\t\treturn result;\n\t} finally {\n\t\tawait release();\n\t}\n}\n\nasync function syncParentDirectory(filePath: string) {\n\tif (process.platform === \"win32\") return;\n\tlet handle: fs.FileHandle | undefined;\n\ttry {\n\t\thandle = await fs.open(path.dirname(filePath), \"r\");\n\t\tawait handle.sync();\n\t} finally {\n\t\tawait handle?.close().catch(() => undefined);\n\t}\n}\n\nasync function publishFileWithoutReplacement(source: string, destination: string) {\n\tawait beforeConfigPublicationHook();\n\tawait renameFileWithoutReplacement(source, destination);\n}\n\nasync function renameFileWithoutReplacement(source: string, destination: string) {\n\tif (await pathExists(destination)) {\n\t\tthrow Object.assign(new Error(`Settings already exist: ${destination}`), { code: \"EEXIST\" });\n\t}\n\tawait fs.rename(source, destination);\n}\n\nasync function pathExists(filePath: string) {\n\ttry {\n\t\tawait fs.lstat(filePath);\n\t\treturn true;\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return false;\n\t\tthrow error;\n\t}\n}\n\nfunction recordConfigMigrationNotice(configPath: string, notice: string) {\n\tif (!configMigrationNotices.has(configPath)) configMigrationNotices.set(configPath, notice);\n}\n", "import { createHash, randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport {\n\ttype ExtensionCommandContext,\n\ttype ExtensionContext,\n\tgetAgentDir,\n} from \"@earendil-works/pi-coding-agent\";\nimport {\n\tactiveLocalConfigPath,\n\tconsumeLocalConfigMigrationNotice,\n\tcreateLocalConfigDocument,\n\tlegacyLocalConfigPath,\n\tlocalConfigPath,\n\tquarantineAndRemoveConfigIfMatches,\n\treadActiveLocalConfigDocumentForRepair,\n\treadMigratingLocalConfigDocument,\n\treplaceLocalConfigDocument,\n\tupdateLocalConfigDocument,\n} from \"./config-file.js\";\nimport {\n\tnormalizeGitBranch,\n\tnormalizeGitDirectory,\n\tnormalizeGitRemote,\n\tnormalizeGitRemoteIdentity,\n} from \"./git-config.js\";\nimport { safeName } from \"./paths.js\";\nimport { stateDir } from \"./state-directory.js\";\nimport { normalizeSyncInclude } from \"./sync-policy.js\";\nimport type {\n\tAnySyncConfig,\n\tOnSwitchAction,\n\tPartialConfig,\n\tPiSyncSettingsV3,\n\tSnapshot,\n\tStorageConnectionSettings,\n\tSyncSetupSettings,\n\tSyncState,\n} from \"./types.js\";\nimport {\n\tnormalizeWebDavIdentityUrl,\n\tnormalizeWebDavPath,\n\tnormalizeWebDavUrl,\n\tvalidateWebDavCredentials,\n} from \"./webdav-config.js\";\n\nconst STATE_VERSION = 2;\nexport const DEFAULT_ON_SWITCH: OnSwitchAction = \"ask-before-pull\";\n\nexport { normalizeExtraFiles, normalizeSyncFiles } from \"./sync-policy.js\";\nexport {\n\tactiveLocalConfigPath,\n\tconsumeLocalConfigMigrationNotice,\n\tcreateLocalConfigDocument,\n\tlegacyLocalConfigPath,\n\tlocalConfigPath,\n\tnormalizeSyncInclude,\n\tquarantineAndRemoveConfigIfMatches,\n\treadActiveLocalConfigDocumentForRepair,\n\treplaceLocalConfigDocument,\n\tupdateLocalConfigDocument,\n};\n\nfunction sessionDirFromContext(ctx: ExtensionCommandContext | ExtensionContext) {\n\tconst manager = ctx.sessionManager as typeof ctx.sessionManager & {\n\t\tusesDefaultSessionDir?: () => boolean;\n\t};\n\tif (manager.usesDefaultSessionDir?.call(manager)) return undefined;\n\treturn typeof manager.getSessionDir === \"function\"\n\t\t? (manager.getSessionDir.call(manager) as string | undefined)\n\t\t: undefined;\n}\n\nexport async function loadConfig(setupName?: string): Promise<AnySyncConfig> {\n\tconst settings = await requireSettings();\n\tconst selectedName = setupName ?? settings.activeSyncSetup;\n\tif (!selectedName) throw new Error(\"No sync setups are configured.\");\n\tvalidateConfigName(selectedName, \"sync setup\");\n\tconst setup = ownObject<SyncSetupSettings>(settings.syncSetups, selectedName);\n\tif (!setup)\n\t\tthrow new Error(`Invalid pi-sync settings: sync setup \u201C${selectedName}\u201D was not found.`);\n\tconst connectionName = setup.storage.connection;\n\tconst connection = ownObject<StorageConnectionSettings>(\n\t\tsettings.storageConnections,\n\t\tconnectionName,\n\t);\n\tif (!connection) {\n\t\tthrow new Error(\n\t\t\t`Invalid pi-sync settings: sync setup \u201C${selectedName}\u201D references missing storage connection \u201C${connectionName}\u201D.`,\n\t\t);\n\t}\n\treturn resolveSyncConfig(\n\t\tselectedName,\n\t\tsetup,\n\t\tconnectionName,\n\t\tconnection,\n\t\tsettings.onSwitch,\n\t\tsettings.skipSecretScan ?? false,\n\t);\n}\n\nexport type SyncSetupStorageReview = Pick<\n\tPartialConfig,\n\t\"connectionName\" | \"storageKind\" | \"storagePath\" | \"bucket\" | \"branch\"\n>;\n\n/** A validated setup-facing projection used by manager and settings UI. */\nexport async function loadPartialConfig(setupName?: string): Promise<PartialConfig> {\n\tconst config = await loadConfig(setupName);\n\treturn {\n\t\tsetupName: config.setupName,\n\t\t...storageReviewFromConfig(config),\n\t\tinclude: [...config.include],\n\t\tautomatic: config.automatic,\n\t\tonSwitch: config.onSwitch,\n\t};\n}\n\nexport function syncSetupStorageReview(\n\tsetupName: string,\n\tsetup: SyncSetupSettings,\n\tconnectionName: string,\n\tconnection: StorageConnectionSettings,\n): SyncSetupStorageReview {\n\treturn storageReviewFromConfig(\n\t\tresolveSyncConfig(setupName, setup, connectionName, connection, DEFAULT_ON_SWITCH, false),\n\t);\n}\n\nexport function syncSetupReviewIdentity(\n\tsetupName: string,\n\tsetup: SyncSetupSettings,\n\tconnectionName: string,\n\tconnection: StorageConnectionSettings,\n) {\n\treturn syncConfigReviewIdentity(\n\t\tresolveSyncConfig(setupName, setup, connectionName, connection, DEFAULT_ON_SWITCH, false),\n\t);\n}\n\nexport function syncConfigReviewIdentity(config: AnySyncConfig) {\n\treturn JSON.stringify([\n\t\tconfig.setupName,\n\t\tconfig.connectionName,\n\t\tbackendIdentityCoordinates(config),\n\t\tconfig.include,\n\t\tconfig.automatic,\n\t]);\n}\n\nexport function syncConfigReviewFingerprint(config: AnySyncConfig) {\n\treturn createHash(\"sha256\").update(syncConfigReviewIdentity(config)).digest(\"hex\");\n}\n\nfunction storageReviewFromConfig(config: AnySyncConfig): SyncSetupStorageReview {\n\treturn {\n\t\tconnectionName: config.connectionName,\n\t\tstorageKind: config.backend.type,\n\t\tstoragePath: config.storagePath,\n\t\t...(config.backend.type === \"s3\"\n\t\t\t? { bucket: config.backend.destination.bucket }\n\t\t\t: config.backend.type === \"git\"\n\t\t\t\t? { branch: config.backend.destination.branch }\n\t\t\t\t: {}),\n\t};\n}\n\nexport async function configuredSyncSetupNames() {\n\tconst settings = await readLocalConfigObject();\n\treturn settings\n\t\t? Object.keys(settings.syncSetups).sort((left, right) => left.localeCompare(right))\n\t\t: [];\n}\n\nexport async function loadOnSwitch(): Promise<OnSwitchAction> {\n\treturn (await requireSettings()).onSwitch;\n}\n\nexport function normalizeOnSwitch(value: unknown): OnSwitchAction {\n\tif (value === \"ask-before-pull\" || value === \"pull-after-switch\" || value === \"switch-only\") {\n\t\treturn value;\n\t}\n\tthrow new Error(\n\t\t'Invalid pi-sync settings: onSwitch must be \"ask-before-pull\", \"pull-after-switch\", or \"switch-only\".',\n\t);\n}\n\nfunction resolveSyncConfig(\n\tsetupName: string,\n\tsetup: SyncSetupSettings,\n\tconnectionName: string,\n\tconnection: StorageConnectionSettings,\n\tonSwitch: OnSwitchAction,\n\tskipSecretScan: boolean,\n): AnySyncConfig {\n\tconst storagePath = normalizeStoragePath(setup.storage.path);\n\tconst namespace = storagePath.slice(storagePath.lastIndexOf(\"/\") + 1);\n\tconst include = normalizeSyncInclude(setup.sync.include);\n\tconst common = {\n\t\tsetupName,\n\t\tconnectionName,\n\t\tstoragePath,\n\t\tsnapshotIdentity: namespace,\n\t\tinclude,\n\t\tautomatic: setup.sync.automatic,\n\t\tonSwitch,\n\t\tskipSecretScan,\n\t};\n\tif (connection.type === \"git\") {\n\t\treturn {\n\t\t\t...common,\n\t\t\tbackend: {\n\t\t\t\ttype: \"git\",\n\t\t\t\tprofile: { kind: \"git\", remote: normalizeGitRemote(connection.remote) as string },\n\t\t\t\tdestination: {\n\t\t\t\t\tbranch: normalizeGitBranch(setup.storage.branch),\n\t\t\t\t\tdirectory: normalizeGitDirectory(storagePath),\n\t\t\t\t\tnamespace,\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\tif (connection.type === \"webdav\") {\n\t\treturn {\n\t\t\t...common,\n\t\t\tbackend: {\n\t\t\t\ttype: \"webdav\",\n\t\t\t\tprofile: {\n\t\t\t\t\tkind: \"webdav\",\n\t\t\t\t\turl: normalizeWebDavUrl(connection.url) as string,\n\t\t\t\t\tusername: connection.credentials.username,\n\t\t\t\t\tpassword: connection.credentials.password,\n\t\t\t\t},\n\t\t\t\tdestination: { path: normalizeWebDavPath(storagePath), namespace },\n\t\t\t},\n\t\t};\n\t}\n\treturn {\n\t\t...common,\n\t\tbackend: {\n\t\t\ttype: \"s3\",\n\t\t\tprofile: {\n\t\t\t\tkind: isCloudflareR2Endpoint(connection.endpoint) ? \"r2\" : \"s3-compatible\",\n\t\t\t\tendpoint: normalizeS3Endpoint(connection.endpoint),\n\t\t\t\tregion: requiredString(connection.region, \"S3 region\"),\n\t\t\t\taccessKeyId: connection.credentials.accessKeyId,\n\t\t\t\tsecretAccessKey: connection.credentials.secretAccessKey,\n\t\t\t\tsessionToken: optionalString(connection.credentials.sessionToken, \"S3 session token\"),\n\t\t\t},\n\t\t\tdestination: {\n\t\t\t\tbucket: normalizeS3Bucket(setup.storage.bucket),\n\t\t\t\tprefix: storagePath,\n\t\t\t\tnamespace,\n\t\t\t},\n\t\t},\n\t};\n}\n\nasync function requireSettings() {\n\tconst settings = await readLocalConfigObject();\n\tif (!settings) {\n\t\tthrow new Error(`Missing pi-sync settings. Use /sync setup or create ${localConfigPath()}.`);\n\t}\n\treturn settings;\n}\n\nexport function validateSettingsDocument(value: Record<string, unknown>): PiSyncSettingsV3 {\n\tif (value.version !== 3) {\n\t\tthrow new Error(\n\t\t\t`Unsupported pi-sync settings: version 3 is required. Keep the existing file for recovery, then create a new version 3 ${path.basename(localConfigPath())}; pi-sync will not migrate or overwrite old settings.`,\n\t\t);\n\t}\n\trejectLegacyFields(\n\t\tvalue,\n\t\t[\n\t\t\t\"profiles\",\n\t\t\t\"targets\",\n\t\t\t\"activeTarget\",\n\t\t\t\"targetSwitchAction\",\n\t\t\t\"endpoint\",\n\t\t\t\"bucket\",\n\t\t\t\"region\",\n\t\t\t\"accessKeyId\",\n\t\t\t\"secretAccessKey\",\n\t\t\t\"sessionToken\",\n\t\t\t\"profile\",\n\t\t\t\"prefix\",\n\t\t\t\"autoSync\",\n\t\t\t\"syncFiles\",\n\t\t\t\"syncSessions\",\n\t\t\t\"extraFiles\",\n\t\t],\n\t\t\"top level\",\n\t);\n\tnormalizeOnSwitch(value.onSwitch);\n\tif (value.skipSecretScan !== undefined && typeof value.skipSecretScan !== \"boolean\") {\n\t\tthrow new Error(\"Invalid pi-sync settings: skipSecretScan must be boolean.\");\n\t}\n\tconst storageConnections = requireNamedObjectMap(\n\t\tvalue.storageConnections,\n\t\t\"storageConnections\",\n\t\t\"storage connection\",\n\t);\n\tconst syncSetups = requireNamedObjectMap(value.syncSetups, \"syncSetups\", \"sync setup\");\n\tfor (const name of Object.keys(storageConnections)) {\n\t\tvalidateStorageConnection(\n\t\t\tname,\n\t\t\trequireOwnObject(storageConnections, name, \"storage connection\") as Record<string, unknown>,\n\t\t);\n\t}\n\tfor (const name of Object.keys(syncSetups)) {\n\t\tvalidateSyncSetup(\n\t\t\tname,\n\t\t\trequireOwnObject(syncSetups, name, \"sync setup\") as Record<string, unknown>,\n\t\t\tstorageConnections,\n\t\t);\n\t}\n\tconst names = Object.keys(syncSetups);\n\tconst activeSyncSetup = optionalCanonicalReference(value.activeSyncSetup, \"activeSyncSetup\");\n\tif (names.length === 0) {\n\t\tif (activeSyncSetup !== undefined) {\n\t\t\tthrow new Error(\"Invalid pi-sync settings: empty syncSetups cannot have activeSyncSetup.\");\n\t\t}\n\t} else if (!activeSyncSetup || !Object.hasOwn(syncSetups, activeSyncSetup)) {\n\t\tthrow new Error(\n\t\t\t\"Invalid pi-sync settings: activeSyncSetup must reference an existing own-property sync setup.\",\n\t\t);\n\t}\n\tvalidateUniqueRemoteSyncSetups(syncSetups, storageConnections);\n\treturn value as PiSyncSettingsV3;\n}\n\nfunction validateStorageConnection(name: string, value: Record<string, unknown>) {\n\trejectLegacyFields(\n\t\tvalue,\n\t\t[\"kind\", \"accessKeyId\", \"secretAccessKey\", \"sessionToken\", \"username\", \"password\"],\n\t\t`storage connection \u201C${name}\u201D`,\n\t);\n\tconst type = requiredString(value.type, `storage connection \u201C${name}\u201D type`);\n\tif (type !== \"s3\" && type !== \"git\" && type !== \"webdav\") {\n\t\tthrow new Error(`Invalid pi-sync settings: storage connection \u201C${name}\u201D has unsupported type.`);\n\t}\n\tconst known = [\"endpoint\", \"region\", \"remote\", \"url\", \"credentials\"];\n\tconst allowed =\n\t\ttype === \"s3\"\n\t\t\t? new Set([\"endpoint\", \"region\", \"credentials\"])\n\t\t\t: type === \"git\"\n\t\t\t\t? new Set([\"remote\"])\n\t\t\t\t: new Set([\"url\", \"credentials\"]);\n\tif (known.some((field) => Object.hasOwn(value, field) && !allowed.has(field))) {\n\t\tthrow new Error(\n\t\t\t`Invalid pi-sync settings: ${type.toUpperCase()} storage connection \u201C${name}\u201D mixes backend fields.`,\n\t\t);\n\t}\n\tif (type === \"git\") {\n\t\tif (!normalizeGitRemote(requiredString(value.remote, `Git remote for \u201C${name}\u201D`))) {\n\t\t\tthrow new Error(`Invalid pi-sync settings: Git remote for \u201C${name}\u201D is required.`);\n\t\t}\n\t\treturn;\n\t}\n\tconst credentials = requireRecord(\n\t\tvalue.credentials,\n\t\t`credentials for storage connection \u201C${name}\u201D`,\n\t);\n\tif (type === \"webdav\") {\n\t\tnormalizeWebDavUrl(requiredString(value.url, `WebDAV URL for \u201C${name}\u201D`));\n\t\tconst username = requiredString(credentials.username, `WebDAV username for \u201C${name}\u201D`);\n\t\tconst password = requiredSecret(credentials.password, `WebDAV password for \u201C${name}\u201D`);\n\t\tif (\n\t\t\t[\"accessKeyId\", \"secretAccessKey\", \"sessionToken\"].some((field) =>\n\t\t\t\tObject.hasOwn(credentials, field),\n\t\t\t)\n\t\t) {\n\t\t\tthrow new Error(`Invalid pi-sync settings: WebDAV credentials for \u201C${name}\u201D mix fields.`);\n\t\t}\n\t\tvalidateWebDavCredentials(username, password);\n\t\treturn;\n\t}\n\tnormalizeS3Endpoint(requiredString(value.endpoint, `S3 endpoint for \u201C${name}\u201D`));\n\trequiredString(value.region, `S3 region for \u201C${name}\u201D`);\n\trequiredString(credentials.accessKeyId, `S3 access key id for \u201C${name}\u201D`);\n\trequiredSecret(credentials.secretAccessKey, `S3 secret access key for \u201C${name}\u201D`);\n\toptionalString(credentials.sessionToken, `S3 session token for \u201C${name}\u201D`);\n\tif ([\"username\", \"password\"].some((field) => Object.hasOwn(credentials, field))) {\n\t\tthrow new Error(`Invalid pi-sync settings: S3 credentials for \u201C${name}\u201D mix fields.`);\n\t}\n}\n\nfunction validateSyncSetup(\n\tname: string,\n\tvalue: Record<string, unknown>,\n\tconnections: Record<string, unknown>,\n) {\n\trejectLegacyFields(\n\t\tvalue,\n\t\t[\n\t\t\t\"profile\",\n\t\t\t\"bucket\",\n\t\t\t\"branch\",\n\t\t\t\"path\",\n\t\t\t\"prefix\",\n\t\t\t\"directory\",\n\t\t\t\"namespace\",\n\t\t\t\"autoSync\",\n\t\t\t\"syncFiles\",\n\t\t\t\"syncSessions\",\n\t\t\t\"extraFiles\",\n\t\t],\n\t\t`sync setup \u201C${name}\u201D`,\n\t);\n\tconst storage = requireRecord(value.storage, `storage for sync setup \u201C${name}\u201D`);\n\tconst sync = requireRecord(value.sync, `sync policy for sync setup \u201C${name}\u201D`);\n\trejectLegacyFields(\n\t\tstorage,\n\t\t[\"profile\", \"prefix\", \"directory\", \"namespace\"],\n\t\t`storage for sync setup \u201C${name}\u201D`,\n\t);\n\trejectLegacyFields(\n\t\tsync,\n\t\t[\"autoSync\", \"syncFiles\", \"syncSessions\", \"extraFiles\"],\n\t\t`sync policy for sync setup \u201C${name}\u201D`,\n\t);\n\tconst connectionName = requiredCanonicalReference(\n\t\tstorage.connection,\n\t\t`storage connection reference for sync setup \u201C${name}\u201D`,\n\t);\n\tvalidateConfigName(connectionName, \"storage connection reference\");\n\tconst connection = ownObject<Record<string, unknown>>(connections, connectionName);\n\tif (!connection) {\n\t\tthrow new Error(\n\t\t\t`Invalid pi-sync settings: sync setup \u201C${name}\u201D references missing storage connection \u201C${connectionName}\u201D.`,\n\t\t);\n\t}\n\tconst type = connection.type;\n\tnormalizeStoragePath(requiredString(storage.path, `storage path for sync setup \u201C${name}\u201D`));\n\tif (type === \"s3\") {\n\t\tnormalizeS3Bucket(requiredString(storage.bucket, `S3 bucket for sync setup \u201C${name}\u201D`));\n\t\tif (Object.hasOwn(storage, \"branch\")) mixedSetupError(\"S3\", name);\n\t} else if (type === \"git\") {\n\t\tnormalizeGitBranch(requiredString(storage.branch, `Git branch for sync setup \u201C${name}\u201D`));\n\t\tif (Object.hasOwn(storage, \"bucket\")) mixedSetupError(\"Git\", name);\n\t} else if (type === \"webdav\") {\n\t\tif (Object.hasOwn(storage, \"bucket\") || Object.hasOwn(storage, \"branch\")) {\n\t\t\tmixedSetupError(\"WebDAV\", name);\n\t\t}\n\t}\n\tif (!Object.hasOwn(sync, \"include\")) {\n\t\tthrow new Error(`Invalid pi-sync settings: sync setup \u201C${name}\u201D is missing sync.include.`);\n\t}\n\tnormalizeSyncInclude(sync.include);\n\tif (typeof sync.automatic !== \"boolean\") {\n\t\tthrow new Error(\n\t\t\t`Invalid pi-sync settings: sync setup \u201C${name}\u201D sync.automatic must be boolean.`,\n\t\t);\n\t}\n}\n\nfunction mixedSetupError(type: string, name: string): never {\n\tthrow new Error(`Invalid pi-sync settings: ${type} sync setup \u201C${name}\u201D mixes backend fields.`);\n}\n\nexport function validateUniqueRemoteSyncSetups(\n\tsetups: Record<string, unknown>,\n\tconnections: Record<string, unknown>,\n) {\n\tconst identities = new Map<string, string>();\n\tfor (const name of Object.keys(setups)) {\n\t\tconst setup = requireOwnObject(setups, name, \"sync setup\") as unknown as SyncSetupSettings;\n\t\tconst connection = requireOwnObject(\n\t\t\tconnections,\n\t\t\tsetup.storage.connection,\n\t\t\t\"storage connection\",\n\t\t) as unknown as StorageConnectionSettings;\n\t\tconst identity = effectiveSyncSetupRemoteIdentity(setup, connection);\n\t\tconst existing = identities.get(identity);\n\t\tif (existing) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid pi-sync settings: sync setups \u201C${existing}\u201D and \u201C${name}\u201D use the same normalized remote location.`,\n\t\t\t);\n\t\t}\n\t\tidentities.set(identity, name);\n\t}\n}\n\nexport function effectiveSyncSetupRemoteIdentity(\n\tsetup: SyncSetupSettings,\n\tconnection: StorageConnectionSettings,\n) {\n\tconst storagePath = normalizeStoragePath(setup.storage.path);\n\tif (connection.type === \"git\") {\n\t\treturn JSON.stringify([\n\t\t\t\"git\",\n\t\t\tnormalizeGitRemoteIdentity(connection.remote),\n\t\t\tnormalizeGitBranch(setup.storage.branch),\n\t\t\tnormalizeGitDirectory(storagePath),\n\t\t]);\n\t}\n\tif (connection.type === \"webdav\") {\n\t\treturn JSON.stringify([\n\t\t\t\"webdav\",\n\t\t\tnormalizeWebDavIdentityUrl(connection.url),\n\t\t\tconnection.credentials.username.trim(),\n\t\t\tnormalizeWebDavPath(storagePath),\n\t\t]);\n\t}\n\treturn JSON.stringify([\n\t\t\"s3\",\n\t\tnormalizeEndpointIdentity(connection.endpoint),\n\t\tnormalizeS3Bucket(setup.storage.bucket),\n\t\tstoragePath,\n\t]);\n}\n\nfunction rejectLegacyFields(\n\tvalue: Record<string, unknown>,\n\tfields: readonly string[],\n\tcontext: string,\n) {\n\tconst field = fields.find((candidate) => Object.hasOwn(value, candidate));\n\tif (field) {\n\t\tthrow new Error(\n\t\t\t`Invalid pi-sync settings: ${context} contains unsupported version 1/2 field \u201C${field}\u201D.`,\n\t\t);\n\t}\n}\n\nfunction requireNamedObjectMap(value: unknown, field: string, itemLabel: string) {\n\tconst result = requireRecord(value, field);\n\tfor (const name of Object.keys(result)) validateConfigName(name, itemLabel);\n\treturn result;\n}\n\nfunction requireOwnObject(value: Record<string, unknown>, key: string, label: string) {\n\tconst item = ownObject(value, key);\n\tif (!item) throw new Error(`Invalid pi-sync settings: ${label} \u201C${key}\u201D must be an object.`);\n\treturn item;\n}\n\nfunction ownObject<T extends object>(value: Record<string, unknown>, key: string): T | undefined {\n\tif (!Object.hasOwn(value, key)) return undefined;\n\tconst item = value[key];\n\treturn item && typeof item === \"object\" && !Array.isArray(item) ? (item as T) : undefined;\n}\n\nfunction requireRecord(value: unknown, field: string): Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new Error(`Invalid pi-sync settings: ${field} must be an object.`);\n\t}\n\treturn value as Record<string, unknown>;\n}\n\nexport function validateConfigName(value: string, field: string) {\n\tif (\n\t\t!value.trim() ||\n\t\tvalue !== value.trim() ||\n\t\tvalue.length > 100 ||\n\t\tvalue === \"__proto__\" ||\n\t\tvalue === \"prototype\" ||\n\t\tvalue === \"constructor\" ||\n\t\thasControlCharacter(value)\n\t) {\n\t\tthrow new Error(`Invalid pi-sync settings: invalid ${field} name.`);\n\t}\n}\n\nfunction requiredString(value: unknown, field: string) {\n\tif (typeof value !== \"string\" || !value.trim() || hasControlCharacter(value)) {\n\t\tthrow new Error(`Invalid pi-sync settings: ${field} must be a non-empty string.`);\n\t}\n\treturn value.trim();\n}\n\nfunction requiredCanonicalReference(value: unknown, field: string) {\n\tconst normalized = requiredString(value, field);\n\tif (value !== normalized) {\n\t\tthrow new Error(`Invalid pi-sync settings: ${field} must not have surrounding whitespace.`);\n\t}\n\treturn normalized;\n}\n\nfunction optionalCanonicalReference(value: unknown, field: string) {\n\tconst normalized = optionalString(value, field);\n\tif (normalized !== undefined && value !== normalized) {\n\t\tthrow new Error(`Invalid pi-sync settings: ${field} must not have surrounding whitespace.`);\n\t}\n\treturn normalized;\n}\n\nfunction requiredSecret(value: unknown, field: string) {\n\tif (typeof value !== \"string\" || !value || hasControlCharacter(value)) {\n\t\tthrow new Error(`Invalid pi-sync settings: ${field} must be configured.`);\n\t}\n\treturn value;\n}\n\nfunction optionalString(value: unknown, field: string) {\n\tif (value === undefined) return undefined;\n\tif (typeof value !== \"string\" || hasControlCharacter(value)) {\n\t\tthrow new Error(`Invalid pi-sync settings: ${field} must be a string.`);\n\t}\n\treturn value.trim() || undefined;\n}\n\nexport function normalizeStoragePath(value: string) {\n\tconst normalized = value.trim().replace(/^\\/+|\\/+$/gu, \"\");\n\tif (\n\t\t!normalized ||\n\t\tnormalized.length > 1024 ||\n\t\tnormalized.startsWith(\"-\") ||\n\t\tnormalized.includes(\"\\\\\") ||\n\t\thasControlCharacter(normalized) ||\n\t\tnormalized.split(\"/\").some((segment) => !segment || segment === \".\" || segment === \"..\")\n\t) {\n\t\tthrow new Error(\"Invalid pi-sync settings: storage.path must be a safe relative path.\");\n\t}\n\treturn normalized;\n}\n\nfunction normalizeS3Endpoint(value: string) {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(value.trim());\n\t} catch {\n\t\tthrow new Error(\"Invalid pi-sync S3 endpoint.\");\n\t}\n\tconst loopback =\n\t\turl.hostname === \"127.0.0.1\" || url.hostname === \"localhost\" || url.hostname === \"[::1]\";\n\tif (\n\t\t(url.protocol !== \"https:\" && !(url.protocol === \"http:\" && loopback)) ||\n\t\turl.username ||\n\t\turl.password ||\n\t\turl.search ||\n\t\turl.hash\n\t) {\n\t\tthrow new Error(\"Invalid pi-sync S3 endpoint: HTTPS is required except for loopback.\");\n\t}\n\turl.pathname = url.pathname.replace(/\\/+$/gu, \"\");\n\treturn url.toString().replace(/\\/$/u, \"\");\n}\n\nfunction normalizeS3Bucket(value: string | undefined) {\n\tconst bucket = requiredString(value, \"S3 bucket\");\n\tif (bucket.includes(\"/\") || bucket.includes(\"\\\\\") || bucket.startsWith(\"-\")) {\n\t\tthrow new Error(\"Invalid pi-sync S3 bucket.\");\n\t}\n\treturn bucket;\n}\n\nfunction normalizeEndpointIdentity(endpoint: string) {\n\ttry {\n\t\tconst url = new URL(endpoint.trim());\n\t\turl.hostname = url.hostname.toLowerCase();\n\t\turl.pathname = url.pathname.replace(/\\/+$/gu, \"\");\n\t\treturn url.toString().replace(/\\/$/u, \"\");\n\t} catch {\n\t\treturn endpoint.trim();\n\t}\n}\n\nexport async function configuredSessionDir() {\n\tconst settings = await readJsonIfExists<{ sessionDir?: string }>(\n\t\tpath.join(agentDir(), \"settings.json\"),\n\t);\n\treturn settings?.sessionDir ? expandHome(settings.sessionDir) : undefined;\n}\n\nexport async function sessionDirForApply(\n\tctx: ExtensionCommandContext | ExtensionContext,\n\tsnapshot: Snapshot,\n) {\n\tconst contextSessionDir = sessionDirFromContext(ctx);\n\tconst localSessionDir = await configuredSessionDir();\n\tif (\n\t\tcontextSessionDir &&\n\t\tpath.resolve(contextSessionDir) !== path.resolve(localSessionDir ?? \"\")\n\t) {\n\t\treturn contextSessionDir;\n\t}\n\treturn sessionDirFromSnapshot(snapshot) ?? contextSessionDir;\n}\n\nfunction sessionDirFromSnapshot(snapshot: Snapshot) {\n\tconst settingsFile = snapshot.files.find((file) => file.path === \"settings.json\");\n\tif (!settingsFile) return undefined;\n\ttry {\n\t\tconst settings = JSON.parse(\n\t\t\tdecodeBase64Strict(settingsFile.contentBase64, settingsFile.path).toString(\"utf8\"),\n\t\t) as { sessionDir?: string };\n\t\treturn settings.sessionDir ? expandHome(settings.sessionDir) : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction decodeBase64Strict(value: string, filePath: string) {\n\tif (!/^[A-Za-z0-9+/]*={0,2}$/.test(value) || value.length % 4 !== 0) {\n\t\tthrow new Error(`Invalid base64 content in snapshot file: ${filePath}`);\n\t}\n\treturn Buffer.from(value, \"base64\");\n}\n\nexport async function readState(profile: string): Promise<SyncState> {\n\treturn (\n\t\t(await readJsonIfExists<SyncState>(statePath(profile))) ?? {\n\t\t\tversion: STATE_VERSION,\n\t\t\tprofile,\n\t\t\tlastFileHashes: {},\n\t\t}\n\t);\n}\n\nexport async function writeState(profile: string, state: SyncState) {\n\tawait writeJson(statePath(profile), state);\n}\n\nexport async function readStateForConfig(config: AnySyncConfig): Promise<SyncState> {\n\treturn (\n\t\t(await readJsonIfExists<SyncState>(statePathForConfig(config))) ?? {\n\t\t\tversion: STATE_VERSION,\n\t\t\tprofile: config.snapshotIdentity,\n\t\t\tlastFileHashes: {},\n\t\t}\n\t);\n}\n\nexport async function writeStateForConfig(config: AnySyncConfig, state: SyncState) {\n\tawait writeJson(statePathForConfig(config), state);\n}\n\nexport function statePathForConfig(config: AnySyncConfig) {\n\tconst identity = backendIdentityCoordinates(config);\n\tconst hash = createHash(\"sha256\").update(identity).digest(\"hex\").slice(0, 16);\n\treturn path.join(stateDir(), \"setups\", `${config.backend.type}-${hash}.state.json`);\n}\n\nfunction backendIdentityCoordinates(config: AnySyncConfig) {\n\tswitch (config.backend.type) {\n\t\tcase \"s3\":\n\t\t\treturn JSON.stringify([\n\t\t\t\t\"s3\",\n\t\t\t\tnormalizeEndpointIdentity(config.backend.profile.endpoint),\n\t\t\t\tconfig.backend.destination.bucket,\n\t\t\t\tconfig.storagePath,\n\t\t\t]);\n\t\tcase \"git\":\n\t\t\treturn JSON.stringify([\n\t\t\t\t\"git\",\n\t\t\t\tnormalizeGitRemoteIdentity(config.backend.profile.remote),\n\t\t\t\tconfig.backend.destination.branch,\n\t\t\t\tconfig.storagePath,\n\t\t\t]);\n\t\tcase \"webdav\":\n\t\t\treturn JSON.stringify([\n\t\t\t\t\"webdav\",\n\t\t\t\tnormalizeWebDavIdentityUrl(config.backend.profile.url),\n\t\t\t\tconfig.backend.profile.username,\n\t\t\t\tconfig.storagePath,\n\t\t\t]);\n\t}\n}\n\nexport function agentDir() {\n\treturn getAgentDir();\n}\n\nfunction expandHome(value: string) {\n\treturn value === \"~\" || value.startsWith(\"~/\") ? path.join(os.homedir(), value.slice(2)) : value;\n}\n\nexport { stateDir } from \"./state-directory.js\";\n\nexport function localConfigTemplate(): PiSyncSettingsV3 {\n\treturn {\n\t\tversion: 3,\n\t\tonSwitch: DEFAULT_ON_SWITCH,\n\t\tskipSecretScan: false,\n\t\tstorageConnections: {},\n\t\tsyncSetups: {},\n\t};\n}\n\nexport async function readLocalConfigDocument() {\n\tconst document = await readMigratingLocalConfigDocument((settings) => {\n\t\tvalidateSettingsDocument(settings);\n\t});\n\tif (document) validateSettingsDocument(document.parsed);\n\treturn document;\n}\n\nexport async function readLocalConfigObject(): Promise<PiSyncSettingsV3 | undefined> {\n\treturn (await readLocalConfigDocument())?.parsed as PiSyncSettingsV3 | undefined;\n}\n\nlet configUpdateQueue: Promise<void> = Promise.resolve();\n\nexport function updateLocalConfig(\n\tupdate: (current: PiSyncSettingsV3) => PiSyncSettingsV3,\n\tsignal?: AbortSignal,\n) {\n\tconst operation = configUpdateQueue.then(() => {\n\t\tsignal?.throwIfAborted();\n\t\treturn performLocalConfigUpdate(update, signal);\n\t});\n\tconfigUpdateQueue = operation.then(\n\t\t() => undefined,\n\t\t() => undefined,\n\t);\n\treturn operation;\n}\n\nasync function performLocalConfigUpdate(\n\tupdate: (current: PiSyncSettingsV3) => PiSyncSettingsV3,\n\tsignal?: AbortSignal,\n) {\n\treturn updateLocalConfigDocument(localConfigTemplate(), update, validateSettingsDocument, signal);\n}\n\nexport async function writeLocalConfigObject(value: PiSyncSettingsV3 | Record<string, unknown>) {\n\tvalidateSettingsDocument(value as Record<string, unknown>);\n\tconst configPath = localConfigPath();\n\tawait fs.mkdir(path.dirname(configPath), { recursive: true });\n\ttry {\n\t\tconst stat = await fs.lstat(configPath);\n\t\tif (stat.isSymbolicLink())\n\t\t\tthrow new Error(`Refusing to overwrite symlinked pi-sync settings: ${configPath}`);\n\t\tif (!stat.isFile()) throw new Error(`pi-sync settings are not a regular file: ${configPath}`);\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n\t}\n\tconst temporaryPath = path.join(\n\t\tpath.dirname(configPath),\n\t\t`.${path.basename(configPath)}.${process.pid}.${randomUUID()}.tmp`,\n\t);\n\tlet handle: fs.FileHandle | undefined;\n\ttry {\n\t\thandle = await fs.open(temporaryPath, \"wx\", 0o600);\n\t\tawait handle.writeFile(`${JSON.stringify(value, null, \"\\t\")}\\n`, \"utf8\");\n\t\tif (process.platform !== \"win32\") await handle.chmod(0o600);\n\t\tawait handle.sync();\n\t\tawait handle.close();\n\t\thandle = undefined;\n\t\tawait fs.rename(temporaryPath, configPath);\n\t} catch (error) {\n\t\tawait handle?.close().catch(() => undefined);\n\t\tawait fs.rm(temporaryPath, { force: true }).catch(() => undefined);\n\t\tthrow error;\n\t}\n}\n\nfunction statePath(profile: string) {\n\treturn path.join(stateDir(), `${safeName(profile)}.state.json`);\n}\n\nexport function lockPath() {\n\treturn path.join(stateDir(), \"lock\");\n}\n\nexport async function ensureStateDir() {\n\tawait fs.mkdir(stateDir(), { recursive: true });\n}\n\nasync function readJsonIfExists<T>(filePath: string): Promise<T | undefined> {\n\ttry {\n\t\treturn JSON.parse(await fs.readFile(filePath, \"utf8\")) as T;\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n\t\tthrow error;\n\t}\n}\n\nexport async function writeJson(filePath: string, value: unknown) {\n\tawait fs.mkdir(path.dirname(filePath), { recursive: true });\n\tconst temp = `${filePath}.${process.pid}.${randomUUID()}.tmp`;\n\tawait fs.writeFile(temp, `${JSON.stringify(value, null, \"\\t\")}\\n`, { mode: 0o600 });\n\tif (process.platform !== \"win32\") await fs.chmod(temp, 0o600);\n\tawait fs.rename(temp, filePath);\n}\n\nexport function sessionTokenWarnings(config: { endpoint?: string; sessionToken?: string }) {\n\tif (!isCloudflareR2Endpoint(config.endpoint) || !config.sessionToken) return [];\n\treturn [\n\t\t\"session token: configured for Cloudflare R2; if R2 rejects X-Amz-Security-Token, pi-sync retries once without it. R2 static access keys usually do not need a session token.\",\n\t];\n}\n\nexport function syncSessionsWarnings(config: { include: readonly string[] }) {\n\tif (!config.include.includes(\"sessions\")) return [];\n\treturn [\n\t\t\"sessions: included; Pi session JSONL can contain prompts, tool output, file paths, images, and secrets. Sync sessions only to storage you trust.\",\n\t];\n}\n\nexport function isCloudflareR2Endpoint(endpoint: string | undefined) {\n\tconst value = endpoint?.trim();\n\tif (!value) return false;\n\ttry {\n\t\tconst hostname = new URL(value).hostname.toLowerCase();\n\t\treturn (\n\t\t\thostname === \"r2.cloudflarestorage.com\" || hostname.endsWith(\".r2.cloudflarestorage.com\")\n\t\t);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport function isEnabled(value: boolean | string | undefined, defaultValue: boolean) {\n\tif (value === undefined) return defaultValue;\n\tif (typeof value === \"boolean\") return value;\n\treturn ![\"0\", \"false\", \"no\", \"off\"].includes(value.trim().toLowerCase());\n}\n\nexport function isExplicitlyEnabled(value: boolean | string | undefined) {\n\tif (typeof value === \"boolean\") return value;\n\treturn [\"1\", \"true\", \"yes\", \"on\"].includes(value?.trim().toLowerCase() ?? \"\");\n}\n\nfunction hasControlCharacter(value: string) {\n\t// biome-ignore lint/suspicious/noControlCharactersInRegex: Stored settings cannot contain controls.\n\treturn /[\\u0000-\\u001f\\u007f-\\u009f]/u.test(value);\n}\n\nexport { isMissingConfigError } from \"./config-errors.js\";\n", "const DEFAULT_PATH = \"pi-sync\";\n\nexport function normalizeWebDavIdentityUrl(value: string) {\n\ttry {\n\t\tconst url = new URL(value.trim());\n\t\turl.username = \"\";\n\t\turl.password = \"\";\n\t\turl.search = \"\";\n\t\turl.hash = \"\";\n\t\turl.pathname = `${url.pathname.replace(/\\/+$/u, \"\")}/`;\n\t\treturn url.toString();\n\t} catch {\n\t\treturn value.trim();\n\t}\n}\n\nexport function normalizeWebDavUrl(value: string | undefined) {\n\tconst normalized = normalizeOptionalString(value);\n\tif (!normalized) return undefined;\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(normalized);\n\t} catch {\n\t\tthrow new Error(\"Invalid pi-sync WebDAV URL.\");\n\t}\n\tif (url.username || url.password || url.search || url.hash) {\n\t\tthrow new Error(\n\t\t\t\"Invalid pi-sync WebDAV URL: credentials, query, and fragment are not allowed.\",\n\t\t);\n\t}\n\tconst loopback =\n\t\turl.hostname === \"127.0.0.1\" ||\n\t\turl.hostname === \"localhost\" ||\n\t\turl.hostname === \"[::1]\" ||\n\t\turl.hostname === \"::1\";\n\tif (url.protocol !== \"https:\" && !(url.protocol === \"http:\" && loopback)) {\n\t\tthrow new Error(\"Invalid pi-sync WebDAV URL: HTTPS is required except for loopback.\");\n\t}\n\turl.pathname = `${url.pathname.replace(/\\/+$/u, \"\")}/`;\n\treturn url.toString();\n}\n\nexport function normalizeWebDavPath(value: string | undefined) {\n\tconst normalized = trimSlashes(normalizeOptionalString(value) ?? DEFAULT_PATH);\n\tif (\n\t\t!normalized ||\n\t\tnormalized.includes(\"\\\\\") ||\n\t\thasControlCharacter(normalized) ||\n\t\tnormalized.split(\"/\").some((segment) => !segment || segment === \".\" || segment === \"..\")\n\t) {\n\t\tthrow new Error(\"Invalid pi-sync WebDAV path.\");\n\t}\n\treturn normalized;\n}\n\nexport function validateWebDavNamespace(value: string) {\n\tif (\n\t\tvalue === \".\" ||\n\t\tvalue === \"..\" ||\n\t\tvalue.includes(\"/\") ||\n\t\tvalue.includes(\"\\\\\") ||\n\t\thasControlCharacter(value)\n\t) {\n\t\tthrow new Error(\"Invalid pi-sync WebDAV namespace.\");\n\t}\n}\n\nexport function validateWebDavCredentials(username: string, password?: string) {\n\tif (\n\t\tusername.includes(\":\") ||\n\t\thasControlCharacter(username) ||\n\t\t(password !== undefined && hasControlCharacter(password))\n\t) {\n\t\tthrow new Error(\"Invalid pi-sync WebDAV credentials.\");\n\t}\n}\n\nfunction normalizeOptionalString(value: string | undefined) {\n\tconst normalized = value?.trim();\n\treturn normalized || undefined;\n}\n\nfunction trimSlashes(value: string) {\n\treturn value.replace(/^\\/+|\\/+$/gu, \"\");\n}\n\nfunction hasControlCharacter(value: string) {\n\treturn [...value].some((character) => {\n\t\tconst code = character.codePointAt(0) ?? 0;\n\t\treturn code < 0x20 || (code >= 0x7f && code <= 0x9f);\n\t});\n}\n", "export function isMissingConfigError(error: unknown) {\n\treturn (\n\t\terror instanceof Error &&\n\t\t(error.message.startsWith(\"Missing pi-sync settings.\") ||\n\t\t\terror.message === \"No sync setups are configured.\")\n\t);\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["installed", "randomUUID", "fs", "path", "getAgentDir", "path", "hasControlCharacter", "path", "getAgentDir", "path", "fs", "randomUUID", "hasControlCharacter"]
7
+ }
@@ -3,20 +3,20 @@
3
3
  import {
4
4
  SyncSetupReviewChangedError,
5
5
  updateSyncSetup
6
- } from "./chunk-4F3W4CSC.ts";
6
+ } from "./chunk-DFXBKHGN.ts";
7
7
  import {
8
8
  createSyncBackend,
9
9
  readSnapshotForHead
10
- } from "./chunk-FR6CVXAL.ts";
10
+ } from "./chunk-5LZALPCD.ts";
11
11
  import {
12
12
  errorMessage,
13
13
  safeTerminalText
14
- } from "./chunk-W64NEHXT.ts";
14
+ } from "./chunk-C7LXZ3UH.ts";
15
15
  import {
16
16
  loadConfig,
17
17
  loadPartialConfig,
18
18
  syncConfigReviewFingerprint
19
- } from "./chunk-APZVBSM6.ts";
19
+ } from "./chunk-5T442OP3.ts";
20
20
  import {
21
21
  compareSyncInclude,
22
22
  inspectRemoteSelection,
@@ -652,4 +652,4 @@ export {
652
652
  runCancellableOperation,
653
653
  showRemoteSelectionReview
654
654
  };
655
- //# sourceMappingURL=chunk-5WJNWFTG.ts.map
655
+ //# sourceMappingURL=chunk-ARN2672F.ts.map
@@ -2,10 +2,10 @@
2
2
  // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
3
3
  import {
4
4
  fileHashMap
5
- } from "./chunk-RGJ6SOYR.ts";
5
+ } from "./chunk-JF6MZCT4.ts";
6
6
  import {
7
7
  agentDir
8
- } from "./chunk-APZVBSM6.ts";
8
+ } from "./chunk-5T442OP3.ts";
9
9
  import {
10
10
  inspectRemoteSelection
11
11
  } from "./chunk-YQ6UW7IF.ts";
@@ -164,4 +164,4 @@ export {
164
164
  publicationCapabilityDescription,
165
165
  safeTerminalText
166
166
  };
167
- //# sourceMappingURL=chunk-W64NEHXT.ts.map
167
+ //# sourceMappingURL=chunk-C7LXZ3UH.ts.map
@@ -6,7 +6,7 @@ import {
6
6
  syncSetupStorageReview,
7
7
  updateLocalConfig,
8
8
  validateConfigName
9
- } from "./chunk-APZVBSM6.ts";
9
+ } from "./chunk-5T442OP3.ts";
10
10
  import {
11
11
  normalizeSyncInclude
12
12
  } from "./chunk-YQ6UW7IF.ts";
@@ -25,6 +25,7 @@ async function saveNewV3Settings(input, signal) {
25
25
  version: 3,
26
26
  activeSyncSetup: input.setupName,
27
27
  onSwitch: "ask-before-pull",
28
+ skipSecretScan: false,
28
29
  storageConnections: { [input.connectionName]: structuredClone(input.connection) },
29
30
  syncSetups: {
30
31
  [input.setupName]: {
@@ -192,4 +193,4 @@ export {
192
193
  removeSyncSetup,
193
194
  removeStorageConnection
194
195
  };
195
- //# sourceMappingURL=chunk-4F3W4CSC.ts.map
196
+ //# sourceMappingURL=chunk-DFXBKHGN.ts.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/settings-management.ts"],
4
+ "sourcesContent": ["import {\n\teffectiveSyncSetupRemoteIdentity,\n\tlocalConfigPath,\n\tnormalizeSyncInclude,\n\ttype SyncSetupStorageReview,\n\tsyncSetupStorageReview,\n\tupdateLocalConfig,\n\tvalidateConfigName,\n} from \"./config.js\";\nimport type { PiSyncSettingsV3, StorageConnectionSettings, SyncSetupSettings } from \"./types.js\";\n\nexport class SyncSetupReviewChangedError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"SyncSetupReviewChangedError\";\n\t}\n}\n\nexport async function saveNewV3Settings(\n\tinput: {\n\t\tsetupName: string;\n\t\tconnectionName: string;\n\t\tconnection: StorageConnectionSettings;\n\t\tsetup: SyncSetupSettings;\n\t},\n\tsignal?: AbortSignal,\n) {\n\tvalidateConfigName(input.setupName, \"sync setup\");\n\tvalidateConfigName(input.connectionName, \"storage connection\");\n\tconst settings: PiSyncSettingsV3 = {\n\t\tversion: 3,\n\t\tactiveSyncSetup: input.setupName,\n\t\tonSwitch: \"ask-before-pull\",\n\t\tskipSecretScan: false,\n\t\tstorageConnections: { [input.connectionName]: structuredClone(input.connection) },\n\t\tsyncSetups: {\n\t\t\t[input.setupName]: {\n\t\t\t\t...structuredClone(input.setup),\n\t\t\t\tstorage: { ...input.setup.storage, connection: input.connectionName },\n\t\t\t},\n\t\t},\n\t};\n\tawait updateLocalConfig((current) => {\n\t\tif (Object.keys(current.storageConnections).length || Object.keys(current.syncSetups).length) {\n\t\t\tthrow new Error(`Settings already exist: ${localConfigPath()}`);\n\t\t}\n\t\treturn settings;\n\t}, signal);\n\treturn settings;\n}\n\nexport async function addStorageConnection(\n\tname: string,\n\tconnection: StorageConnectionSettings,\n\tsignal?: AbortSignal,\n) {\n\tvalidateConfigName(name, \"storage connection\");\n\tawait updateSettings((settings) => {\n\t\tif (Object.hasOwn(settings.storageConnections, name)) {\n\t\t\tthrow new Error(`Storage connection already exists: ${name}`);\n\t\t}\n\t\treturn {\n\t\t\t...settings,\n\t\t\tstorageConnections: {\n\t\t\t\t...settings.storageConnections,\n\t\t\t\t[name]: structuredClone(connection),\n\t\t\t},\n\t\t};\n\t}, signal);\n}\n\nexport async function updateStorageConnection(\n\tname: string,\n\tupdate: (connection: StorageConnectionSettings) => StorageConnectionSettings,\n\texpectedSetups?: readonly string[],\n\tsignal?: AbortSignal,\n) {\n\tvalidateConfigName(name, \"storage connection\");\n\tawait updateSettings((settings) => {\n\t\tconst connection = settings.storageConnections[name];\n\t\tif (!connection) throw new Error(`Storage connection not found: ${name}`);\n\t\tconst currentSetups = referencingSetupNames(settings.syncSetups, name);\n\t\tif (expectedSetups && !sameNames(currentSetups, expectedSetups)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Storage connection \u201C${name}\u201D usage changed while it was open; reopen it and review the affected sync setups.`,\n\t\t\t);\n\t\t}\n\t\tconst nextConnection = update(structuredClone(connection));\n\t\tconst nextConnections = { ...settings.storageConnections, [name]: nextConnection };\n\t\tassertUniqueLocations(settings.syncSetups, nextConnections);\n\t\treturn { ...settings, storageConnections: nextConnections };\n\t}, signal);\n}\n\nexport async function addSyncSetup(name: string, setup: SyncSetupSettings, signal?: AbortSignal) {\n\tvalidateConfigName(name, \"sync setup\");\n\tawait updateSettings((settings) => {\n\t\tif (Object.hasOwn(settings.syncSetups, name))\n\t\t\tthrow new Error(`Sync setup already exists: ${name}`);\n\t\tif (!Object.hasOwn(settings.storageConnections, setup.storage.connection)) {\n\t\t\tthrow new Error(`Storage connection not found: ${setup.storage.connection}`);\n\t\t}\n\t\tconst nextSetups = { ...settings.syncSetups, [name]: structuredClone(setup) };\n\t\tassertUniqueLocations(nextSetups, settings.storageConnections);\n\t\treturn {\n\t\t\t...settings,\n\t\t\tsyncSetups: nextSetups,\n\t\t\t...(settings.activeSyncSetup ? {} : { activeSyncSetup: name }),\n\t\t};\n\t}, signal);\n}\n\nexport async function updateSyncSetup(\n\tname: string,\n\tupdate: (setup: SyncSetupSettings) => SyncSetupSettings,\n\toptions: {\n\t\texpectedStorage?: SyncSetupStorageReview;\n\t\texpectedInclude?: readonly string[];\n\t\tsignal?: AbortSignal;\n\t} = {},\n) {\n\tvalidateConfigName(name, \"sync setup\");\n\tawait updateSettings((settings) => {\n\t\tconst setup = settings.syncSetups[name];\n\t\tif (!setup) throw new Error(`Sync setup not found: ${name}`);\n\t\tif (\n\t\t\toptions.expectedInclude &&\n\t\t\t!sameNames(normalizeSyncInclude(setup.sync.include), options.expectedInclude)\n\t\t) {\n\t\t\tthrow new SyncSetupReviewChangedError(\n\t\t\t\t`Sync setup \u201C${name}\u201D included content changed while it was open; reopen it and review the current selection.`,\n\t\t\t);\n\t\t}\n\t\tif (options.expectedStorage) {\n\t\t\tconst connectionName = setup.storage.connection;\n\t\t\tconst connection = settings.storageConnections[connectionName];\n\t\t\tif (\n\t\t\t\t!connection ||\n\t\t\t\t!sameStorageReview(\n\t\t\t\t\tsyncSetupStorageReview(name, setup, connectionName, connection),\n\t\t\t\t\toptions.expectedStorage,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tthrow new SyncSetupReviewChangedError(\n\t\t\t\t\t`Sync setup \u201C${name}\u201D storage changed while it was open; reopen it and review the current storage location.`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tconst nextSetup = update(structuredClone(setup));\n\t\tif (!Object.hasOwn(settings.storageConnections, nextSetup.storage.connection)) {\n\t\t\tthrow new Error(`Storage connection not found: ${nextSetup.storage.connection}`);\n\t\t}\n\t\tconst nextSetups = { ...settings.syncSetups, [name]: nextSetup };\n\t\tassertUniqueLocations(nextSetups, settings.storageConnections);\n\t\treturn { ...settings, syncSetups: nextSetups };\n\t}, options.signal);\n}\n\nexport async function removeSyncSetup(name: string, signal?: AbortSignal) {\n\tvalidateConfigName(name, \"sync setup\");\n\tawait updateSettings((settings) => {\n\t\tif (!Object.hasOwn(settings.syncSetups, name)) throw new Error(`Sync setup not found: ${name}`);\n\t\tconst isCurrent = settings.activeSyncSetup === name;\n\t\tif (isCurrent && Object.keys(settings.syncSetups).length > 1) {\n\t\t\tthrow new Error(\"Switch to another sync setup before removing the current setup.\");\n\t\t}\n\t\tconst syncSetups = { ...settings.syncSetups };\n\t\tdelete syncSetups[name];\n\t\tconst next = { ...settings, syncSetups };\n\t\tif (isCurrent) delete next.activeSyncSetup;\n\t\treturn next;\n\t}, signal);\n}\n\nexport async function removeStorageConnection(name: string, signal?: AbortSignal) {\n\tvalidateConfigName(name, \"storage connection\");\n\tawait updateSettings((settings) => {\n\t\tconst referenced = referencingSetupNames(settings.syncSetups, name)[0];\n\t\tif (referenced) {\n\t\t\tthrow new Error(`Storage connection \u201C${name}\u201D is used by sync setup \u201C${referenced}\u201D.`);\n\t\t}\n\t\tif (!Object.hasOwn(settings.storageConnections, name)) {\n\t\t\tthrow new Error(`Storage connection not found: ${name}`);\n\t\t}\n\t\tconst storageConnections = { ...settings.storageConnections };\n\t\tdelete storageConnections[name];\n\t\treturn { ...settings, storageConnections };\n\t}, signal);\n}\n\nasync function updateSettings(\n\tupdate: (settings: PiSyncSettingsV3) => PiSyncSettingsV3,\n\tsignal?: AbortSignal,\n) {\n\treturn updateLocalConfig((settings) => {\n\t\tif (settings.version !== 3) {\n\t\t\tthrow new Error(\"Storage connections and sync setups require version 3 pi-sync settings.\");\n\t\t}\n\t\treturn update(settings);\n\t}, signal);\n}\n\nfunction referencingSetupNames(setups: Record<string, SyncSetupSettings>, connection: string) {\n\treturn Object.entries(setups)\n\t\t.filter(([, setup]) => setup.storage.connection === connection)\n\t\t.map(([name]) => name)\n\t\t.sort((left, right) => left.localeCompare(right));\n}\n\nfunction assertUniqueLocations(\n\tsetups: Record<string, SyncSetupSettings>,\n\tconnections: Record<string, StorageConnectionSettings>,\n) {\n\tconst identities = new Map<string, string>();\n\tfor (const [name, setup] of Object.entries(setups)) {\n\t\tconst connection = connections[setup.storage.connection];\n\t\tif (!connection) throw new Error(`Storage connection not found: ${setup.storage.connection}`);\n\t\tconst identity = effectiveSyncSetupRemoteIdentity(setup, connection);\n\t\tconst previous = identities.get(identity);\n\t\tif (previous) {\n\t\t\tthrow new Error(`Sync setup \u201C${name}\u201D duplicates the storage location of \u201C${previous}\u201D.`);\n\t\t}\n\t\tidentities.set(identity, name);\n\t}\n}\n\nfunction sameNames(left: readonly string[], right: readonly string[]) {\n\treturn left.length === right.length && left.every((name, index) => name === right[index]);\n}\n\nfunction sameStorageReview(left: SyncSetupStorageReview, right: SyncSetupStorageReview) {\n\treturn (\n\t\tleft.connectionName === right.connectionName &&\n\t\tleft.storageKind === right.storageKind &&\n\t\tleft.storagePath === right.storagePath &&\n\t\tleft.bucket === right.bucket &&\n\t\tleft.branch === right.branch\n\t);\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -2,10 +2,10 @@
2
2
  // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
3
3
  import {
4
4
  safeTerminalText
5
- } from "./chunk-W64NEHXT.ts";
5
+ } from "./chunk-C7LXZ3UH.ts";
6
6
  import {
7
7
  syncConfigReviewFingerprint
8
- } from "./chunk-APZVBSM6.ts";
8
+ } from "./chunk-5T442OP3.ts";
9
9
  import {
10
10
  compareSyncInclude,
11
11
  sameSyncInclude
@@ -79,4 +79,4 @@ export {
79
79
  syncAttentionMatchesConfig,
80
80
  createSyncAttentionController
81
81
  };
82
- //# sourceMappingURL=chunk-JNOOSPEW.ts.map
82
+ //# sourceMappingURL=chunk-E4COSV32.ts.map
@@ -6,7 +6,7 @@ import {
6
6
  import {
7
7
  SetupPullRequiresUiError,
8
8
  safeTerminalText
9
- } from "./chunk-W64NEHXT.ts";
9
+ } from "./chunk-C7LXZ3UH.ts";
10
10
  import {
11
11
  configuredSyncSetupNames,
12
12
  loadConfig,
@@ -14,7 +14,7 @@ import {
14
14
  syncConfigReviewIdentity,
15
15
  syncSetupReviewIdentity,
16
16
  updateLocalConfig
17
- } from "./chunk-APZVBSM6.ts";
17
+ } from "./chunk-5T442OP3.ts";
18
18
 
19
19
  // src/setup-switch.ts
20
20
  var SETUP_SWITCH_ACTION_OPTIONS = [
@@ -131,4 +131,4 @@ export {
131
131
  saveOnSwitch,
132
132
  useSyncSetup
133
133
  };
134
- //# sourceMappingURL=chunk-BHJUISB4.ts.map
134
+ //# sourceMappingURL=chunk-GLQLN5GV.ts.map
@@ -3,7 +3,7 @@
3
3
  import {
4
4
  agentDir,
5
5
  configuredSessionDir
6
- } from "./chunk-APZVBSM6.ts";
6
+ } from "./chunk-5T442OP3.ts";
7
7
  import {
8
8
  DEFAULT_SYNC_INCLUDE,
9
9
  canonicalSnapshotPathForConfig,
@@ -353,4 +353,4 @@ export {
353
353
  mergeRemotePreservedFiles,
354
354
  mergeRemoteSessionFiles
355
355
  };
356
- //# sourceMappingURL=chunk-EWX3TPLQ.ts.map
356
+ //# sourceMappingURL=chunk-HVUSHMVL.ts.map
@@ -3,7 +3,7 @@
3
3
  import {
4
4
  filterSnapshotForConfigPolicy,
5
5
  isSessionPath
6
- } from "./chunk-EWX3TPLQ.ts";
6
+ } from "./chunk-HVUSHMVL.ts";
7
7
  import {
8
8
  canonicalSnapshotPathForConfig,
9
9
  customIncludePathsByLower,
@@ -125,4 +125,4 @@ export {
125
125
  canPullRemoteSettingsOnFirstSync,
126
126
  canPullRemoteSessionsOnFirstSync
127
127
  };
128
- //# sourceMappingURL=chunk-RGJ6SOYR.ts.map
128
+ //# sourceMappingURL=chunk-JF6MZCT4.ts.map
@@ -3,7 +3,7 @@
3
3
  import {
4
4
  ensureStateDir,
5
5
  lockPath
6
- } from "./chunk-APZVBSM6.ts";
6
+ } from "./chunk-5T442OP3.ts";
7
7
  import {
8
8
  LOCKFILE_FS_ADAPTER,
9
9
  LOCK_GUARD_STALE_MS,
@@ -256,4 +256,4 @@ export {
256
256
  isStaleLock,
257
257
  unlock
258
258
  };
259
- //# sourceMappingURL=chunk-LJDSHNS3.ts.map
259
+ //# sourceMappingURL=chunk-WSOBYHIZ.ts.map
@@ -2,13 +2,13 @@
2
2
  // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
3
3
  import {
4
4
  withLock
5
- } from "./chunk-LJDSHNS3.ts";
5
+ } from "./chunk-WSOBYHIZ.ts";
6
6
  import {
7
7
  sessionStorageRoot
8
- } from "./chunk-EWX3TPLQ.ts";
8
+ } from "./chunk-HVUSHMVL.ts";
9
9
  import {
10
10
  agentDir
11
- } from "./chunk-APZVBSM6.ts";
11
+ } from "./chunk-5T442OP3.ts";
12
12
  import {
13
13
  stateDir
14
14
  } from "./chunk-F5QL2GPY.ts";
@@ -200,4 +200,4 @@ export {
200
200
  recoverSnapshotTransactionsOnStartup,
201
201
  recoverPendingSnapshotTransactions
202
202
  };
203
- //# sourceMappingURL=chunk-3NDD5QPM.ts.map
203
+ //# sourceMappingURL=chunk-X7SQ2EQM.ts.map
@@ -2,12 +2,12 @@
2
2
  // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
3
3
  import {
4
4
  updateSyncSetup
5
- } from "./chunk-4F3W4CSC.ts";
5
+ } from "./chunk-DFXBKHGN.ts";
6
6
  import {
7
7
  agentDir,
8
8
  loadConfig,
9
9
  localConfigPath
10
- } from "./chunk-APZVBSM6.ts";
10
+ } from "./chunk-5T442OP3.ts";
11
11
  import "./chunk-F5QL2GPY.ts";
12
12
  import {
13
13
  BUILT_IN_SYNC_ROOTS,
@@ -287,4 +287,4 @@ function safeTerminalText(value) {
287
287
  export {
288
288
  showFileSelection
289
289
  };
290
- //# sourceMappingURL=file-selection-4UABOP44.ts.map
290
+ //# sourceMappingURL=file-selection-RKEHALNQ.ts.map
@@ -0,0 +1,18 @@
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-44LPGQTI.ts";
6
+ import "./chunk-ARN2672F.ts";
7
+ import "./chunk-DFXBKHGN.ts";
8
+ import "./chunk-5LZALPCD.ts";
9
+ import "./chunk-C7LXZ3UH.ts";
10
+ import "./chunk-JF6MZCT4.ts";
11
+ import "./chunk-HVUSHMVL.ts";
12
+ import "./chunk-5T442OP3.ts";
13
+ import "./chunk-F5QL2GPY.ts";
14
+ import "./chunk-YQ6UW7IF.ts";
15
+ export {
16
+ dispatchManagerResult
17
+ };
18
+ //# sourceMappingURL=manager-result-dispatcher-LWPYJAD5.ts.map
@@ -2,7 +2,7 @@
2
2
  // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
3
3
  import {
4
4
  dispatchManagerResult
5
- } from "./chunk-LONPFFNP.ts";
5
+ } from "./chunk-44LPGQTI.ts";
6
6
  import {
7
7
  errorMessage,
8
8
  ownRecord,
@@ -10,7 +10,7 @@ import {
10
10
  requiredInput,
11
11
  runCancellableOperation,
12
12
  safeTerminalText as safeTerminalText2
13
- } from "./chunk-5WJNWFTG.ts";
13
+ } from "./chunk-ARN2672F.ts";
14
14
  import {
15
15
  addStorageConnection,
16
16
  addSyncSetup,
@@ -19,31 +19,31 @@ import {
19
19
  saveNewV3Settings,
20
20
  updateStorageConnection,
21
21
  updateSyncSetup
22
- } from "./chunk-4F3W4CSC.ts";
22
+ } from "./chunk-DFXBKHGN.ts";
23
23
  import {
24
24
  syncAttentionMatchesConfig
25
- } from "./chunk-JNOOSPEW.ts";
25
+ } from "./chunk-E4COSV32.ts";
26
26
  import {
27
27
  SETUP_SWITCH_ACTION_OPTIONS,
28
28
  saveOnSwitch,
29
29
  setupSwitchActionFromLabel,
30
30
  setupSwitchActionLabel,
31
31
  useSyncSetup
32
- } from "./chunk-BHJUISB4.ts";
32
+ } from "./chunk-GLQLN5GV.ts";
33
33
  import {
34
34
  setSyncSetupCompletions
35
35
  } from "./chunk-4U6AFLJB.ts";
36
- import "./chunk-FR6CVXAL.ts";
36
+ import "./chunk-5LZALPCD.ts";
37
37
  import {
38
38
  inspectLock,
39
39
  isLockGuardHeld,
40
40
  isStaleLock
41
- } from "./chunk-LJDSHNS3.ts";
41
+ } from "./chunk-WSOBYHIZ.ts";
42
42
  import {
43
43
  safeTerminalText
44
- } from "./chunk-W64NEHXT.ts";
45
- import "./chunk-RGJ6SOYR.ts";
46
- import "./chunk-EWX3TPLQ.ts";
44
+ } from "./chunk-C7LXZ3UH.ts";
45
+ import "./chunk-JF6MZCT4.ts";
46
+ import "./chunk-HVUSHMVL.ts";
47
47
  import {
48
48
  activeLocalConfigPath,
49
49
  configuredSyncSetupNames,
@@ -57,9 +57,10 @@ import {
57
57
  readLocalConfigObject,
58
58
  readStateForConfig,
59
59
  syncConfigReviewIdentity,
60
+ updateLocalConfig,
60
61
  validateWebDavCredentials,
61
62
  validateWebDavNamespace
62
- } from "./chunk-APZVBSM6.ts";
63
+ } from "./chunk-5T442OP3.ts";
63
64
  import {
64
65
  normalizeGitBranch,
65
66
  normalizeGitDirectory,
@@ -384,7 +385,7 @@ function blockedSyncMenuItem(label, manager) {
384
385
  };
385
386
  }
386
387
  async function showManagerAttention(ctx, attention, runRoute, signal, onSelectionResolved) {
387
- const { showRemoteSelectionReview } = await import("./remote-selection-ui-LHSAGKGA.ts");
388
+ const { showRemoteSelectionReview } = await import("./remote-selection-ui-NUF5P4ZJ.ts");
388
389
  if (signal?.aborted) return "close";
389
390
  const review = await showRemoteSelectionReview(
390
391
  ctx,
@@ -1167,6 +1168,14 @@ async function showSyncSettings(ctx, runRoute, signal) {
1167
1168
  values: ["On", "Off"],
1168
1169
  action: "automatic"
1169
1170
  },
1171
+ {
1172
+ id: "skipSecretScan",
1173
+ label: "Skip secret scan",
1174
+ description: "Allow pushes without checking managed local files for possible secrets.",
1175
+ currentValue: state.skipSecretScan ? "On" : "Off",
1176
+ values: ["On", "Off"],
1177
+ action: "skip-secret-scan"
1178
+ },
1170
1179
  {
1171
1180
  id: "onSwitch",
1172
1181
  label: "After switching setup",
@@ -1216,6 +1225,25 @@ async function showSyncSettings(ctx, runRoute, signal) {
1216
1225
  return { kind: "rejected" };
1217
1226
  }
1218
1227
  },
1228
+ "skip-secret-scan": async ({ value, signal: actionSignal }) => {
1229
+ const skipSecretScan = value === "On";
1230
+ const mutationSignal = signal ? AbortSignal.any([signal, actionSignal]) : actionSignal;
1231
+ try {
1232
+ const latest = await loadConfig(setupName);
1233
+ if (mutationSignal.aborted) return { kind: "rejected" };
1234
+ if (latest.skipSecretScan === skipSecretScan) return { kind: "stay" };
1235
+ await updateLocalConfig((settings) => ({ ...settings, skipSecretScan }), mutationSignal);
1236
+ if (mutationSignal.aborted) return { kind: "rejected" };
1237
+ ctx.ui.notify(
1238
+ `Secret scan ${skipSecretScan ? "disabled" : "enabled"} for pushes.`,
1239
+ "info"
1240
+ );
1241
+ return { kind: "stay" };
1242
+ } catch (error) {
1243
+ if (!mutationSignal.aborted) notifySaveFailure(ctx, error);
1244
+ return { kind: "rejected" };
1245
+ }
1246
+ },
1219
1247
  "on-switch": async ({ value, signal: actionSignal }) => {
1220
1248
  const action = value ? setupSwitchActionFromLabel(value) : void 0;
1221
1249
  if (!action) return { kind: "rejected" };
@@ -1240,7 +1268,7 @@ async function showSyncSettings(ctx, runRoute, signal) {
1240
1268
  },
1241
1269
  "remote-include": async ({ signal: actionSignal }) => {
1242
1270
  const reviewSignal = signal ? AbortSignal.any([signal, actionSignal]) : actionSignal;
1243
- const { showRemoteSelectionReview } = await import("./remote-selection-ui-LHSAGKGA.ts");
1271
+ const { showRemoteSelectionReview } = await import("./remote-selection-ui-NUF5P4ZJ.ts");
1244
1272
  if (reviewSignal.aborted) return { kind: "rejected" };
1245
1273
  const review = await showRemoteSelectionReview(ctx, setupName, reviewSignal, void 0, {
1246
1274
  origin: "settings",
@@ -2754,4 +2782,4 @@ export {
2754
2782
  showSetupWizard,
2755
2783
  showSyncManager
2756
2784
  };
2757
- //# sourceMappingURL=manager-ui-QO2P4V3Z.ts.map
2785
+ //# sourceMappingURL=manager-ui-NF4RUHBY.ts.map