@narumitw/pi-sync 0.53.1 → 0.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/README.md +6 -4
  2. package/dist/chunks/{chunk-TRCSEIAQ.ts → chunk-5ZWQ33XL.ts} +38 -18
  3. package/dist/chunks/{chunk-TRCSEIAQ.ts.map → chunk-5ZWQ33XL.ts.map} +2 -2
  4. package/dist/chunks/{chunk-FJGNDYGC.ts → chunk-VHXBCEVF.ts} +2 -2
  5. package/dist/chunks/{manager-result-dispatcher-AAEAYX57.ts → manager-result-dispatcher-6MQKFCWB.ts} +3 -3
  6. package/dist/chunks/{manager-ui-MHAHAKG3.ts → manager-ui-IURS4WXY.ts} +674 -609
  7. package/dist/chunks/manager-ui-IURS4WXY.ts.map +7 -0
  8. package/dist/chunks/{remote-selection-ui-Q2HUIBTL.ts → remote-selection-ui-6LJJ4IMQ.ts} +2 -2
  9. package/dist/chunks/{sync-operations-Y27F5T7W.ts → sync-operations-OWTE3ZL2.ts} +14 -8
  10. package/dist/chunks/{sync-operations-Y27F5T7W.ts.map → sync-operations-OWTE3ZL2.ts.map} +2 -2
  11. package/dist/index.ts +31 -6
  12. package/dist/index.ts.map +3 -3
  13. package/docs/settings.md +11 -3
  14. package/package.json +4 -4
  15. package/src/commands/command-execution.ts +3 -0
  16. package/src/commands/command-handler.ts +8 -1
  17. package/src/sync/sync-mutations.ts +9 -7
  18. package/src/sync/sync-queries.ts +1 -0
  19. package/src/ui/cancellable-operation.ts +47 -17
  20. package/src/ui/manager-attention.ts +3 -5
  21. package/src/ui/manager-state.ts +32 -15
  22. package/src/ui/manager-ui.ts +59 -87
  23. package/src/ui/operation-dialogs.ts +29 -0
  24. package/src/ui/settings-ui.ts +140 -46
  25. package/src/ui/setup/setup-actions.ts +2 -2
  26. package/dist/chunks/manager-ui-MHAHAKG3.ts.map +0 -7
  27. /package/dist/chunks/{chunk-FJGNDYGC.ts.map → chunk-VHXBCEVF.ts.map} +0 -0
  28. /package/dist/chunks/{manager-result-dispatcher-AAEAYX57.ts.map → manager-result-dispatcher-6MQKFCWB.ts.map} +0 -0
  29. /package/dist/chunks/{remote-selection-ui-Q2HUIBTL.ts.map → remote-selection-ui-6LJJ4IMQ.ts.map} +0 -0
package/README.md CHANGED
@@ -73,14 +73,16 @@ Automatic sync: On (startup check; shutdown pushes selected content if sessions
73
73
  Remote status: Not checked
74
74
  ```
75
75
 
76
- Primary actions include **Sync now**, **Switch sync setup**, **Status & changes**, **Settings**, and **More…**.
76
+ Use **Sync now** for bidirectional merging, or **Pull from remote…** and **Push to remote…** for reviewed directional transfers. **Settings**, **History**, and **Diagnostics** are also directly available. Switching appears only when multiple valid setups exist; review and access-recovery actions appear when needed. Pull and Push do not implicitly force overwrites.
77
+
78
+ The main summary uses local state and cached check-time observations, not a fresh remote comparison. Use `/sync status` for a fresh check, `/sync diff` for differences, and `/sync help` for usage; the manager shows these access hints instead of separate Status and Help actions.
77
79
 
78
80
  After Pi Sync detects an included-content mismatch, the manager shows **Sync status: Review needed** and puts **Review synced content (recommended)** first.
79
81
  **Sync now** remains unavailable until you review the mismatch.
80
82
  Opening the manager does not make another remote request.
81
- Under **More…**, **Storage connections** holds reusable server addresses and sign-in details; **Sync setups** holds content, destination, and automatic-sync choices. **Edit storage location…** changes only bucket, branch, or path, not the connection or included content. Use **Settings** for the current setup's content and automatic sync; make another setup current before changing those settings.
83
+ **Settings** keeps content, destination, automation, merge, and global preferences on one searchable screen without category submenus. **Compare synced content** sits beside **Included content**. **Storage location** edits only the current setup's bucket, branch, or path; it does not change the connection or included content. **Manage sync setups** and **Manage storage connections** open the existing catalogs. Connections hold reusable server addresses and sign-in details, and edits show every affected setup. Make another setup current before changing its preferences. Simple preferences save immediately; complex editors and risky changes retain their reviews. RPC reports the manual settings path and preserves catalog management without opening the TUI preference editor.
82
84
 
83
- **More… → Check setup** (also `/sync doctor`) reports configuration and backend-specific access checks. S3/R2 performs a read-only request: success does not prove write access or snapshot validity, and an ambiguous 404 does not prove a bucket is missing. Check the indicated credentials, address, bucket, or path before retrying. Git checks remote reads and the local cache, not write access. WebDAV uses an isolated write/cleanup probe and repairs the active snapshot's history entry if missing. The existing **History & recovery** route remains available.
85
+ **Diagnostics** (also `/sync doctor`) reports configuration and backend-specific access checks. S3/R2 performs a read-only request: success does not prove write access or snapshot validity, and an ambiguous 404 does not prove a bucket is missing. Check the indicated credentials, address, bucket, or path before retrying. Git checks remote reads and the local cache, not write access. WebDAV uses an isolated write/cleanup probe and repairs the active snapshot's history entry if missing. **History** opens the snapshot list directly for reviewed rollback. Recorded unresolved groups have a separate **Review unresolved conflicts** action.
84
86
 
85
87
  On secondary menus, **Back** and Escape return to the previous screen. In setup inputs and save reviews, cancellation (including Ctrl+C) discards the current unsaved draft and returns to its owning menu. Session replacement or shutdown closes the owning flow.
86
88
  Specialized operation and masked-credential prompts show the effective cancellation bindings and keep Ctrl+C as a hard-cancel input when Back is remapped.
@@ -176,7 +178,7 @@ Successful transfers show one summary. They do not reload resources, activate ex
176
178
 
177
179
  **Settings → Content / partial sync (experimental)** controls independent `sync.mergeContent` and `sync.partialSync` opt-ins, both default **Off**. Saving opts into settings version 5; partial publications use snapshot version 3, rejected by older readers. Supported Markdown/plain-text resources merge bounded independent line edits without Git or conflict markers. Diff grids and hunk comparisons share an eight-million-work-unit budget across the operation and its retries; exhausted paths remain conflicts for review. Same-session reconciliation only accepts validated complete byte-prefix extensions; divergent histories and the loaded session require review. A syntactically clean text merge is **not a semantic correctness guarantee**.
178
180
 
179
- Partial sync keeps each side's unresolved versions, preserves their previous accepted hashes/ancestors, and advances only independent paths. Resource/collision dependency groups are withheld together, including local-only files, never represented as deletion. **More… → History & recovery… → Review unresolved conflicts**, or `/sync conflicts`, opens exact private versions on request and resolves one freshly validated whole group. Automatic pushes, non-forced push/pull, and rollback refuse unresolved groups; use group review or an explicit manual push/pull force direction instead. Artifacts remain below the denied state root, with stable conflict identity and at most 32 proven-completed records retained; unresolved or unrecognized evidence is never automatically pruned. Failed attempts release only newly created artifacts whose inode/content ownership and lack of state/journal references are verified. See [content merge and partial recovery](./docs/content-merge-audit.md).
181
+ Partial sync keeps each side's unresolved versions, preserves their previous accepted hashes/ancestors, and advances only independent paths. Resource/collision dependency groups are withheld together, including local-only files, never represented as deletion. The conditional **Review unresolved conflicts** action, or `/sync conflicts`, opens exact private versions on request and resolves one freshly validated whole group. Automatic pushes, non-forced push/pull, and rollback refuse unresolved groups; use group review or an explicit manual push/pull force direction instead. Artifacts remain below the denied state root, with stable conflict identity and at most 32 proven-completed records retained; unresolved or unrecognized evidence is never automatically pruned. Failed attempts release only newly created artifacts whose inode/content ownership and lack of state/journal references are verified. See [content merge and partial recovery](./docs/content-merge-audit.md).
180
182
 
181
183
  **Settings → Show status (all setups)** defaults to **On**. Turning it Off immediately clears and suppresses pi-sync status text for background checks, transfers, and review attention; widgets and notifications remain available.
182
184
 
@@ -35,11 +35,12 @@ import { defineMenu, runMenu } from "@narumitw/pi-tui-kit";
35
35
 
36
36
  // src/ui/cancellable-operation.ts
37
37
  import { BorderedLoader } from "@earendil-works/pi-coding-agent";
38
- import { Key, matchesKey, truncateToWidth } from "@earendil-works/pi-tui";
38
+ import { isKeyRelease, Key, matchesKey, truncateToWidth } from "@earendil-works/pi-tui";
39
39
  import { formatInteractionHints, runCustomInteraction } from "@narumitw/pi-tui-kit";
40
40
  async function runCancellableOperation(ctx, message, route, runRoute, options = {}) {
41
41
  const {
42
42
  commitAware = false,
43
+ cancelAcrossDialogs = false,
43
44
  cancelledMessage = "Check cancelled; no settings or files were changed.",
44
45
  target,
45
46
  signal
@@ -60,12 +61,37 @@ async function runCancellableOperation(ctx, message, route, runRoute, options =
60
61
  label: "cancel"
61
62
  }
62
63
  ]);
63
- const operation = runRoute(
64
- route,
65
- interactionSignal,
66
- commitAware ? () => commitStarted = true : void 0,
67
- target
68
- ).then(
64
+ const cancel = (data) => {
65
+ if (isKeyRelease(data)) return false;
66
+ if (!matchesKey(data, Key.ctrl("c")) && !keybindings.matches(data, "tui.select.cancel")) return false;
67
+ if (commitStarted) {
68
+ ctx.ui.notify("Applying or publishing has started and cannot be cancelled safely.", "warning");
69
+ } else complete({ cancelled: true });
70
+ return true;
71
+ };
72
+ let activeDialogs = 0;
73
+ const unsubscribe = cancelAcrossDialogs ? ctx.ui.onTerminalInput((data) => {
74
+ if (isKeyRelease(data)) return;
75
+ if (activeDialogs > 0 && !matchesKey(data, Key.ctrl("c"))) return;
76
+ return cancel(data) ? { consume: true } : void 0;
77
+ }) : void 0;
78
+ let pendingRoute;
79
+ try {
80
+ pendingRoute = runRoute(
81
+ route,
82
+ interactionSignal,
83
+ commitAware ? () => commitStarted = true : void 0,
84
+ target,
85
+ cancelAcrossDialogs ? (active) => {
86
+ activeDialogs += active ? 1 : -1;
87
+ } : void 0
88
+ );
89
+ } catch (error) {
90
+ unsubscribe?.();
91
+ loader.dispose();
92
+ throw error;
93
+ }
94
+ const operation = pendingRoute.then(
69
95
  (result) => {
70
96
  routeResult = result;
71
97
  complete({});
@@ -84,17 +110,11 @@ async function runCancellableOperation(ctx, message, route, runRoute, options =
84
110
  ];
85
111
  },
86
112
  invalidate: () => loader.invalidate(),
87
- handleInput(data) {
88
- if (!matchesKey(data, Key.ctrl("c")) && !keybindings.matches(data, "tui.select.cancel")) {
89
- return;
90
- }
91
- if (commitStarted) {
92
- ctx.ui.notify("Applying or publishing has started and cannot be cancelled safely.", "warning");
93
- return;
94
- }
95
- complete({ cancelled: true });
113
+ handleInput: cancel,
114
+ dispose() {
115
+ unsubscribe?.();
116
+ loader.dispose();
96
117
  },
97
- dispose: () => loader.dispose(),
98
118
  waitForPending: () => operation
99
119
  };
100
120
  }
@@ -603,4 +623,4 @@ export {
603
623
  runCancellableOperation,
604
624
  showRemoteSelectionReview
605
625
  };
606
- //# sourceMappingURL=chunk-TRCSEIAQ.ts.map
626
+ //# sourceMappingURL=chunk-5ZWQ33XL.ts.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/ui/remote-selection-ui.ts", "../../src/ui/cancellable-operation.ts"],
4
- "sourcesContent": ["import type { ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { defineMenu, runMenu } from \"@narumitw/pi-tui-kit\";\nimport { createSyncBackend, type SyncBackendFactory } from \"../backends/backend-factory.js\";\nimport type { RemoteHead, SyncBackend } from \"../backends/sync-backend.js\";\nimport {\n loadConfig,\n loadPartialConfig,\n type SyncSetupStorageReview,\n syncConfigReviewFingerprint,\n} from \"../settings/config.js\";\nimport { SyncSetupReviewChangedError, updateSyncSetup } from \"../settings/settings-management.js\";\nimport type { AnySyncConfig, PartialConfig } from \"../settings/settings-types.js\";\nimport { readSnapshotForHead } from \"../sync/remote-snapshot.js\";\nimport { errorMessage } from \"../sync/sync-errors.js\";\nimport {\n compareSyncInclude,\n inspectRemoteSelection,\n type RemoteSelectionDecision,\n type RemoteSelectionState,\n sameSyncInclude,\n} from \"../sync/sync-policy.js\";\nimport { type RunRoute, type RunRouteResult, runCancellableOperation } from \"./cancellable-operation.js\";\nimport { setSyncStatus } from \"./sync-status.js\";\nimport { safeTerminalText } from \"./terminal-text.js\";\n\nexport type RemoteSelectionOrigin = \"settings\" | \"sync\" | \"pull\" | \"push\";\n\nexport interface RemoteSelectionReviewOptions {\n decision?: RemoteSelectionDecision;\n origin?: RemoteSelectionOrigin;\n runRoute?: RunRoute;\n cancelLabel?: string;\n /** The explicit mismatch is resolved or superseded; this does not imply file equality. */\n onSelectionResolved?: () => void;\n withStateAccess?: <T>(task: () => Promise<T>) => Promise<T>;\n}\n\nexport type RemoteSelectionReviewResult =\n | { kind: \"back\" }\n | { kind: \"closed\" }\n | { kind: \"done\" }\n | { kind: \"stale\" }\n | { kind: \"route-result\"; result: RunRouteResult; route: \"sync\" | \"pull\" | \"push\" };\n\nexport async function showRemoteSelectionReview(\n ctx: ExtensionContext,\n setupName?: string,\n signal?: AbortSignal,\n factory: SyncBackendFactory = createSyncBackend,\n options: RemoteSelectionReviewOptions = {},\n): Promise<RemoteSelectionReviewResult> {\n try {\n let decision = options.decision;\n if (!decision) {\n const inspected = await inspectConfiguredRemoteSelection(ctx, setupName, signal, factory);\n if (!inspected || signal?.aborted) return { kind: \"stale\" };\n // A successful fresh read can supersede an old explicit mismatch without\n // changing local settings. This is not user cancellation or proof of file equality.\n if (inspected.kind === \"empty\" || inspected.state.kind !== \"different\") {\n options.onSelectionResolved?.();\n }\n if (inspected.kind === \"empty\") {\n ctx.ui.notify(\"Remote storage has no snapshot or synced-content list yet.\", \"info\");\n return { kind: \"back\" };\n }\n if (inspected.state.kind === \"same\") {\n ctx.ui.notify(\"Remote synced content already matches this sync setup.\", \"info\");\n return { kind: \"back\" };\n }\n if (inspected.state.kind === \"legacy\") {\n if (ctx.mode !== \"tui\") {\n ctx.ui.notify(formatLegacySummary(inspected.config, inspected.state.discovered), \"info\");\n return { kind: \"back\" };\n }\n await showLegacyDiscovery(ctx, inspected.config, inspected.state.discovered, signal);\n return signal?.aborted ? { kind: \"stale\" } : { kind: \"back\" };\n }\n decision = decisionFromState(inspected.config, inspected.state);\n }\n\n if (ctx.mode !== \"tui\") {\n ctx.ui.notify(formatRemoteSelectionSummary(decision), \"warning\");\n return { kind: \"back\" };\n }\n\n let currentDecision = decision;\n for (;;) {\n if (signal?.aborted) return { kind: \"stale\" };\n const result = await showSelectionDifference(\n ctx,\n currentDecision,\n options.origin ?? \"settings\",\n options.runRoute,\n signal,\n factory,\n options,\n );\n if (result.kind !== \"refresh\") return result;\n const refreshed = await runWithOptionalStateAccess(options, () =>\n inspectConfiguredRemoteSelection(ctx, currentDecision.setupName, signal, factory),\n );\n if (!refreshed || signal?.aborted) return { kind: \"stale\" };\n if (refreshed.kind === \"empty\") {\n options.onSelectionResolved?.();\n ctx.ui.notify(\"Remote storage no longer has a snapshot or synced-content list.\", \"warning\");\n return { kind: \"back\" };\n }\n if (refreshed.state.kind !== \"different\") {\n ctx.ui.notify(\n refreshed.state.kind === \"same\"\n ? \"Remote synced content now matches this sync setup.\"\n : \"The refreshed legacy snapshot has no authoritative synced-content list.\",\n \"info\",\n );\n options.onSelectionResolved?.();\n return { kind: \"done\" };\n }\n currentDecision = decisionFromState(refreshed.config, refreshed.state);\n }\n } catch (error) {\n if (signal?.aborted) return { kind: \"stale\" };\n ctx.ui.notify(`Could not review synced content: ${errorMessage(error)}`, \"error\");\n return { kind: \"back\" };\n } finally {\n setSyncStatus(ctx, undefined);\n }\n}\n\ntype DifferenceFlowResult = RemoteSelectionReviewResult | { kind: \"refresh\" };\n\nasync function showSelectionDifference(\n ctx: ExtensionContext,\n initialDecision: RemoteSelectionDecision,\n origin: RemoteSelectionOrigin,\n runRoute: RunRoute | undefined,\n sessionSignal: AbortSignal | undefined,\n factory: SyncBackendFactory,\n options: Pick<RemoteSelectionReviewOptions, \"cancelLabel\" | \"onSelectionResolved\" | \"withStateAccess\">,\n): Promise<DifferenceFlowResult> {\n type Screen = \"choice\" | \"review\" | \"saved\";\n type Action = \"adopt\" | \"keep\" | \"cancel\" | \"continue\" | \"done\";\n interface FlowState {\n decision: RemoteSelectionDecision;\n saved: boolean;\n }\n let flowState: FlowState = { decision: initialDecision, saved: false };\n let continuationReview: PartialConfig | undefined;\n let nextResult: RemoteSelectionReviewResult | undefined;\n let refreshRequested = false;\n const route = origin === \"settings\" ? \"sync\" : origin;\n const menu = defineMenu<FlowState, Screen, Action, ExtensionContext>({\n start: \"choice\",\n screens: {\n choice: ({ state }) => ({\n kind: \"actions\",\n title: \"Synced content differs\",\n lines: selectionSummaryLines(state.decision),\n items: [\n {\n id: \"review\",\n label: \"Review all paths (recommended)\",\n description: \"Compare exact remote-only, device-only, and ordered lists.\",\n to: \"review\",\n },\n {\n id: \"adopt\",\n label: \"Use remote content list\",\n description: \"Save the reviewed list on this device without pulling files.\",\n action: \"adopt\",\n },\n {\n id: \"keep\",\n label: \"Keep this device's content list and update remote\u2026\",\n description: \"Open the existing exact force-push preview without skipping confirmation.\",\n action: \"keep\",\n },\n { id: \"cancel\", label: options.cancelLabel ?? \"Cancel\", action: \"cancel\" },\n ],\n hint: \"back\",\n }),\n review: ({ state }) => ({\n kind: \"review\",\n title: `Review synced content \u00B7 ${safeTerminalText(state.decision.setupName)}`,\n content: formatSelectionDifference(state.decision),\n format: { kind: \"text\" },\n viewportSize: \"adaptive\",\n hint: \"back\",\n }),\n saved: ({ state }) => ({\n kind: \"actions\",\n title: \"Remote content list saved\",\n lines: [\n `Sync setup: ${safeTerminalText(state.decision.setupName)}`,\n \"Only the included-content setting was saved.\",\n \"No files were pulled and sync state was not changed.\",\n ],\n items: [\n ...(runRoute\n ? [\n {\n id: \"continue\",\n label: continueLabel(origin),\n description: \"Start a fresh check and exact preview for this sync setup.\",\n action: \"continue\" as const,\n },\n ]\n : []),\n { id: \"done\", label: \"Done\", action: \"done\" },\n ],\n hint: \"close\",\n }),\n },\n actions: {\n adopt: async ({ state, signal: actionSignal }) => {\n const signal = combineSignals(sessionSignal, actionSignal);\n try {\n const currentConfig = await loadConfig(state.decision.setupName);\n if (signal.aborted) return { kind: \"close\" as const };\n assertLocalSelectionCurrent(currentConfig, state.decision);\n if (!currentConfig.include.includes(\"sessions\") && state.decision.remoteInclude.includes(\"sessions\")) {\n const acknowledged = await ctx.ui.confirm(\n \"Use a content list that includes session conversations?\",\n \"Session JSONL may contain prompts, tool output, file paths, images, and secrets. This saves the list only; it does not pull files.\",\n { signal },\n );\n if (signal.aborted) return { kind: \"close\" as const };\n if (!acknowledged) return { kind: \"stay\" as const };\n }\n const review = await runWithOptionalStateAccess(options, async () => {\n const loaded = await loadAdoptionReview(state.decision, signal, factory);\n if (signal.aborted) throw signal.reason;\n await revalidateAndAdopt(loaded, state.decision, signal);\n return loaded;\n });\n if (signal.aborted) return { kind: \"close\" as const };\n options.onSelectionResolved?.();\n continuationReview = {\n ...review.storageReview,\n setupName: state.decision.setupName,\n include: [...state.decision.remoteInclude],\n automatic: review.config.automatic,\n automaticTransfer: review.config.automaticTransfer,\n onSwitch: review.config.onSwitch,\n showStatus: review.config.showStatus,\n };\n flowState = { decision: state.decision, saved: true };\n return { kind: \"to\" as const, screen: \"saved\" as const };\n } catch (error) {\n if (signal.aborted) return { kind: \"close\" as const };\n if (isStaleReviewError(error)) {\n ctx.ui.notify(`${errorMessage(error)} Refreshing the comparison.`, \"warning\");\n refreshRequested = true;\n return { kind: \"close\" as const };\n }\n ctx.ui.notify(`Could not save the remote content list: ${errorMessage(error)}`, \"error\");\n return { kind: \"stay\" as const };\n }\n },\n keep: async ({ state, signal: actionSignal }) => {\n if (!runRoute) {\n ctx.ui.notify(\"The reviewed update-remote route is unavailable.\", \"error\");\n return { kind: \"stay\" as const };\n }\n const signal = combineSignals(sessionSignal, actionSignal);\n try {\n const latest = await loadConfig(state.decision.setupName);\n if (signal.aborted) return { kind: \"close\" as const };\n assertLocalSelectionCurrent(latest, state.decision);\n const result = await runCancellableOperation(\n ctx,\n \"Preparing this device's push preview\u2026\",\n \"push --force\",\n runRoute,\n {\n commitAware: true,\n cancelledMessage: \"Push preparation cancelled; no remote files were changed.\",\n target: state.decision.setupName,\n signal,\n },\n );\n return handleNestedRouteResult(result, \"push\");\n } catch (error) {\n if (signal.aborted) return { kind: \"close\" as const };\n if (isStaleReviewError(error)) {\n ctx.ui.notify(`${errorMessage(error)} Refreshing the comparison.`, \"warning\");\n refreshRequested = true;\n return { kind: \"close\" as const };\n }\n ctx.ui.notify(`Could not prepare the remote update: ${errorMessage(error)}`, \"error\");\n return { kind: \"stay\" as const };\n }\n },\n continue: async ({ state, signal: actionSignal }) => {\n if (!runRoute || !continuationReview) return { kind: \"stay\" as const };\n const signal = combineSignals(sessionSignal, actionSignal);\n try {\n const latest = await loadPartialConfig(state.decision.setupName);\n if (signal.aborted) return { kind: \"close\" as const };\n if (!sameContinuationReview(latest, continuationReview)) {\n throw new StaleRemoteSelectionReviewError(\n `Sync setup \u201C${safeTerminalText(state.decision.setupName)}\u201D changed after the remote content list was saved.`,\n );\n }\n const result = await runCancellableOperation(ctx, continueBusyLabel(origin), route, runRoute, {\n commitAware: true,\n cancelledMessage: continuationCancelledMessage(route),\n target: state.decision.setupName,\n signal,\n });\n return handleNestedRouteResult(result, route);\n } catch (error) {\n if (signal.aborted) return { kind: \"close\" as const };\n ctx.ui.notify(`Could not continue: ${errorMessage(error)}`, \"error\");\n return { kind: \"stay\" as const };\n }\n },\n cancel: async () => ({ kind: \"back\" }),\n done: async () => {\n nextResult = { kind: \"done\" };\n return { kind: \"close\" };\n },\n },\n });\n\n function handleNestedRouteResult(\n result: Awaited<ReturnType<typeof runCancellableOperation>>,\n nestedRoute: \"sync\" | \"pull\" | \"push\",\n ) {\n if (result.kind === \"completed\" && result.outcome === \"applied\") {\n options.onSelectionResolved?.();\n }\n if (result.kind === \"closed\") {\n nextResult = { kind: \"closed\" };\n return { kind: \"close\" as const };\n }\n if (\n result.kind === \"cancelled\" ||\n (result.kind === \"completed\" && result.outcome === \"cancelled\") ||\n result.kind === \"failed\"\n ) {\n return { kind: \"stay\" as const };\n }\n nextResult = { kind: \"route-result\", result, route: nestedRoute };\n return { kind: \"close\" as const };\n }\n\n const menuResult = await runMenu(ctx, menu, {\n getState: () => flowState,\n signal: sessionSignal,\n isCurrent: () => !sessionSignal?.aborted,\n onError: (_menuCtx, error) => ctx.ui.notify(errorMessage(error), \"error\"),\n });\n if (sessionSignal?.aborted || menuResult.kind === \"stale\") return { kind: \"stale\" };\n if (refreshRequested) return { kind: \"refresh\" };\n if (nextResult) return nextResult;\n if (menuResult.kind === \"closed\") {\n return menuResult.reason === \"back\" ? { kind: \"back\" } : { kind: \"closed\" };\n }\n return { kind: \"closed\" };\n}\n\ninterface AdoptionReview {\n config: AnySyncConfig;\n storageReview: SyncSetupStorageReview;\n backend: SyncBackend;\n reviewedHead: RemoteHead;\n}\n\nasync function loadAdoptionReview(\n decision: RemoteSelectionDecision,\n signal: AbortSignal,\n factory: SyncBackendFactory,\n): Promise<AdoptionReview> {\n const config = await loadConfig(decision.setupName);\n throwIfAborted(signal);\n assertLocalSelectionCurrent(config, decision);\n const partial = await loadPartialConfig(decision.setupName);\n throwIfAborted(signal);\n if (!sameSyncInclude(partial.include, decision.localInclude)) {\n throw new StaleRemoteSelectionReviewError(\n `Sync setup \u201C${safeTerminalText(decision.setupName)}\u201D changed while the comparison was open.`,\n );\n }\n const backend = await factory(config);\n throwIfAborted(signal);\n const reviewedHead = await backend.readHead(signal);\n throwIfAborted(signal);\n if (!reviewedHead) {\n throw new StaleRemoteSelectionReviewError(\"Remote storage changed while the comparison was open.\");\n }\n const snapshot = await readSnapshotForHead(backend, reviewedHead, signal);\n throwIfAborted(signal);\n const state = inspectRemoteSelection(config.include, snapshot);\n if (state.kind !== \"different\" || !sameSyncInclude(state.include, decision.remoteInclude)) {\n throw new StaleRemoteSelectionReviewError(\"Remote synced content changed while the comparison was open.\");\n }\n return { config, storageReview: partial, backend, reviewedHead };\n}\n\nasync function revalidateAndAdopt(review: AdoptionReview, decision: RemoteSelectionDecision, signal: AbortSignal) {\n const currentHead = await review.backend.readHead(signal);\n throwIfAborted(signal);\n if (!currentHead || !review.backend.sameRevision(review.reviewedHead.revision, currentHead.revision)) {\n throw new StaleRemoteSelectionReviewError(\"Remote storage changed while the comparison was open.\");\n }\n const currentSnapshot = await readSnapshotForHead(review.backend, currentHead, signal);\n throwIfAborted(signal);\n const currentState = inspectRemoteSelection(review.config.include, currentSnapshot);\n if (currentState.kind !== \"different\" || !sameSyncInclude(currentState.include, decision.remoteInclude)) {\n throw new StaleRemoteSelectionReviewError(\"Remote synced content changed while the comparison was open.\");\n }\n await updateSyncSetup(\n decision.setupName,\n (setup) => ({\n ...setup,\n sync: { ...setup.sync, include: [...decision.remoteInclude] },\n }),\n {\n expectedStorage: review.storageReview,\n expectedInclude: decision.localInclude,\n signal,\n },\n );\n}\n\nasync function inspectConfiguredRemoteSelection(\n ctx: ExtensionContext,\n setupName: string | undefined,\n signal: AbortSignal | undefined,\n factory: SyncBackendFactory,\n): Promise<\n | { kind: \"empty\"; config: AnySyncConfig }\n | { kind: \"selection\"; config: AnySyncConfig; state: RemoteSelectionState }\n | undefined\n> {\n const config = await loadConfig(setupName);\n if (signal?.aborted) return undefined;\n setSyncStatus(ctx, `checking synced content for ${safeTerminalText(config.setupName)}`);\n const backend = await factory(config);\n if (signal?.aborted) return undefined;\n const head = await backend.readHead(signal);\n if (signal?.aborted) return undefined;\n if (!head) return { kind: \"empty\", config };\n const snapshot = await readSnapshotForHead(backend, head, signal);\n if (signal?.aborted) return undefined;\n return {\n kind: \"selection\",\n config,\n state: inspectRemoteSelection(config.include, snapshot),\n };\n}\n\nasync function showLegacyDiscovery(\n ctx: ExtensionContext,\n config: AnySyncConfig,\n discovered: string[],\n signal?: AbortSignal,\n) {\n const menu = defineMenu<undefined, \"choice\" | \"review\", \"back\", ExtensionContext>({\n start: \"choice\",\n screens: {\n choice: () => ({\n kind: \"actions\",\n title: `Compare synced content \u00B7 ${safeTerminalText(config.setupName)}`,\n lines: [\n \"This legacy snapshot has no portable synced-content list.\",\n \"Discovered paths are partial and read-only; preserved files may not have been selected.\",\n ],\n items: [\n { id: \"review\", label: \"Review discovered paths\", to: \"review\" },\n { id: \"back\", label: \"Back\", action: \"back\" },\n ],\n hint: \"close\",\n }),\n review: () => ({\n kind: \"review\",\n title: \"Partial discovery from legacy snapshot\",\n content: [\n \"Partial discovery only \u2014 not an authoritative selection.\",\n \"\",\n ...(discovered.length > 0\n ? discovered.map((item) => `Discovered: ${safeTerminalText(item)}`)\n : [\"No safe paths were discovered.\"]),\n \"\",\n \"Use Add custom path\u2026 in the local Included Content editor if needed.\",\n ].join(\"\\n\"),\n format: { kind: \"text\" },\n viewportSize: \"adaptive\",\n hint: \"back\",\n }),\n },\n actions: { back: async () => ({ kind: \"close\" }) },\n });\n await runMenu(ctx, menu, {\n getState: () => undefined,\n signal,\n isCurrent: () => !signal?.aborted,\n });\n}\n\nfunction selectionSummaryLines(decision: RemoteSelectionDecision) {\n const comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n return [\n `Sync setup: ${safeTerminalText(decision.setupName)}`,\n \"Nothing changed. Review both lists before choosing what happens next.\",\n ...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n ? [\"Only the ordering differs; membership is the same.\"]\n : [`Remote-only paths: ${comparison.remoteOnly.length} \u00B7 Device-only paths: ${comparison.localOnly.length}`]),\n ];\n}\n\nfunction formatSelectionDifference(decision: RemoteSelectionDecision) {\n const comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n return [\n ...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n ? [\"Only ordering differs; both lists contain the same paths.\", \"\"]\n : []),\n \"Remote-only paths:\",\n ...(comparison.remoteOnly.length > 0\n ? comparison.remoteOnly.map((item) => `+ ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"Device-only paths:\",\n ...(comparison.localOnly.length > 0\n ? comparison.localOnly.map((item) => `- ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"Remote ordered list:\",\n ...(decision.remoteInclude.length > 0\n ? decision.remoteInclude.map((item, index) => `${index + 1}. ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"This device's ordered list:\",\n ...(decision.localInclude.length > 0\n ? decision.localInclude.map((item, index) => `${index + 1}. ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"Using the remote list saves settings only and does not pull files.\",\n ].join(\"\\n\");\n}\n\nfunction formatRemoteSelectionSummary(decision: RemoteSelectionDecision) {\n const comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n return [\n `Synced content for \u201C${safeTerminalText(decision.setupName)}\u201D differs from this device.`,\n `Remote-only: ${safeList(comparison.remoteOnly)}`,\n `Device-only: ${safeList(comparison.localOnly)}`,\n ...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n ? [\n \"Only ordering differs.\",\n `Remote order: ${safeList(decision.remoteInclude)}`,\n `Device order: ${safeList(decision.localInclude)}`,\n ]\n : []),\n \"Run /sync in TUI to choose a content list; RPC review is read-only.\",\n ].join(\"\\n\");\n}\n\nfunction formatLegacySummary(config: AnySyncConfig, discovered: readonly string[]) {\n return `Remote snapshot for \u201C${safeTerminalText(config.setupName)}\u201D has no portable synced-content list; ${discovered.length} safe path${discovered.length === 1 ? \" was\" : \"s were\"} discovered, but the result is partial and read-only.`;\n}\n\nfunction decisionFromState(\n config: AnySyncConfig,\n state: Extract<RemoteSelectionState, { kind: \"different\" }>,\n): RemoteSelectionDecision {\n return {\n setupName: config.setupName,\n configIdentity: syncConfigReviewFingerprint(config),\n localInclude: [...config.include],\n remoteInclude: [...state.include],\n };\n}\n\nfunction assertLocalSelectionCurrent(config: AnySyncConfig, decision: RemoteSelectionDecision) {\n if (\n syncConfigReviewFingerprint(config) === decision.configIdentity &&\n sameSyncInclude(config.include, decision.localInclude)\n ) {\n return;\n }\n throw new StaleRemoteSelectionReviewError(\n `Sync setup \u201C${safeTerminalText(config.setupName)}\u201D changed while the comparison was open.`,\n );\n}\n\nfunction sameContinuationReview(left: PartialConfig, right: PartialConfig) {\n return (\n left.setupName === right.setupName &&\n left.connectionName === right.connectionName &&\n left.storageKind === right.storageKind &&\n left.storagePath === right.storagePath &&\n left.bucket === right.bucket &&\n left.branch === right.branch &&\n sameSyncInclude(left.include, right.include)\n );\n}\n\nfunction continueLabel(origin: RemoteSelectionOrigin) {\n if (origin === \"pull\") return \"Continue Pull now\u2026\";\n if (origin === \"push\") return \"Continue Push now\u2026\";\n return \"Continue Sync now\u2026\";\n}\n\nfunction continueBusyLabel(origin: RemoteSelectionOrigin) {\n if (origin === \"pull\") return \"Checking remote changes\u2026\";\n if (origin === \"push\") return \"Preparing push preview\u2026\";\n return \"Checking current sync setup\u2026\";\n}\n\nfunction continuationCancelledMessage(route: \"sync\" | \"pull\" | \"push\") {\n if (route === \"pull\") return \"Pull check cancelled; no local files were changed.\";\n if (route === \"push\") return \"Push preparation cancelled; no remote files were changed.\";\n return \"Sync check cancelled; no settings or files were changed.\";\n}\n\nfunction safeList(values: readonly string[]) {\n return values.length > 0 ? values.map(safeTerminalText).join(\", \") : \"none\";\n}\n\nclass StaleRemoteSelectionReviewError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"StaleRemoteSelectionReviewError\";\n }\n}\n\nfunction isStaleReviewError(error: unknown) {\n return error instanceof StaleRemoteSelectionReviewError || error instanceof SyncSetupReviewChangedError;\n}\n\nfunction runWithOptionalStateAccess<T>(\n options: Pick<RemoteSelectionReviewOptions, \"withStateAccess\">,\n task: () => Promise<T>,\n) {\n return options.withStateAccess ? options.withStateAccess(task) : task();\n}\n\nfunction combineSignals(sessionSignal: AbortSignal | undefined, actionSignal: AbortSignal) {\n return sessionSignal ? AbortSignal.any([sessionSignal, actionSignal]) : actionSignal;\n}\n\nfunction throwIfAborted(signal: AbortSignal) {\n if (!signal.aborted) return;\n throw signal.reason instanceof Error ? signal.reason : new DOMException(\"The operation was aborted\", \"AbortError\");\n}\n", "import { BorderedLoader, type ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { Key, matchesKey, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { formatInteractionHints, runCustomInteraction } from \"@narumitw/pi-tui-kit\";\nimport type { SetupPullOutcome } from \"../sync/setup-switch.js\";\nimport type { SyncDecision } from \"../sync/sync-decision.js\";\nimport type { RemoteSelectionDecision } from \"../sync/sync-policy.js\";\n\nexport type RunRouteResult =\n | { kind: \"completed\"; outcome?: SetupPullOutcome }\n | { kind: \"decision-required\"; decision: SyncDecision }\n | { kind: \"remote-selection-required\"; decision: RemoteSelectionDecision }\n | { kind: \"failed\" };\n\nexport type RunRoute = (\n route: string,\n signal?: AbortSignal,\n onCommit?: () => void,\n target?: string,\n) => Promise<RunRouteResult | undefined>;\n\nexport type CancellableOperationResult = RunRouteResult | { kind: \"closed\" } | { kind: \"cancelled\" };\n\ninterface CancellableOperationOptions {\n commitAware?: boolean;\n cancelledMessage?: string | null;\n target?: string;\n signal?: AbortSignal;\n}\n\nexport async function runCancellableOperation(\n ctx: ExtensionContext,\n message: string,\n route: string,\n runRoute: RunRoute,\n options: CancellableOperationOptions = {},\n): Promise<CancellableOperationResult> {\n const {\n commitAware = false,\n cancelledMessage = \"Check cancelled; no settings or files were changed.\",\n target,\n signal,\n } = options;\n if (ctx.mode !== \"tui\") {\n return (await runRoute(route, signal, undefined, target)) ?? { kind: \"failed\" };\n }\n let commitStarted = false;\n let routeResult: RunRouteResult | undefined;\n const interaction = await runCustomInteraction<{ cancelled?: boolean; error?: unknown }, ExtensionContext>(ctx, {\n signal,\n isCurrent: () => !signal?.aborted,\n create: ({ tui, theme, keybindings, signal: interactionSignal, complete }) => {\n const loader = new BorderedLoader(tui, theme, message, { cancellable: false });\n const cancelHint = formatInteractionHints(keybindings, [\n {\n keys: [...keybindings.getKeys(\"tui.select.cancel\").filter((key) => !hasControlCharacter(key)), \"ctrl+c\"],\n label: \"cancel\",\n },\n ]);\n const operation = runRoute(\n route,\n interactionSignal,\n commitAware ? () => (commitStarted = true) : undefined,\n target,\n ).then(\n (result) => {\n routeResult = result;\n complete({});\n },\n (error: unknown) => complete({ error }),\n );\n return {\n render(width: number) {\n const safeWidth = Math.max(1, width);\n const lines = loader.render(safeWidth);\n const bottomBorder = lines.at(-1);\n return [\n ...lines.slice(0, -1),\n truncateToWidth(theme.fg(\"dim\", cancelHint), safeWidth, \"\"),\n ...(bottomBorder === undefined ? [] : [bottomBorder]),\n ];\n },\n invalidate: () => loader.invalidate(),\n handleInput(data: string) {\n if (!matchesKey(data, Key.ctrl(\"c\")) && !keybindings.matches(data, \"tui.select.cancel\")) {\n return;\n }\n if (commitStarted) {\n ctx.ui.notify(\"Applying or publishing has started and cannot be cancelled safely.\", \"warning\");\n return;\n }\n complete({ cancelled: true });\n },\n dispose: () => loader.dispose(),\n waitForPending: () => operation,\n };\n },\n });\n if (interaction.kind === \"error\") throw interaction.error;\n if (interaction.kind !== \"completed\") return { kind: \"closed\" };\n if (interaction.value.cancelled) {\n if (cancelledMessage) ctx.ui.notify(cancelledMessage, \"info\");\n return { kind: \"cancelled\" };\n }\n if (interaction.value.error) throw interaction.value.error;\n return routeResult ?? { kind: \"failed\" };\n}\n\nfunction hasControlCharacter(value: string) {\n // biome-ignore lint/suspicious/noControlCharactersInRegex: Unsafe key labels must be omitted.\n return /[\\u0000-\\u001f\\u007f-\\u009f]/u.test(value);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { defineMenu, runMenu } from \"@narumitw/pi-tui-kit\";\nimport { createSyncBackend, type SyncBackendFactory } from \"../backends/backend-factory.js\";\nimport type { RemoteHead, SyncBackend } from \"../backends/sync-backend.js\";\nimport {\n loadConfig,\n loadPartialConfig,\n type SyncSetupStorageReview,\n syncConfigReviewFingerprint,\n} from \"../settings/config.js\";\nimport { SyncSetupReviewChangedError, updateSyncSetup } from \"../settings/settings-management.js\";\nimport type { AnySyncConfig, PartialConfig } from \"../settings/settings-types.js\";\nimport { readSnapshotForHead } from \"../sync/remote-snapshot.js\";\nimport { errorMessage } from \"../sync/sync-errors.js\";\nimport {\n compareSyncInclude,\n inspectRemoteSelection,\n type RemoteSelectionDecision,\n type RemoteSelectionState,\n sameSyncInclude,\n} from \"../sync/sync-policy.js\";\nimport { type RunRoute, type RunRouteResult, runCancellableOperation } from \"./cancellable-operation.js\";\nimport { setSyncStatus } from \"./sync-status.js\";\nimport { safeTerminalText } from \"./terminal-text.js\";\n\nexport type RemoteSelectionOrigin = \"settings\" | \"sync\" | \"pull\" | \"push\";\n\nexport interface RemoteSelectionReviewOptions {\n decision?: RemoteSelectionDecision;\n origin?: RemoteSelectionOrigin;\n runRoute?: RunRoute;\n cancelLabel?: string;\n /** The explicit mismatch is resolved or superseded; this does not imply file equality. */\n onSelectionResolved?: () => void;\n withStateAccess?: <T>(task: () => Promise<T>) => Promise<T>;\n}\n\nexport type RemoteSelectionReviewResult =\n | { kind: \"back\" }\n | { kind: \"closed\" }\n | { kind: \"done\" }\n | { kind: \"stale\" }\n | { kind: \"route-result\"; result: RunRouteResult; route: \"sync\" | \"pull\" | \"push\" };\n\nexport async function showRemoteSelectionReview(\n ctx: ExtensionContext,\n setupName?: string,\n signal?: AbortSignal,\n factory: SyncBackendFactory = createSyncBackend,\n options: RemoteSelectionReviewOptions = {},\n): Promise<RemoteSelectionReviewResult> {\n try {\n let decision = options.decision;\n if (!decision) {\n const inspected = await inspectConfiguredRemoteSelection(ctx, setupName, signal, factory);\n if (!inspected || signal?.aborted) return { kind: \"stale\" };\n // A successful fresh read can supersede an old explicit mismatch without\n // changing local settings. This is not user cancellation or proof of file equality.\n if (inspected.kind === \"empty\" || inspected.state.kind !== \"different\") {\n options.onSelectionResolved?.();\n }\n if (inspected.kind === \"empty\") {\n ctx.ui.notify(\"Remote storage has no snapshot or synced-content list yet.\", \"info\");\n return { kind: \"back\" };\n }\n if (inspected.state.kind === \"same\") {\n ctx.ui.notify(\"Remote synced content already matches this sync setup.\", \"info\");\n return { kind: \"back\" };\n }\n if (inspected.state.kind === \"legacy\") {\n if (ctx.mode !== \"tui\") {\n ctx.ui.notify(formatLegacySummary(inspected.config, inspected.state.discovered), \"info\");\n return { kind: \"back\" };\n }\n await showLegacyDiscovery(ctx, inspected.config, inspected.state.discovered, signal);\n return signal?.aborted ? { kind: \"stale\" } : { kind: \"back\" };\n }\n decision = decisionFromState(inspected.config, inspected.state);\n }\n\n if (ctx.mode !== \"tui\") {\n ctx.ui.notify(formatRemoteSelectionSummary(decision), \"warning\");\n return { kind: \"back\" };\n }\n\n let currentDecision = decision;\n for (;;) {\n if (signal?.aborted) return { kind: \"stale\" };\n const result = await showSelectionDifference(\n ctx,\n currentDecision,\n options.origin ?? \"settings\",\n options.runRoute,\n signal,\n factory,\n options,\n );\n if (result.kind !== \"refresh\") return result;\n const refreshed = await runWithOptionalStateAccess(options, () =>\n inspectConfiguredRemoteSelection(ctx, currentDecision.setupName, signal, factory),\n );\n if (!refreshed || signal?.aborted) return { kind: \"stale\" };\n if (refreshed.kind === \"empty\") {\n options.onSelectionResolved?.();\n ctx.ui.notify(\"Remote storage no longer has a snapshot or synced-content list.\", \"warning\");\n return { kind: \"back\" };\n }\n if (refreshed.state.kind !== \"different\") {\n ctx.ui.notify(\n refreshed.state.kind === \"same\"\n ? \"Remote synced content now matches this sync setup.\"\n : \"The refreshed legacy snapshot has no authoritative synced-content list.\",\n \"info\",\n );\n options.onSelectionResolved?.();\n return { kind: \"done\" };\n }\n currentDecision = decisionFromState(refreshed.config, refreshed.state);\n }\n } catch (error) {\n if (signal?.aborted) return { kind: \"stale\" };\n ctx.ui.notify(`Could not review synced content: ${errorMessage(error)}`, \"error\");\n return { kind: \"back\" };\n } finally {\n setSyncStatus(ctx, undefined);\n }\n}\n\ntype DifferenceFlowResult = RemoteSelectionReviewResult | { kind: \"refresh\" };\n\nasync function showSelectionDifference(\n ctx: ExtensionContext,\n initialDecision: RemoteSelectionDecision,\n origin: RemoteSelectionOrigin,\n runRoute: RunRoute | undefined,\n sessionSignal: AbortSignal | undefined,\n factory: SyncBackendFactory,\n options: Pick<RemoteSelectionReviewOptions, \"cancelLabel\" | \"onSelectionResolved\" | \"withStateAccess\">,\n): Promise<DifferenceFlowResult> {\n type Screen = \"choice\" | \"review\" | \"saved\";\n type Action = \"adopt\" | \"keep\" | \"cancel\" | \"continue\" | \"done\";\n interface FlowState {\n decision: RemoteSelectionDecision;\n saved: boolean;\n }\n let flowState: FlowState = { decision: initialDecision, saved: false };\n let continuationReview: PartialConfig | undefined;\n let nextResult: RemoteSelectionReviewResult | undefined;\n let refreshRequested = false;\n const route = origin === \"settings\" ? \"sync\" : origin;\n const menu = defineMenu<FlowState, Screen, Action, ExtensionContext>({\n start: \"choice\",\n screens: {\n choice: ({ state }) => ({\n kind: \"actions\",\n title: \"Synced content differs\",\n lines: selectionSummaryLines(state.decision),\n items: [\n {\n id: \"review\",\n label: \"Review all paths (recommended)\",\n description: \"Compare exact remote-only, device-only, and ordered lists.\",\n to: \"review\",\n },\n {\n id: \"adopt\",\n label: \"Use remote content list\",\n description: \"Save the reviewed list on this device without pulling files.\",\n action: \"adopt\",\n },\n {\n id: \"keep\",\n label: \"Keep this device's content list and update remote\u2026\",\n description: \"Open the existing exact force-push preview without skipping confirmation.\",\n action: \"keep\",\n },\n { id: \"cancel\", label: options.cancelLabel ?? \"Cancel\", action: \"cancel\" },\n ],\n hint: \"back\",\n }),\n review: ({ state }) => ({\n kind: \"review\",\n title: `Review synced content \u00B7 ${safeTerminalText(state.decision.setupName)}`,\n content: formatSelectionDifference(state.decision),\n format: { kind: \"text\" },\n viewportSize: \"adaptive\",\n hint: \"back\",\n }),\n saved: ({ state }) => ({\n kind: \"actions\",\n title: \"Remote content list saved\",\n lines: [\n `Sync setup: ${safeTerminalText(state.decision.setupName)}`,\n \"Only the included-content setting was saved.\",\n \"No files were pulled and sync state was not changed.\",\n ],\n items: [\n ...(runRoute\n ? [\n {\n id: \"continue\",\n label: continueLabel(origin),\n description: \"Start a fresh check and exact preview for this sync setup.\",\n action: \"continue\" as const,\n },\n ]\n : []),\n { id: \"done\", label: \"Done\", action: \"done\" },\n ],\n hint: \"close\",\n }),\n },\n actions: {\n adopt: async ({ state, signal: actionSignal }) => {\n const signal = combineSignals(sessionSignal, actionSignal);\n try {\n const currentConfig = await loadConfig(state.decision.setupName);\n if (signal.aborted) return { kind: \"close\" as const };\n assertLocalSelectionCurrent(currentConfig, state.decision);\n if (!currentConfig.include.includes(\"sessions\") && state.decision.remoteInclude.includes(\"sessions\")) {\n const acknowledged = await ctx.ui.confirm(\n \"Use a content list that includes session conversations?\",\n \"Session JSONL may contain prompts, tool output, file paths, images, and secrets. This saves the list only; it does not pull files.\",\n { signal },\n );\n if (signal.aborted) return { kind: \"close\" as const };\n if (!acknowledged) return { kind: \"stay\" as const };\n }\n const review = await runWithOptionalStateAccess(options, async () => {\n const loaded = await loadAdoptionReview(state.decision, signal, factory);\n if (signal.aborted) throw signal.reason;\n await revalidateAndAdopt(loaded, state.decision, signal);\n return loaded;\n });\n if (signal.aborted) return { kind: \"close\" as const };\n options.onSelectionResolved?.();\n continuationReview = {\n ...review.storageReview,\n setupName: state.decision.setupName,\n include: [...state.decision.remoteInclude],\n automatic: review.config.automatic,\n automaticTransfer: review.config.automaticTransfer,\n onSwitch: review.config.onSwitch,\n showStatus: review.config.showStatus,\n };\n flowState = { decision: state.decision, saved: true };\n return { kind: \"to\" as const, screen: \"saved\" as const };\n } catch (error) {\n if (signal.aborted) return { kind: \"close\" as const };\n if (isStaleReviewError(error)) {\n ctx.ui.notify(`${errorMessage(error)} Refreshing the comparison.`, \"warning\");\n refreshRequested = true;\n return { kind: \"close\" as const };\n }\n ctx.ui.notify(`Could not save the remote content list: ${errorMessage(error)}`, \"error\");\n return { kind: \"stay\" as const };\n }\n },\n keep: async ({ state, signal: actionSignal }) => {\n if (!runRoute) {\n ctx.ui.notify(\"The reviewed update-remote route is unavailable.\", \"error\");\n return { kind: \"stay\" as const };\n }\n const signal = combineSignals(sessionSignal, actionSignal);\n try {\n const latest = await loadConfig(state.decision.setupName);\n if (signal.aborted) return { kind: \"close\" as const };\n assertLocalSelectionCurrent(latest, state.decision);\n const result = await runCancellableOperation(\n ctx,\n \"Preparing this device's push preview\u2026\",\n \"push --force\",\n runRoute,\n {\n commitAware: true,\n cancelledMessage: \"Push preparation cancelled; no remote files were changed.\",\n target: state.decision.setupName,\n signal,\n },\n );\n return handleNestedRouteResult(result, \"push\");\n } catch (error) {\n if (signal.aborted) return { kind: \"close\" as const };\n if (isStaleReviewError(error)) {\n ctx.ui.notify(`${errorMessage(error)} Refreshing the comparison.`, \"warning\");\n refreshRequested = true;\n return { kind: \"close\" as const };\n }\n ctx.ui.notify(`Could not prepare the remote update: ${errorMessage(error)}`, \"error\");\n return { kind: \"stay\" as const };\n }\n },\n continue: async ({ state, signal: actionSignal }) => {\n if (!runRoute || !continuationReview) return { kind: \"stay\" as const };\n const signal = combineSignals(sessionSignal, actionSignal);\n try {\n const latest = await loadPartialConfig(state.decision.setupName);\n if (signal.aborted) return { kind: \"close\" as const };\n if (!sameContinuationReview(latest, continuationReview)) {\n throw new StaleRemoteSelectionReviewError(\n `Sync setup \u201C${safeTerminalText(state.decision.setupName)}\u201D changed after the remote content list was saved.`,\n );\n }\n const result = await runCancellableOperation(ctx, continueBusyLabel(origin), route, runRoute, {\n commitAware: true,\n cancelledMessage: continuationCancelledMessage(route),\n target: state.decision.setupName,\n signal,\n });\n return handleNestedRouteResult(result, route);\n } catch (error) {\n if (signal.aborted) return { kind: \"close\" as const };\n ctx.ui.notify(`Could not continue: ${errorMessage(error)}`, \"error\");\n return { kind: \"stay\" as const };\n }\n },\n cancel: async () => ({ kind: \"back\" }),\n done: async () => {\n nextResult = { kind: \"done\" };\n return { kind: \"close\" };\n },\n },\n });\n\n function handleNestedRouteResult(\n result: Awaited<ReturnType<typeof runCancellableOperation>>,\n nestedRoute: \"sync\" | \"pull\" | \"push\",\n ) {\n if (result.kind === \"completed\" && result.outcome === \"applied\") {\n options.onSelectionResolved?.();\n }\n if (result.kind === \"closed\") {\n nextResult = { kind: \"closed\" };\n return { kind: \"close\" as const };\n }\n if (\n result.kind === \"cancelled\" ||\n (result.kind === \"completed\" && result.outcome === \"cancelled\") ||\n result.kind === \"failed\"\n ) {\n return { kind: \"stay\" as const };\n }\n nextResult = { kind: \"route-result\", result, route: nestedRoute };\n return { kind: \"close\" as const };\n }\n\n const menuResult = await runMenu(ctx, menu, {\n getState: () => flowState,\n signal: sessionSignal,\n isCurrent: () => !sessionSignal?.aborted,\n onError: (_menuCtx, error) => ctx.ui.notify(errorMessage(error), \"error\"),\n });\n if (sessionSignal?.aborted || menuResult.kind === \"stale\") return { kind: \"stale\" };\n if (refreshRequested) return { kind: \"refresh\" };\n if (nextResult) return nextResult;\n if (menuResult.kind === \"closed\") {\n return menuResult.reason === \"back\" ? { kind: \"back\" } : { kind: \"closed\" };\n }\n return { kind: \"closed\" };\n}\n\ninterface AdoptionReview {\n config: AnySyncConfig;\n storageReview: SyncSetupStorageReview;\n backend: SyncBackend;\n reviewedHead: RemoteHead;\n}\n\nasync function loadAdoptionReview(\n decision: RemoteSelectionDecision,\n signal: AbortSignal,\n factory: SyncBackendFactory,\n): Promise<AdoptionReview> {\n const config = await loadConfig(decision.setupName);\n throwIfAborted(signal);\n assertLocalSelectionCurrent(config, decision);\n const partial = await loadPartialConfig(decision.setupName);\n throwIfAborted(signal);\n if (!sameSyncInclude(partial.include, decision.localInclude)) {\n throw new StaleRemoteSelectionReviewError(\n `Sync setup \u201C${safeTerminalText(decision.setupName)}\u201D changed while the comparison was open.`,\n );\n }\n const backend = await factory(config);\n throwIfAborted(signal);\n const reviewedHead = await backend.readHead(signal);\n throwIfAborted(signal);\n if (!reviewedHead) {\n throw new StaleRemoteSelectionReviewError(\"Remote storage changed while the comparison was open.\");\n }\n const snapshot = await readSnapshotForHead(backend, reviewedHead, signal);\n throwIfAborted(signal);\n const state = inspectRemoteSelection(config.include, snapshot);\n if (state.kind !== \"different\" || !sameSyncInclude(state.include, decision.remoteInclude)) {\n throw new StaleRemoteSelectionReviewError(\"Remote synced content changed while the comparison was open.\");\n }\n return { config, storageReview: partial, backend, reviewedHead };\n}\n\nasync function revalidateAndAdopt(review: AdoptionReview, decision: RemoteSelectionDecision, signal: AbortSignal) {\n const currentHead = await review.backend.readHead(signal);\n throwIfAborted(signal);\n if (!currentHead || !review.backend.sameRevision(review.reviewedHead.revision, currentHead.revision)) {\n throw new StaleRemoteSelectionReviewError(\"Remote storage changed while the comparison was open.\");\n }\n const currentSnapshot = await readSnapshotForHead(review.backend, currentHead, signal);\n throwIfAborted(signal);\n const currentState = inspectRemoteSelection(review.config.include, currentSnapshot);\n if (currentState.kind !== \"different\" || !sameSyncInclude(currentState.include, decision.remoteInclude)) {\n throw new StaleRemoteSelectionReviewError(\"Remote synced content changed while the comparison was open.\");\n }\n await updateSyncSetup(\n decision.setupName,\n (setup) => ({\n ...setup,\n sync: { ...setup.sync, include: [...decision.remoteInclude] },\n }),\n {\n expectedStorage: review.storageReview,\n expectedInclude: decision.localInclude,\n signal,\n },\n );\n}\n\nasync function inspectConfiguredRemoteSelection(\n ctx: ExtensionContext,\n setupName: string | undefined,\n signal: AbortSignal | undefined,\n factory: SyncBackendFactory,\n): Promise<\n | { kind: \"empty\"; config: AnySyncConfig }\n | { kind: \"selection\"; config: AnySyncConfig; state: RemoteSelectionState }\n | undefined\n> {\n const config = await loadConfig(setupName);\n if (signal?.aborted) return undefined;\n setSyncStatus(ctx, `checking synced content for ${safeTerminalText(config.setupName)}`);\n const backend = await factory(config);\n if (signal?.aborted) return undefined;\n const head = await backend.readHead(signal);\n if (signal?.aborted) return undefined;\n if (!head) return { kind: \"empty\", config };\n const snapshot = await readSnapshotForHead(backend, head, signal);\n if (signal?.aborted) return undefined;\n return {\n kind: \"selection\",\n config,\n state: inspectRemoteSelection(config.include, snapshot),\n };\n}\n\nasync function showLegacyDiscovery(\n ctx: ExtensionContext,\n config: AnySyncConfig,\n discovered: string[],\n signal?: AbortSignal,\n) {\n const menu = defineMenu<undefined, \"choice\" | \"review\", \"back\", ExtensionContext>({\n start: \"choice\",\n screens: {\n choice: () => ({\n kind: \"actions\",\n title: `Compare synced content \u00B7 ${safeTerminalText(config.setupName)}`,\n lines: [\n \"This legacy snapshot has no portable synced-content list.\",\n \"Discovered paths are partial and read-only; preserved files may not have been selected.\",\n ],\n items: [\n { id: \"review\", label: \"Review discovered paths\", to: \"review\" },\n { id: \"back\", label: \"Back\", action: \"back\" },\n ],\n hint: \"close\",\n }),\n review: () => ({\n kind: \"review\",\n title: \"Partial discovery from legacy snapshot\",\n content: [\n \"Partial discovery only \u2014 not an authoritative selection.\",\n \"\",\n ...(discovered.length > 0\n ? discovered.map((item) => `Discovered: ${safeTerminalText(item)}`)\n : [\"No safe paths were discovered.\"]),\n \"\",\n \"Use Add custom path\u2026 in the local Included Content editor if needed.\",\n ].join(\"\\n\"),\n format: { kind: \"text\" },\n viewportSize: \"adaptive\",\n hint: \"back\",\n }),\n },\n actions: { back: async () => ({ kind: \"close\" }) },\n });\n await runMenu(ctx, menu, {\n getState: () => undefined,\n signal,\n isCurrent: () => !signal?.aborted,\n });\n}\n\nfunction selectionSummaryLines(decision: RemoteSelectionDecision) {\n const comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n return [\n `Sync setup: ${safeTerminalText(decision.setupName)}`,\n \"Nothing changed. Review both lists before choosing what happens next.\",\n ...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n ? [\"Only the ordering differs; membership is the same.\"]\n : [`Remote-only paths: ${comparison.remoteOnly.length} \u00B7 Device-only paths: ${comparison.localOnly.length}`]),\n ];\n}\n\nfunction formatSelectionDifference(decision: RemoteSelectionDecision) {\n const comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n return [\n ...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n ? [\"Only ordering differs; both lists contain the same paths.\", \"\"]\n : []),\n \"Remote-only paths:\",\n ...(comparison.remoteOnly.length > 0\n ? comparison.remoteOnly.map((item) => `+ ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"Device-only paths:\",\n ...(comparison.localOnly.length > 0\n ? comparison.localOnly.map((item) => `- ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"Remote ordered list:\",\n ...(decision.remoteInclude.length > 0\n ? decision.remoteInclude.map((item, index) => `${index + 1}. ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"This device's ordered list:\",\n ...(decision.localInclude.length > 0\n ? decision.localInclude.map((item, index) => `${index + 1}. ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"Using the remote list saves settings only and does not pull files.\",\n ].join(\"\\n\");\n}\n\nfunction formatRemoteSelectionSummary(decision: RemoteSelectionDecision) {\n const comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n return [\n `Synced content for \u201C${safeTerminalText(decision.setupName)}\u201D differs from this device.`,\n `Remote-only: ${safeList(comparison.remoteOnly)}`,\n `Device-only: ${safeList(comparison.localOnly)}`,\n ...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n ? [\n \"Only ordering differs.\",\n `Remote order: ${safeList(decision.remoteInclude)}`,\n `Device order: ${safeList(decision.localInclude)}`,\n ]\n : []),\n \"Run /sync in TUI to choose a content list; RPC review is read-only.\",\n ].join(\"\\n\");\n}\n\nfunction formatLegacySummary(config: AnySyncConfig, discovered: readonly string[]) {\n return `Remote snapshot for \u201C${safeTerminalText(config.setupName)}\u201D has no portable synced-content list; ${discovered.length} safe path${discovered.length === 1 ? \" was\" : \"s were\"} discovered, but the result is partial and read-only.`;\n}\n\nfunction decisionFromState(\n config: AnySyncConfig,\n state: Extract<RemoteSelectionState, { kind: \"different\" }>,\n): RemoteSelectionDecision {\n return {\n setupName: config.setupName,\n configIdentity: syncConfigReviewFingerprint(config),\n localInclude: [...config.include],\n remoteInclude: [...state.include],\n };\n}\n\nfunction assertLocalSelectionCurrent(config: AnySyncConfig, decision: RemoteSelectionDecision) {\n if (\n syncConfigReviewFingerprint(config) === decision.configIdentity &&\n sameSyncInclude(config.include, decision.localInclude)\n ) {\n return;\n }\n throw new StaleRemoteSelectionReviewError(\n `Sync setup \u201C${safeTerminalText(config.setupName)}\u201D changed while the comparison was open.`,\n );\n}\n\nfunction sameContinuationReview(left: PartialConfig, right: PartialConfig) {\n return (\n left.setupName === right.setupName &&\n left.connectionName === right.connectionName &&\n left.storageKind === right.storageKind &&\n left.storagePath === right.storagePath &&\n left.bucket === right.bucket &&\n left.branch === right.branch &&\n sameSyncInclude(left.include, right.include)\n );\n}\n\nfunction continueLabel(origin: RemoteSelectionOrigin) {\n if (origin === \"pull\") return \"Continue Pull now\u2026\";\n if (origin === \"push\") return \"Continue Push now\u2026\";\n return \"Continue Sync now\u2026\";\n}\n\nfunction continueBusyLabel(origin: RemoteSelectionOrigin) {\n if (origin === \"pull\") return \"Checking remote changes\u2026\";\n if (origin === \"push\") return \"Preparing push preview\u2026\";\n return \"Checking current sync setup\u2026\";\n}\n\nfunction continuationCancelledMessage(route: \"sync\" | \"pull\" | \"push\") {\n if (route === \"pull\") return \"Pull check cancelled; no local files were changed.\";\n if (route === \"push\") return \"Push preparation cancelled; no remote files were changed.\";\n return \"Sync check cancelled; no settings or files were changed.\";\n}\n\nfunction safeList(values: readonly string[]) {\n return values.length > 0 ? values.map(safeTerminalText).join(\", \") : \"none\";\n}\n\nclass StaleRemoteSelectionReviewError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"StaleRemoteSelectionReviewError\";\n }\n}\n\nfunction isStaleReviewError(error: unknown) {\n return error instanceof StaleRemoteSelectionReviewError || error instanceof SyncSetupReviewChangedError;\n}\n\nfunction runWithOptionalStateAccess<T>(\n options: Pick<RemoteSelectionReviewOptions, \"withStateAccess\">,\n task: () => Promise<T>,\n) {\n return options.withStateAccess ? options.withStateAccess(task) : task();\n}\n\nfunction combineSignals(sessionSignal: AbortSignal | undefined, actionSignal: AbortSignal) {\n return sessionSignal ? AbortSignal.any([sessionSignal, actionSignal]) : actionSignal;\n}\n\nfunction throwIfAborted(signal: AbortSignal) {\n if (!signal.aborted) return;\n throw signal.reason instanceof Error ? signal.reason : new DOMException(\"The operation was aborted\", \"AbortError\");\n}\n", "import { BorderedLoader, type ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { isKeyRelease, Key, matchesKey, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { formatInteractionHints, runCustomInteraction } from \"@narumitw/pi-tui-kit\";\nimport type { SetupPullOutcome } from \"../sync/setup-switch.js\";\nimport type { SyncDecision } from \"../sync/sync-decision.js\";\nimport type { RemoteSelectionDecision } from \"../sync/sync-policy.js\";\n\nexport type RunRouteResult =\n | { kind: \"completed\"; outcome?: SetupPullOutcome }\n | { kind: \"decision-required\"; decision: SyncDecision }\n | { kind: \"remote-selection-required\"; decision: RemoteSelectionDecision }\n | { kind: \"failed\" };\n\nexport type RunRoute = (\n route: string,\n signal?: AbortSignal,\n onCommit?: () => void,\n target?: string,\n onDialog?: (active: boolean) => void,\n) => Promise<RunRouteResult | undefined>;\n\nexport type CancellableOperationResult = RunRouteResult | { kind: \"closed\" } | { kind: \"cancelled\" };\n\ninterface CancellableOperationOptions {\n commitAware?: boolean;\n cancelAcrossDialogs?: boolean;\n cancelledMessage?: string | null;\n target?: string;\n signal?: AbortSignal;\n}\n\nexport async function runCancellableOperation(\n ctx: ExtensionContext,\n message: string,\n route: string,\n runRoute: RunRoute,\n options: CancellableOperationOptions = {},\n): Promise<CancellableOperationResult> {\n const {\n commitAware = false,\n cancelAcrossDialogs = false,\n cancelledMessage = \"Check cancelled; no settings or files were changed.\",\n target,\n signal,\n } = options;\n if (ctx.mode !== \"tui\") {\n return (await runRoute(route, signal, undefined, target)) ?? { kind: \"failed\" };\n }\n let commitStarted = false;\n let routeResult: RunRouteResult | undefined;\n const interaction = await runCustomInteraction<{ cancelled?: boolean; error?: unknown }, ExtensionContext>(ctx, {\n signal,\n isCurrent: () => !signal?.aborted,\n create: ({ tui, theme, keybindings, signal: interactionSignal, complete }) => {\n const loader = new BorderedLoader(tui, theme, message, { cancellable: false });\n const cancelHint = formatInteractionHints(keybindings, [\n {\n keys: [...keybindings.getKeys(\"tui.select.cancel\").filter((key) => !hasControlCharacter(key)), \"ctrl+c\"],\n label: \"cancel\",\n },\n ]);\n const cancel = (data: string) => {\n // Raw terminal listeners run before Pi filters Kitty key releases.\n if (isKeyRelease(data)) return false;\n if (!matchesKey(data, Key.ctrl(\"c\")) && !keybindings.matches(data, \"tui.select.cancel\")) return false;\n if (commitStarted) {\n ctx.ui.notify(\"Applying or publishing has started and cannot be cancelled safely.\", \"warning\");\n } else complete({ cancelled: true });\n return true;\n };\n // Pi dialogs replace this loader and restore the normal editor. Defer\n // ordinary keys while they are open; retain raw cancellation afterward.\n // Ctrl+C remains the root flow's hard-cancel path regardless of focus.\n let activeDialogs = 0;\n const unsubscribe = cancelAcrossDialogs\n ? ctx.ui.onTerminalInput((data) => {\n if (isKeyRelease(data)) return;\n if (activeDialogs > 0 && !matchesKey(data, Key.ctrl(\"c\"))) return;\n return cancel(data) ? { consume: true } : undefined;\n })\n : undefined;\n let pendingRoute: ReturnType<RunRoute>;\n try {\n pendingRoute = runRoute(\n route,\n interactionSignal,\n commitAware ? () => (commitStarted = true) : undefined,\n target,\n cancelAcrossDialogs\n ? (active) => {\n activeDialogs += active ? 1 : -1;\n }\n : undefined,\n );\n } catch (error) {\n unsubscribe?.();\n loader.dispose();\n throw error;\n }\n const operation = pendingRoute.then(\n (result) => {\n routeResult = result;\n complete({});\n },\n (error: unknown) => complete({ error }),\n );\n return {\n render(width: number) {\n const safeWidth = Math.max(1, width);\n const lines = loader.render(safeWidth);\n const bottomBorder = lines.at(-1);\n return [\n ...lines.slice(0, -1),\n truncateToWidth(theme.fg(\"dim\", cancelHint), safeWidth, \"\"),\n ...(bottomBorder === undefined ? [] : [bottomBorder]),\n ];\n },\n invalidate: () => loader.invalidate(),\n handleInput: cancel,\n dispose() {\n unsubscribe?.();\n loader.dispose();\n },\n waitForPending: () => operation,\n };\n },\n });\n if (interaction.kind === \"error\") throw interaction.error;\n if (interaction.kind !== \"completed\") return { kind: \"closed\" };\n if (interaction.value.cancelled) {\n if (cancelledMessage) ctx.ui.notify(cancelledMessage, \"info\");\n return { kind: \"cancelled\" };\n }\n if (interaction.value.error) throw interaction.value.error;\n return routeResult ?? { kind: \"failed\" };\n}\n\nfunction hasControlCharacter(value: string) {\n // biome-ignore lint/suspicious/noControlCharactersInRegex: Unsafe key labels must be omitted.\n return /[\\u0000-\\u001f\\u007f-\\u009f]/u.test(value);\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,SAAS,YAAY,eAAe;;;ACDpC,SAAS,sBAA6C;AACtD,SAAS,cAAc,KAAK,YAAY,uBAAuB;AAC/D,SAAS,wBAAwB,4BAA4B;AA6B7D,eAAsB,wBACpB,KACA,SACA,OACA,UACA,UAAuC,CAAC,GACH;AACrC,QAAM;AAAA,IACJ,cAAc;AAAA,IACd,sBAAsB;AAAA,IACtB,mBAAmB;AAAA,IACnB;AAAA,IACA;AAAA,EACF,IAAI;AACJ,MAAI,IAAI,SAAS,OAAO;AACtB,WAAQ,MAAM,SAAS,OAAO,QAAQ,QAAW,MAAM,KAAM,EAAE,MAAM,SAAS;AAAA,EAChF;AACA,MAAI,gBAAgB;AACpB,MAAI;AACJ,QAAM,cAAc,MAAM,qBAAiF,KAAK;AAAA,IAC9G;AAAA,IACA,WAAW,MAAM,CAAC,QAAQ;AAAA,IAC1B,QAAQ,CAAC,EAAE,KAAK,OAAO,aAAa,QAAQ,mBAAmB,SAAS,MAAM;AAC5E,YAAM,SAAS,IAAI,eAAe,KAAK,OAAO,SAAS,EAAE,aAAa,MAAM,CAAC;AAC7E,YAAM,aAAa,uBAAuB,aAAa;AAAA,QACrD;AAAA,UACE,MAAM,CAAC,GAAG,YAAY,QAAQ,mBAAmB,EAAE,OAAO,CAAC,QAAQ,CAAC,oBAAoB,GAAG,CAAC,GAAG,QAAQ;AAAA,UACvG,OAAO;AAAA,QACT;AAAA,MACF,CAAC;AACD,YAAM,SAAS,CAAC,SAAiB;AAE/B,YAAI,aAAa,IAAI,EAAG,QAAO;AAC/B,YAAI,CAAC,WAAW,MAAM,IAAI,KAAK,GAAG,CAAC,KAAK,CAAC,YAAY,QAAQ,MAAM,mBAAmB,EAAG,QAAO;AAChG,YAAI,eAAe;AACjB,cAAI,GAAG,OAAO,sEAAsE,SAAS;AAAA,QAC/F,MAAO,UAAS,EAAE,WAAW,KAAK,CAAC;AACnC,eAAO;AAAA,MACT;AAIA,UAAI,gBAAgB;AACpB,YAAM,cAAc,sBAChB,IAAI,GAAG,gBAAgB,CAAC,SAAS;AAC/B,YAAI,aAAa,IAAI,EAAG;AACxB,YAAI,gBAAgB,KAAK,CAAC,WAAW,MAAM,IAAI,KAAK,GAAG,CAAC,EAAG;AAC3D,eAAO,OAAO,IAAI,IAAI,EAAE,SAAS,KAAK,IAAI;AAAA,MAC5C,CAAC,IACD;AACJ,UAAI;AACJ,UAAI;AACF,uBAAe;AAAA,UACb;AAAA,UACA;AAAA,UACA,cAAc,MAAO,gBAAgB,OAAQ;AAAA,UAC7C;AAAA,UACA,sBACI,CAAC,WAAW;AACV,6BAAiB,SAAS,IAAI;AAAA,UAChC,IACA;AAAA,QACN;AAAA,MACF,SAAS,OAAO;AACd,sBAAc;AACd,eAAO,QAAQ;AACf,cAAM;AAAA,MACR;AACA,YAAM,YAAY,aAAa;AAAA,QAC7B,CAAC,WAAW;AACV,wBAAc;AACd,mBAAS,CAAC,CAAC;AAAA,QACb;AAAA,QACA,CAAC,UAAmB,SAAS,EAAE,MAAM,CAAC;AAAA,MACxC;AACA,aAAO;AAAA,QACL,OAAO,OAAe;AACpB,gBAAM,YAAY,KAAK,IAAI,GAAG,KAAK;AACnC,gBAAM,QAAQ,OAAO,OAAO,SAAS;AACrC,gBAAM,eAAe,MAAM,GAAG,EAAE;AAChC,iBAAO;AAAA,YACL,GAAG,MAAM,MAAM,GAAG,EAAE;AAAA,YACpB,gBAAgB,MAAM,GAAG,OAAO,UAAU,GAAG,WAAW,EAAE;AAAA,YAC1D,GAAI,iBAAiB,SAAY,CAAC,IAAI,CAAC,YAAY;AAAA,UACrD;AAAA,QACF;AAAA,QACA,YAAY,MAAM,OAAO,WAAW;AAAA,QACpC,aAAa;AAAA,QACb,UAAU;AACR,wBAAc;AACd,iBAAO,QAAQ;AAAA,QACjB;AAAA,QACA,gBAAgB,MAAM;AAAA,MACxB;AAAA,IACF;AAAA,EACF,CAAC;AACD,MAAI,YAAY,SAAS,QAAS,OAAM,YAAY;AACpD,MAAI,YAAY,SAAS,YAAa,QAAO,EAAE,MAAM,SAAS;AAC9D,MAAI,YAAY,MAAM,WAAW;AAC/B,QAAI,iBAAkB,KAAI,GAAG,OAAO,kBAAkB,MAAM;AAC5D,WAAO,EAAE,MAAM,YAAY;AAAA,EAC7B;AACA,MAAI,YAAY,MAAM,MAAO,OAAM,YAAY,MAAM;AACrD,SAAO,eAAe,EAAE,MAAM,SAAS;AACzC;AAEA,SAAS,oBAAoB,OAAe;AAE1C,SAAO,gCAAgC,KAAK,KAAK;AACnD;;;ADhGA,eAAsB,0BACpB,KACA,WACA,QACA,UAA8B,mBAC9B,UAAwC,CAAC,GACH;AACtC,MAAI;AACF,QAAI,WAAW,QAAQ;AACvB,QAAI,CAAC,UAAU;AACb,YAAM,YAAY,MAAM,iCAAiC,KAAK,WAAW,QAAQ,OAAO;AACxF,UAAI,CAAC,aAAa,QAAQ,QAAS,QAAO,EAAE,MAAM,QAAQ;AAG1D,UAAI,UAAU,SAAS,WAAW,UAAU,MAAM,SAAS,aAAa;AACtE,gBAAQ,sBAAsB;AAAA,MAChC;AACA,UAAI,UAAU,SAAS,SAAS;AAC9B,YAAI,GAAG,OAAO,8DAA8D,MAAM;AAClF,eAAO,EAAE,MAAM,OAAO;AAAA,MACxB;AACA,UAAI,UAAU,MAAM,SAAS,QAAQ;AACnC,YAAI,GAAG,OAAO,0DAA0D,MAAM;AAC9E,eAAO,EAAE,MAAM,OAAO;AAAA,MACxB;AACA,UAAI,UAAU,MAAM,SAAS,UAAU;AACrC,YAAI,IAAI,SAAS,OAAO;AACtB,cAAI,GAAG,OAAO,oBAAoB,UAAU,QAAQ,UAAU,MAAM,UAAU,GAAG,MAAM;AACvF,iBAAO,EAAE,MAAM,OAAO;AAAA,QACxB;AACA,cAAM,oBAAoB,KAAK,UAAU,QAAQ,UAAU,MAAM,YAAY,MAAM;AACnF,eAAO,QAAQ,UAAU,EAAE,MAAM,QAAQ,IAAI,EAAE,MAAM,OAAO;AAAA,MAC9D;AACA,iBAAW,kBAAkB,UAAU,QAAQ,UAAU,KAAK;AAAA,IAChE;AAEA,QAAI,IAAI,SAAS,OAAO;AACtB,UAAI,GAAG,OAAO,6BAA6B,QAAQ,GAAG,SAAS;AAC/D,aAAO,EAAE,MAAM,OAAO;AAAA,IACxB;AAEA,QAAI,kBAAkB;AACtB,eAAS;AACP,UAAI,QAAQ,QAAS,QAAO,EAAE,MAAM,QAAQ;AAC5C,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,QACA;AAAA,QACA,QAAQ,UAAU;AAAA,QAClB,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,UAAI,OAAO,SAAS,UAAW,QAAO;AACtC,YAAM,YAAY,MAAM;AAAA,QAA2B;AAAA,QAAS,MAC1D,iCAAiC,KAAK,gBAAgB,WAAW,QAAQ,OAAO;AAAA,MAClF;AACA,UAAI,CAAC,aAAa,QAAQ,QAAS,QAAO,EAAE,MAAM,QAAQ;AAC1D,UAAI,UAAU,SAAS,SAAS;AAC9B,gBAAQ,sBAAsB;AAC9B,YAAI,GAAG,OAAO,mEAAmE,SAAS;AAC1F,eAAO,EAAE,MAAM,OAAO;AAAA,MACxB;AACA,UAAI,UAAU,MAAM,SAAS,aAAa;AACxC,YAAI,GAAG;AAAA,UACL,UAAU,MAAM,SAAS,SACrB,uDACA;AAAA,UACJ;AAAA,QACF;AACA,gBAAQ,sBAAsB;AAC9B,eAAO,EAAE,MAAM,OAAO;AAAA,MACxB;AACA,wBAAkB,kBAAkB,UAAU,QAAQ,UAAU,KAAK;AAAA,IACvE;AAAA,EACF,SAAS,OAAO;AACd,QAAI,QAAQ,QAAS,QAAO,EAAE,MAAM,QAAQ;AAC5C,QAAI,GAAG,OAAO,oCAAoC,aAAa,KAAK,CAAC,IAAI,OAAO;AAChF,WAAO,EAAE,MAAM,OAAO;AAAA,EACxB,UAAE;AACA,kBAAc,KAAK,MAAS;AAAA,EAC9B;AACF;AAIA,eAAe,wBACb,KACA,iBACA,QACA,UACA,eACA,SACA,SAC+B;AAO/B,MAAI,YAAuB,EAAE,UAAU,iBAAiB,OAAO,MAAM;AACrE,MAAI;AACJ,MAAI;AACJ,MAAI,mBAAmB;AACvB,QAAM,QAAQ,WAAW,aAAa,SAAS;AAC/C,QAAM,OAAO,WAAwD;AAAA,IACnE,OAAO;AAAA,IACP,SAAS;AAAA,MACP,QAAQ,CAAC,EAAE,MAAM,OAAO;AAAA,QACtB,MAAM;AAAA,QACN,OAAO;AAAA,QACP,OAAO,sBAAsB,MAAM,QAAQ;AAAA,QAC3C,OAAO;AAAA,UACL;AAAA,YACE,IAAI;AAAA,YACJ,OAAO;AAAA,YACP,aAAa;AAAA,YACb,IAAI;AAAA,UACN;AAAA,UACA;AAAA,YACE,IAAI;AAAA,YACJ,OAAO;AAAA,YACP,aAAa;AAAA,YACb,QAAQ;AAAA,UACV;AAAA,UACA;AAAA,YACE,IAAI;AAAA,YACJ,OAAO;AAAA,YACP,aAAa;AAAA,YACb,QAAQ;AAAA,UACV;AAAA,UACA,EAAE,IAAI,UAAU,OAAO,QAAQ,eAAe,UAAU,QAAQ,SAAS;AAAA,QAC3E;AAAA,QACA,MAAM;AAAA,MACR;AAAA,MACA,QAAQ,CAAC,EAAE,MAAM,OAAO;AAAA,QACtB,MAAM;AAAA,QACN,OAAO,8BAA2B,iBAAiB,MAAM,SAAS,SAAS,CAAC;AAAA,QAC5E,SAAS,0BAA0B,MAAM,QAAQ;AAAA,QACjD,QAAQ,EAAE,MAAM,OAAO;AAAA,QACvB,cAAc;AAAA,QACd,MAAM;AAAA,MACR;AAAA,MACA,OAAO,CAAC,EAAE,MAAM,OAAO;AAAA,QACrB,MAAM;AAAA,QACN,OAAO;AAAA,QACP,OAAO;AAAA,UACL,eAAe,iBAAiB,MAAM,SAAS,SAAS,CAAC;AAAA,UACzD;AAAA,UACA;AAAA,QACF;AAAA,QACA,OAAO;AAAA,UACL,GAAI,WACA;AAAA,YACE;AAAA,cACE,IAAI;AAAA,cACJ,OAAO,cAAc,MAAM;AAAA,cAC3B,aAAa;AAAA,cACb,QAAQ;AAAA,YACV;AAAA,UACF,IACA,CAAC;AAAA,UACL,EAAE,IAAI,QAAQ,OAAO,QAAQ,QAAQ,OAAO;AAAA,QAC9C;AAAA,QACA,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,OAAO,OAAO,EAAE,OAAO,QAAQ,aAAa,MAAM;AAChD,cAAM,SAAS,eAAe,eAAe,YAAY;AACzD,YAAI;AACF,gBAAM,gBAAgB,MAAM,WAAW,MAAM,SAAS,SAAS;AAC/D,cAAI,OAAO,QAAS,QAAO,EAAE,MAAM,QAAiB;AACpD,sCAA4B,eAAe,MAAM,QAAQ;AACzD,cAAI,CAAC,cAAc,QAAQ,SAAS,UAAU,KAAK,MAAM,SAAS,cAAc,SAAS,UAAU,GAAG;AACpG,kBAAM,eAAe,MAAM,IAAI,GAAG;AAAA,cAChC;AAAA,cACA;AAAA,cACA,EAAE,OAAO;AAAA,YACX;AACA,gBAAI,OAAO,QAAS,QAAO,EAAE,MAAM,QAAiB;AACpD,gBAAI,CAAC,aAAc,QAAO,EAAE,MAAM,OAAgB;AAAA,UACpD;AACA,gBAAM,SAAS,MAAM,2BAA2B,SAAS,YAAY;AACnE,kBAAM,SAAS,MAAM,mBAAmB,MAAM,UAAU,QAAQ,OAAO;AACvE,gBAAI,OAAO,QAAS,OAAM,OAAO;AACjC,kBAAM,mBAAmB,QAAQ,MAAM,UAAU,MAAM;AACvD,mBAAO;AAAA,UACT,CAAC;AACD,cAAI,OAAO,QAAS,QAAO,EAAE,MAAM,QAAiB;AACpD,kBAAQ,sBAAsB;AAC9B,+BAAqB;AAAA,YACnB,GAAG,OAAO;AAAA,YACV,WAAW,MAAM,SAAS;AAAA,YAC1B,SAAS,CAAC,GAAG,MAAM,SAAS,aAAa;AAAA,YACzC,WAAW,OAAO,OAAO;AAAA,YACzB,mBAAmB,OAAO,OAAO;AAAA,YACjC,UAAU,OAAO,OAAO;AAAA,YACxB,YAAY,OAAO,OAAO;AAAA,UAC5B;AACA,sBAAY,EAAE,UAAU,MAAM,UAAU,OAAO,KAAK;AACpD,iBAAO,EAAE,MAAM,MAAe,QAAQ,QAAiB;AAAA,QACzD,SAAS,OAAO;AACd,cAAI,OAAO,QAAS,QAAO,EAAE,MAAM,QAAiB;AACpD,cAAI,mBAAmB,KAAK,GAAG;AAC7B,gBAAI,GAAG,OAAO,GAAG,aAAa,KAAK,CAAC,+BAA+B,SAAS;AAC5E,+BAAmB;AACnB,mBAAO,EAAE,MAAM,QAAiB;AAAA,UAClC;AACA,cAAI,GAAG,OAAO,2CAA2C,aAAa,KAAK,CAAC,IAAI,OAAO;AACvF,iBAAO,EAAE,MAAM,OAAgB;AAAA,QACjC;AAAA,MACF;AAAA,MACA,MAAM,OAAO,EAAE,OAAO,QAAQ,aAAa,MAAM;AAC/C,YAAI,CAAC,UAAU;AACb,cAAI,GAAG,OAAO,oDAAoD,OAAO;AACzE,iBAAO,EAAE,MAAM,OAAgB;AAAA,QACjC;AACA,cAAM,SAAS,eAAe,eAAe,YAAY;AACzD,YAAI;AACF,gBAAM,SAAS,MAAM,WAAW,MAAM,SAAS,SAAS;AACxD,cAAI,OAAO,QAAS,QAAO,EAAE,MAAM,QAAiB;AACpD,sCAA4B,QAAQ,MAAM,QAAQ;AAClD,gBAAM,SAAS,MAAM;AAAA,YACnB;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,cACE,aAAa;AAAA,cACb,kBAAkB;AAAA,cAClB,QAAQ,MAAM,SAAS;AAAA,cACvB;AAAA,YACF;AAAA,UACF;AACA,iBAAO,wBAAwB,QAAQ,MAAM;AAAA,QAC/C,SAAS,OAAO;AACd,cAAI,OAAO,QAAS,QAAO,EAAE,MAAM,QAAiB;AACpD,cAAI,mBAAmB,KAAK,GAAG;AAC7B,gBAAI,GAAG,OAAO,GAAG,aAAa,KAAK,CAAC,+BAA+B,SAAS;AAC5E,+BAAmB;AACnB,mBAAO,EAAE,MAAM,QAAiB;AAAA,UAClC;AACA,cAAI,GAAG,OAAO,wCAAwC,aAAa,KAAK,CAAC,IAAI,OAAO;AACpF,iBAAO,EAAE,MAAM,OAAgB;AAAA,QACjC;AAAA,MACF;AAAA,MACA,UAAU,OAAO,EAAE,OAAO,QAAQ,aAAa,MAAM;AACnD,YAAI,CAAC,YAAY,CAAC,mBAAoB,QAAO,EAAE,MAAM,OAAgB;AACrE,cAAM,SAAS,eAAe,eAAe,YAAY;AACzD,YAAI;AACF,gBAAM,SAAS,MAAM,kBAAkB,MAAM,SAAS,SAAS;AAC/D,cAAI,OAAO,QAAS,QAAO,EAAE,MAAM,QAAiB;AACpD,cAAI,CAAC,uBAAuB,QAAQ,kBAAkB,GAAG;AACvD,kBAAM,IAAI;AAAA,cACR,oBAAe,iBAAiB,MAAM,SAAS,SAAS,CAAC;AAAA,YAC3D;AAAA,UACF;AACA,gBAAM,SAAS,MAAM,wBAAwB,KAAK,kBAAkB,MAAM,GAAG,OAAO,UAAU;AAAA,YAC5F,aAAa;AAAA,YACb,kBAAkB,6BAA6B,KAAK;AAAA,YACpD,QAAQ,MAAM,SAAS;AAAA,YACvB;AAAA,UACF,CAAC;AACD,iBAAO,wBAAwB,QAAQ,KAAK;AAAA,QAC9C,SAAS,OAAO;AACd,cAAI,OAAO,QAAS,QAAO,EAAE,MAAM,QAAiB;AACpD,cAAI,GAAG,OAAO,uBAAuB,aAAa,KAAK,CAAC,IAAI,OAAO;AACnE,iBAAO,EAAE,MAAM,OAAgB;AAAA,QACjC;AAAA,MACF;AAAA,MACA,QAAQ,aAAa,EAAE,MAAM,OAAO;AAAA,MACpC,MAAM,YAAY;AAChB,qBAAa,EAAE,MAAM,OAAO;AAC5B,eAAO,EAAE,MAAM,QAAQ;AAAA,MACzB;AAAA,IACF;AAAA,EACF,CAAC;AAED,WAAS,wBACP,QACA,aACA;AACA,QAAI,OAAO,SAAS,eAAe,OAAO,YAAY,WAAW;AAC/D,cAAQ,sBAAsB;AAAA,IAChC;AACA,QAAI,OAAO,SAAS,UAAU;AAC5B,mBAAa,EAAE,MAAM,SAAS;AAC9B,aAAO,EAAE,MAAM,QAAiB;AAAA,IAClC;AACA,QACE,OAAO,SAAS,eACf,OAAO,SAAS,eAAe,OAAO,YAAY,eACnD,OAAO,SAAS,UAChB;AACA,aAAO,EAAE,MAAM,OAAgB;AAAA,IACjC;AACA,iBAAa,EAAE,MAAM,gBAAgB,QAAQ,OAAO,YAAY;AAChE,WAAO,EAAE,MAAM,QAAiB;AAAA,EAClC;AAEA,QAAM,aAAa,MAAM,QAAQ,KAAK,MAAM;AAAA,IAC1C,UAAU,MAAM;AAAA,IAChB,QAAQ;AAAA,IACR,WAAW,MAAM,CAAC,eAAe;AAAA,IACjC,SAAS,CAAC,UAAU,UAAU,IAAI,GAAG,OAAO,aAAa,KAAK,GAAG,OAAO;AAAA,EAC1E,CAAC;AACD,MAAI,eAAe,WAAW,WAAW,SAAS,QAAS,QAAO,EAAE,MAAM,QAAQ;AAClF,MAAI,iBAAkB,QAAO,EAAE,MAAM,UAAU;AAC/C,MAAI,WAAY,QAAO;AACvB,MAAI,WAAW,SAAS,UAAU;AAChC,WAAO,WAAW,WAAW,SAAS,EAAE,MAAM,OAAO,IAAI,EAAE,MAAM,SAAS;AAAA,EAC5E;AACA,SAAO,EAAE,MAAM,SAAS;AAC1B;AASA,eAAe,mBACb,UACA,QACA,SACyB;AACzB,QAAM,SAAS,MAAM,WAAW,SAAS,SAAS;AAClD,iBAAe,MAAM;AACrB,8BAA4B,QAAQ,QAAQ;AAC5C,QAAM,UAAU,MAAM,kBAAkB,SAAS,SAAS;AAC1D,iBAAe,MAAM;AACrB,MAAI,CAAC,gBAAgB,QAAQ,SAAS,SAAS,YAAY,GAAG;AAC5D,UAAM,IAAI;AAAA,MACR,oBAAe,iBAAiB,SAAS,SAAS,CAAC;AAAA,IACrD;AAAA,EACF;AACA,QAAM,UAAU,MAAM,QAAQ,MAAM;AACpC,iBAAe,MAAM;AACrB,QAAM,eAAe,MAAM,QAAQ,SAAS,MAAM;AAClD,iBAAe,MAAM;AACrB,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI,gCAAgC,uDAAuD;AAAA,EACnG;AACA,QAAM,WAAW,MAAM,oBAAoB,SAAS,cAAc,MAAM;AACxE,iBAAe,MAAM;AACrB,QAAM,QAAQ,uBAAuB,OAAO,SAAS,QAAQ;AAC7D,MAAI,MAAM,SAAS,eAAe,CAAC,gBAAgB,MAAM,SAAS,SAAS,aAAa,GAAG;AACzF,UAAM,IAAI,gCAAgC,8DAA8D;AAAA,EAC1G;AACA,SAAO,EAAE,QAAQ,eAAe,SAAS,SAAS,aAAa;AACjE;AAEA,eAAe,mBAAmB,QAAwB,UAAmC,QAAqB;AAChH,QAAM,cAAc,MAAM,OAAO,QAAQ,SAAS,MAAM;AACxD,iBAAe,MAAM;AACrB,MAAI,CAAC,eAAe,CAAC,OAAO,QAAQ,aAAa,OAAO,aAAa,UAAU,YAAY,QAAQ,GAAG;AACpG,UAAM,IAAI,gCAAgC,uDAAuD;AAAA,EACnG;AACA,QAAM,kBAAkB,MAAM,oBAAoB,OAAO,SAAS,aAAa,MAAM;AACrF,iBAAe,MAAM;AACrB,QAAM,eAAe,uBAAuB,OAAO,OAAO,SAAS,eAAe;AAClF,MAAI,aAAa,SAAS,eAAe,CAAC,gBAAgB,aAAa,SAAS,SAAS,aAAa,GAAG;AACvG,UAAM,IAAI,gCAAgC,8DAA8D;AAAA,EAC1G;AACA,QAAM;AAAA,IACJ,SAAS;AAAA,IACT,CAAC,WAAW;AAAA,MACV,GAAG;AAAA,MACH,MAAM,EAAE,GAAG,MAAM,MAAM,SAAS,CAAC,GAAG,SAAS,aAAa,EAAE;AAAA,IAC9D;AAAA,IACA;AAAA,MACE,iBAAiB,OAAO;AAAA,MACxB,iBAAiB,SAAS;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAe,iCACb,KACA,WACA,QACA,SAKA;AACA,QAAM,SAAS,MAAM,WAAW,SAAS;AACzC,MAAI,QAAQ,QAAS,QAAO;AAC5B,gBAAc,KAAK,+BAA+B,iBAAiB,OAAO,SAAS,CAAC,EAAE;AACtF,QAAM,UAAU,MAAM,QAAQ,MAAM;AACpC,MAAI,QAAQ,QAAS,QAAO;AAC5B,QAAM,OAAO,MAAM,QAAQ,SAAS,MAAM;AAC1C,MAAI,QAAQ,QAAS,QAAO;AAC5B,MAAI,CAAC,KAAM,QAAO,EAAE,MAAM,SAAS,OAAO;AAC1C,QAAM,WAAW,MAAM,oBAAoB,SAAS,MAAM,MAAM;AAChE,MAAI,QAAQ,QAAS,QAAO;AAC5B,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,OAAO,uBAAuB,OAAO,SAAS,QAAQ;AAAA,EACxD;AACF;AAEA,eAAe,oBACb,KACA,QACA,YACA,QACA;AACA,QAAM,OAAO,WAAqE;AAAA,IAChF,OAAO;AAAA,IACP,SAAS;AAAA,MACP,QAAQ,OAAO;AAAA,QACb,MAAM;AAAA,QACN,OAAO,+BAA4B,iBAAiB,OAAO,SAAS,CAAC;AAAA,QACrE,OAAO;AAAA,UACL;AAAA,UACA;AAAA,QACF;AAAA,QACA,OAAO;AAAA,UACL,EAAE,IAAI,UAAU,OAAO,2BAA2B,IAAI,SAAS;AAAA,UAC/D,EAAE,IAAI,QAAQ,OAAO,QAAQ,QAAQ,OAAO;AAAA,QAC9C;AAAA,QACA,MAAM;AAAA,MACR;AAAA,MACA,QAAQ,OAAO;AAAA,QACb,MAAM;AAAA,QACN,OAAO;AAAA,QACP,SAAS;AAAA,UACP;AAAA,UACA;AAAA,UACA,GAAI,WAAW,SAAS,IACpB,WAAW,IAAI,CAAC,SAAS,eAAe,iBAAiB,IAAI,CAAC,EAAE,IAChE,CAAC,gCAAgC;AAAA,UACrC;AAAA,UACA;AAAA,QACF,EAAE,KAAK,IAAI;AAAA,QACX,QAAQ,EAAE,MAAM,OAAO;AAAA,QACvB,cAAc;AAAA,QACd,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,SAAS,EAAE,MAAM,aAAa,EAAE,MAAM,QAAQ,GAAG;AAAA,EACnD,CAAC;AACD,QAAM,QAAQ,KAAK,MAAM;AAAA,IACvB,UAAU,MAAM;AAAA,IAChB;AAAA,IACA,WAAW,MAAM,CAAC,QAAQ;AAAA,EAC5B,CAAC;AACH;AAEA,SAAS,sBAAsB,UAAmC;AAChE,QAAM,aAAa,mBAAmB,SAAS,cAAc,SAAS,aAAa;AACnF,SAAO;AAAA,IACL,eAAe,iBAAiB,SAAS,SAAS,CAAC;AAAA,IACnD;AAAA,IACA,GAAI,WAAW,WAAW,WAAW,KAAK,WAAW,UAAU,WAAW,IACtE,CAAC,oDAAoD,IACrD,CAAC,sBAAsB,WAAW,WAAW,MAAM,4BAAyB,WAAW,UAAU,MAAM,EAAE;AAAA,EAC/G;AACF;AAEA,SAAS,0BAA0B,UAAmC;AACpE,QAAM,aAAa,mBAAmB,SAAS,cAAc,SAAS,aAAa;AACnF,SAAO;AAAA,IACL,GAAI,WAAW,WAAW,WAAW,KAAK,WAAW,UAAU,WAAW,IACtE,CAAC,6DAA6D,EAAE,IAChE,CAAC;AAAA,IACL;AAAA,IACA,GAAI,WAAW,WAAW,SAAS,IAC/B,WAAW,WAAW,IAAI,CAAC,SAAS,KAAK,iBAAiB,IAAI,CAAC,EAAE,IACjE,CAAC,QAAQ;AAAA,IACb;AAAA,IACA;AAAA,IACA,GAAI,WAAW,UAAU,SAAS,IAC9B,WAAW,UAAU,IAAI,CAAC,SAAS,KAAK,iBAAiB,IAAI,CAAC,EAAE,IAChE,CAAC,QAAQ;AAAA,IACb;AAAA,IACA;AAAA,IACA,GAAI,SAAS,cAAc,SAAS,IAChC,SAAS,cAAc,IAAI,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,iBAAiB,IAAI,CAAC,EAAE,IACrF,CAAC,QAAQ;AAAA,IACb;AAAA,IACA;AAAA,IACA,GAAI,SAAS,aAAa,SAAS,IAC/B,SAAS,aAAa,IAAI,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,iBAAiB,IAAI,CAAC,EAAE,IACpF,CAAC,QAAQ;AAAA,IACb;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEA,SAAS,6BAA6B,UAAmC;AACvE,QAAM,aAAa,mBAAmB,SAAS,cAAc,SAAS,aAAa;AACnF,SAAO;AAAA,IACL,4BAAuB,iBAAiB,SAAS,SAAS,CAAC;AAAA,IAC3D,gBAAgB,SAAS,WAAW,UAAU,CAAC;AAAA,IAC/C,gBAAgB,SAAS,WAAW,SAAS,CAAC;AAAA,IAC9C,GAAI,WAAW,WAAW,WAAW,KAAK,WAAW,UAAU,WAAW,IACtE;AAAA,MACE;AAAA,MACA,iBAAiB,SAAS,SAAS,aAAa,CAAC;AAAA,MACjD,iBAAiB,SAAS,SAAS,YAAY,CAAC;AAAA,IAClD,IACA,CAAC;AAAA,IACL;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEA,SAAS,oBAAoB,QAAuB,YAA+B;AACjF,SAAO,6BAAwB,iBAAiB,OAAO,SAAS,CAAC,+CAA0C,WAAW,MAAM,aAAa,WAAW,WAAW,IAAI,SAAS,QAAQ;AACtL;AAEA,SAAS,kBACP,QACA,OACyB;AACzB,SAAO;AAAA,IACL,WAAW,OAAO;AAAA,IAClB,gBAAgB,4BAA4B,MAAM;AAAA,IAClD,cAAc,CAAC,GAAG,OAAO,OAAO;AAAA,IAChC,eAAe,CAAC,GAAG,MAAM,OAAO;AAAA,EAClC;AACF;AAEA,SAAS,4BAA4B,QAAuB,UAAmC;AAC7F,MACE,4BAA4B,MAAM,MAAM,SAAS,kBACjD,gBAAgB,OAAO,SAAS,SAAS,YAAY,GACrD;AACA;AAAA,EACF;AACA,QAAM,IAAI;AAAA,IACR,oBAAe,iBAAiB,OAAO,SAAS,CAAC;AAAA,EACnD;AACF;AAEA,SAAS,uBAAuB,MAAqB,OAAsB;AACzE,SACE,KAAK,cAAc,MAAM,aACzB,KAAK,mBAAmB,MAAM,kBAC9B,KAAK,gBAAgB,MAAM,eAC3B,KAAK,gBAAgB,MAAM,eAC3B,KAAK,WAAW,MAAM,UACtB,KAAK,WAAW,MAAM,UACtB,gBAAgB,KAAK,SAAS,MAAM,OAAO;AAE/C;AAEA,SAAS,cAAc,QAA+B;AACpD,MAAI,WAAW,OAAQ,QAAO;AAC9B,MAAI,WAAW,OAAQ,QAAO;AAC9B,SAAO;AACT;AAEA,SAAS,kBAAkB,QAA+B;AACxD,MAAI,WAAW,OAAQ,QAAO;AAC9B,MAAI,WAAW,OAAQ,QAAO;AAC9B,SAAO;AACT;AAEA,SAAS,6BAA6B,OAAiC;AACrE,MAAI,UAAU,OAAQ,QAAO;AAC7B,MAAI,UAAU,OAAQ,QAAO;AAC7B,SAAO;AACT;AAEA,SAAS,SAAS,QAA2B;AAC3C,SAAO,OAAO,SAAS,IAAI,OAAO,IAAI,gBAAgB,EAAE,KAAK,IAAI,IAAI;AACvE;AAEA,IAAM,kCAAN,cAA8C,MAAM;AAAA,EAClD,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAEA,SAAS,mBAAmB,OAAgB;AAC1C,SAAO,iBAAiB,mCAAmC,iBAAiB;AAC9E;AAEA,SAAS,2BACP,SACA,MACA;AACA,SAAO,QAAQ,kBAAkB,QAAQ,gBAAgB,IAAI,IAAI,KAAK;AACxE;AAEA,SAAS,eAAe,eAAwC,cAA2B;AACzF,SAAO,gBAAgB,YAAY,IAAI,CAAC,eAAe,YAAY,CAAC,IAAI;AAC1E;AAEA,SAAS,eAAe,QAAqB;AAC3C,MAAI,CAAC,OAAO,QAAS;AACrB,QAAM,OAAO,kBAAkB,QAAQ,OAAO,SAAS,IAAI,aAAa,6BAA6B,YAAY;AACnH;",
6
6
  "names": []
7
7
  }
@@ -3,7 +3,7 @@
3
3
  import {
4
4
  runCancellableOperation,
5
5
  showRemoteSelectionReview
6
- } from "./chunk-TRCSEIAQ.ts";
6
+ } from "./chunk-5ZWQ33XL.ts";
7
7
  import {
8
8
  safeTerminalText
9
9
  } from "./chunk-AMJRUXFT.ts";
@@ -206,4 +206,4 @@ async function dispatchManagerResult(ctx, initialResult, origin, runRoute, signa
206
206
  export {
207
207
  dispatchManagerResult
208
208
  };
209
- //# sourceMappingURL=chunk-FJGNDYGC.ts.map
209
+ //# sourceMappingURL=chunk-VHXBCEVF.ts.map
@@ -2,8 +2,8 @@
2
2
  // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
3
3
  import {
4
4
  dispatchManagerResult
5
- } from "./chunk-FJGNDYGC.ts";
6
- import "./chunk-TRCSEIAQ.ts";
5
+ } from "./chunk-VHXBCEVF.ts";
6
+ import "./chunk-5ZWQ33XL.ts";
7
7
  import "./chunk-V6VZ5TLG.ts";
8
8
  import "./chunk-SDZCTCYQ.ts";
9
9
  import "./chunk-K3RIEL6J.ts";
@@ -20,4 +20,4 @@ import "./chunk-HUZ5CR4W.ts";
20
20
  export {
21
21
  dispatchManagerResult
22
22
  };
23
- //# sourceMappingURL=manager-result-dispatcher-AAEAYX57.ts.map
23
+ //# sourceMappingURL=manager-result-dispatcher-6MQKFCWB.ts.map