@skaile/workspaces 0.53.0 → 1.1.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 (224) hide show
  1. package/CHANGELOG.md +109 -0
  2. package/dist/{asset-feeds-OEGJ6NOF.js → asset-feeds-NIAABO6U.js} +9 -9
  3. package/dist/{asset-feeds-OEGJ6NOF.js.map → asset-feeds-NIAABO6U.js.map} +1 -1
  4. package/dist/asset-manager/index.js +6 -6
  5. package/dist/asset-manager/installer.js +5 -5
  6. package/dist/asset-manager/src/index.d.ts +128 -0
  7. package/dist/asset-manager/src/index.d.ts.map +1 -1
  8. package/dist/bridge/drivers/claude-sdk.js +2 -2
  9. package/dist/bridge/drivers/codex.js +1 -1
  10. package/dist/bridge/drivers/continue.js +2 -2
  11. package/dist/bridge/drivers/echo.js +1 -1
  12. package/dist/bridge/drivers/gemini.js +3 -3
  13. package/dist/bridge/drivers/goose.js +2 -2
  14. package/dist/bridge/drivers/omp.js +1 -1
  15. package/dist/bridge/drivers/opencode.js +2 -2
  16. package/dist/bridge/drivers/qwen.js +3 -3
  17. package/dist/bridge/index.js +3 -3
  18. package/dist/{chunk-7ZWLZ5H3.js → chunk-35TLBMHX.js} +4 -4
  19. package/dist/{chunk-7ZWLZ5H3.js.map → chunk-35TLBMHX.js.map} +1 -1
  20. package/dist/{chunk-6VUP6XHK.js → chunk-52XHXSBN.js} +3 -3
  21. package/dist/{chunk-6VUP6XHK.js.map → chunk-52XHXSBN.js.map} +1 -1
  22. package/dist/{chunk-NXC6IEL4.js → chunk-5AGARSQT.js} +267 -261
  23. package/dist/chunk-5AGARSQT.js.map +1 -0
  24. package/dist/{chunk-QLLFCQU5.js → chunk-B4IOSXRZ.js} +485 -1502
  25. package/dist/chunk-B4IOSXRZ.js.map +1 -0
  26. package/dist/{chunk-VE2UIJ7Y.js → chunk-BCJL2UNH.js} +4 -44
  27. package/dist/chunk-BCJL2UNH.js.map +1 -0
  28. package/dist/{chunk-W53D5Q52.js → chunk-BM37QD6U.js} +3 -3
  29. package/dist/{chunk-W53D5Q52.js.map → chunk-BM37QD6U.js.map} +1 -1
  30. package/dist/{chunk-WD2NRI3T.js → chunk-DMHVL5MC.js} +5 -5
  31. package/dist/{chunk-WD2NRI3T.js.map → chunk-DMHVL5MC.js.map} +1 -1
  32. package/dist/{chunk-V4BGVOJC.js → chunk-EE4NL25D.js} +28 -19
  33. package/dist/chunk-EE4NL25D.js.map +1 -0
  34. package/dist/{chunk-VGT2R662.js → chunk-G2X3THJV.js} +5 -5
  35. package/dist/{chunk-VGT2R662.js.map → chunk-G2X3THJV.js.map} +1 -1
  36. package/dist/{chunk-3IHBGDCG.js → chunk-INUQVXUE.js} +2 -2
  37. package/dist/{chunk-3IHBGDCG.js.map → chunk-INUQVXUE.js.map} +1 -1
  38. package/dist/{chunk-UTHEIPEY.js → chunk-KVZ6XKVN.js} +56 -14
  39. package/dist/chunk-KVZ6XKVN.js.map +1 -0
  40. package/dist/{chunk-TCNYSHPM.js → chunk-L3SLC3S4.js} +253 -14
  41. package/dist/chunk-L3SLC3S4.js.map +1 -0
  42. package/dist/{chunk-3KPNDTMR.js → chunk-MG6UIS7G.js} +3 -3
  43. package/dist/{chunk-3KPNDTMR.js.map → chunk-MG6UIS7G.js.map} +1 -1
  44. package/dist/{chunk-LKOMH3QC.js → chunk-OIGYDVCM.js} +3 -3
  45. package/dist/{chunk-LKOMH3QC.js.map → chunk-OIGYDVCM.js.map} +1 -1
  46. package/dist/{chunk-N5AE5SOC.js → chunk-QVE3ILCY.js} +2 -2
  47. package/dist/{chunk-N5AE5SOC.js.map → chunk-QVE3ILCY.js.map} +1 -1
  48. package/dist/{chunk-GYPA2Q7F.js → chunk-SHOKXRL4.js} +21 -4
  49. package/dist/chunk-SHOKXRL4.js.map +1 -0
  50. package/dist/{chunk-6AD3NS7R.js → chunk-U5J77IIZ.js} +4 -4
  51. package/dist/{chunk-6AD3NS7R.js.map → chunk-U5J77IIZ.js.map} +1 -1
  52. package/dist/{chunk-OYMSCV7T.js → chunk-UY5Q2NZH.js} +3 -3
  53. package/dist/{chunk-OYMSCV7T.js.map → chunk-UY5Q2NZH.js.map} +1 -1
  54. package/dist/{chunk-2D5YE3FL.js → chunk-VYIK5IE5.js} +85 -6
  55. package/dist/chunk-VYIK5IE5.js.map +1 -0
  56. package/dist/{chunk-EOINYN5T.js → chunk-YI5OZ7QO.js} +3 -3
  57. package/dist/{chunk-EOINYN5T.js.map → chunk-YI5OZ7QO.js.map} +1 -1
  58. package/dist/{chunk-BXC5547R.js → chunk-Z4EJOBEL.js} +7 -7
  59. package/dist/{chunk-BXC5547R.js.map → chunk-Z4EJOBEL.js.map} +1 -1
  60. package/dist/{chunk-2ZK7M2SG.js → chunk-ZUE2PIJ5.js} +3 -3
  61. package/dist/{chunk-2ZK7M2SG.js.map → chunk-ZUE2PIJ5.js.map} +1 -1
  62. package/dist/cli/index.js +189 -56
  63. package/dist/cli/index.js.map +1 -1
  64. package/dist/cli/src/commands/catalog.d.ts +18 -0
  65. package/dist/cli/src/commands/catalog.d.ts.map +1 -1
  66. package/dist/cli/src/commands/manage.d.ts.map +1 -1
  67. package/dist/cli/src/commands/tree.d.ts.map +1 -1
  68. package/dist/cli/src/commands/why.d.ts.map +1 -1
  69. package/dist/cli/src/helpers.d.ts +25 -0
  70. package/dist/cli/src/helpers.d.ts.map +1 -1
  71. package/dist/connectors/config.js +5 -5
  72. package/dist/connectors/index.js +6 -8
  73. package/dist/connectors/src/config.d.ts +1 -74
  74. package/dist/connectors/src/config.d.ts.map +1 -1
  75. package/dist/connectors/src/connector-manager.d.ts +13 -137
  76. package/dist/connectors/src/connector-manager.d.ts.map +1 -1
  77. package/dist/connectors/src/connector-registry.d.ts.map +1 -1
  78. package/dist/connectors/src/connector-types.d.ts +3 -25
  79. package/dist/connectors/src/connector-types.d.ts.map +1 -1
  80. package/dist/connectors/src/fleet-utils.d.ts +2 -30
  81. package/dist/connectors/src/fleet-utils.d.ts.map +1 -1
  82. package/dist/connectors/src/fs-utils.d.ts +1 -2
  83. package/dist/connectors/src/fs-utils.d.ts.map +1 -1
  84. package/dist/connectors/src/index.d.ts +2 -12
  85. package/dist/connectors/src/index.d.ts.map +1 -1
  86. package/dist/connectors/src/watcher.d.ts +1 -5
  87. package/dist/connectors/src/watcher.d.ts.map +1 -1
  88. package/dist/core/index.js +4 -4
  89. package/dist/core/runtime-assets.js +2 -2
  90. package/dist/core/src/index.d.ts +1 -1
  91. package/dist/core/src/index.d.ts.map +1 -1
  92. package/dist/core/src/repo-manager.d.ts +19 -1
  93. package/dist/core/src/repo-manager.d.ts.map +1 -1
  94. package/dist/core/src/walker.d.ts +7 -0
  95. package/dist/core/src/walker.d.ts.map +1 -1
  96. package/dist/core/workspace-config.js +1 -1
  97. package/dist/deploy/index.js +4 -4
  98. package/dist/discovery/index.js +1 -1
  99. package/dist/discovery/src/discover.d.ts.map +1 -1
  100. package/dist/discovery/src/index.d.ts +1 -1
  101. package/dist/discovery/src/index.d.ts.map +1 -1
  102. package/dist/discovery/src/reference-lint.d.ts +30 -0
  103. package/dist/discovery/src/reference-lint.d.ts.map +1 -1
  104. package/dist/discovery/src/tree-entries.d.ts.map +1 -1
  105. package/dist/{ensure-sources-GJOXWVWO.js → ensure-sources-MJYHZ77Y.js} +14 -7
  106. package/dist/ensure-sources-MJYHZ77Y.js.map +1 -0
  107. package/dist/factory-assets/connectors/box/CONNECTOR.md +33 -0
  108. package/dist/factory-assets/connectors/box/driver.d.ts +27 -0
  109. package/dist/factory-assets/connectors/box/driver.d.ts.map +1 -0
  110. package/dist/{connectors/rclone-config.d.ts → factory-assets/connectors/box.d.ts} +1 -1
  111. package/dist/factory-assets/connectors/box.js +20 -0
  112. package/dist/factory-assets/connectors/box.js.map +1 -0
  113. package/dist/factory-assets/connectors/deploy.js +6 -8
  114. package/dist/factory-assets/connectors/devserver.js +6 -8
  115. package/dist/factory-assets/connectors/flow/adapter.js +6 -8
  116. package/dist/factory-assets/connectors/flow/engine.js +4 -4
  117. package/dist/factory-assets/connectors/flow/run-flow.js +7 -9
  118. package/dist/factory-assets/connectors/flow.js +6 -8
  119. package/dist/factory-assets/connectors/git.js +6 -8
  120. package/dist/factory-assets/connectors/gmail.js +6 -8
  121. package/dist/factory-assets/connectors/googledrive/CONNECTOR.md +14 -128
  122. package/dist/factory-assets/connectors/googledrive/driver.d.ts +6 -13
  123. package/dist/factory-assets/connectors/googledrive/driver.d.ts.map +1 -1
  124. package/dist/factory-assets/connectors/googledrive.js +6 -8
  125. package/dist/factory-assets/connectors/local.js +6 -8
  126. package/dist/factory-assets/connectors/mattermost.js +6 -8
  127. package/dist/factory-assets/connectors/memory.js +6 -8
  128. package/dist/factory-assets/connectors/minio.js +6 -8
  129. package/dist/factory-assets/connectors/postgres.js +6 -8
  130. package/dist/factory-assets/connectors/s3.js +6 -8
  131. package/dist/factory-assets/connectors/sharepoint/CONNECTOR.md +13 -159
  132. package/dist/factory-assets/connectors/sharepoint/driver.d.ts +6 -12
  133. package/dist/factory-assets/connectors/sharepoint/driver.d.ts.map +1 -1
  134. package/dist/factory-assets/connectors/sharepoint.js +6 -8
  135. package/dist/factory-assets/connectors/sqlite.js +6 -8
  136. package/dist/factory-assets/connectors/static-server.js +6 -8
  137. package/dist/factory-assets/connectors/tunnel.js +6 -8
  138. package/dist/factory-assets/connectors/webdav/CONNECTOR.md +13 -118
  139. package/dist/factory-assets/connectors/webdav/driver.d.ts +6 -15
  140. package/dist/factory-assets/connectors/webdav/driver.d.ts.map +1 -1
  141. package/dist/factory-assets/connectors/webdav.js +6 -8
  142. package/dist/factory-assets/connectors/xstate-store.js +6 -8
  143. package/dist/factory-assets/connectors/xstate.js +6 -8
  144. package/dist/factory-assets/skaile.manifest.yaml +4 -1
  145. package/dist/{flows-AGPIE6JM.js → flows-4Z74KY2H.js} +4 -4
  146. package/dist/{flows-AGPIE6JM.js.map → flows-4Z74KY2H.js.map} +1 -1
  147. package/dist/helpers-7KOVCMHW.js +22 -0
  148. package/dist/{helpers-F4NZ66VD.js.map → helpers-7KOVCMHW.js.map} +1 -1
  149. package/dist/library/index.js +7 -7
  150. package/dist/library/install.js +4 -4
  151. package/dist/library/src/library.d.ts +6 -0
  152. package/dist/library/src/library.d.ts.map +1 -1
  153. package/dist/library/src/local/db.d.ts.map +1 -1
  154. package/dist/library/src/local/library.d.ts +9 -0
  155. package/dist/library/src/local/library.d.ts.map +1 -1
  156. package/dist/library/src/local/local-catalog-source.d.ts +9 -0
  157. package/dist/library/src/local/local-catalog-source.d.ts.map +1 -1
  158. package/dist/library/src/local/schema.d.ts +19 -0
  159. package/dist/library/src/local/schema.d.ts.map +1 -1
  160. package/dist/open-library-PGTL332T.js +29 -0
  161. package/dist/{open-library-ERKRGH4B.js.map → open-library-PGTL332T.js.map} +1 -1
  162. package/dist/{paths-D6RUQ522.js → paths-S7QNXYMB.js} +7 -7
  163. package/dist/{paths-D6RUQ522.js.map → paths-S7QNXYMB.js.map} +1 -1
  164. package/dist/{plugin-store-SGNJTBYS.js → plugin-store-3DAVGKHN.js} +6 -6
  165. package/dist/{plugin-store-SGNJTBYS.js.map → plugin-store-3DAVGKHN.js.map} +1 -1
  166. package/dist/runner/index.js +11 -13
  167. package/dist/runner/src/serve.d.ts.map +1 -1
  168. package/dist/sdk/asset-manager.js +6 -6
  169. package/dist/sdk/bridge.js +3 -3
  170. package/dist/sdk/core.js +4 -4
  171. package/dist/sdk/flow.js +4 -4
  172. package/dist/sdk/index.js +11 -13
  173. package/dist/sdk/index.js.map +1 -1
  174. package/dist/sdk/runner.js +11 -13
  175. package/dist/{setup-IV2JFW3T.js → setup-WBGDT2WY.js} +9 -9
  176. package/dist/{setup-IV2JFW3T.js.map → setup-WBGDT2WY.js.map} +1 -1
  177. package/dist/{source-FGOMQMZT.js → source-FJXRQ2NU.js} +18 -12
  178. package/dist/{source-FGOMQMZT.js.map → source-FJXRQ2NU.js.map} +1 -1
  179. package/dist/{store-client-GJT2XQ5Z.js → store-client-YGDN4L2G.js} +7 -7
  180. package/dist/{store-client-GJT2XQ5Z.js.map → store-client-YGDN4L2G.js.map} +1 -1
  181. package/dist/tui/index.js +11 -13
  182. package/dist/tui/index.js.map +1 -1
  183. package/dist/workspace-plugin/adapters/mcp.js +2 -2
  184. package/dist/workspace-plugin/adapters/omp.js +3 -3
  185. package/dist/workspace-plugin/index.js +1 -1
  186. package/package.json +7 -13
  187. package/dist/chunk-2D5YE3FL.js.map +0 -1
  188. package/dist/chunk-GYPA2Q7F.js.map +0 -1
  189. package/dist/chunk-NXC6IEL4.js.map +0 -1
  190. package/dist/chunk-OVRSNIKJ.js +0 -72
  191. package/dist/chunk-OVRSNIKJ.js.map +0 -1
  192. package/dist/chunk-QLLFCQU5.js.map +0 -1
  193. package/dist/chunk-RAIRWFAN.js +0 -843
  194. package/dist/chunk-RAIRWFAN.js.map +0 -1
  195. package/dist/chunk-TCNYSHPM.js.map +0 -1
  196. package/dist/chunk-UTHEIPEY.js.map +0 -1
  197. package/dist/chunk-V4BGVOJC.js.map +0 -1
  198. package/dist/chunk-VE2UIJ7Y.js.map +0 -1
  199. package/dist/connectors/rclone-config.js +0 -4
  200. package/dist/connectors/rclone-config.js.map +0 -1
  201. package/dist/connectors/rclone.d.ts +0 -2
  202. package/dist/connectors/rclone.js +0 -5
  203. package/dist/connectors/rclone.js.map +0 -1
  204. package/dist/connectors/src/fleet-health-gate.d.ts +0 -105
  205. package/dist/connectors/src/fleet-health-gate.d.ts.map +0 -1
  206. package/dist/connectors/src/mount-placeholder.d.ts +0 -131
  207. package/dist/connectors/src/mount-placeholder.d.ts.map +0 -1
  208. package/dist/connectors/src/rclone-config/googledrive.d.ts +0 -59
  209. package/dist/connectors/src/rclone-config/googledrive.d.ts.map +0 -1
  210. package/dist/connectors/src/rclone-config/index.d.ts +0 -9
  211. package/dist/connectors/src/rclone-config/index.d.ts.map +0 -1
  212. package/dist/connectors/src/rclone-config/onedrive.d.ts +0 -48
  213. package/dist/connectors/src/rclone-config/onedrive.d.ts.map +0 -1
  214. package/dist/connectors/src/rclone-config/sanitize.d.ts +0 -9
  215. package/dist/connectors/src/rclone-config/sanitize.d.ts.map +0 -1
  216. package/dist/connectors/src/rclone-config/webdav.d.ts +0 -50
  217. package/dist/connectors/src/rclone-config/webdav.d.ts.map +0 -1
  218. package/dist/connectors/src/rclone-process-manager.d.ts +0 -316
  219. package/dist/connectors/src/rclone-process-manager.d.ts.map +0 -1
  220. package/dist/connectors/src/rclone-token-refresh.d.ts +0 -84
  221. package/dist/connectors/src/rclone-token-refresh.d.ts.map +0 -1
  222. package/dist/ensure-sources-GJOXWVWO.js.map +0 -1
  223. package/dist/helpers-F4NZ66VD.js +0 -4
  224. package/dist/open-library-ERKRGH4B.js +0 -23
@@ -1,316 +0,0 @@
1
- /**
2
- * RcloneProcessManager — supervises an rclone FUSE subprocess per mount.
3
- *
4
- * Responsibilities:
5
- * - Spawn rclone with a per-mount config + cache dir, wait for the FUSE
6
- * mountpoint to appear, then return a handle.
7
- * - Pipe rclone's JSON-formatted log lines into the parent driver's
8
- * {@link Logger} via a child source `${driverName}+rclone`.
9
- * - Coordinate graceful stop (flush → SIGTERM → fusermount fallback).
10
- * - Expose `flush` (POST /vfs/refresh + poll /vfs/stats), `statSize`
11
- * (operations/stat → authoritative remote size, backing the read-path
12
- * stale-tail gate) and `status` (process liveness + cache-dir size).
13
- *
14
- * Cross-link: see `workspaces/core/CLAUDE.md` § Logging for the
15
- * `createLogger` / `LogStore` contract, and
16
- * `_devlog/specs/2026-05-01-debug-logging-design.md` for the source taxonomy.
17
- */
18
- import type { Logger } from "@skaile/workspaces/types";
19
- /** Default rclone `--vfs-write-back` delay; raised from 5s so a rapidly-rewritten file settles before upload (avoids mid-write "sizes differ" aborts). */
20
- export declare const DEFAULT_VFS_WRITE_BACK = "30s";
21
- /** Consecutive failed upload retries for one object before a stuck-upload error is surfaced. */
22
- export declare const DEFAULT_UPLOAD_STUCK_THRESHOLD = 3;
23
- /**
24
- * Spawn-time configuration for a single rclone FUSE mount.
25
- * @docLink packages/connectors/api-reference#rclone-spawn-config
26
- */
27
- export interface RcloneSpawnConfig {
28
- /** Logical mount id; used as `instance` and as part of the rclone config filename. */
29
- mountId: string;
30
- /**
31
- * Driver name (e.g. "sharepoint", "webdav"); used to derive the rclone
32
- * subprocess child logger subkind: `${driverName}+rclone`.
33
- */
34
- driverName: string;
35
- /** Absolute path inside the container where rclone will FUSE-mount. Created if missing. */
36
- mountPoint: string;
37
- /** Absolute path inside the container for the vfs cache. Created if missing. */
38
- cacheDir: string;
39
- /** Full INI text for rclone.conf (one [remote] section, named `skaile-<mountId>`). */
40
- rcloneConfig: string;
41
- /** Remote spec, e.g. `skaile-foo:/Clients/KADK`. */
42
- remote: string;
43
- /** rclone --vfs-cache-mode value. */
44
- vfsCacheMode: "minimal" | "writes" | "full";
45
- /** Per-mount cache size cap. Default: '5G'. */
46
- cacheMaxSize?: string;
47
- /** Per-mount cache age cap. Default: '168h'. */
48
- cacheMaxAge?: string;
49
- /**
50
- * Skip rclone's post-transfer size + checksum verification by appending
51
- * `--ignore-size --ignore-checksum`. Default: false (verification on).
52
- *
53
- * Escape hatch for remotes that mutate uploaded bytes server-side (notably
54
- * SharePoint Online normalising LF→CRLF on text/html), which makes the
55
- * remote object a different size/hash than the local source. rclone reads
56
- * that as `corrupted on transfer`, deletes the upload, and retries forever,
57
- * so the file never durably lands. Enabling this trades integrity
58
- * verification for sync-ability and must only be set by drivers that have
59
- * confirmed the mutation is benign. Off-by-default; wired per-driver, never
60
- * globally.
61
- */
62
- ignoreSizeCheck?: boolean;
63
- /**
64
- * rclone `--vfs-write-back` delay (e.g. '30s', '1m'). Controls how long a
65
- * dirty file sits before rclone starts uploading it. Default:
66
- * {@link DEFAULT_VFS_WRITE_BACK}. Raise it when the agent rewrites files
67
- * faster than they upload, to avoid mid-write "sizes differ" aborts.
68
- */
69
- vfsWriteBack?: string;
70
- /**
71
- * Consecutive upload retries for one object before {@link onUploadStuck}
72
- * fires. Default: {@link DEFAULT_UPLOAD_STUCK_THRESHOLD}.
73
- */
74
- uploadStuckThreshold?: number;
75
- /**
76
- * Optional hook invoked once per object when its upload has failed
77
- * `uploadStuckThreshold` times in a row. spawn() always also logs an
78
- * error-level entry through the `${driverName}+rclone` child logger; this
79
- * hook lets callers surface the stranded file elsewhere (e.g. a sync event).
80
- */
81
- onUploadStuck?: (object: string, tries: number) => void;
82
- /**
83
- * Optional hook invoked when rclone reports an OAuth auth failure (notably
84
- * `invalid_client` / `couldn't fetch token`, the symptom of an expired
85
- * access token that rclone cannot self-refresh). Wired by the mount driver
86
- * to the reactive arm of its token-refresh controller. Fires per matching
87
- * log line; the controller dedupes via its in-flight guard + cooldown.
88
- */
89
- onAuthError?: () => void;
90
- /**
91
- * Parent driver Logger — already tagged
92
- * `{kind:"mount", subkind:<driver>, instance:<mountId>}` by ConnectorManager.
93
- * Used for manager-level events; rclone subprocess events go through the
94
- * derived `child({subkind: \`${driverName}+rclone\`})` logger.
95
- */
96
- log: Logger;
97
- }
98
- /**
99
- * Handle returned by `RcloneProcessManager.spawn()` once the FUSE mountpoint is confirmed.
100
- * @docLink packages/connectors/api-reference#rclone-handle
101
- */
102
- export interface RcloneHandle {
103
- /** OS process id of the rclone subprocess. */
104
- pid: number;
105
- /** Confirmed FUSE mountpoint (echo of input). */
106
- mountPoint: string;
107
- /** Cache directory (echo of input). */
108
- cacheDir: string;
109
- /** The local rc API address rclone is bound to, e.g. '127.0.0.1:54321'. */
110
- rcAddr: string;
111
- }
112
- /**
113
- * Manages rclone FUSE subprocesses for mount drivers. Stateless across instances —
114
- * the internal handle registry is module-scoped so a fresh `RcloneProcessManager`
115
- * can still find handles created by a previous instance.
116
- * @docLink packages/connectors/api-reference#rclone-process-manager
117
- */
118
- export declare class RcloneProcessManager {
119
- private readonly now;
120
- /**
121
- * @param now Injectable clock (ms) used only to timestamp the quarantine dir
122
- * on a poisoned-cache reset, so the move-aside name is deterministic in tests.
123
- */
124
- constructor(now?: () => number);
125
- /**
126
- * Spawn an rclone FUSE mount with one-shot poisoned-cache recovery. Delegates
127
- * to {@link spawnOnce}; if that fails specifically because the persistent VFS
128
- * cache was poisoned (a prior container SIGKILLed mid-write left `vfs`/`vfsMeta`
129
- * referencing missing backing files), quarantine the cache and retry the mount
130
- * exactly once on a clean rebuild from the authoritative remote.
131
- *
132
- * The retry is single-shot and bounded: if the fresh-cache mount also fails the
133
- * cause is connectivity/token (not the cache), so the error propagates without
134
- * a second reset — never a reset/respawn loop. A non-poison failure, or a
135
- * poison failure with nothing to quarantine, propagates immediately.
136
- */
137
- spawn(config: RcloneSpawnConfig): Promise<RcloneHandle>;
138
- /**
139
- * Spawn an rclone FUSE mount. Resolves once the mountpoint is confirmed
140
- * present in `/proc/self/mounts`. Throws on timeout, on early exit, or
141
- * if invariants are violated. A readiness-timeout accompanied by the
142
- * poisoned-cache log signature throws {@link CachePoisonedMountError} so the
143
- * public {@link spawn} can apply its quarantine-and-retry recovery.
144
- */
145
- protected spawnOnce(config: RcloneSpawnConfig): Promise<RcloneHandle>;
146
- /**
147
- * Stop an rclone subprocess. Attempts a flush first, then SIGTERM, then
148
- * SIGKILL + fusermount3 if `graceMs` elapses without the mountpoint
149
- * disappearing.
150
- *
151
- * `graceMs` bounds both the flush stabilization gate and the SIGTERM→SIGKILL
152
- * window — it is *not* a single total wall-clock cap: the flush also waits on
153
- * rclone's `/vfs/stats` drain (its own 60s ceiling) between the two.
154
- */
155
- stop(handle: RcloneHandle, opts?: {
156
- graceMs?: number;
157
- }): Promise<void>;
158
- /**
159
- * Apply a freshly-rendered rclone INI to a running mount by recycling the
160
- * process: flush + stop the current rclone, then re-spawn at the same
161
- * mountpoint/cacheDir with the new config. Returns the new handle.
162
- *
163
- * rclone holds the OAuth token in memory (baked into the config at spawn);
164
- * there is no rc command to swap it on a live `onedrive` backend, so a
165
- * recycle is the reliable way to apply a refreshed token. The vfs cache dir
166
- * is reused, so the remount revalidates rather than re-downloads. During the
167
- * brief unmount window the read-only mount-placeholder barrier underneath is
168
- * exposed (writes fail with EROFS, not EIO) — see ConnectorManager's
169
- * read-only-until-ready guarantee.
170
- */
171
- reconfigure(handle: RcloneHandle, rcloneConfig: string): Promise<RcloneHandle>;
172
- /**
173
- * Force rclone to upload pending writes, then wait until the in-use
174
- * counter reaches zero.
175
- *
176
- * Before issuing the refresh it waits for the vfs cache dir to go quiescent
177
- * (no write for `stabilityThresholdMs`, bounded by `stabilizeTimeoutMs`) so a
178
- * close/hibernate-triggered flush doesn't snapshot a half-written file and
179
- * trigger rclone's mid-write "sizes differ" abort. Pass `stabilize: false`
180
- * to skip the gate.
181
- */
182
- flush(handle: RcloneHandle, opts?: {
183
- stabilize?: boolean;
184
- stabilityThresholdMs?: number;
185
- stabilizeTimeoutMs?: number;
186
- }): Promise<void>;
187
- /**
188
- * Authoritative remote byte size for a mount-relative path, via rclone's
189
- * `operations/stat` rc endpoint. Backs the mount read-path stale-tail gate:
190
- * `operations/stat` hits the backend object directly, so it returns the true
191
- * remote size even when the VFS cache is serving a non-truncated item (and
192
- * `statSync` on the FUSE mount reports the inflated length). Returns `null`
193
- * when the handle is unknown, the object is missing / a directory, or the
194
- * call fails — the caller then trusts the on-disk bytes.
195
- */
196
- statSize(handle: RcloneHandle, relPath: string): Promise<number | null>;
197
- /** Liveness + cache-dir size. */
198
- status(handle: RcloneHandle): Promise<{
199
- alive: boolean;
200
- cacheBytes: number;
201
- }>;
202
- }
203
- /**
204
- * Per-process state threaded through {@link _routeRcloneLogLine} so it can
205
- * detect a sustained upload failure (the same object failing to upload K times
206
- * in a row) and surface it exactly once, instead of letting rclone retry
207
- * silently at INFO level forever.
208
- */
209
- export interface RcloneLogRouteContext {
210
- /** Consecutive retries for one object before {@link onUploadStuck} fires. */
211
- stuckThreshold?: number;
212
- /** Objects already alerted on, to fire once and not on every later retry. */
213
- alertedObjects?: Set<string>;
214
- /** Per-object consecutive `itemNotFound` count; escalates at {@link stuckThreshold}. */
215
- itemNotFoundCounts?: Map<string, number>;
216
- /** Called the first time an object crosses {@link stuckThreshold}. */
217
- onUploadStuck?: (object: string, tries: number) => void;
218
- /** Called when a line matches an OAuth auth-failure pattern. */
219
- onAuthError?: () => void;
220
- }
221
- /**
222
- * Thrown by {@link RcloneProcessManager.spawnOnce} when a mount-readiness
223
- * failure was accompanied by the {@link CACHE_POISON_RE} signature, so
224
- * {@link RcloneProcessManager.spawn} knows the failure is a recoverable
225
- * poisoned cache (quarantine + single retry) rather than a connectivity/token
226
- * fault. Its `message` is the full mount-failure detail (including the stderr
227
- * tail), so surfacing it directly when recovery declines loses no diagnostics.
228
- */
229
- export declare class CachePoisonedMountError extends Error {
230
- constructor(message: string);
231
- }
232
- /**
233
- * @internal
234
- * True when an rclone log line carries the poisoned-VFS-cache signature
235
- * ({@link CACHE_POISON_RE}). Exported for tests; not part of the public API.
236
- */
237
- export declare function _isCachePoisonLine(line: string): boolean;
238
- /**
239
- * Move a poisoned rclone VFS cache aside so the next spawn rebuilds a clean one
240
- * from the authoritative remote. Moves `<cacheDir>/vfs` + `<cacheDir>/vfsMeta`
241
- * (whichever exist) into `<cacheDir>/.corrupt-<ISO>` — a move-aside, never a
242
- * delete, so any (junk) un-uploaded bytes stay recoverable for forensics. The
243
- * quarantine dir is nested inside `cacheDir` (not a sibling) so it lives within
244
- * the per-session cache dir the platform removes wholesale on session close —
245
- * bounding its lifetime to the session — and rclone only reads its own
246
- * `vfs`/`vfsMeta` subdirs, so the dotted sibling is inert to the live mount.
247
- * (A bounded retain-N/reap-after-M GC of repeated resets within one long-lived
248
- * session is a follow-up; session-close cleanup covers the common case.)
249
- *
250
- * Returns the quarantine dir path when anything was moved, else `null` (nothing
251
- * to quarantine — the failure was not a poisoned cache). `nowMs` is injected for
252
- * deterministic test timestamps. Exported for tests; not part of the public API.
253
- */
254
- export declare function quarantineCacheDir(cacheDir: string, nowMs: number): Promise<string | null>;
255
- /**
256
- * @internal
257
- * Route a single rclone log line (JSON or raw) to the appropriate Logger
258
- * call. Exported for tests; not part of the public API. When `ctx` is
259
- * supplied, also tracks consecutive upload failures per object and invokes
260
- * `ctx.onUploadStuck` once the retry count for an object reaches the threshold.
261
- */
262
- export declare function _routeRcloneLogLine(line: string, log: Logger, ctx?: RcloneLogRouteContext): void;
263
- /**
264
- * @internal
265
- * Build the `rclone mount` argv from a spawn config. Extracted from spawn() so
266
- * the flag wiring (notably `--vfs-write-back` and the conditional
267
- * `--ignore-size --ignore-checksum`) is unit-testable without actually
268
- * launching rclone. Exported for tests; not part of the public API.
269
- */
270
- export declare function _buildRcloneArgs(config: RcloneSpawnConfig, io: {
271
- configPath: string;
272
- rcAddr: string;
273
- }): string[];
274
- /**
275
- * @internal
276
- * Split an rclone mount `remote` (`skaile-<id>:/base/path`) plus a
277
- * mount-relative path into the `{fs, remote}` pair rclone's `operations/stat`
278
- * rc command expects: `fs` is the backend root (`skaile-<id>:`) and `remote` is
279
- * the object path within it. Leading/trailing slashes are normalised away so
280
- * the join is stable regardless of how either side is slashed. Exported for
281
- * tests; not part of the public API.
282
- */
283
- export declare function _operationsStatTarget(remote: string, relPath: string): {
284
- fs: string;
285
- remote: string;
286
- };
287
- /**
288
- * Query rclone's `operations/stat` rc endpoint for the authoritative remote
289
- * size of `relPath` under `remote`. Returns the byte size, or `null` when the
290
- * object is missing, is a directory, the call fails, or the size is absent.
291
- *
292
- * Unlike a `statSync` on the FUSE mount, `operations/stat` resolves the object
293
- * against the backend directly, so it is not subject to the VFS cache's
294
- * non-truncated stale tail. Pass `fetchImpl` to test without a live rc server.
295
- */
296
- export declare function fetchAuthoritativeSize(rcAddr: string, remote: string, relPath: string, fetchImpl?: typeof fetch): Promise<number | null>;
297
- /**
298
- * Poll `dir` until its newest file mtime is at least `thresholdMs` in the past
299
- * (no write for that long), or `timeoutMs` elapses. Returns true if it went
300
- * quiescent, false on timeout. An empty/missing dir counts as quiescent.
301
- */
302
- export declare function awaitQuiescent(dir: string, opts: {
303
- thresholdMs: number;
304
- timeoutMs: number;
305
- pollMs: number;
306
- }): Promise<boolean>;
307
- /**
308
- * @internal
309
- * Returns true if a FUSE mount is present at `mountPoint` in the given
310
- * /proc/self/mounts text. The fstype check (field 3, `fuse.*`) is essential:
311
- * the deferred-mount barrier leaves a `tmpfs` mounted at the same path, so a
312
- * path-only match would report the *barrier* as the confirmed mount and mask a
313
- * dead rclone process. Exported for tests; not part of the public API.
314
- */
315
- export declare function _fuseMountPresent(procMountsText: string, mountPoint: string): boolean;
316
- //# sourceMappingURL=rclone-process-manager.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rclone-process-manager.d.ts","sourceRoot":"","sources":["../../../connectors/src/rclone-process-manager.ts"],"names":[],"mappings":"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"}
@@ -1,84 +0,0 @@
1
- /**
2
- * Proactive + reactive OAuth token refresh for rclone-backed mounts.
3
- * See `connectors/CLAUDE.md` § Rclone Process Manager → Token refresh.
4
- */
5
- import type { TokenMediator } from "./connector-types.js";
6
- import type { RcloneHandle } from "./rclone-process-manager.js";
7
- /**
8
- * Safety margin between the scheduled refresh and the token's declared expiry.
9
- * Default 5 minutes: long enough that any in-flight read/write at fire time
10
- * still has a usable token through the recycle, short enough that a server
11
- * clock skew of a few seconds does not push the fire-time past expiry. Matches
12
- * the AI-credential and git-mount refresh leads.
13
- */
14
- export declare const PROACTIVE_RCLONE_REFRESH_MARGIN_MS: number;
15
- /** Default cooldown suppressing reactive triggers right after a refresh. */
16
- export declare const DEFAULT_REACTIVE_COOLDOWN_MS: number;
17
- /**
18
- * Minimal slice of `RcloneProcessManager` the refresh controller needs: swap
19
- * the live mount onto a freshly-rendered INI (`reconfigure`), and stop a
20
- * process the controller spawned but can no longer own (`stop`, used to clean
21
- * up when `disconnect()` races a mid-recycle spawn).
22
- */
23
- export interface RcloneReconfigurable {
24
- reconfigure(handle: RcloneHandle, rcloneConfig: string): Promise<RcloneHandle>;
25
- stop(handle: RcloneHandle): Promise<void>;
26
- }
27
- /**
28
- * Caller-supplied dependencies for {@link createRcloneTokenRefresh}.
29
- *
30
- * - `tokenMediator` runs the actual backend mint round-trip.
31
- * - `renderConfig(token)` re-renders the rclone INI for the freshly-minted
32
- * access token (driver-specific: onedrive vs webdav backend shape).
33
- * - `rclone.reconfigure` recycles the process onto the new INI.
34
- * - `handleRef.current` is the live rclone handle; the controller updates it
35
- * in place on every successful recycle so the driver's `disconnect()` stops
36
- * the current process.
37
- * - `now` / `setTimeoutImpl` / `clearTimeoutImpl` are injected for tests.
38
- */
39
- export interface RcloneTokenRefreshDeps {
40
- connectorId: string;
41
- tokenMediator: TokenMediator;
42
- renderConfig: (token: string) => string | Promise<string>;
43
- rclone: RcloneReconfigurable;
44
- handleRef: {
45
- current: RcloneHandle | null;
46
- };
47
- log: (line: string) => void;
48
- now?: () => number;
49
- setTimeoutImpl?: (handler: () => void, ms: number) => {
50
- unref?: () => void;
51
- };
52
- clearTimeoutImpl?: (handle: {
53
- unref?: () => void;
54
- }) => void;
55
- marginMs?: number;
56
- reactiveCooldownMs?: number;
57
- }
58
- export interface RcloneTokenRefreshController {
59
- /**
60
- * Arm the timer for `expiresAtIso - marginMs`. Cancels any prior pending
61
- * fire. `null` / `undefined` / unparseable cancels without re-arming
62
- * (static-credential / standalone semantics). A past fire-time refreshes on
63
- * the next tick.
64
- */
65
- schedule(expiresAtIso: string | null | undefined): void;
66
- /**
67
- * Reactive safety net: invoke when rclone reports an auth failure. Triggers
68
- * an immediate refresh unless one is already in flight or the last refresh
69
- * was within the cooldown window (prevents a stream of failure lines from
70
- * spinning the recycle loop).
71
- */
72
- onAuthError(): void;
73
- /** Cancel any pending fire. Idempotent. */
74
- cancel(): void;
75
- /** Whether a proactive timer is currently armed. Exposed for tests. */
76
- isPending(): boolean;
77
- }
78
- /**
79
- * Build a refresh controller bound to one rclone mount. One controller per
80
- * connect — the driver constructs it after the initial spawn and disposes it
81
- * via `cancel()` in `disconnect()`.
82
- */
83
- export declare function createRcloneTokenRefresh(deps: RcloneTokenRefreshDeps): RcloneTokenRefreshController;
84
- //# sourceMappingURL=rclone-token-refresh.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rclone-token-refresh.d.ts","sourceRoot":"","sources":["../../../connectors/src/rclone-token-refresh.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE;;;;;;GAMG;AACH,eAAO,MAAM,kCAAkC,QAAgB,CAAC;AAEhE,4EAA4E;AAC5E,eAAO,MAAM,4BAA4B,QAAY,CAAC;AAStD;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/E,IAAI,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,aAAa,CAAC;IAC7B,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1D,MAAM,EAAE,oBAAoB,CAAC;IAC7B,SAAS,EAAE;QAAE,OAAO,EAAE,YAAY,GAAG,IAAI,CAAA;KAAE,CAAC;IAC5C,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK;QAAE,KAAK,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;IAC7E,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,KAAK,IAAI,CAAC;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,4BAA4B;IAC3C;;;;;OAKG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC;IACxD;;;;;OAKG;IACH,WAAW,IAAI,IAAI,CAAC;IACpB,2CAA2C;IAC3C,MAAM,IAAI,IAAI,CAAC;IACf,uEAAuE;IACvE,SAAS,IAAI,OAAO,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,sBAAsB,GAC3B,4BAA4B,CA+J9B"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../cli/src/ensure-sources.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAqBA,SAAS,gBAAgB,GAAA,EAAqB;AAC5C,EAAA,OAAY,IAAA,CAAA,IAAA,CAAK,iBAAA,EAAkB,EAAG,GAAG,CAAA;AAC3C;AASA,SAAS,kBAAA,CAAmB,UAAkB,KAAA,EAAsC;AAClF,EAAA,IAAI;AACF,IAAA,OAAO,mBAAA,CAAoB,IAAA,CAAK,QAAQ,CAAA,CAAE,UAAA,EAAW;AAAA,EACvD,SAAS,GAAA,EAAK;AACZ,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,MAAA,CAAO,CAAA,eAAA,EAAkB,QAAQ,CAAA,EAAA,EAAK,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AAAA,IAC1F;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAMA,SAAS,kBAAA,CAAmB,KAAA,EAAoB,KAAA,EAAgB,MAAA,EAA4B;AAC1F,EAAA,MAAM,GAAA,GAAM,cAAA,CAAe,KAAA,CAAM,GAAG,CAAA;AACpC,EAAA,MAAM,IAAA,GAAO,eAAA,CAAgB,KAAA,CAAM,GAAG,CAAA;AACtC,EAAA,MAAM,IAAA,GAAO,gBAAgB,GAAG,CAAA;AAChC,EAAA,IAAI,UAAA,CAAW,IAAI,CAAA,EAAG;AACpB,IAAA,MAAA,CAAO,MAAA,CAAO,KAAK,IAAI,CAAA;AACvB,IAAA;AAAA,EACF;AACA,EAAA,SAAA,CAAe,aAAQ,IAAI,CAAA,EAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AACjD,EAAA,MAAM,IAAA,GAAO,CAAC,OAAA,EAAS,KAAA,CAAM,KAAK,IAAI,CAAA;AACtC,EAAA,IAAI,KAAA,CAAM,KAAK,IAAA,CAAK,MAAA,CAAO,GAAG,CAAA,EAAG,UAAA,EAAY,MAAM,GAAG,CAAA;AACtD,EAAA,MAAM,KAAA,GAAQ,UAAU,KAAA,EAAO,IAAA,EAAM,EAAE,KAAA,EAAO,KAAA,GAAQ,MAAA,GAAS,SAAA,EAAW,CAAA;AAC1E,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,MAAA,CAAO,MAAA,CAAO,KAAK,IAAI,CAAA;AACvB,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,MAAA,CAAO,CAAA,qBAAA,EAAwB,KAAA,CAAM,GAAG,CAAA,CAAE,CAAA;AAAA,IAC5C;AACA,IAAA;AAAA,EACF;AACA,EAAA,MAAA,CAAO,MAAA,CAAO,KAAK,IAAI,CAAA;AACzB;AAGA,SAAS,kBAAkB,MAAA,EAA4B;AACrD,EAAA,KAAA,MAAW,KAAK,MAAA,CAAO,MAAA,EAAQ,KAAA,CAAM,CAAA,eAAA,EAAkB,CAAC,CAAA,EAAA,CAAI,CAAA;AAC5D,EAAA,IAAI,MAAA,CAAO,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG;AAC5B,IAAA,OAAA,CAAQ,yBAAyB,MAAA,CAAO,MAAA,CAAO,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAAA,EAC7D;AACF;AAUO,SAAS,mBAAA,CACd,UAAA,EACA,IAAA,GAA4B,EAAC,EACf;AACd,EAAA,MAAM,MAAA,GAAuB,EAAE,MAAA,EAAQ,EAAC,EAAG,QAAQ,EAAC,EAAG,MAAA,EAAQ,EAAC,EAAE;AAClE,EAAA,MAAM,QAAA,GAAgB,IAAA,CAAA,IAAA,CAAK,UAAA,EAAY,aAAa,CAAA;AACpD,EAAA,IAAI,CAAC,UAAA,CAAW,QAAQ,CAAA,EAAG,OAAO,MAAA;AAElC,EAAA,MAAM,KAAA,GAAQ,KAAK,KAAA,IAAS,KAAA;AAC5B,EAAA,MAAM,OAAA,GAAU,kBAAA,CAAmB,QAAA,EAAU,KAAK,CAAA;AAClD,EAAA,IAAI,OAAA,KAAY,MAAM,OAAO,MAAA;AAC7B,EAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AAEjC,EAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,IAAA,kBAAA,CAAmB,KAAA,EAAO,OAAO,MAAM,CAAA;AAAA,EACzC;AAEA,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,iBAAA,CAAkB,MAAM,CAAA;AAAA,EAC1B;AAEA,EAAA,OAAO,MAAA;AACT","file":"ensure-sources-GJOXWVWO.js","sourcesContent":["/**\n * ensure-sources.ts — hydrate the `~/.skaile/cache/sources/` clone cache from a\n * project's `skaile.yaml` `sources:` entries.\n *\n * Called by `skaile init` (idempotent: no-op when no sources declared) and\n * `skaile install` so checking out a project pulls its source clones onto\n * the local machine.\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport { existsSync, mkdirSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport {\n getGlobalCacheDir,\n type SourceEntry,\n sourceCacheKey,\n sourceShortName,\n WorkspaceYamlEditor,\n} from \"@skaile/workspaces/core\";\nimport { logErr, logInfo, logOk } from \"./helpers.ts\";\n\nfunction sourceClonePath(key: string): string {\n return path.join(getGlobalCacheDir(), key);\n}\n\nexport interface EnsureResult {\n cloned: string[];\n cached: string[];\n failed: string[];\n}\n\n/** Load `sources:` from a project's `skaile.yaml`, or `null` when unavailable. */\nfunction loadProjectSources(yamlPath: string, quiet: boolean): SourceEntry[] | null {\n try {\n return WorkspaceYamlEditor.load(yamlPath).getSources();\n } catch (err) {\n if (!quiet) {\n logErr(`Could not read ${yamlPath}: ${err instanceof Error ? err.message : String(err)}`);\n }\n return null;\n }\n}\n\n/**\n * Hydrate a single source entry into `result`: skip when already cached,\n * otherwise clone and record success/failure. Mutates `result` in place.\n */\nfunction hydrateSourceEntry(entry: SourceEntry, quiet: boolean, result: EnsureResult): void {\n const key = sourceCacheKey(entry.url);\n const slug = sourceShortName(entry.url);\n const dest = sourceClonePath(key);\n if (existsSync(dest)) {\n result.cached.push(slug);\n return;\n }\n mkdirSync(path.dirname(dest), { recursive: true });\n const args = [\"clone\", entry.url, dest];\n if (entry.pin) args.splice(1, 0, \"--branch\", entry.pin);\n const clone = spawnSync(\"git\", args, { stdio: quiet ? \"pipe\" : \"inherit\" });\n if (clone.status !== 0) {\n result.failed.push(slug);\n if (quiet) {\n logErr(`git clone failed for ${entry.url}`);\n }\n return;\n }\n result.cloned.push(slug);\n}\n\n/** Log a full-hydrate summary of cloned + reused-cached entries. */\nfunction logHydrateSummary(result: EnsureResult): void {\n for (const n of result.cloned) logOk(`Cloned source \"${n}\".`);\n if (result.cached.length > 0) {\n logInfo(`Reused cached clones: ${result.cached.join(\", \")}`);\n }\n}\n\n/**\n * Walk `projectDir/skaile.yaml` `sources:` and clone any entries whose\n * clone directory does not yet exist under `~/.skaile/cache/sources/`. Existing\n * clones are left untouched — this is hydration, not sync.\n *\n * Quiet by default: when `quiet: true` the helper only prints failures.\n * On full hydrate (`quiet: false`) it logs each cloned/cached entry.\n */\nexport function ensureSourcesCloned(\n projectDir: string,\n opts: { quiet?: boolean } = {},\n): EnsureResult {\n const result: EnsureResult = { cloned: [], cached: [], failed: [] };\n const yamlPath = path.join(projectDir, \"skaile.yaml\");\n if (!existsSync(yamlPath)) return result;\n\n const quiet = opts.quiet ?? false;\n const sources = loadProjectSources(yamlPath, quiet);\n if (sources === null) return result;\n if (sources.length === 0) return result;\n\n for (const entry of sources) {\n hydrateSourceEntry(entry, quiet, result);\n }\n\n if (!quiet) {\n logHydrateSummary(result);\n }\n\n return result;\n}\n"]}
@@ -1,4 +0,0 @@
1
- export { KIND_COL_WIDTH, S, colorRef, fitWidth, formatRelativeTime, kindColor, kindColorPad, logErr, logInfo, logOk, logWarn } from './chunk-GYPA2Q7F.js';
2
- import './chunk-NSBPE2FW.js';
3
- //# sourceMappingURL=helpers-F4NZ66VD.js.map
4
- //# sourceMappingURL=helpers-F4NZ66VD.js.map
@@ -1,23 +0,0 @@
1
- export { openCatalogSource, openLibrary, openLibraryManager, resolveCatalogSource } from './chunk-WD2NRI3T.js';
2
- import './chunk-GYPA2Q7F.js';
3
- import './chunk-2D5YE3FL.js';
4
- import './chunk-UTHEIPEY.js';
5
- import './chunk-JXT46QFC.js';
6
- import './chunk-UKJMQZV6.js';
7
- import './chunk-R7FOF242.js';
8
- import './chunk-SKADPHAM.js';
9
- import './chunk-3KPNDTMR.js';
10
- import './chunk-ZAP2BDHG.js';
11
- import './chunk-W53D5Q52.js';
12
- import './chunk-NXC6IEL4.js';
13
- import './chunk-DZCK7GRW.js';
14
- import './chunk-BQCGFPHW.js';
15
- import './chunk-GEEW6SY2.js';
16
- import './chunk-F3HNW354.js';
17
- import './chunk-MENCWIHW.js';
18
- import './chunk-K5GBV4SA.js';
19
- import './chunk-JB35MVBN.js';
20
- import './chunk-CU5Z7GH3.js';
21
- import './chunk-NSBPE2FW.js';
22
- //# sourceMappingURL=open-library-ERKRGH4B.js.map
23
- //# sourceMappingURL=open-library-ERKRGH4B.js.map