@narumitw/pi-sync 0.49.9 → 0.49.11

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 (61) hide show
  1. package/README.md +10 -1
  2. package/dist/chunks/chunk-3GRWMWUZ.ts +213 -0
  3. package/dist/chunks/chunk-3GRWMWUZ.ts.map +7 -0
  4. package/dist/chunks/chunk-3NDD5QPM.ts +203 -0
  5. package/dist/chunks/chunk-3NDD5QPM.ts.map +7 -0
  6. package/dist/chunks/chunk-4F3W4CSC.ts +195 -0
  7. package/dist/chunks/chunk-4F3W4CSC.ts.map +7 -0
  8. package/dist/chunks/chunk-4U6AFLJB.ts +221 -0
  9. package/dist/chunks/chunk-4U6AFLJB.ts.map +7 -0
  10. package/dist/chunks/chunk-5MQ76BK5.ts +34 -0
  11. package/dist/chunks/chunk-5MQ76BK5.ts.map +7 -0
  12. package/dist/chunks/chunk-APZVBSM6.ts +1238 -0
  13. package/dist/chunks/chunk-APZVBSM6.ts.map +7 -0
  14. package/dist/chunks/chunk-BHJUISB4.ts +134 -0
  15. package/dist/chunks/chunk-BHJUISB4.ts.map +7 -0
  16. package/dist/chunks/chunk-D3S54OXI.ts +653 -0
  17. package/dist/chunks/chunk-D3S54OXI.ts.map +7 -0
  18. package/dist/chunks/chunk-EWX3TPLQ.ts +356 -0
  19. package/dist/chunks/chunk-EWX3TPLQ.ts.map +7 -0
  20. package/dist/chunks/chunk-F5QL2GPY.ts +341 -0
  21. package/dist/chunks/chunk-F5QL2GPY.ts.map +7 -0
  22. package/dist/chunks/chunk-FR6CVXAL.ts +81 -0
  23. package/dist/chunks/chunk-FR6CVXAL.ts.map +7 -0
  24. package/dist/chunks/chunk-HGV24P4T.ts +53 -0
  25. package/dist/chunks/chunk-HGV24P4T.ts.map +7 -0
  26. package/dist/chunks/chunk-JNOOSPEW.ts +82 -0
  27. package/dist/chunks/chunk-JNOOSPEW.ts.map +7 -0
  28. package/dist/chunks/chunk-LJDSHNS3.ts +259 -0
  29. package/dist/chunks/chunk-LJDSHNS3.ts.map +7 -0
  30. package/dist/chunks/chunk-RGJ6SOYR.ts +128 -0
  31. package/dist/chunks/chunk-RGJ6SOYR.ts.map +7 -0
  32. package/dist/chunks/chunk-W64NEHXT.ts +167 -0
  33. package/dist/chunks/chunk-W64NEHXT.ts.map +7 -0
  34. package/dist/chunks/chunk-YQ6UW7IF.ts +394 -0
  35. package/dist/chunks/chunk-YQ6UW7IF.ts.map +7 -0
  36. package/dist/chunks/file-selection-4UABOP44.ts +290 -0
  37. package/dist/chunks/file-selection-4UABOP44.ts.map +7 -0
  38. package/dist/chunks/git-backend-E3UOUUOM.ts +1104 -0
  39. package/dist/chunks/git-backend-E3UOUUOM.ts.map +7 -0
  40. package/dist/chunks/manager-result-dispatcher-YKBLZ7KL.ts +18 -0
  41. package/dist/chunks/manager-result-dispatcher-YKBLZ7KL.ts.map +7 -0
  42. package/dist/chunks/manager-ui-7E25VWUP.ts +2754 -0
  43. package/dist/chunks/manager-ui-7E25VWUP.ts.map +7 -0
  44. package/dist/chunks/remote-selection-ui-J6OW5DKZ.ts +17 -0
  45. package/dist/chunks/remote-selection-ui-J6OW5DKZ.ts.map +7 -0
  46. package/dist/chunks/s3-backend-3QZGO2EF.ts +680 -0
  47. package/dist/chunks/s3-backend-3QZGO2EF.ts.map +7 -0
  48. package/dist/chunks/setup-switch-X3W3FALZ.ts +27 -0
  49. package/dist/chunks/setup-switch-X3W3FALZ.ts.map +7 -0
  50. package/dist/chunks/snapshot-WBSV4MQG.ts +45 -0
  51. package/dist/chunks/snapshot-WBSV4MQG.ts.map +7 -0
  52. package/dist/chunks/sync-operations-MPAFVVHA.ts +1112 -0
  53. package/dist/chunks/sync-operations-MPAFVVHA.ts.map +7 -0
  54. package/dist/chunks/sync-state-36H7ULG2.ts +41 -0
  55. package/dist/chunks/sync-state-36H7ULG2.ts.map +7 -0
  56. package/dist/chunks/webdav-backend-ZD5RHRIU.ts +869 -0
  57. package/dist/chunks/webdav-backend-ZD5RHRIU.ts.map +7 -0
  58. package/dist/index.ts +668 -0
  59. package/dist/index.ts.map +7 -0
  60. package/package.json +10 -6
  61. package/src/state-directory.ts +55 -1
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/sync-extension.ts"],
4
+ "sourcesContent": ["import type {\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionContext,\n} from \"@earendil-works/pi-coding-agent\";\nimport type { RunRouteResult } from \"./cancellable-operation.js\";\nimport {\n\tcompleteSyncArguments,\n\tparseOptions,\n\tresolveSyncCommand,\n\tsetSyncSetupCompletions,\n\tsplitArgs,\n\tusage,\n\tvalidateCommandOptions,\n} from \"./command.js\";\nimport {\n\tactiveLocalConfigPath,\n\tconfiguredSyncSetupNames,\n\tconsumeLocalConfigMigrationNotice,\n\tcreateLocalConfigDocument,\n\tensureStateDir,\n\tisMissingConfigError,\n\tloadConfig,\n\tloadPartialConfig,\n\tlocalConfigPath,\n\tlocalConfigTemplate,\n\treadLocalConfigObject,\n\treadStateForConfig,\n\tsessionTokenWarnings,\n\tsyncSessionsWarnings,\n} from \"./config.js\";\nimport { unlock, withLock } from \"./lock.js\";\nimport { recoverSnapshotTransactionsOnStartup } from \"./snapshot-transaction.js\";\nimport {\n\tmigrateLegacyStateDirectory,\n\tstateDirectoryMigrationNotice,\n\twithStateDirectoryAccess,\n} from \"./state-directory.js\";\nimport {\n\tcreateSyncAttentionController,\n\ttype SyncAttentionController,\n\ttype SyncAttentionOrigin,\n\tsyncAttentionMatchesConfig,\n} from \"./sync-attention.js\";\nimport {\n\terrorMessage,\n\tisSyncDecisionRequiredError,\n\tSetupPullRequiresUiError,\n} from \"./sync-errors.js\";\nimport {\n\tformatRemoteSelectionMismatch,\n\ttype RemoteSelectionDecision,\n\tRemoteSelectionMismatchError,\n} from \"./sync-policy.js\";\nimport type { AnySyncConfig, CommandOptions, SnapshotOptions } from \"./types.js\";\n\nconst STATUS_KEY = \"sync\";\n\ntype SetupSwitchModule = Pick<typeof import(\"./setup-switch.js\"), \"useSyncSetup\">;\ntype SnapshotModule = Pick<typeof import(\"./snapshot.js\"), \"createSnapshot\">;\ntype SyncStateModule = Pick<typeof import(\"./sync-state.js\"), \"hasLocalChanges\">;\ntype SyncOperations = typeof import(\"./sync-operations.js\");\n\nexport interface SyncDependencies {\n\tloadSetupSwitch(): Promise<SetupSwitchModule>;\n\tloadSnapshot(): Promise<SnapshotModule>;\n\tloadSyncState(): Promise<SyncStateModule>;\n\tloadSyncOperations(): Promise<SyncOperations>;\n}\n\ninterface SyncLoaders {\n\tsetupSwitch(): Promise<SetupSwitchModule>;\n\tsnapshot(): Promise<SnapshotModule>;\n\tsyncState(): Promise<SyncStateModule>;\n\toperations(): Promise<SyncOperations>;\n}\n\nconst AUTO_SYNC_OPTIONS: CommandOptions = {\n\tyes: true,\n\tforce: false,\n\tstale: false,\n\tsilent: true,\n\treload: false,\n\tauto: true,\n\targs: [],\n};\nexport default function sync(pi: ExtensionAPI, dependencies: Partial<SyncDependencies> = {}) {\n\tconst loaders: SyncLoaders = {\n\t\tsetupSwitch: cachedModuleLoader(\n\t\t\tdependencies.loadSetupSwitch ?? (() => import(\"./setup-switch.js\")),\n\t\t),\n\t\tsnapshot: cachedModuleLoader(dependencies.loadSnapshot ?? (() => import(\"./snapshot.js\"))),\n\t\tsyncState: cachedModuleLoader(dependencies.loadSyncState ?? (() => import(\"./sync-state.js\"))),\n\t\toperations: cachedModuleLoader(\n\t\t\tdependencies.loadSyncOperations ?? (() => import(\"./sync-operations.js\")),\n\t\t),\n\t};\n\tconst attention = createSyncAttentionController();\n\tlet sessionAbort = new AbortController();\n\tlet shutdownAbort: AbortController | undefined;\n\n\tpi.registerCommand(\"sync\", {\n\t\tdescription: \"Sync Pi settings through Git, WebDAV, R2, or S3-compatible storage\",\n\t\tgetArgumentCompletions: completeSyncArguments,\n\t\thandler: async (args, ctx) => {\n\t\t\tif (!ctx.hasUI) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"/sync requires TUI or RPC mode so results and safety prompts are observable.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst run = () => handleCommand(args, ctx, sessionAbort.signal, loaders, attention);\n\t\t\tif (splitArgs(args)[0] === \"migrate-state\") await run();\n\t\t\telse await withStateDirectoryAccess(run);\n\t\t},\n\t});\n\n\tpi.on(\"session_start\", async (_event, ctx) => {\n\t\tshutdownAbort?.abort(new DOMException(\"Session replaced\", \"AbortError\"));\n\t\tshutdownAbort = undefined;\n\t\tsessionAbort.abort(new DOMException(\"Session replaced\", \"AbortError\"));\n\t\tsessionAbort = new AbortController();\n\t\tconst signal = sessionAbort.signal;\n\t\tattention.reset(ctx);\n\t\tlet decision: RemoteSelectionDecision | undefined;\n\t\ttry {\n\t\t\tdecision = await withStateDirectoryAccess(() => startSession(ctx, signal, loaders));\n\t\t} catch (error) {\n\t\t\tif (signal.aborted) return;\n\t\t\tctx.ui.notify(`pi-sync state access failed: ${errorMessage(error)}`, \"error\");\n\t\t\treturn;\n\t\t}\n\t\tif (!decision || signal.aborted) return;\n\t\tattention.set(decision, \"sync\");\n\t\tif (ctx.mode !== \"tui\") {\n\t\t\tctx.ui.notify(\n\t\t\t\t`pi-sync auto sync skipped: ${formatRemoteSelectionMismatch(\n\t\t\t\t\tdecision.setupName,\n\t\t\t\t\tdecision.localInclude,\n\t\t\t\t\tdecision.remoteInclude,\n\t\t\t\t)}\\nRPC review is read-only.`,\n\t\t\t\t\"warning\",\n\t\t\t);\n\t\t} else if (attention.markOffered()) {\n\t\t\tawait resolveSelectionAttention(ctx, attention, signal, loaders, {\n\t\t\t\tcancelLabel: \"Later\",\n\t\t\t\twithStateAccess: withStateDirectoryAccess,\n\t\t\t});\n\t\t}\n\t\tif (!signal.aborted) attention.publish(ctx);\n\t});\n\n\tpi.on(\"session_shutdown\", async (event, ctx) => {\n\t\tsessionAbort.abort(new DOMException(\"Session shut down\", \"AbortError\"));\n\t\tattention.reset(ctx);\n\t\tshutdownAbort?.abort(new DOMException(\"Session shut down again\", \"AbortError\"));\n\t\tconst controller = new AbortController();\n\t\tshutdownAbort = controller;\n\t\tconst signal = combineSignals(controller.signal, AbortSignal.timeout(30_000));\n\t\tconst reason =\n\t\t\ttypeof event === \"object\" && event ? (event as { reason?: string }).reason : undefined;\n\t\ttry {\n\t\t\tif (reason !== \"reload\") {\n\t\t\t\tawait withStateDirectoryAccess(async () => {\n\t\t\t\t\tif (signal.aborted) return;\n\t\t\t\t\tawait autoPushSessions(ctx, signal, loaders);\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (!signal.aborted) {\n\t\t\t\tctx.ui.notify(`pi-sync session push skipped: ${errorMessage(error)}`, \"warning\");\n\t\t\t}\n\t\t} finally {\n\t\t\tif (shutdownAbort === controller) shutdownAbort = undefined;\n\t\t}\n\t\tif (signal.aborted) return;\n\t\tctx.ui.setStatus(STATUS_KEY, undefined);\n\t});\n}\n\nasync function startSession(ctx: ExtensionContext, signal: AbortSignal, loaders: SyncLoaders) {\n\tif (signal.aborted) return;\n\ttry {\n\t\tconst migrationNotice = stateDirectoryMigrationNotice();\n\t\tif (migrationNotice) ctx.ui.notify(migrationNotice, \"warning\");\n\t} catch (error) {\n\t\tctx.ui.notify(`pi-sync state directory requires attention: ${errorMessage(error)}`, \"error\");\n\t\treturn;\n\t}\n\ttry {\n\t\tawait recoverSnapshotTransactionsOnStartup();\n\t\tif (signal.aborted) return;\n\t} catch (error) {\n\t\tif (signal.aborted) return;\n\t\tctx.ui.notify(`pi-sync recovery required: ${errorMessage(error)}`, \"error\");\n\t\treturn;\n\t}\n\ttry {\n\t\tsetSyncSetupCompletions(await configuredSyncSetupNames());\n\t\tif (signal.aborted) return;\n\t} catch {\n\t\tif (signal.aborted) return;\n\t\tsetSyncSetupCompletions([]);\n\t}\n\tconst migrationNotice = consumeLocalConfigMigrationNotice();\n\tif (migrationNotice) ctx.ui.notify(migrationNotice, \"warning\");\n\tif (signal.aborted) return;\n\treturn autoSync(ctx, signal, loaders);\n}\n\nasync function handleCommand(\n\trawArgs: string,\n\tctx: ExtensionCommandContext,\n\tsessionSignal: AbortSignal,\n\tloaders: SyncLoaders,\n\tattention: SyncAttentionController,\n) {\n\tif (!rawArgs.trim()) {\n\t\ttry {\n\t\t\tconst { showSyncManager } = await import(\"./manager-ui.js\");\n\t\t\tif (sessionSignal.aborted) return;\n\t\t\tawait showSyncManager(\n\t\t\t\tctx,\n\t\t\t\t(route, signal, onCommit, target) =>\n\t\t\t\t\texecuteCommand(\n\t\t\t\t\t\troute,\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\tcombineSignals(sessionSignal, signal),\n\t\t\t\t\t\tloaders,\n\t\t\t\t\t\tonCommit,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t),\n\t\t\t\tsessionSignal,\n\t\t\t\t{\n\t\t\t\t\tgetAttention: () => attention.current(),\n\t\t\t\t\tonSelectionResolved: (expected) => {\n\t\t\t\t\t\tif (attention.current() === expected) attention.clear(ctx);\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tif (sessionSignal.aborted) return;\n\t\t\tctx.ui.setStatus(STATUS_KEY, undefined);\n\t\t\tctx.ui.notify(errorMessage(error), \"error\");\n\t\t}\n\t\tif (!sessionSignal.aborted) attention.publish(ctx);\n\t\treturn;\n\t}\n\tconst result = await executeCommand(rawArgs, ctx, sessionSignal, loaders);\n\tif (result.kind === \"decision-required\") {\n\t\tctx.ui.notify(result.decision.directMessage, \"error\");\n\t} else if (result.kind === \"remote-selection-required\") {\n\t\tconst origin = directSelectionOrigin(rawArgs);\n\t\tif (origin) attention.set(result.decision, origin);\n\t\tconst deterministic = splitArgs(rawArgs).some((arg) => arg === \"--yes\" || arg === \"-y\");\n\t\tif (origin && ctx.mode === \"tui\" && !deterministic) {\n\t\t\tawait resolveSelectionAttention(ctx, attention, sessionSignal, loaders);\n\t\t} else {\n\t\t\tctx.ui.notify(\n\t\t\t\tformatRemoteSelectionMismatch(\n\t\t\t\t\tresult.decision.setupName,\n\t\t\t\t\tresult.decision.localInclude,\n\t\t\t\t\tresult.decision.remoteInclude,\n\t\t\t\t),\n\t\t\t\t\"error\",\n\t\t\t);\n\t\t}\n\t}\n\tawait clearAttentionAfterCompletedOperation(rawArgs, result, ctx, attention, sessionSignal);\n\tawait reconcileSelectionAttention(ctx, attention, sessionSignal);\n\tif (!sessionSignal.aborted) attention.publish(ctx);\n}\n\nasync function clearAttentionAfterCompletedOperation(\n\trawArgs: string,\n\tresult: RunRouteResult,\n\tctx: ExtensionContext,\n\tattention: SyncAttentionController,\n\tsignal: AbortSignal,\n) {\n\tif (result.kind !== \"completed\" || result.outcome === \"cancelled\" || signal.aborted) return;\n\tconst [command, ...rest] = splitArgs(rawArgs);\n\tif (command !== \"sync\" && command !== \"pull\" && command !== \"push\") return;\n\tconst current = attention.current();\n\tif (!current) return;\n\ttry {\n\t\tconst options = parseOptions(rest);\n\t\tconst setupName = options.setup ?? (await loadConfig()).setupName;\n\t\tif (signal.aborted || attention.current() !== current) return;\n\t\tif (current.decision.setupName === setupName) attention.clear(ctx);\n\t} catch {\n\t\t// Attention reconciliation below owns malformed or concurrently changed settings.\n\t}\n}\n\nasync function reconcileSelectionAttention(\n\tctx: ExtensionContext,\n\tattention: SyncAttentionController,\n\tsignal: AbortSignal,\n) {\n\tconst current = attention.current();\n\tif (!current || signal.aborted) return;\n\ttry {\n\t\tconst config = await loadConfig(current.decision.setupName);\n\t\tif (signal.aborted || attention.current() !== current) return;\n\t\tif (!syncAttentionMatchesConfig(current, config)) attention.clear(ctx);\n\t} catch {\n\t\tif (!signal.aborted && attention.current() === current) attention.clear(ctx);\n\t}\n}\n\nfunction directSelectionOrigin(rawArgs: string): SyncAttentionOrigin | undefined {\n\tconst command = splitArgs(rawArgs)[0];\n\treturn command === \"sync\" || command === \"pull\" || command === \"push\" ? command : undefined;\n}\n\nasync function resolveSelectionAttention(\n\tctx: ExtensionContext,\n\tattention: SyncAttentionController,\n\tsignal: AbortSignal,\n\tloaders: SyncLoaders,\n\toptions: {\n\t\tcancelLabel?: string;\n\t\twithStateAccess?: <T>(task: () => Promise<T>) => Promise<T>;\n\t} = {},\n) {\n\tconst current = attention.current();\n\tif (!current || signal.aborted) return;\n\tconst { dispatchManagerResult } = await import(\"./manager-result-dispatcher.js\");\n\tif (signal.aborted || attention.current() !== current) return;\n\tawait dispatchManagerResult(\n\t\tctx,\n\t\t{ kind: \"remote-selection-required\", decision: current.decision },\n\t\tcurrent.origin,\n\t\t(route, actionSignal, onCommit, target) => {\n\t\t\tconst execute = () =>\n\t\t\t\texecuteRecoveryCommand(\n\t\t\t\t\troute,\n\t\t\t\t\tctx,\n\t\t\t\t\tcombineSignals(signal, actionSignal),\n\t\t\t\t\tloaders,\n\t\t\t\t\tonCommit,\n\t\t\t\t\ttarget,\n\t\t\t\t);\n\t\t\treturn options.withStateAccess ? options.withStateAccess(execute) : execute();\n\t\t},\n\t\tsignal,\n\t\t{\n\t\t\tcancelLabel: options.cancelLabel,\n\t\t\twithStateAccess: options.withStateAccess,\n\t\t\tonSelectionResolved: () => {\n\t\t\t\tif (attention.current() === current) attention.clear(ctx);\n\t\t\t},\n\t\t},\n\t);\n}\n\nasync function executeRecoveryCommand(\n\trawArgs: string,\n\tctx: ExtensionContext,\n\tsignal: AbortSignal | undefined,\n\tloaders: SyncLoaders,\n\tonCommit?: () => void,\n\tsetup?: string,\n): Promise<RunRouteResult> {\n\ttry {\n\t\tconst [subcommand, ...rest] = splitArgs(rawArgs);\n\t\tif (subcommand !== \"sync\" && subcommand !== \"pull\" && subcommand !== \"push\") {\n\t\t\tthrow new Error(`Unsupported sync recovery route: ${subcommand ?? \"missing\"}`);\n\t\t}\n\t\tconst options = parseOptions(rest);\n\t\tif (setup !== undefined) options.setup = setup;\n\t\tif (signal) options.signal = signal;\n\t\tif (onCommit) options.onCommit = onCommit;\n\t\toptions.reload = false;\n\t\toptions.auto = false;\n\t\tvalidateCommandOptions(subcommand, options);\n\t\tconst operations = await loaders.operations();\n\t\tthrowIfAborted(options.signal);\n\t\tif (subcommand === \"push\") {\n\t\t\tconst outcome = await withLock(\"push\", () => operations.push(ctx, options));\n\t\t\treturn { kind: \"completed\", ...(outcome ? { outcome } : {}) };\n\t\t}\n\t\tif (subcommand === \"pull\") {\n\t\t\tconst outcome = await withLock(\"pull\", () => operations.pull(ctx, options));\n\t\t\treturn { kind: \"completed\", ...(outcome ? { outcome } : {}) };\n\t\t}\n\t\tawait withLock(\"sync\", () => operations.syncBoth(ctx, options));\n\t\treturn { kind: \"completed\" };\n\t} catch (error) {\n\t\tif (signal?.aborted) return { kind: \"failed\" };\n\t\tctx.ui.setStatus(STATUS_KEY, undefined);\n\t\tif (error instanceof RemoteSelectionMismatchError) {\n\t\t\treturn { kind: \"remote-selection-required\", decision: error.decision };\n\t\t}\n\t\tif (isSyncDecisionRequiredError(error)) {\n\t\t\treturn { kind: \"decision-required\", decision: error.decision };\n\t\t}\n\t\tctx.ui.notify(errorMessage(error), \"error\");\n\t\treturn { kind: \"failed\" };\n\t}\n}\n\nasync function executeCommand(\n\trawArgs: string,\n\tctx: ExtensionCommandContext,\n\tsignal: AbortSignal | undefined,\n\tloaders: SyncLoaders,\n\tonCommit?: () => void,\n\tsetup?: string,\n): Promise<RunRouteResult> {\n\ttry {\n\t\tconst command = await resolveSyncCommand(rawArgs, ctx);\n\t\tif (signal?.aborted || !command) return { kind: \"completed\" };\n\t\tconst { subcommand, rest } = command;\n\t\tconst options = parseOptions(rest);\n\t\tif (setup !== undefined) options.setup = setup;\n\t\tif (signal) options.signal = signal;\n\t\tif (onCommit) options.onCommit = onCommit;\n\t\tvalidateCommandOptions(subcommand, options);\n\n\t\tswitch (subcommand) {\n\t\t\tcase \"help\":\n\t\t\t\tctx.ui.notify(usage(), \"info\");\n\t\t\t\treturn { kind: \"completed\" };\n\t\t\tcase \"use\": {\n\t\t\t\tconst { useSyncSetup } = await loaders.setupSwitch();\n\t\t\t\tthrowIfAborted(options.signal);\n\t\t\t\tawait useSyncSetup(\n\t\t\t\t\tctx,\n\t\t\t\t\toptions.args[0] ?? \"\",\n\t\t\t\t\tasync (selectedSetup) => {\n\t\t\t\t\t\tconst operations = await loaders.operations();\n\t\t\t\t\t\tthrowIfAborted(options.signal);\n\t\t\t\t\t\treturn withLock(\"pull\", () =>\n\t\t\t\t\t\t\toperations.pull(ctx, { ...options, setup: selectedSetup }),\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t\tundefined,\n\t\t\t\t\toptions.signal,\n\t\t\t\t);\n\t\t\t\treturn { kind: \"completed\" };\n\t\t\t}\n\t\t\tcase \"init\":\n\t\t\t\tawait initConfig(ctx, signal);\n\t\t\t\treturn { kind: \"completed\" };\n\t\t\tcase \"config\":\n\t\t\t\tawait showConfig(ctx, options);\n\t\t\t\treturn { kind: \"completed\" };\n\t\t\tcase \"files\": {\n\t\t\t\tconst { showFileSelection } = await import(\"./file-selection.js\");\n\t\t\t\tthrowIfAborted(options.signal);\n\t\t\t\tawait showFileSelection(ctx, options.setup, options.signal);\n\t\t\t\treturn { kind: \"completed\" };\n\t\t\t}\n\t\t\tcase \"status\": {\n\t\t\t\tconst operations = await loaders.operations();\n\t\t\t\tthrowIfAborted(options.signal);\n\t\t\t\tawait operations.status(ctx, options);\n\t\t\t\treturn { kind: \"completed\" };\n\t\t\t}\n\t\t\tcase \"diff\": {\n\t\t\t\tconst operations = await loaders.operations();\n\t\t\t\tthrowIfAborted(options.signal);\n\t\t\t\tawait operations.diff(ctx, options);\n\t\t\t\treturn { kind: \"completed\" };\n\t\t\t}\n\t\t\tcase \"doctor\": {\n\t\t\t\tconst operations = await loaders.operations();\n\t\t\t\tthrowIfAborted(options.signal);\n\t\t\t\tawait operations.doctor(ctx, options);\n\t\t\t\treturn { kind: \"completed\" };\n\t\t\t}\n\t\t\tcase \"push\": {\n\t\t\t\tconst operations = await loaders.operations();\n\t\t\t\tthrowIfAborted(options.signal);\n\t\t\t\tconst outcome = await withLock(\"push\", () => operations.push(ctx, options));\n\t\t\t\treturn { kind: \"completed\", ...(outcome ? { outcome } : {}) };\n\t\t\t}\n\t\t\tcase \"pull\": {\n\t\t\t\tconst operations = await loaders.operations();\n\t\t\t\tthrowIfAborted(options.signal);\n\t\t\t\tconst outcome = await withLock(\"pull\", () => operations.pull(ctx, options));\n\t\t\t\treturn { kind: \"completed\", ...(outcome ? { outcome } : {}) };\n\t\t\t}\n\t\t\tcase \"sync\": {\n\t\t\t\tconst operations = await loaders.operations();\n\t\t\t\tthrowIfAborted(options.signal);\n\t\t\t\tawait withLock(\"sync\", () => operations.syncBoth(ctx, options));\n\t\t\t\treturn { kind: \"completed\" };\n\t\t\t}\n\t\t\tcase \"history\": {\n\t\t\t\tconst operations = await loaders.operations();\n\t\t\t\tthrowIfAborted(options.signal);\n\t\t\t\tawait operations.history(ctx, options);\n\t\t\t\treturn { kind: \"completed\" };\n\t\t\t}\n\t\t\tcase \"rollback\": {\n\t\t\t\tconst operations = await loaders.operations();\n\t\t\t\tthrowIfAborted(options.signal);\n\t\t\t\tawait withLock(\"rollback\", () => operations.rollback(ctx, options));\n\t\t\t\treturn { kind: \"completed\" };\n\t\t\t}\n\t\t\tcase \"migrate-state\":\n\t\t\t\tawait migrateStateDirectory(ctx, options);\n\t\t\t\treturn { kind: \"completed\" };\n\t\t\tcase \"unlock\":\n\t\t\t\tawait unlock(ctx, options);\n\t\t\t\treturn { kind: \"completed\" };\n\t\t\tdefault:\n\t\t\t\tctx.ui.notify(`Unknown /sync command: ${subcommand}\\n\\n${usage()}`, \"warning\");\n\t\t\t\treturn { kind: \"failed\" };\n\t\t}\n\t} catch (error) {\n\t\tif (signal?.aborted) return { kind: \"failed\" };\n\t\tctx.ui.setStatus(STATUS_KEY, undefined);\n\t\tif (error instanceof SetupPullRequiresUiError) throw error;\n\t\tif (error instanceof RemoteSelectionMismatchError) {\n\t\t\treturn { kind: \"remote-selection-required\", decision: error.decision };\n\t\t}\n\t\tif (isSyncDecisionRequiredError(error)) {\n\t\t\treturn { kind: \"decision-required\", decision: error.decision };\n\t\t}\n\t\tctx.ui.notify(errorMessage(error), \"error\");\n\t\treturn { kind: \"failed\" };\n\t}\n}\n\nasync function migrateStateDirectory(ctx: ExtensionCommandContext, options: CommandOptions) {\n\tconst notice = stateDirectoryMigrationNotice();\n\tif (!notice) {\n\t\tctx.ui.notify(\"pi-sync already uses the canonical pi-sync/ state directory.\", \"info\");\n\t\treturn;\n\t}\n\tif (\n\t\t!options.yes &&\n\t\t!(await ctx.ui.confirm(\n\t\t\t\"Migrate pi-sync state directory\",\n\t\t\t\"Confirm that every other Pi process is closed. pi-sync will atomically rename .pisync/ to pi-sync/ without merging or deleting either root.\",\n\t\t\t{ signal: options.signal },\n\t\t))\n\t) {\n\t\tctx.ui.notify(\"pi-sync state migration cancelled.\", \"info\");\n\t\treturn;\n\t}\n\tthrowIfAborted(options.signal);\n\tconst result = await migrateLegacyStateDirectory();\n\tthrowIfAborted(options.signal);\n\tif (result.status === \"ready\") {\n\t\tctx.ui.notify(\"pi-sync already uses the canonical pi-sync/ state directory.\", \"info\");\n\t\treturn;\n\t}\n\tctx.ui.notify(result.message, result.status === \"migrated\" ? \"info\" : \"warning\");\n}\n\nasync function autoSync(\n\tctx: ExtensionContext,\n\tsignal: AbortSignal,\n\tloaders: SyncLoaders,\n): Promise<RemoteSelectionDecision | undefined> {\n\ttry {\n\t\tconst partial = await loadPartialConfig();\n\t\tthrowIfAborted(signal);\n\t\tif (!partial.automatic) return;\n\t\tawait ensureStateDir();\n\t\tthrowIfAborted(signal);\n\t\tawait loadConfig();\n\t\tthrowIfAborted(signal);\n\t\tconst operations = await loaders.operations();\n\t\tthrowIfAborted(signal);\n\t\tawait withLock(\"auto-sync\", () => {\n\t\t\tthrowIfAborted(signal);\n\t\t\treturn operations.syncBoth(ctx, { ...AUTO_SYNC_OPTIONS, signal });\n\t\t});\n\t} catch (error) {\n\t\tif (signal.aborted || isMissingConfigError(error)) return;\n\t\tctx.ui.setStatus(STATUS_KEY, undefined);\n\t\tif (error instanceof RemoteSelectionMismatchError) return error.decision;\n\t\tctx.ui.notify(`pi-sync auto sync skipped: ${errorMessage(error)}`, \"warning\");\n\t}\n}\n\nasync function autoPushSessions(ctx: ExtensionContext, signal: AbortSignal, loaders: SyncLoaders) {\n\ttry {\n\t\tconst partial = await loadPartialConfig();\n\t\tthrowIfAborted(signal);\n\t\tif (!partial.automatic) return;\n\t\tif (!partial.include.includes(\"sessions\")) return;\n\t\tawait ensureStateDir();\n\t\tthrowIfAborted(signal);\n\t\tconst config = await loadConfig();\n\t\tthrowIfAborted(signal);\n\t\tif (!config.include.includes(\"sessions\")) return;\n\t\tconst [operations, snapshotModule, syncStateModule] = await Promise.all([\n\t\t\tloaders.operations(),\n\t\t\tloaders.snapshot(),\n\t\t\tloaders.syncState(),\n\t\t]);\n\t\tthrowIfAborted(signal);\n\t\tawait withLock(\"auto-session-push\", async () => {\n\t\t\tthrowIfAborted(signal);\n\t\t\tconst state = await readStateForConfig(config);\n\t\t\tthrowIfAborted(signal);\n\t\t\tconst local = await snapshotModule.createSnapshot(\n\t\t\t\tconfig.snapshotIdentity,\n\t\t\t\tsnapshotOptionsForContext(ctx, config),\n\t\t\t);\n\t\t\tthrowIfAborted(signal);\n\t\t\tif (!syncStateModule.hasLocalChanges(local, state, config)) return;\n\t\t\tawait operations.push(ctx, { ...AUTO_SYNC_OPTIONS, signal }, { config, state, local });\n\t\t});\n\t} catch (error) {\n\t\tif (signal.aborted || isMissingConfigError(error)) return;\n\t\tctx.ui.setStatus(STATUS_KEY, undefined);\n\t\tctx.ui.notify(`pi-sync session push skipped: ${errorMessage(error)}`, \"warning\");\n\t}\n}\n\nasync function initConfig(ctx: ExtensionCommandContext, signal?: AbortSignal) {\n\tconst configPath = localConfigPath();\n\tif (await readLocalConfigObject()) {\n\t\tctx.ui.notify(`Config already exists: ${await activeLocalConfigPath()}`, \"info\");\n\t\treturn;\n\t}\n\n\tif (ctx.mode === \"tui\") {\n\t\tconst { showSetupWizard } = await import(\"./manager-ui.js\");\n\t\tthrowIfAborted(signal);\n\t\tawait showSetupWizard(ctx, signal);\n\t\treturn;\n\t}\n\tawait createLocalConfigDocument(localConfigTemplate());\n\tctx.ui.notify(\n\t\t`Created ${configPath}. Add a storage connection and sync setup before syncing.`,\n\t\t\"info\",\n\t);\n}\n\nasync function showConfig(ctx: ExtensionCommandContext, options: CommandOptions) {\n\tconst config = await loadConfig(options.setup);\n\tconst warnings = [\n\t\t...(config.backend.type === \"s3\" ? sessionTokenWarnings(config.backend.profile) : []),\n\t\t...syncSessionsWarnings(config),\n\t];\n\tconst storageLines = configStorageLines(config);\n\tctx.ui.notify(\n\t\t[\n\t\t\t\"pi-sync config:\",\n\t\t\t`sync setup: ${config.setupName}`,\n\t\t\t`storage connection: ${config.connectionName}`,\n\t\t\t...storageLines,\n\t\t\t`storage path: ${config.storagePath}`,\n\t\t\t`automatic sync: ${config.automatic ? \"enabled\" : \"disabled\"}`,\n\t\t\t`included content: ${config.include.join(\", \") || \"none\"}`,\n\t\t\t`sessions: ${config.include.includes(\"sessions\") ? \"included\" : \"not included\"}`,\n\t\t\t`settings file: ${localConfigPath()}`,\n\t\t\t...warnings,\n\t\t].join(\"\\n\"),\n\t\twarnings.length > 0 ? \"warning\" : \"info\",\n\t);\n}\n\nfunction configStorageLines(config: AnySyncConfig) {\n\tswitch (config.backend.type) {\n\t\tcase \"git\":\n\t\t\treturn [\n\t\t\t\t\"kind: git\",\n\t\t\t\t`remote: ${displayGitRemote(config.backend.profile.remote)}`,\n\t\t\t\t\"authentication: existing Git/SSH credentials (not stored)\",\n\t\t\t\t`branch: ${config.backend.destination.branch}`,\n\t\t\t];\n\t\tcase \"webdav\":\n\t\t\treturn [\n\t\t\t\t\"kind: webdav\",\n\t\t\t\t`url: ${displayWebDavUrl(config.backend.profile.url, config.backend.profile.username)}`,\n\t\t\t\t\"username: configured (value hidden)\",\n\t\t\t\t\"password: configured\",\n\t\t\t];\n\t\tcase \"s3\":\n\t\t\treturn [\n\t\t\t\t\"kind: s3\",\n\t\t\t\t`endpoint: ${config.backend.profile.endpoint}`,\n\t\t\t\t`bucket: ${config.backend.destination.bucket}`,\n\t\t\t\t`region: ${config.backend.profile.region}`,\n\t\t\t\t\"access key id: configured\",\n\t\t\t\t\"secret access key: configured\",\n\t\t\t\t`session token: ${config.backend.profile.sessionToken ? \"configured\" : \"not configured\"}`,\n\t\t\t];\n\t}\n}\n\nfunction displayGitRemote(value: string | undefined) {\n\tif (!value) return \"missing\";\n\ttry {\n\t\tconst url = new URL(value);\n\t\turl.username = \"\";\n\t\turl.password = \"\";\n\t\turl.search = \"\";\n\t\turl.hash = \"\";\n\t\treturn url.toString();\n\t} catch {\n\t\treturn value.replace(/^(?:[^@\\s]+@)?(?<host>[^:]+):.+$/u, \"$<host>:\u2026\");\n\t}\n}\n\nfunction displayWebDavUrl(value: string | undefined, username: string | undefined) {\n\tif (!value) return \"missing\";\n\ttry {\n\t\tconst url = new URL(value);\n\t\turl.username = \"\";\n\t\turl.password = \"\";\n\t\turl.search = \"\";\n\t\turl.hash = \"\";\n\t\treturn username ? `${url.origin}/\u2026` : `${url.origin}${url.pathname}`;\n\t} catch {\n\t\treturn \"invalid (value hidden)\";\n\t}\n}\n\nfunction throwIfAborted(signal?: AbortSignal) {\n\tif (!signal?.aborted) return;\n\tthrow signal.reason instanceof Error\n\t\t? signal.reason\n\t\t: new DOMException(\"The operation was aborted\", \"AbortError\");\n}\n\nfunction combineSignals(primary: AbortSignal, secondary?: AbortSignal) {\n\treturn secondary ? AbortSignal.any([primary, secondary]) : primary;\n}\n\nfunction snapshotOptionsForContext(\n\tctx: ExtensionCommandContext | ExtensionContext,\n\tconfig: AnySyncConfig,\n): SnapshotOptions {\n\treturn {\n\t\tinclude: config.include,\n\t\tsessionDir: sessionDirFromContext(ctx),\n\t};\n}\n\nfunction sessionDirFromContext(ctx: ExtensionCommandContext | ExtensionContext) {\n\tconst manager = ctx.sessionManager as typeof ctx.sessionManager & {\n\t\tusesDefaultSessionDir?: () => boolean;\n\t};\n\tconst usesDefaultSessionDir = manager.usesDefaultSessionDir;\n\tif (typeof usesDefaultSessionDir === \"function\" && usesDefaultSessionDir.call(manager)) {\n\t\treturn undefined;\n\t}\n\tconst getSessionDir = manager.getSessionDir;\n\treturn typeof getSessionDir === \"function\"\n\t\t? (getSessionDir.call(manager) as string | undefined)\n\t\t: undefined;\n}\n\nfunction cachedModuleLoader<Module>(load: () => Promise<Module>): () => Promise<Module> {\n\tlet pending: Promise<Module> | undefined;\n\treturn () => {\n\t\tif (!pending) {\n\t\t\tpending = load().catch((error) => {\n\t\t\t\tpending = undefined;\n\t\t\t\tthrow error;\n\t\t\t});\n\t\t}\n\t\treturn pending;\n\t};\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDA,IAAM,aAAa;AAqBnB,IAAM,oBAAoC;AAAA,EACzC,KAAK;AAAA,EACL,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,MAAM,CAAC;AACR;AACe,SAAR,KAAsB,IAAkB,eAA0C,CAAC,GAAG;AAC5F,QAAM,UAAuB;AAAA,IAC5B,aAAa;AAAA,MACZ,aAAa,oBAAoB,MAAM,OAAO,mCAAmB;AAAA,IAClE;AAAA,IACA,UAAU,mBAAmB,aAAa,iBAAiB,MAAM,OAAO,+BAAe,EAAE;AAAA,IACzF,WAAW,mBAAmB,aAAa,kBAAkB,MAAM,OAAO,iCAAiB,EAAE;AAAA,IAC7F,YAAY;AAAA,MACX,aAAa,uBAAuB,MAAM,OAAO,sCAAsB;AAAA,IACxE;AAAA,EACD;AACA,QAAM,YAAY,8BAA8B;AAChD,MAAI,eAAe,IAAI,gBAAgB;AACvC,MAAI;AAEJ,KAAG,gBAAgB,QAAQ;AAAA,IAC1B,aAAa;AAAA,IACb,wBAAwB;AAAA,IACxB,SAAS,OAAO,MAAM,QAAQ;AAC7B,UAAI,CAAC,IAAI,OAAO;AACf,cAAM,IAAI;AAAA,UACT;AAAA,QACD;AAAA,MACD;AACA,YAAM,MAAM,MAAM,cAAc,MAAM,KAAK,aAAa,QAAQ,SAAS,SAAS;AAClF,UAAI,UAAU,IAAI,EAAE,CAAC,MAAM,gBAAiB,OAAM,IAAI;AAAA,UACjD,OAAM,yBAAyB,GAAG;AAAA,IACxC;AAAA,EACD,CAAC;AAED,KAAG,GAAG,iBAAiB,OAAO,QAAQ,QAAQ;AAC7C,mBAAe,MAAM,IAAI,aAAa,oBAAoB,YAAY,CAAC;AACvE,oBAAgB;AAChB,iBAAa,MAAM,IAAI,aAAa,oBAAoB,YAAY,CAAC;AACrE,mBAAe,IAAI,gBAAgB;AACnC,UAAM,SAAS,aAAa;AAC5B,cAAU,MAAM,GAAG;AACnB,QAAI;AACJ,QAAI;AACH,iBAAW,MAAM,yBAAyB,MAAM,aAAa,KAAK,QAAQ,OAAO,CAAC;AAAA,IACnF,SAAS,OAAO;AACf,UAAI,OAAO,QAAS;AACpB,UAAI,GAAG,OAAO,gCAAgC,aAAa,KAAK,CAAC,IAAI,OAAO;AAC5E;AAAA,IACD;AACA,QAAI,CAAC,YAAY,OAAO,QAAS;AACjC,cAAU,IAAI,UAAU,MAAM;AAC9B,QAAI,IAAI,SAAS,OAAO;AACvB,UAAI,GAAG;AAAA,QACN,8BAA8B;AAAA,UAC7B,SAAS;AAAA,UACT,SAAS;AAAA,UACT,SAAS;AAAA,QACV,CAAC;AAAA;AAAA,QACD;AAAA,MACD;AAAA,IACD,WAAW,UAAU,YAAY,GAAG;AACnC,YAAM,0BAA0B,KAAK,WAAW,QAAQ,SAAS;AAAA,QAChE,aAAa;AAAA,QACb,iBAAiB;AAAA,MAClB,CAAC;AAAA,IACF;AACA,QAAI,CAAC,OAAO,QAAS,WAAU,QAAQ,GAAG;AAAA,EAC3C,CAAC;AAED,KAAG,GAAG,oBAAoB,OAAO,OAAO,QAAQ;AAC/C,iBAAa,MAAM,IAAI,aAAa,qBAAqB,YAAY,CAAC;AACtE,cAAU,MAAM,GAAG;AACnB,mBAAe,MAAM,IAAI,aAAa,2BAA2B,YAAY,CAAC;AAC9E,UAAM,aAAa,IAAI,gBAAgB;AACvC,oBAAgB;AAChB,UAAM,SAAS,eAAe,WAAW,QAAQ,YAAY,QAAQ,GAAM,CAAC;AAC5E,UAAM,SACL,OAAO,UAAU,YAAY,QAAS,MAA8B,SAAS;AAC9E,QAAI;AACH,UAAI,WAAW,UAAU;AACxB,cAAM,yBAAyB,YAAY;AAC1C,cAAI,OAAO,QAAS;AACpB,gBAAM,iBAAiB,KAAK,QAAQ,OAAO;AAAA,QAC5C,CAAC;AAAA,MACF;AAAA,IACD,SAAS,OAAO;AACf,UAAI,CAAC,OAAO,SAAS;AACpB,YAAI,GAAG,OAAO,iCAAiC,aAAa,KAAK,CAAC,IAAI,SAAS;AAAA,MAChF;AAAA,IACD,UAAE;AACD,UAAI,kBAAkB,WAAY,iBAAgB;AAAA,IACnD;AACA,QAAI,OAAO,QAAS;AACpB,QAAI,GAAG,UAAU,YAAY,MAAS;AAAA,EACvC,CAAC;AACF;AAEA,eAAe,aAAa,KAAuB,QAAqB,SAAsB;AAC7F,MAAI,OAAO,QAAS;AACpB,MAAI;AACH,UAAMA,mBAAkB,8BAA8B;AACtD,QAAIA,iBAAiB,KAAI,GAAG,OAAOA,kBAAiB,SAAS;AAAA,EAC9D,SAAS,OAAO;AACf,QAAI,GAAG,OAAO,+CAA+C,aAAa,KAAK,CAAC,IAAI,OAAO;AAC3F;AAAA,EACD;AACA,MAAI;AACH,UAAM,qCAAqC;AAC3C,QAAI,OAAO,QAAS;AAAA,EACrB,SAAS,OAAO;AACf,QAAI,OAAO,QAAS;AACpB,QAAI,GAAG,OAAO,8BAA8B,aAAa,KAAK,CAAC,IAAI,OAAO;AAC1E;AAAA,EACD;AACA,MAAI;AACH,4BAAwB,MAAM,yBAAyB,CAAC;AACxD,QAAI,OAAO,QAAS;AAAA,EACrB,QAAQ;AACP,QAAI,OAAO,QAAS;AACpB,4BAAwB,CAAC,CAAC;AAAA,EAC3B;AACA,QAAM,kBAAkB,kCAAkC;AAC1D,MAAI,gBAAiB,KAAI,GAAG,OAAO,iBAAiB,SAAS;AAC7D,MAAI,OAAO,QAAS;AACpB,SAAO,SAAS,KAAK,QAAQ,OAAO;AACrC;AAEA,eAAe,cACd,SACA,KACA,eACA,SACA,WACC;AACD,MAAI,CAAC,QAAQ,KAAK,GAAG;AACpB,QAAI;AACH,YAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,iCAAiB;AAC1D,UAAI,cAAc,QAAS;AAC3B,YAAM;AAAA,QACL;AAAA,QACA,CAAC,OAAO,QAAQ,UAAU,WACzB;AAAA,UACC;AAAA,UACA;AAAA,UACA,eAAe,eAAe,MAAM;AAAA,UACpC;AAAA,UACA;AAAA,UACA;AAAA,QACD;AAAA,QACD;AAAA,QACA;AAAA,UACC,cAAc,MAAM,UAAU,QAAQ;AAAA,UACtC,qBAAqB,CAAC,aAAa;AAClC,gBAAI,UAAU,QAAQ,MAAM,SAAU,WAAU,MAAM,GAAG;AAAA,UAC1D;AAAA,QACD;AAAA,MACD;AAAA,IACD,SAAS,OAAO;AACf,UAAI,cAAc,QAAS;AAC3B,UAAI,GAAG,UAAU,YAAY,MAAS;AACtC,UAAI,GAAG,OAAO,aAAa,KAAK,GAAG,OAAO;AAAA,IAC3C;AACA,QAAI,CAAC,cAAc,QAAS,WAAU,QAAQ,GAAG;AACjD;AAAA,EACD;AACA,QAAM,SAAS,MAAM,eAAe,SAAS,KAAK,eAAe,OAAO;AACxE,MAAI,OAAO,SAAS,qBAAqB;AACxC,QAAI,GAAG,OAAO,OAAO,SAAS,eAAe,OAAO;AAAA,EACrD,WAAW,OAAO,SAAS,6BAA6B;AACvD,UAAM,SAAS,sBAAsB,OAAO;AAC5C,QAAI,OAAQ,WAAU,IAAI,OAAO,UAAU,MAAM;AACjD,UAAM,gBAAgB,UAAU,OAAO,EAAE,KAAK,CAAC,QAAQ,QAAQ,WAAW,QAAQ,IAAI;AACtF,QAAI,UAAU,IAAI,SAAS,SAAS,CAAC,eAAe;AACnD,YAAM,0BAA0B,KAAK,WAAW,eAAe,OAAO;AAAA,IACvE,OAAO;AACN,UAAI,GAAG;AAAA,QACN;AAAA,UACC,OAAO,SAAS;AAAA,UAChB,OAAO,SAAS;AAAA,UAChB,OAAO,SAAS;AAAA,QACjB;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACA,QAAM,sCAAsC,SAAS,QAAQ,KAAK,WAAW,aAAa;AAC1F,QAAM,4BAA4B,KAAK,WAAW,aAAa;AAC/D,MAAI,CAAC,cAAc,QAAS,WAAU,QAAQ,GAAG;AAClD;AAEA,eAAe,sCACd,SACA,QACA,KACA,WACA,QACC;AACD,MAAI,OAAO,SAAS,eAAe,OAAO,YAAY,eAAe,OAAO,QAAS;AACrF,QAAM,CAAC,SAAS,GAAG,IAAI,IAAI,UAAU,OAAO;AAC5C,MAAI,YAAY,UAAU,YAAY,UAAU,YAAY,OAAQ;AACpE,QAAM,UAAU,UAAU,QAAQ;AAClC,MAAI,CAAC,QAAS;AACd,MAAI;AACH,UAAM,UAAU,aAAa,IAAI;AACjC,UAAM,YAAY,QAAQ,UAAU,MAAM,WAAW,GAAG;AACxD,QAAI,OAAO,WAAW,UAAU,QAAQ,MAAM,QAAS;AACvD,QAAI,QAAQ,SAAS,cAAc,UAAW,WAAU,MAAM,GAAG;AAAA,EAClE,QAAQ;AAAA,EAER;AACD;AAEA,eAAe,4BACd,KACA,WACA,QACC;AACD,QAAM,UAAU,UAAU,QAAQ;AAClC,MAAI,CAAC,WAAW,OAAO,QAAS;AAChC,MAAI;AACH,UAAM,SAAS,MAAM,WAAW,QAAQ,SAAS,SAAS;AAC1D,QAAI,OAAO,WAAW,UAAU,QAAQ,MAAM,QAAS;AACvD,QAAI,CAAC,2BAA2B,SAAS,MAAM,EAAG,WAAU,MAAM,GAAG;AAAA,EACtE,QAAQ;AACP,QAAI,CAAC,OAAO,WAAW,UAAU,QAAQ,MAAM,QAAS,WAAU,MAAM,GAAG;AAAA,EAC5E;AACD;AAEA,SAAS,sBAAsB,SAAkD;AAChF,QAAM,UAAU,UAAU,OAAO,EAAE,CAAC;AACpC,SAAO,YAAY,UAAU,YAAY,UAAU,YAAY,SAAS,UAAU;AACnF;AAEA,eAAe,0BACd,KACA,WACA,QACA,SACA,UAGI,CAAC,GACJ;AACD,QAAM,UAAU,UAAU,QAAQ;AAClC,MAAI,CAAC,WAAW,OAAO,QAAS;AAChC,QAAM,EAAE,sBAAsB,IAAI,MAAM,OAAO,gDAAgC;AAC/E,MAAI,OAAO,WAAW,UAAU,QAAQ,MAAM,QAAS;AACvD,QAAM;AAAA,IACL;AAAA,IACA,EAAE,MAAM,6BAA6B,UAAU,QAAQ,SAAS;AAAA,IAChE,QAAQ;AAAA,IACR,CAAC,OAAO,cAAc,UAAU,WAAW;AAC1C,YAAM,UAAU,MACf;AAAA,QACC;AAAA,QACA;AAAA,QACA,eAAe,QAAQ,YAAY;AAAA,QACnC;AAAA,QACA;AAAA,QACA;AAAA,MACD;AACD,aAAO,QAAQ,kBAAkB,QAAQ,gBAAgB,OAAO,IAAI,QAAQ;AAAA,IAC7E;AAAA,IACA;AAAA,IACA;AAAA,MACC,aAAa,QAAQ;AAAA,MACrB,iBAAiB,QAAQ;AAAA,MACzB,qBAAqB,MAAM;AAC1B,YAAI,UAAU,QAAQ,MAAM,QAAS,WAAU,MAAM,GAAG;AAAA,MACzD;AAAA,IACD;AAAA,EACD;AACD;AAEA,eAAe,uBACd,SACA,KACA,QACA,SACA,UACA,OAC0B;AAC1B,MAAI;AACH,UAAM,CAAC,YAAY,GAAG,IAAI,IAAI,UAAU,OAAO;AAC/C,QAAI,eAAe,UAAU,eAAe,UAAU,eAAe,QAAQ;AAC5E,YAAM,IAAI,MAAM,oCAAoC,cAAc,SAAS,EAAE;AAAA,IAC9E;AACA,UAAM,UAAU,aAAa,IAAI;AACjC,QAAI,UAAU,OAAW,SAAQ,QAAQ;AACzC,QAAI,OAAQ,SAAQ,SAAS;AAC7B,QAAI,SAAU,SAAQ,WAAW;AACjC,YAAQ,SAAS;AACjB,YAAQ,OAAO;AACf,2BAAuB,YAAY,OAAO;AAC1C,UAAM,aAAa,MAAM,QAAQ,WAAW;AAC5C,mBAAe,QAAQ,MAAM;AAC7B,QAAI,eAAe,QAAQ;AAC1B,YAAM,UAAU,MAAM,SAAS,QAAQ,MAAM,WAAW,KAAK,KAAK,OAAO,CAAC;AAC1E,aAAO,EAAE,MAAM,aAAa,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC,EAAG;AAAA,IAC7D;AACA,QAAI,eAAe,QAAQ;AAC1B,YAAM,UAAU,MAAM,SAAS,QAAQ,MAAM,WAAW,KAAK,KAAK,OAAO,CAAC;AAC1E,aAAO,EAAE,MAAM,aAAa,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC,EAAG;AAAA,IAC7D;AACA,UAAM,SAAS,QAAQ,MAAM,WAAW,SAAS,KAAK,OAAO,CAAC;AAC9D,WAAO,EAAE,MAAM,YAAY;AAAA,EAC5B,SAAS,OAAO;AACf,QAAI,QAAQ,QAAS,QAAO,EAAE,MAAM,SAAS;AAC7C,QAAI,GAAG,UAAU,YAAY,MAAS;AACtC,QAAI,iBAAiB,8BAA8B;AAClD,aAAO,EAAE,MAAM,6BAA6B,UAAU,MAAM,SAAS;AAAA,IACtE;AACA,QAAI,4BAA4B,KAAK,GAAG;AACvC,aAAO,EAAE,MAAM,qBAAqB,UAAU,MAAM,SAAS;AAAA,IAC9D;AACA,QAAI,GAAG,OAAO,aAAa,KAAK,GAAG,OAAO;AAC1C,WAAO,EAAE,MAAM,SAAS;AAAA,EACzB;AACD;AAEA,eAAe,eACd,SACA,KACA,QACA,SACA,UACA,OAC0B;AAC1B,MAAI;AACH,UAAM,UAAU,MAAM,mBAAmB,SAAS,GAAG;AACrD,QAAI,QAAQ,WAAW,CAAC,QAAS,QAAO,EAAE,MAAM,YAAY;AAC5D,UAAM,EAAE,YAAY,KAAK,IAAI;AAC7B,UAAM,UAAU,aAAa,IAAI;AACjC,QAAI,UAAU,OAAW,SAAQ,QAAQ;AACzC,QAAI,OAAQ,SAAQ,SAAS;AAC7B,QAAI,SAAU,SAAQ,WAAW;AACjC,2BAAuB,YAAY,OAAO;AAE1C,YAAQ,YAAY;AAAA,MACnB,KAAK;AACJ,YAAI,GAAG,OAAO,MAAM,GAAG,MAAM;AAC7B,eAAO,EAAE,MAAM,YAAY;AAAA,MAC5B,KAAK,OAAO;AACX,cAAM,EAAE,aAAa,IAAI,MAAM,QAAQ,YAAY;AACnD,uBAAe,QAAQ,MAAM;AAC7B,cAAM;AAAA,UACL;AAAA,UACA,QAAQ,KAAK,CAAC,KAAK;AAAA,UACnB,OAAO,kBAAkB;AACxB,kBAAM,aAAa,MAAM,QAAQ,WAAW;AAC5C,2BAAe,QAAQ,MAAM;AAC7B,mBAAO;AAAA,cAAS;AAAA,cAAQ,MACvB,WAAW,KAAK,KAAK,EAAE,GAAG,SAAS,OAAO,cAAc,CAAC;AAAA,YAC1D;AAAA,UACD;AAAA,UACA;AAAA,UACA,QAAQ;AAAA,QACT;AACA,eAAO,EAAE,MAAM,YAAY;AAAA,MAC5B;AAAA,MACA,KAAK;AACJ,cAAM,WAAW,KAAK,MAAM;AAC5B,eAAO,EAAE,MAAM,YAAY;AAAA,MAC5B,KAAK;AACJ,cAAM,WAAW,KAAK,OAAO;AAC7B,eAAO,EAAE,MAAM,YAAY;AAAA,MAC5B,KAAK,SAAS;AACb,cAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,qCAAqB;AAChE,uBAAe,QAAQ,MAAM;AAC7B,cAAM,kBAAkB,KAAK,QAAQ,OAAO,QAAQ,MAAM;AAC1D,eAAO,EAAE,MAAM,YAAY;AAAA,MAC5B;AAAA,MACA,KAAK,UAAU;AACd,cAAM,aAAa,MAAM,QAAQ,WAAW;AAC5C,uBAAe,QAAQ,MAAM;AAC7B,cAAM,WAAW,OAAO,KAAK,OAAO;AACpC,eAAO,EAAE,MAAM,YAAY;AAAA,MAC5B;AAAA,MACA,KAAK,QAAQ;AACZ,cAAM,aAAa,MAAM,QAAQ,WAAW;AAC5C,uBAAe,QAAQ,MAAM;AAC7B,cAAM,WAAW,KAAK,KAAK,OAAO;AAClC,eAAO,EAAE,MAAM,YAAY;AAAA,MAC5B;AAAA,MACA,KAAK,UAAU;AACd,cAAM,aAAa,MAAM,QAAQ,WAAW;AAC5C,uBAAe,QAAQ,MAAM;AAC7B,cAAM,WAAW,OAAO,KAAK,OAAO;AACpC,eAAO,EAAE,MAAM,YAAY;AAAA,MAC5B;AAAA,MACA,KAAK,QAAQ;AACZ,cAAM,aAAa,MAAM,QAAQ,WAAW;AAC5C,uBAAe,QAAQ,MAAM;AAC7B,cAAM,UAAU,MAAM,SAAS,QAAQ,MAAM,WAAW,KAAK,KAAK,OAAO,CAAC;AAC1E,eAAO,EAAE,MAAM,aAAa,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC,EAAG;AAAA,MAC7D;AAAA,MACA,KAAK,QAAQ;AACZ,cAAM,aAAa,MAAM,QAAQ,WAAW;AAC5C,uBAAe,QAAQ,MAAM;AAC7B,cAAM,UAAU,MAAM,SAAS,QAAQ,MAAM,WAAW,KAAK,KAAK,OAAO,CAAC;AAC1E,eAAO,EAAE,MAAM,aAAa,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC,EAAG;AAAA,MAC7D;AAAA,MACA,KAAK,QAAQ;AACZ,cAAM,aAAa,MAAM,QAAQ,WAAW;AAC5C,uBAAe,QAAQ,MAAM;AAC7B,cAAM,SAAS,QAAQ,MAAM,WAAW,SAAS,KAAK,OAAO,CAAC;AAC9D,eAAO,EAAE,MAAM,YAAY;AAAA,MAC5B;AAAA,MACA,KAAK,WAAW;AACf,cAAM,aAAa,MAAM,QAAQ,WAAW;AAC5C,uBAAe,QAAQ,MAAM;AAC7B,cAAM,WAAW,QAAQ,KAAK,OAAO;AACrC,eAAO,EAAE,MAAM,YAAY;AAAA,MAC5B;AAAA,MACA,KAAK,YAAY;AAChB,cAAM,aAAa,MAAM,QAAQ,WAAW;AAC5C,uBAAe,QAAQ,MAAM;AAC7B,cAAM,SAAS,YAAY,MAAM,WAAW,SAAS,KAAK,OAAO,CAAC;AAClE,eAAO,EAAE,MAAM,YAAY;AAAA,MAC5B;AAAA,MACA,KAAK;AACJ,cAAM,sBAAsB,KAAK,OAAO;AACxC,eAAO,EAAE,MAAM,YAAY;AAAA,MAC5B,KAAK;AACJ,cAAM,OAAO,KAAK,OAAO;AACzB,eAAO,EAAE,MAAM,YAAY;AAAA,MAC5B;AACC,YAAI,GAAG,OAAO,0BAA0B,UAAU;AAAA;AAAA,EAAO,MAAM,CAAC,IAAI,SAAS;AAC7E,eAAO,EAAE,MAAM,SAAS;AAAA,IAC1B;AAAA,EACD,SAAS,OAAO;AACf,QAAI,QAAQ,QAAS,QAAO,EAAE,MAAM,SAAS;AAC7C,QAAI,GAAG,UAAU,YAAY,MAAS;AACtC,QAAI,iBAAiB,yBAA0B,OAAM;AACrD,QAAI,iBAAiB,8BAA8B;AAClD,aAAO,EAAE,MAAM,6BAA6B,UAAU,MAAM,SAAS;AAAA,IACtE;AACA,QAAI,4BAA4B,KAAK,GAAG;AACvC,aAAO,EAAE,MAAM,qBAAqB,UAAU,MAAM,SAAS;AAAA,IAC9D;AACA,QAAI,GAAG,OAAO,aAAa,KAAK,GAAG,OAAO;AAC1C,WAAO,EAAE,MAAM,SAAS;AAAA,EACzB;AACD;AAEA,eAAe,sBAAsB,KAA8B,SAAyB;AAC3F,QAAM,SAAS,8BAA8B;AAC7C,MAAI,CAAC,QAAQ;AACZ,QAAI,GAAG,OAAO,gEAAgE,MAAM;AACpF;AAAA,EACD;AACA,MACC,CAAC,QAAQ,OACT,CAAE,MAAM,IAAI,GAAG;AAAA,IACd;AAAA,IACA;AAAA,IACA,EAAE,QAAQ,QAAQ,OAAO;AAAA,EAC1B,GACC;AACD,QAAI,GAAG,OAAO,sCAAsC,MAAM;AAC1D;AAAA,EACD;AACA,iBAAe,QAAQ,MAAM;AAC7B,QAAM,SAAS,MAAM,4BAA4B;AACjD,iBAAe,QAAQ,MAAM;AAC7B,MAAI,OAAO,WAAW,SAAS;AAC9B,QAAI,GAAG,OAAO,gEAAgE,MAAM;AACpF;AAAA,EACD;AACA,MAAI,GAAG,OAAO,OAAO,SAAS,OAAO,WAAW,aAAa,SAAS,SAAS;AAChF;AAEA,eAAe,SACd,KACA,QACA,SAC+C;AAC/C,MAAI;AACH,UAAM,UAAU,MAAM,kBAAkB;AACxC,mBAAe,MAAM;AACrB,QAAI,CAAC,QAAQ,UAAW;AACxB,UAAM,eAAe;AACrB,mBAAe,MAAM;AACrB,UAAM,WAAW;AACjB,mBAAe,MAAM;AACrB,UAAM,aAAa,MAAM,QAAQ,WAAW;AAC5C,mBAAe,MAAM;AACrB,UAAM,SAAS,aAAa,MAAM;AACjC,qBAAe,MAAM;AACrB,aAAO,WAAW,SAAS,KAAK,EAAE,GAAG,mBAAmB,OAAO,CAAC;AAAA,IACjE,CAAC;AAAA,EACF,SAAS,OAAO;AACf,QAAI,OAAO,WAAW,qBAAqB,KAAK,EAAG;AACnD,QAAI,GAAG,UAAU,YAAY,MAAS;AACtC,QAAI,iBAAiB,6BAA8B,QAAO,MAAM;AAChE,QAAI,GAAG,OAAO,8BAA8B,aAAa,KAAK,CAAC,IAAI,SAAS;AAAA,EAC7E;AACD;AAEA,eAAe,iBAAiB,KAAuB,QAAqB,SAAsB;AACjG,MAAI;AACH,UAAM,UAAU,MAAM,kBAAkB;AACxC,mBAAe,MAAM;AACrB,QAAI,CAAC,QAAQ,UAAW;AACxB,QAAI,CAAC,QAAQ,QAAQ,SAAS,UAAU,EAAG;AAC3C,UAAM,eAAe;AACrB,mBAAe,MAAM;AACrB,UAAM,SAAS,MAAM,WAAW;AAChC,mBAAe,MAAM;AACrB,QAAI,CAAC,OAAO,QAAQ,SAAS,UAAU,EAAG;AAC1C,UAAM,CAAC,YAAY,gBAAgB,eAAe,IAAI,MAAM,QAAQ,IAAI;AAAA,MACvE,QAAQ,WAAW;AAAA,MACnB,QAAQ,SAAS;AAAA,MACjB,QAAQ,UAAU;AAAA,IACnB,CAAC;AACD,mBAAe,MAAM;AACrB,UAAM,SAAS,qBAAqB,YAAY;AAC/C,qBAAe,MAAM;AACrB,YAAM,QAAQ,MAAM,mBAAmB,MAAM;AAC7C,qBAAe,MAAM;AACrB,YAAM,QAAQ,MAAM,eAAe;AAAA,QAClC,OAAO;AAAA,QACP,0BAA0B,KAAK,MAAM;AAAA,MACtC;AACA,qBAAe,MAAM;AACrB,UAAI,CAAC,gBAAgB,gBAAgB,OAAO,OAAO,MAAM,EAAG;AAC5D,YAAM,WAAW,KAAK,KAAK,EAAE,GAAG,mBAAmB,OAAO,GAAG,EAAE,QAAQ,OAAO,MAAM,CAAC;AAAA,IACtF,CAAC;AAAA,EACF,SAAS,OAAO;AACf,QAAI,OAAO,WAAW,qBAAqB,KAAK,EAAG;AACnD,QAAI,GAAG,UAAU,YAAY,MAAS;AACtC,QAAI,GAAG,OAAO,iCAAiC,aAAa,KAAK,CAAC,IAAI,SAAS;AAAA,EAChF;AACD;AAEA,eAAe,WAAW,KAA8B,QAAsB;AAC7E,QAAM,aAAa,gBAAgB;AACnC,MAAI,MAAM,sBAAsB,GAAG;AAClC,QAAI,GAAG,OAAO,0BAA0B,MAAM,sBAAsB,CAAC,IAAI,MAAM;AAC/E;AAAA,EACD;AAEA,MAAI,IAAI,SAAS,OAAO;AACvB,UAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,iCAAiB;AAC1D,mBAAe,MAAM;AACrB,UAAM,gBAAgB,KAAK,MAAM;AACjC;AAAA,EACD;AACA,QAAM,0BAA0B,oBAAoB,CAAC;AACrD,MAAI,GAAG;AAAA,IACN,WAAW,UAAU;AAAA,IACrB;AAAA,EACD;AACD;AAEA,eAAe,WAAW,KAA8B,SAAyB;AAChF,QAAM,SAAS,MAAM,WAAW,QAAQ,KAAK;AAC7C,QAAM,WAAW;AAAA,IAChB,GAAI,OAAO,QAAQ,SAAS,OAAO,qBAAqB,OAAO,QAAQ,OAAO,IAAI,CAAC;AAAA,IACnF,GAAG,qBAAqB,MAAM;AAAA,EAC/B;AACA,QAAM,eAAe,mBAAmB,MAAM;AAC9C,MAAI,GAAG;AAAA,IACN;AAAA,MACC;AAAA,MACA,eAAe,OAAO,SAAS;AAAA,MAC/B,uBAAuB,OAAO,cAAc;AAAA,MAC5C,GAAG;AAAA,MACH,iBAAiB,OAAO,WAAW;AAAA,MACnC,mBAAmB,OAAO,YAAY,YAAY,UAAU;AAAA,MAC5D,qBAAqB,OAAO,QAAQ,KAAK,IAAI,KAAK,MAAM;AAAA,MACxD,aAAa,OAAO,QAAQ,SAAS,UAAU,IAAI,aAAa,cAAc;AAAA,MAC9E,kBAAkB,gBAAgB,CAAC;AAAA,MACnC,GAAG;AAAA,IACJ,EAAE,KAAK,IAAI;AAAA,IACX,SAAS,SAAS,IAAI,YAAY;AAAA,EACnC;AACD;AAEA,SAAS,mBAAmB,QAAuB;AAClD,UAAQ,OAAO,QAAQ,MAAM;AAAA,IAC5B,KAAK;AACJ,aAAO;AAAA,QACN;AAAA,QACA,WAAW,iBAAiB,OAAO,QAAQ,QAAQ,MAAM,CAAC;AAAA,QAC1D;AAAA,QACA,WAAW,OAAO,QAAQ,YAAY,MAAM;AAAA,MAC7C;AAAA,IACD,KAAK;AACJ,aAAO;AAAA,QACN;AAAA,QACA,QAAQ,iBAAiB,OAAO,QAAQ,QAAQ,KAAK,OAAO,QAAQ,QAAQ,QAAQ,CAAC;AAAA,QACrF;AAAA,QACA;AAAA,MACD;AAAA,IACD,KAAK;AACJ,aAAO;AAAA,QACN;AAAA,QACA,aAAa,OAAO,QAAQ,QAAQ,QAAQ;AAAA,QAC5C,WAAW,OAAO,QAAQ,YAAY,MAAM;AAAA,QAC5C,WAAW,OAAO,QAAQ,QAAQ,MAAM;AAAA,QACxC;AAAA,QACA;AAAA,QACA,kBAAkB,OAAO,QAAQ,QAAQ,eAAe,eAAe,gBAAgB;AAAA,MACxF;AAAA,EACF;AACD;AAEA,SAAS,iBAAiB,OAA2B;AACpD,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI;AACH,UAAM,MAAM,IAAI,IAAI,KAAK;AACzB,QAAI,WAAW;AACf,QAAI,WAAW;AACf,QAAI,SAAS;AACb,QAAI,OAAO;AACX,WAAO,IAAI,SAAS;AAAA,EACrB,QAAQ;AACP,WAAO,MAAM,QAAQ,qCAAqC,gBAAW;AAAA,EACtE;AACD;AAEA,SAAS,iBAAiB,OAA2B,UAA8B;AAClF,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI;AACH,UAAM,MAAM,IAAI,IAAI,KAAK;AACzB,QAAI,WAAW;AACf,QAAI,WAAW;AACf,QAAI,SAAS;AACb,QAAI,OAAO;AACX,WAAO,WAAW,GAAG,IAAI,MAAM,YAAO,GAAG,IAAI,MAAM,GAAG,IAAI,QAAQ;AAAA,EACnE,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAEA,SAAS,eAAe,QAAsB;AAC7C,MAAI,CAAC,QAAQ,QAAS;AACtB,QAAM,OAAO,kBAAkB,QAC5B,OAAO,SACP,IAAI,aAAa,6BAA6B,YAAY;AAC9D;AAEA,SAAS,eAAe,SAAsB,WAAyB;AACtE,SAAO,YAAY,YAAY,IAAI,CAAC,SAAS,SAAS,CAAC,IAAI;AAC5D;AAEA,SAAS,0BACR,KACA,QACkB;AAClB,SAAO;AAAA,IACN,SAAS,OAAO;AAAA,IAChB,YAAY,sBAAsB,GAAG;AAAA,EACtC;AACD;AAEA,SAAS,sBAAsB,KAAiD;AAC/E,QAAM,UAAU,IAAI;AAGpB,QAAM,wBAAwB,QAAQ;AACtC,MAAI,OAAO,0BAA0B,cAAc,sBAAsB,KAAK,OAAO,GAAG;AACvF,WAAO;AAAA,EACR;AACA,QAAM,gBAAgB,QAAQ;AAC9B,SAAO,OAAO,kBAAkB,aAC5B,cAAc,KAAK,OAAO,IAC3B;AACJ;AAEA,SAAS,mBAA2B,MAAoD;AACvF,MAAI;AACJ,SAAO,MAAM;AACZ,QAAI,CAAC,SAAS;AACb,gBAAU,KAAK,EAAE,MAAM,CAAC,UAAU;AACjC,kBAAU;AACV,cAAM;AAAA,MACP,CAAC;AAAA,IACF;AACA,WAAO;AAAA,EACR;AACD;",
6
+ "names": ["migrationNotice"]
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@narumitw/pi-sync",
3
- "version": "0.49.9",
3
+ "version": "0.49.11",
4
4
  "description": "Pi extension that syncs Pi configuration through Git, WebDAV, Cloudflare R2, or S3-compatible storage.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -22,20 +22,23 @@
22
22
  ],
23
23
  "files": [
24
24
  "src",
25
+ "dist",
25
26
  "README.md",
26
27
  "LICENSE"
27
28
  ],
28
29
  "pi": {
29
30
  "extensions": [
30
- "./src/index.ts"
31
+ "./dist/index.ts"
31
32
  ]
32
33
  },
33
34
  "piExtension": {
34
35
  "lifecycle": "stable"
35
36
  },
36
37
  "scripts": {
37
- "check": "biome check . && npm run typecheck",
38
+ "build": "node scripts/build-runtime.mjs",
39
+ "check": "npm run build && biome check . && npm run typecheck",
38
40
  "format": "biome check --write .",
41
+ "prepack": "npm run build",
39
42
  "typecheck": "tsc --noEmit"
40
43
  },
41
44
  "dependencies": {
@@ -44,10 +47,11 @@
44
47
  "proper-lockfile": "^4.1.2"
45
48
  },
46
49
  "devDependencies": {
47
- "@biomejs/biome": "2.5.7",
48
- "@earendil-works/pi-coding-agent": "0.84.1",
49
- "@earendil-works/pi-tui": "0.84.1",
50
+ "@biomejs/biome": "2.5.8",
51
+ "@earendil-works/pi-coding-agent": "0.84.2",
52
+ "@earendil-works/pi-tui": "0.84.2",
50
53
  "@types/proper-lockfile": "^4.1.4",
54
+ "esbuild": "0.28.1",
51
55
  "typescript": "7.0.2"
52
56
  },
53
57
  "peerDependencies": {
@@ -22,6 +22,14 @@ interface StateDirectoryGuard {
22
22
  throwIfCompromised: () => void;
23
23
  }
24
24
 
25
+ interface SharedStateDirectoryGuard {
26
+ guard: Promise<StateDirectoryGuard>;
27
+ users: number;
28
+ closing?: Promise<void>;
29
+ }
30
+
31
+ const sharedStateDirectoryGuards = new Map<string, SharedStateDirectoryGuard>();
32
+
25
33
  export function stateDir() {
26
34
  const roots = inspectStateRoots();
27
35
  if (roots.canonical) return canonicalStateDir();
@@ -40,7 +48,9 @@ export function stateDirectoryMigrationNotice() {
40
48
  }
41
49
 
42
50
  export async function withStateDirectoryAccess<T>(fn: () => Promise<T>): Promise<T> {
43
- return runWithStateDirectoryGuard(await acquireStateDirectoryGuard(), fn);
51
+ const roots = inspectStateRoots();
52
+ if (!roots.legacy) return fn();
53
+ return runWithStateDirectoryGuard(await acquireSharedStateDirectoryGuard(), fn);
44
54
  }
45
55
 
46
56
  export async function migrateLegacyStateDirectory(): Promise<StateDirectoryPreparation> {
@@ -87,6 +97,50 @@ export async function migrateLegacyStateDirectory(): Promise<StateDirectoryPrepa
87
97
  });
88
98
  }
89
99
 
100
+ async function acquireSharedStateDirectoryGuard(): Promise<StateDirectoryGuard> {
101
+ const key = migrationLockPath();
102
+ for (;;) {
103
+ let shared = sharedStateDirectoryGuards.get(key);
104
+ if (shared?.closing) {
105
+ await shared.closing;
106
+ continue;
107
+ }
108
+ if (!shared) {
109
+ shared = { guard: acquireStateDirectoryGuard(), users: 0 };
110
+ sharedStateDirectoryGuards.set(key, shared);
111
+ }
112
+ shared.users += 1;
113
+ let guard: StateDirectoryGuard;
114
+ try {
115
+ guard = await shared.guard;
116
+ } catch (error) {
117
+ if (sharedStateDirectoryGuards.get(key) === shared) {
118
+ sharedStateDirectoryGuards.delete(key);
119
+ }
120
+ throw error;
121
+ }
122
+ let released = false;
123
+ return {
124
+ throwIfCompromised: guard.throwIfCompromised,
125
+ release: async () => {
126
+ if (released) return;
127
+ released = true;
128
+ shared.users -= 1;
129
+ if (shared.users > 0) return;
130
+ const closing = guard.release();
131
+ shared.closing = closing;
132
+ try {
133
+ await closing;
134
+ } finally {
135
+ if (sharedStateDirectoryGuards.get(key) === shared) {
136
+ sharedStateDirectoryGuards.delete(key);
137
+ }
138
+ }
139
+ },
140
+ };
141
+ }
142
+ }
143
+
90
144
  async function acquireStateDirectoryGuard(): Promise<StateDirectoryGuard> {
91
145
  let compromisedError: Error | undefined;
92
146
  const release = await lockfile.lock(getAgentDir(), {