@skaile/workspaces 0.52.0 → 1.0.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 (140) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/{asset-feeds-OEGJ6NOF.js → asset-feeds-677S5NX7.js} +7 -7
  3. package/dist/{asset-feeds-OEGJ6NOF.js.map → asset-feeds-677S5NX7.js.map} +1 -1
  4. package/dist/asset-manager/index.js +5 -5
  5. package/dist/asset-manager/installer.js +4 -4
  6. package/dist/{chunk-6K4RVXAM.js → chunk-43JDPQJ4.js} +3 -3
  7. package/dist/{chunk-6K4RVXAM.js.map → chunk-43JDPQJ4.js.map} +1 -1
  8. package/dist/{chunk-EOINYN5T.js → chunk-DW5MIJK3.js} +3 -3
  9. package/dist/{chunk-EOINYN5T.js.map → chunk-DW5MIJK3.js.map} +1 -1
  10. package/dist/{chunk-VE2UIJ7Y.js → chunk-EXNTTJGP.js} +3 -43
  11. package/dist/chunk-EXNTTJGP.js.map +1 -0
  12. package/dist/{chunk-7ZWLZ5H3.js → chunk-FLRHP3UC.js} +3 -3
  13. package/dist/{chunk-7ZWLZ5H3.js.map → chunk-FLRHP3UC.js.map} +1 -1
  14. package/dist/{chunk-MGB657EG.js → chunk-K5JIAHDV.js} +16 -7
  15. package/dist/chunk-K5JIAHDV.js.map +1 -0
  16. package/dist/{chunk-3IHBGDCG.js → chunk-KSISPZV3.js} +2 -2
  17. package/dist/{chunk-3IHBGDCG.js.map → chunk-KSISPZV3.js.map} +1 -1
  18. package/dist/{chunk-WD2NRI3T.js → chunk-PLQVAEM2.js} +2 -2
  19. package/dist/{chunk-WD2NRI3T.js.map → chunk-PLQVAEM2.js.map} +1 -1
  20. package/dist/{chunk-TCNYSHPM.js → chunk-SFVEHSCI.js} +4 -4
  21. package/dist/{chunk-TCNYSHPM.js.map → chunk-SFVEHSCI.js.map} +1 -1
  22. package/dist/{chunk-QLLFCQU5.js → chunk-WSQ5J7CE.js} +403 -1469
  23. package/dist/chunk-WSQ5J7CE.js.map +1 -0
  24. package/dist/{chunk-BXC5547R.js → chunk-XD7GYMAU.js} +3 -3
  25. package/dist/{chunk-BXC5547R.js.map → chunk-XD7GYMAU.js.map} +1 -1
  26. package/dist/cli/index.js +30 -32
  27. package/dist/cli/index.js.map +1 -1
  28. package/dist/connectors/config.js +4 -4
  29. package/dist/connectors/index.js +5 -7
  30. package/dist/connectors/src/config.d.ts +1 -74
  31. package/dist/connectors/src/config.d.ts.map +1 -1
  32. package/dist/connectors/src/connector-manager.d.ts +13 -137
  33. package/dist/connectors/src/connector-manager.d.ts.map +1 -1
  34. package/dist/connectors/src/connector-types.d.ts +3 -25
  35. package/dist/connectors/src/connector-types.d.ts.map +1 -1
  36. package/dist/connectors/src/fleet-utils.d.ts +2 -30
  37. package/dist/connectors/src/fleet-utils.d.ts.map +1 -1
  38. package/dist/connectors/src/fs-utils.d.ts +1 -2
  39. package/dist/connectors/src/fs-utils.d.ts.map +1 -1
  40. package/dist/connectors/src/index.d.ts +2 -12
  41. package/dist/connectors/src/index.d.ts.map +1 -1
  42. package/dist/connectors/src/watcher.d.ts +1 -5
  43. package/dist/connectors/src/watcher.d.ts.map +1 -1
  44. package/dist/core/index.js +3 -3
  45. package/dist/deploy/index.js +3 -3
  46. package/dist/{ensure-sources-GJOXWVWO.js → ensure-sources-OCMHK7LT.js} +5 -5
  47. package/dist/{ensure-sources-GJOXWVWO.js.map → ensure-sources-OCMHK7LT.js.map} +1 -1
  48. package/dist/factory-assets/connectors/deploy.js +5 -7
  49. package/dist/factory-assets/connectors/devserver.js +5 -7
  50. package/dist/factory-assets/connectors/flow/adapter.js +5 -7
  51. package/dist/factory-assets/connectors/flow/engine.js +3 -3
  52. package/dist/factory-assets/connectors/flow/run-flow.js +6 -8
  53. package/dist/factory-assets/connectors/flow.js +5 -7
  54. package/dist/factory-assets/connectors/git.js +5 -7
  55. package/dist/factory-assets/connectors/gmail.js +5 -7
  56. package/dist/factory-assets/connectors/googledrive/CONNECTOR.md +14 -128
  57. package/dist/factory-assets/connectors/googledrive/driver.d.ts +6 -13
  58. package/dist/factory-assets/connectors/googledrive/driver.d.ts.map +1 -1
  59. package/dist/factory-assets/connectors/googledrive.js +5 -7
  60. package/dist/factory-assets/connectors/local.js +5 -7
  61. package/dist/factory-assets/connectors/mattermost.js +5 -7
  62. package/dist/factory-assets/connectors/memory.js +5 -7
  63. package/dist/factory-assets/connectors/minio.js +5 -7
  64. package/dist/factory-assets/connectors/postgres.js +5 -7
  65. package/dist/factory-assets/connectors/s3.js +5 -7
  66. package/dist/factory-assets/connectors/sharepoint/CONNECTOR.md +13 -159
  67. package/dist/factory-assets/connectors/sharepoint/driver.d.ts +6 -12
  68. package/dist/factory-assets/connectors/sharepoint/driver.d.ts.map +1 -1
  69. package/dist/factory-assets/connectors/sharepoint.js +5 -7
  70. package/dist/factory-assets/connectors/sqlite.js +5 -7
  71. package/dist/factory-assets/connectors/static-server.js +5 -7
  72. package/dist/factory-assets/connectors/tunnel.js +5 -7
  73. package/dist/factory-assets/connectors/webdav/CONNECTOR.md +13 -118
  74. package/dist/factory-assets/connectors/webdav/driver.d.ts +6 -15
  75. package/dist/factory-assets/connectors/webdav/driver.d.ts.map +1 -1
  76. package/dist/factory-assets/connectors/webdav.js +5 -7
  77. package/dist/factory-assets/connectors/xstate-store.js +5 -7
  78. package/dist/factory-assets/connectors/xstate.js +5 -7
  79. package/dist/{flows-AGPIE6JM.js → flows-36PZESON.js} +4 -4
  80. package/dist/{flows-AGPIE6JM.js.map → flows-36PZESON.js.map} +1 -1
  81. package/dist/library/index.js +4 -4
  82. package/dist/library/install.js +3 -3
  83. package/dist/{open-library-ERKRGH4B.js → open-library-WRFYABFP.js} +7 -7
  84. package/dist/{open-library-ERKRGH4B.js.map → open-library-WRFYABFP.js.map} +1 -1
  85. package/dist/{paths-D6RUQ522.js → paths-EUNVMONC.js} +5 -5
  86. package/dist/{paths-D6RUQ522.js.map → paths-EUNVMONC.js.map} +1 -1
  87. package/dist/{plugin-store-SGNJTBYS.js → plugin-store-35KIMX6W.js} +5 -5
  88. package/dist/{plugin-store-SGNJTBYS.js.map → plugin-store-35KIMX6W.js.map} +1 -1
  89. package/dist/runner/index.js +7 -9
  90. package/dist/runner/src/serve.d.ts +6 -4
  91. package/dist/runner/src/serve.d.ts.map +1 -1
  92. package/dist/sdk/asset-manager.js +5 -5
  93. package/dist/sdk/core.js +3 -3
  94. package/dist/sdk/flow.js +3 -3
  95. package/dist/sdk/index.js +7 -9
  96. package/dist/sdk/index.js.map +1 -1
  97. package/dist/sdk/runner.js +7 -9
  98. package/dist/{setup-IV2JFW3T.js → setup-HM6HATAC.js} +5 -5
  99. package/dist/{setup-IV2JFW3T.js.map → setup-HM6HATAC.js.map} +1 -1
  100. package/dist/{source-FGOMQMZT.js → source-EZ5Y3CKP.js} +8 -8
  101. package/dist/{source-FGOMQMZT.js.map → source-EZ5Y3CKP.js.map} +1 -1
  102. package/dist/{store-client-GJT2XQ5Z.js → store-client-BUUF7BPK.js} +5 -5
  103. package/dist/{store-client-GJT2XQ5Z.js.map → store-client-BUUF7BPK.js.map} +1 -1
  104. package/dist/tui/index.js +7 -9
  105. package/dist/tui/index.js.map +1 -1
  106. package/dist/workspace-plugin/adapters/mcp.js +3 -3
  107. package/dist/workspace-plugin/adapters/omp.js +3 -3
  108. package/dist/workspace-plugin/index.js +1 -1
  109. package/package.json +1 -13
  110. package/dist/chunk-MGB657EG.js.map +0 -1
  111. package/dist/chunk-OVRSNIKJ.js +0 -72
  112. package/dist/chunk-OVRSNIKJ.js.map +0 -1
  113. package/dist/chunk-QLLFCQU5.js.map +0 -1
  114. package/dist/chunk-RAIRWFAN.js +0 -843
  115. package/dist/chunk-RAIRWFAN.js.map +0 -1
  116. package/dist/chunk-VE2UIJ7Y.js.map +0 -1
  117. package/dist/connectors/rclone-config.d.ts +0 -2
  118. package/dist/connectors/rclone-config.js +0 -4
  119. package/dist/connectors/rclone-config.js.map +0 -1
  120. package/dist/connectors/rclone.d.ts +0 -2
  121. package/dist/connectors/rclone.js +0 -5
  122. package/dist/connectors/rclone.js.map +0 -1
  123. package/dist/connectors/src/fleet-health-gate.d.ts +0 -105
  124. package/dist/connectors/src/fleet-health-gate.d.ts.map +0 -1
  125. package/dist/connectors/src/mount-placeholder.d.ts +0 -131
  126. package/dist/connectors/src/mount-placeholder.d.ts.map +0 -1
  127. package/dist/connectors/src/rclone-config/googledrive.d.ts +0 -59
  128. package/dist/connectors/src/rclone-config/googledrive.d.ts.map +0 -1
  129. package/dist/connectors/src/rclone-config/index.d.ts +0 -9
  130. package/dist/connectors/src/rclone-config/index.d.ts.map +0 -1
  131. package/dist/connectors/src/rclone-config/onedrive.d.ts +0 -48
  132. package/dist/connectors/src/rclone-config/onedrive.d.ts.map +0 -1
  133. package/dist/connectors/src/rclone-config/sanitize.d.ts +0 -9
  134. package/dist/connectors/src/rclone-config/sanitize.d.ts.map +0 -1
  135. package/dist/connectors/src/rclone-config/webdav.d.ts +0 -50
  136. package/dist/connectors/src/rclone-config/webdav.d.ts.map +0 -1
  137. package/dist/connectors/src/rclone-process-manager.d.ts +0 -316
  138. package/dist/connectors/src/rclone-process-manager.d.ts.map +0 -1
  139. package/dist/connectors/src/rclone-token-refresh.d.ts +0 -84
  140. package/dist/connectors/src/rclone-token-refresh.d.ts.map +0 -1
@@ -1,21 +1,19 @@
1
- export { MinIOConnector, createConnector10 as createConnector } from '../../chunk-QLLFCQU5.js';
2
- import '../../chunk-OVRSNIKJ.js';
3
- import '../../chunk-VE2UIJ7Y.js';
4
- import '../../chunk-RAIRWFAN.js';
1
+ export { MinIOConnector, createConnector10 as createConnector } from '../../chunk-WSQ5J7CE.js';
2
+ import '../../chunk-EXNTTJGP.js';
5
3
  import '../../chunk-6E6PKKAD.js';
6
4
  import '../../chunk-SKADPHAM.js';
7
5
  import '../../chunk-DEYYRFQU.js';
8
6
  import '../../chunk-IFGTRL2I.js';
9
7
  import '../../chunk-3KPNDTMR.js';
10
- import '../../chunk-ZAP2BDHG.js';
11
8
  import '../../chunk-W53D5Q52.js';
9
+ import '../../chunk-F3HNW354.js';
10
+ import '../../chunk-K5GBV4SA.js';
11
+ import '../../chunk-ZAP2BDHG.js';
12
12
  import '../../chunk-NXC6IEL4.js';
13
13
  import '../../chunk-DZCK7GRW.js';
14
14
  import '../../chunk-BQCGFPHW.js';
15
15
  import '../../chunk-GEEW6SY2.js';
16
- import '../../chunk-F3HNW354.js';
17
16
  import '../../chunk-MENCWIHW.js';
18
- import '../../chunk-K5GBV4SA.js';
19
17
  import '../../chunk-JB35MVBN.js';
20
18
  import '../../chunk-NSBPE2FW.js';
21
19
  //# sourceMappingURL=minio.js.map
@@ -1,21 +1,19 @@
1
- export { PostgresConnector, createConnector11 as createConnector } from '../../chunk-QLLFCQU5.js';
2
- import '../../chunk-OVRSNIKJ.js';
3
- import '../../chunk-VE2UIJ7Y.js';
4
- import '../../chunk-RAIRWFAN.js';
1
+ export { PostgresConnector, createConnector11 as createConnector } from '../../chunk-WSQ5J7CE.js';
2
+ import '../../chunk-EXNTTJGP.js';
5
3
  import '../../chunk-6E6PKKAD.js';
6
4
  import '../../chunk-SKADPHAM.js';
7
5
  import '../../chunk-DEYYRFQU.js';
8
6
  import '../../chunk-IFGTRL2I.js';
9
7
  import '../../chunk-3KPNDTMR.js';
10
- import '../../chunk-ZAP2BDHG.js';
11
8
  import '../../chunk-W53D5Q52.js';
9
+ import '../../chunk-F3HNW354.js';
10
+ import '../../chunk-K5GBV4SA.js';
11
+ import '../../chunk-ZAP2BDHG.js';
12
12
  import '../../chunk-NXC6IEL4.js';
13
13
  import '../../chunk-DZCK7GRW.js';
14
14
  import '../../chunk-BQCGFPHW.js';
15
15
  import '../../chunk-GEEW6SY2.js';
16
- import '../../chunk-F3HNW354.js';
17
16
  import '../../chunk-MENCWIHW.js';
18
- import '../../chunk-K5GBV4SA.js';
19
17
  import '../../chunk-JB35MVBN.js';
20
18
  import '../../chunk-NSBPE2FW.js';
21
19
  //# sourceMappingURL=postgres.js.map
@@ -1,21 +1,19 @@
1
- export { S3Connector, createConnector12 as createConnector } from '../../chunk-QLLFCQU5.js';
2
- import '../../chunk-OVRSNIKJ.js';
3
- import '../../chunk-VE2UIJ7Y.js';
4
- import '../../chunk-RAIRWFAN.js';
1
+ export { S3Connector, createConnector12 as createConnector } from '../../chunk-WSQ5J7CE.js';
2
+ import '../../chunk-EXNTTJGP.js';
5
3
  import '../../chunk-6E6PKKAD.js';
6
4
  import '../../chunk-SKADPHAM.js';
7
5
  import '../../chunk-DEYYRFQU.js';
8
6
  import '../../chunk-IFGTRL2I.js';
9
7
  import '../../chunk-3KPNDTMR.js';
10
- import '../../chunk-ZAP2BDHG.js';
11
8
  import '../../chunk-W53D5Q52.js';
9
+ import '../../chunk-F3HNW354.js';
10
+ import '../../chunk-K5GBV4SA.js';
11
+ import '../../chunk-ZAP2BDHG.js';
12
12
  import '../../chunk-NXC6IEL4.js';
13
13
  import '../../chunk-DZCK7GRW.js';
14
14
  import '../../chunk-BQCGFPHW.js';
15
15
  import '../../chunk-GEEW6SY2.js';
16
- import '../../chunk-F3HNW354.js';
17
16
  import '../../chunk-MENCWIHW.js';
18
- import '../../chunk-K5GBV4SA.js';
19
17
  import '../../chunk-JB35MVBN.js';
20
18
  import '../../chunk-NSBPE2FW.js';
21
19
  //# sourceMappingURL=s3.js.map
@@ -1,181 +1,35 @@
1
1
  ---
2
2
  name: sharepoint
3
- description: "SharePoint/OneDrive connector via rclone FUSE."
4
- version: "0.2.0"
3
+ description: "SharePoint/OneDrive connector for host fleet-managed bind mounts."
4
+ version: "0.3.0"
5
5
  entry: ./driver.ts
6
- fields:
7
- - key: auth
8
- label: "Bearer token or JSON credential bundle"
9
- required: true
10
- sensitive: true
11
- - key: options.driveId
12
- label: "Microsoft Graph drive ID"
13
- required: true
14
- sensitive: false
15
- - key: options.folderPath
16
- label: "Path to mount within the drive (e.g. /Shared Documents/project)"
17
- required: true
18
- sensitive: false
19
- - key: options.folderId
20
- label: "Graph folder item ID (display only — rclone uses folderPath)"
21
- required: false
22
- sensitive: false
23
- - key: options.basePath
24
- label: "Subfolder appended under folderPath"
25
- required: false
26
- sensitive: false
27
- - key: options.cacheMaxSize
28
- label: "rclone VFS cache size cap (e.g. '5G'). Default: 5G"
29
- required: false
30
- sensitive: false
31
- - key: options.cacheMaxAge
32
- label: "rclone VFS cache age cap (e.g. '168h'). Default: 168h"
33
- required: false
34
- sensitive: false
35
- - key: options.vfsWriteBack
36
- label: "rclone VFS write-back delay before upload (e.g. '30s', '1m'). Default: 30s"
37
- required: false
38
- sensitive: false
39
- - key: options.ignoreSizeCheck
40
- label: "Skip rclone post-transfer size/checksum verification (SharePoint byte-mutation workaround). Default: false"
41
- required: false
42
- sensitive: false
6
+ fields: []
43
7
  keywords:
44
8
  - sharepoint
45
9
  - onedrive
46
10
  - microsoft
47
11
  - graph
48
12
  - office365
49
- - rclone
13
+ - fleet
50
14
  ---
51
15
 
52
16
  ## SharePoint Connector
53
17
 
54
- Exposes a SharePoint or OneDrive folder via rclone's FUSE backend. The driver
55
- delegates the entire data plane (enumeration, download, upload, change
56
- detection, cache management) to an `rclone mount` subprocess managed by
57
- `RcloneProcessManager`.
18
+ Exposes a SharePoint or OneDrive folder that has already been mounted by the
19
+ host fleet and bind-mounted into the agent container.
58
20
 
59
- ### Configuration
21
+ Package-side SharePoint connectors do not spawn or configure a cloud data plane.
22
+ At connect time the connector id must be listed in `SKAILE_FLEET_MANAGED_MOUNTS`;
23
+ otherwise connect fails with a host fleet-managed mount requirement.
60
24
 
61
25
  ```yaml
62
26
  connectors:
63
27
  - id: project-docs
64
28
  driver: sharepoint
65
29
  access: read-write
66
- auth: env:SHAREPOINT_TOKEN
67
- mount:
68
- source: /Shared Documents/project
69
- options:
70
- driveId: b!abc123...
71
- folderPath: /Shared Documents/project
72
- basePath: subfolder/optional
73
- cacheMaxSize: 5G
74
- cacheMaxAge: 168h
75
- vfsWriteBack: 30s
76
- ignoreSizeCheck: false # see "Server-side byte mutation" below
77
30
  ```
78
31
 
79
- `vfsWriteBack` controls how long a dirty file sits in the VFS cache before
80
- rclone starts uploading it (rclone's `--vfs-write-back`). The default was raised
81
- from rclone's old 5s to **30s** to avoid an active-write race: when the agent
82
- rewrites a file faster than the write-back delay (e.g. a build script
83
- regenerating an HTML report every few seconds), a short delay lets an upload
84
- start mid-write, the source grows during transfer, and rclone aborts with
85
- `corrupted on transfer: sizes differ` and retries indefinitely. Raise it further
86
- for workloads that rewrite large files in tight loops.
87
-
88
- `folderPath` is required: rclone's onedrive backend addresses content by path,
89
- not by Graph item ID. Provide the full path within the drive (the platform
90
- typically derives this from the picker selection).
91
-
92
- ### Authentication
93
-
94
- The `auth` field can be:
95
- - A plain Bearer token string (rclone has no refresh path; on 401 the next
96
- session start re-provisions a fresh token from the platform DB).
97
- - A JSON object with OAuth refresh support — emitted into the rclone config so
98
- rclone can refresh autonomously:
99
- ```json
100
- {
101
- "accessToken": "...",
102
- "refreshToken": "...",
103
- "expiresAt": 1234567890,
104
- "tenantId": "...",
105
- "clientId": "...",
106
- "clientSecret": "..."
107
- }
108
- ```
109
-
110
- ### Implementation: rclone FUSE
111
-
112
- - **mount**: Renders an `[skaile-<id>]` rclone config (onedrive backend, drive
113
- ID + OAuth token JSON), spawns `rclone mount` with VFS caching, returns once
114
- the FUSE mountpoint is confirmed in `/proc/self/mounts`.
115
- - **VFS cache mode**: `read-only` mounts use `minimal`; `read-write` uses
116
- `full` so writes are buffered locally before upload.
117
- - **Size/checksum verification**: on by default. `options.ignoreSizeCheck:
118
- true` appends `--ignore-size --ignore-checksum` — see "Server-side byte
119
- mutation" below.
120
- - **Cache directory**: `/var/cache/skaile/<mountId>` (the parent
121
- `/var/cache/skaile` is bind-mounted from the host per session). The cache
122
- root is overridable via the `SKAILE_RCLONE_CACHE_BASE` env var.
123
- - **write-back**: `--vfs-write-back` defaults to 30s (configurable via
124
- `options.vfsWriteBack`) so a rapidly-rewritten file settles before rclone
125
- uploads it.
126
- - **sync**: Calls `RcloneProcessManager.flush`, which first waits for the VFS
127
- cache dir to go quiescent (no write within a stability window, bounded by a
128
- timeout) so close/hibernate doesn't snapshot a half-written file, then POSTs
129
- `/vfs/refresh` and waits for the in-use counter to reach zero.
130
- - **stuck-upload signal**: if the same object fails to upload 3 times in a row,
131
- the connector emits an error-level log (`event: sync_status`, `phase: error`)
132
- through the `sharepoint+rclone` subkind so a permanently-failing upload — one
133
- that would otherwise retry silently every few minutes forever — is surfaced.
134
- - **unmount**: `RcloneProcessManager.stop` flushes, sends SIGTERM, falls back
135
- to SIGKILL + `fusermount3 -u` after a 30s grace.
136
- - **onHibernate / onSessionClose**: Always flush. Cheap and the right default;
137
- no opt-out toggles.
138
- - **Logs**: rclone subprocess JSON log lines are routed through a child
139
- logger with subkind `sharepoint+rclone`, alongside the driver's own
140
- `sharepoint` entries — both visible via `skaile session logs --kind mount`.
141
-
142
- ### Server-side byte mutation (`options.ignoreSizeCheck`)
143
-
144
- SharePoint Online normalises some text uploads server-side (observed: `*.html`
145
- having `LF` rewritten to `CRLF`), so the stored object ends up a different byte
146
- size — and a different checksum — than the local source. rclone's
147
- post-transfer verification correctly flags this as `corrupted on transfer:
148
- sizes differ`, deletes the just-uploaded object ("Removing failed copy"), and
149
- retries indefinitely. The affected file therefore **never durably lands on the
150
- remote**, so other sessions sharing the same project never see it. Sibling
151
- `*.md` / `*.mjs` uploads are unaffected because they aren't normalised.
152
-
153
- Setting `options.ignoreSizeCheck: true` appends `--ignore-size
154
- --ignore-checksum` to this mount's `rclone mount` invocation, so rclone accepts
155
- the upload despite the size/hash drift and the file lands. **This trades
156
- integrity verification for sync-ability:** a genuinely truncated or corrupted
157
- upload would no longer be caught for this mount. Leave it `false` unless you
158
- have confirmed the remote is mutating bytes benignly (e.g. newline
159
- normalisation) and the alternative is permanently stranded files.
160
-
161
- - **Scope:** SharePoint connector only — it is not a global rclone flag and is
162
- not exposed by the other rclone-backed connectors.
163
- - **Off by default:** when unset or `false`, rclone verifies every upload as
164
- before.
165
-
166
- ### Fleet-managed mode (Phase 7B)
167
-
168
- When the `SKAILE_FLEET_MANAGED_MOUNTS` env var lists this mount's id, the
169
- host-side `RcloneFleetService` (in the platform backend) has already
170
- spawned a shared `rclone mount` process and bind-mounted its FUSE
171
- mountpoint into the container at the driver's `targetDir`. The driver
172
- short-circuits its own rclone spawn:
173
-
174
- - `mount()` verifies the bind mount is live (`stat` + `readdir` poll up
175
- to 3s), then returns a no-op handle with `state.fleetManaged = true`.
176
- - `unmount()`, `sync()`, `onHibernate()`, `onSessionClose()` all return
177
- early — the fleet owns the rclone process and is responsible for
178
- flushing and teardown.
179
-
180
- The env var is comma-separated; an empty / unset value preserves the
181
- per-session behaviour described above.
32
+ The host is responsible for authentication, remote configuration, cache
33
+ lifecycle, upload flushing, and health handling. The package driver verifies the
34
+ bind is readable, returns a handle with `mountPath`, and treats sync/hibernate/
35
+ close as no-op success.
@@ -1,27 +1,21 @@
1
1
  /**
2
- * SharePointConnector — SharePoint/OneDrive filesystem-face connector backed by rclone FUSE.
2
+ * SharePointConnector — host fleet-managed SharePoint/OneDrive filesystem connector.
3
3
  *
4
- * The whole data plane (enumeration, download, upload, change detection,
5
- * cache eviction) is delegated to an `rclone mount` subprocess managed by
6
- * {@link RcloneProcessManager}. This connector only parses the declaration,
7
- * renders the rclone config, hands it off, and forwards lifecycle hooks.
4
+ * Cloud mounts are prepared outside the agent container and exposed through a
5
+ * bind mount. The package-side driver only verifies the bind and returns a
6
+ * no-op lifecycle handle.
8
7
  */
9
8
  import type { ConnectContext, ConnectorDeclaration, ConnectorHandle, FilesystemFace } from "@skaile/workspaces/connectors";
10
9
  import { AbstractConnector } from "@skaile/workspaces/connectors";
11
10
  /**
12
- * Filesystem-face connector for SharePoint and OneDrive — delegates the data plane to an
13
- * `rclone mount` subprocess via `RcloneProcessManager` using the OneDrive backend.
14
- * Supports OAuth2 access tokens with optional refresh, and fleet-managed mode via
15
- * `SKAILE_FLEET_MANAGED_MOUNTS`.
11
+ * Filesystem-face connector for host fleet-managed SharePoint and OneDrive mounts.
16
12
  * @docLink packages/factory-assets/concepts#sharepoint-connector
17
13
  */
18
14
  export declare class SharePointConnector extends AbstractConnector {
19
15
  readonly name = "sharepoint";
20
- private rclone;
21
16
  readonly filesystem: FilesystemFace;
22
17
  connect(declaration: ConnectorDeclaration, ctx: ConnectContext): Promise<ConnectorHandle>;
23
- disconnect(handle: ConnectorHandle): Promise<void>;
24
- private _sync;
18
+ disconnect(_handle: ConnectorHandle): Promise<void>;
25
19
  onHibernate(handle: ConnectorHandle): Promise<string | undefined>;
26
20
  onSessionClose(handle: ConnectorHandle): Promise<string | undefined>;
27
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../../../factory-assets/connectors/sharepoint/driver.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,cAAc,EAIf,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,iBAAiB,EASlB,MAAM,+BAA+B,CAAC;AAmCvC;;;;;;GAMG;AACH,qBAAa,mBAAoB,SAAQ,iBAAiB;IACxD,QAAQ,CAAC,IAAI,gBAAgB;IAE7B,OAAO,CAAC,MAAM,CAA8B;IAE5C,QAAQ,CAAC,UAAU,EAAE,cAAc,CAKjC;IAEI,OAAO,CAAC,WAAW,EAAE,oBAAoB,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAwJzF,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;YAO1C,KAAK;IAwBJ,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAOjE,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CAMpF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,mBAAmB,CAErD"}
1
+ {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../../../factory-assets/connectors/sharepoint/driver.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,cAAc,EAGf,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,iBAAiB,EAGlB,MAAM,+BAA+B,CAAC;AASvC;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,iBAAiB;IACxD,QAAQ,CAAC,IAAI,gBAAgB;IAE7B,QAAQ,CAAC,UAAU,EAAE,cAAc,CAGjC;IAEI,OAAO,CAAC,WAAW,EAAE,oBAAoB,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAqBzF,UAAU,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAE1C,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAKjE,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CAIpF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,mBAAmB,CAErD"}
@@ -1,21 +1,19 @@
1
- export { SharePointConnector, createConnector13 as createConnector } from '../../chunk-QLLFCQU5.js';
2
- import '../../chunk-OVRSNIKJ.js';
3
- import '../../chunk-VE2UIJ7Y.js';
4
- import '../../chunk-RAIRWFAN.js';
1
+ export { SharePointConnector, createConnector13 as createConnector } from '../../chunk-WSQ5J7CE.js';
2
+ import '../../chunk-EXNTTJGP.js';
5
3
  import '../../chunk-6E6PKKAD.js';
6
4
  import '../../chunk-SKADPHAM.js';
7
5
  import '../../chunk-DEYYRFQU.js';
8
6
  import '../../chunk-IFGTRL2I.js';
9
7
  import '../../chunk-3KPNDTMR.js';
10
- import '../../chunk-ZAP2BDHG.js';
11
8
  import '../../chunk-W53D5Q52.js';
9
+ import '../../chunk-F3HNW354.js';
10
+ import '../../chunk-K5GBV4SA.js';
11
+ import '../../chunk-ZAP2BDHG.js';
12
12
  import '../../chunk-NXC6IEL4.js';
13
13
  import '../../chunk-DZCK7GRW.js';
14
14
  import '../../chunk-BQCGFPHW.js';
15
15
  import '../../chunk-GEEW6SY2.js';
16
- import '../../chunk-F3HNW354.js';
17
16
  import '../../chunk-MENCWIHW.js';
18
- import '../../chunk-K5GBV4SA.js';
19
17
  import '../../chunk-JB35MVBN.js';
20
18
  import '../../chunk-NSBPE2FW.js';
21
19
  //# sourceMappingURL=sharepoint.js.map
@@ -1,21 +1,19 @@
1
- export { SQLiteConnector, createConnector14 as createConnector } from '../../chunk-QLLFCQU5.js';
2
- import '../../chunk-OVRSNIKJ.js';
3
- import '../../chunk-VE2UIJ7Y.js';
4
- import '../../chunk-RAIRWFAN.js';
1
+ export { SQLiteConnector, createConnector14 as createConnector } from '../../chunk-WSQ5J7CE.js';
2
+ import '../../chunk-EXNTTJGP.js';
5
3
  import '../../chunk-6E6PKKAD.js';
6
4
  import '../../chunk-SKADPHAM.js';
7
5
  import '../../chunk-DEYYRFQU.js';
8
6
  import '../../chunk-IFGTRL2I.js';
9
7
  import '../../chunk-3KPNDTMR.js';
10
- import '../../chunk-ZAP2BDHG.js';
11
8
  import '../../chunk-W53D5Q52.js';
9
+ import '../../chunk-F3HNW354.js';
10
+ import '../../chunk-K5GBV4SA.js';
11
+ import '../../chunk-ZAP2BDHG.js';
12
12
  import '../../chunk-NXC6IEL4.js';
13
13
  import '../../chunk-DZCK7GRW.js';
14
14
  import '../../chunk-BQCGFPHW.js';
15
15
  import '../../chunk-GEEW6SY2.js';
16
- import '../../chunk-F3HNW354.js';
17
16
  import '../../chunk-MENCWIHW.js';
18
- import '../../chunk-K5GBV4SA.js';
19
17
  import '../../chunk-JB35MVBN.js';
20
18
  import '../../chunk-NSBPE2FW.js';
21
19
  //# sourceMappingURL=sqlite.js.map
@@ -1,21 +1,19 @@
1
- export { StaticServerConnector, createConnector15 as createConnector } from '../../chunk-QLLFCQU5.js';
2
- import '../../chunk-OVRSNIKJ.js';
3
- import '../../chunk-VE2UIJ7Y.js';
4
- import '../../chunk-RAIRWFAN.js';
1
+ export { StaticServerConnector, createConnector15 as createConnector } from '../../chunk-WSQ5J7CE.js';
2
+ import '../../chunk-EXNTTJGP.js';
5
3
  import '../../chunk-6E6PKKAD.js';
6
4
  import '../../chunk-SKADPHAM.js';
7
5
  import '../../chunk-DEYYRFQU.js';
8
6
  import '../../chunk-IFGTRL2I.js';
9
7
  import '../../chunk-3KPNDTMR.js';
10
- import '../../chunk-ZAP2BDHG.js';
11
8
  import '../../chunk-W53D5Q52.js';
9
+ import '../../chunk-F3HNW354.js';
10
+ import '../../chunk-K5GBV4SA.js';
11
+ import '../../chunk-ZAP2BDHG.js';
12
12
  import '../../chunk-NXC6IEL4.js';
13
13
  import '../../chunk-DZCK7GRW.js';
14
14
  import '../../chunk-BQCGFPHW.js';
15
15
  import '../../chunk-GEEW6SY2.js';
16
- import '../../chunk-F3HNW354.js';
17
16
  import '../../chunk-MENCWIHW.js';
18
- import '../../chunk-K5GBV4SA.js';
19
17
  import '../../chunk-JB35MVBN.js';
20
18
  import '../../chunk-NSBPE2FW.js';
21
19
  //# sourceMappingURL=static-server.js.map
@@ -1,21 +1,19 @@
1
- export { TunnelConnector, createConnector16 as createConnector } from '../../chunk-QLLFCQU5.js';
2
- import '../../chunk-OVRSNIKJ.js';
3
- import '../../chunk-VE2UIJ7Y.js';
4
- import '../../chunk-RAIRWFAN.js';
1
+ export { TunnelConnector, createConnector16 as createConnector } from '../../chunk-WSQ5J7CE.js';
2
+ import '../../chunk-EXNTTJGP.js';
5
3
  import '../../chunk-6E6PKKAD.js';
6
4
  import '../../chunk-SKADPHAM.js';
7
5
  import '../../chunk-DEYYRFQU.js';
8
6
  import '../../chunk-IFGTRL2I.js';
9
7
  import '../../chunk-3KPNDTMR.js';
10
- import '../../chunk-ZAP2BDHG.js';
11
8
  import '../../chunk-W53D5Q52.js';
9
+ import '../../chunk-F3HNW354.js';
10
+ import '../../chunk-K5GBV4SA.js';
11
+ import '../../chunk-ZAP2BDHG.js';
12
12
  import '../../chunk-NXC6IEL4.js';
13
13
  import '../../chunk-DZCK7GRW.js';
14
14
  import '../../chunk-BQCGFPHW.js';
15
15
  import '../../chunk-GEEW6SY2.js';
16
- import '../../chunk-F3HNW354.js';
17
16
  import '../../chunk-MENCWIHW.js';
18
- import '../../chunk-K5GBV4SA.js';
19
17
  import '../../chunk-JB35MVBN.js';
20
18
  import '../../chunk-NSBPE2FW.js';
21
19
  //# sourceMappingURL=tunnel.js.map
@@ -1,139 +1,34 @@
1
1
  ---
2
2
  name: webdav
3
- description: "WebDAV server connector via rclone FUSE."
4
- version: "0.3.0"
3
+ description: "WebDAV connector for host fleet-managed bind mounts."
4
+ version: "0.4.0"
5
5
  entry: ./driver.ts
6
- fields:
7
- - key: source
8
- label: "WebDAV server URL"
9
- required: true
10
- sensitive: false
11
- - key: auth
12
- label: "Credentials (username:password or Bearer token)"
13
- required: false
14
- sensitive: true
15
- - key: options.vendor
16
- label: "WebDAV vendor (nextcloud | owncloud | sharepoint | fastmail | other). Default: other"
17
- required: false
18
- sensitive: false
19
- - key: options.basePath
20
- label: "Subfolder appended under the WebDAV URL"
21
- required: false
22
- sensitive: false
23
- - key: options.cacheMaxSize
24
- label: "rclone VFS cache size cap (e.g. '5G'). Default: 5G"
25
- required: false
26
- sensitive: false
27
- - key: options.cacheMaxAge
28
- label: "rclone VFS cache age cap (e.g. '168h'). Default: 168h"
29
- required: false
30
- sensitive: false
31
- - key: options.vfsWriteBack
32
- label: "rclone VFS write-back delay before upload (e.g. '30s', '1m'). Default: 30s"
33
- required: false
34
- sensitive: false
6
+ fields: []
35
7
  keywords:
36
8
  - webdav
37
9
  - nextcloud
38
10
  - owncloud
39
11
  - fastmail
40
- - rclone
12
+ - fleet
41
13
  ---
42
14
 
43
15
  ## WebDAV Connector
44
16
 
45
- Exposes a WebDAV server directory via rclone's FUSE backend. The driver
46
- delegates the entire data plane (enumeration, download, upload, change
47
- detection, cache management) to an `rclone mount` subprocess managed by
48
- `RcloneProcessManager`.
17
+ Exposes a WebDAV-backed folder that has already been mounted by the host fleet
18
+ and bind-mounted into the agent container.
49
19
 
50
- ### Configuration
20
+ Package-side WebDAV connectors do not spawn or configure a cloud data plane. At
21
+ connect time the connector id must be listed in `SKAILE_FLEET_MANAGED_MOUNTS`;
22
+ otherwise connect fails with a host fleet-managed mount requirement.
51
23
 
52
24
  ```yaml
53
25
  connectors:
54
26
  - id: shared-docs
55
27
  driver: webdav
56
28
  access: read-write
57
- auth: env:WEBDAV_CREDENTIALS
58
- mount:
59
- source: https://cloud.example.com/remote.php/dav/files/user
60
- options:
61
- vendor: nextcloud
62
- basePath: Documents/project
63
- cacheMaxSize: 5G
64
- cacheMaxAge: 168h
65
- vfsWriteBack: 30s
66
29
  ```
67
30
 
68
- `vfsWriteBack` controls rclone's `--vfs-write-back` how long a dirty file
69
- sits before upload. Default raised from 5s to 30s so a rapidly-rewritten file
70
- settles before transfer instead of aborting with `sizes differ`.
71
-
72
- `mount.source` is the WebDAV endpoint URL. `basePath` is an optional subfolder
73
- appended to that URL when constructing the rclone remote.
74
-
75
- ### NextCloud / ownCloud
76
-
77
- NextCloud and ownCloud expose a standard WebDAV endpoint at
78
- `https://<host>/remote.php/dav/files/<username>`. Set `vendor: nextcloud`
79
- (or `owncloud`) so rclone uses the right quirks.
80
-
81
- ```yaml
82
- connectors:
83
- - id: nextcloud-docs
84
- driver: webdav
85
- access: read-write
86
- auth: env:NEXTCLOUD_CREDENTIALS
87
- mount:
88
- source: https://nextcloud.example.com/remote.php/dav/files/alice
89
- options:
90
- vendor: nextcloud
91
- basePath: Documents/project
92
- ```
93
-
94
- ### Authentication
95
-
96
- The `auth` field resolves to one of:
97
- - `username:password` -- Basic/Digest authentication. The first colon
98
- separates the two parts; passwords containing colons are preserved.
99
- - A bare token string -- Bearer token authentication (OAuth WebDAV).
100
- - Empty / undefined -- anonymous WebDAV (no auth header).
101
-
102
- Plaintext passwords are passed through `rclone obscure` before being written
103
- into the rclone config — rclone's `pass` field is not plaintext.
104
-
105
- ### Implementation: rclone FUSE
106
-
107
- - **mount**: Renders an `[skaile-<id>]` rclone config (webdav backend, URL +
108
- vendor + obscured credentials), spawns `rclone mount` with VFS caching,
109
- returns once the FUSE mountpoint is confirmed in `/proc/self/mounts`.
110
- - **VFS cache mode**: `read-only` mounts use `minimal`; `read-write` uses
111
- `full` so writes are buffered locally before upload.
112
- - **Cache directory**: `/var/cache/skaile/<mountId>` (the parent
113
- `/var/cache/skaile` is bind-mounted from the host per session).
114
- - **sync**: Calls `RcloneProcessManager.flush` (POSTs `/vfs/refresh` then waits
115
- for the in-use counter to reach zero).
116
- - **unmount**: `RcloneProcessManager.stop` flushes, sends SIGTERM, falls back
117
- to SIGKILL + `fusermount3 -u` after a 30s grace.
118
- - **onHibernate / onSessionClose**: Always flush. Cheap and the right default;
119
- no opt-out toggles.
120
- - **Logs**: rclone subprocess JSON log lines are routed through a child
121
- logger with subkind `webdav+rclone`, alongside the driver's own
122
- `webdav` entries — both visible via `skaile session logs --kind mount`.
123
-
124
- ### Fleet-managed mode (Phase 7B)
125
-
126
- When the `SKAILE_FLEET_MANAGED_MOUNTS` env var lists this mount's id, the
127
- host-side `RcloneFleetService` (in the platform backend) has already
128
- spawned a shared `rclone mount` process and bind-mounted its FUSE
129
- mountpoint into the container at the driver's `targetDir`. The driver
130
- short-circuits its own rclone spawn:
131
-
132
- - `mount()` verifies the bind mount is live (`stat` + `readdir` poll up
133
- to 3s), then returns a no-op handle with `state.fleetManaged = true`.
134
- - `unmount()`, `sync()`, `onHibernate()`, `onSessionClose()` all return
135
- early — the fleet owns the rclone process and is responsible for
136
- flushing and teardown.
137
-
138
- The env var is comma-separated; an empty / unset value preserves the
139
- per-session behaviour described above.
31
+ The host is responsible for authentication, remote configuration, cache
32
+ lifecycle, upload flushing, and health handling. The package driver verifies the
33
+ bind is readable, returns a handle with `mountPath`, and treats sync/hibernate/
34
+ close as no-op success.
@@ -1,30 +1,21 @@
1
1
  /**
2
- * WebDAVConnector -- WebDAV server filesystem-face connector backed by rclone FUSE.
2
+ * WebDAVConnector host fleet-managed WebDAV filesystem connector.
3
3
  *
4
- * The whole data plane (enumeration, download, upload, change detection,
5
- * cache eviction) is delegated to an `rclone mount` subprocess managed by
6
- * {@link RcloneProcessManager}. This connector only parses the declaration,
7
- * obscures the password, renders the rclone config, hands it off, and
8
- * forwards lifecycle hooks.
4
+ * Cloud mounts are prepared outside the agent container and exposed through a
5
+ * bind mount. The package-side driver only verifies the bind and returns a
6
+ * no-op lifecycle handle.
9
7
  */
10
8
  import type { ConnectContext, ConnectorDeclaration, ConnectorHandle, FilesystemFace } from "@skaile/workspaces/connectors";
11
9
  import { AbstractConnector } from "@skaile/workspaces/connectors";
12
10
  /**
13
- * Filesystem-face connector for WebDAV servers (Nextcloud, ownCloud, SharePoint-WebDAV,
14
- * Fastmail, generic) — delegates the data plane to an `rclone mount` subprocess via
15
- * `RcloneProcessManager`. Supports fleet-managed mode where the host has pre-mounted
16
- * the share via `SKAILE_FLEET_MANAGED_MOUNTS`.
11
+ * Filesystem-face connector for host fleet-managed WebDAV mounts.
17
12
  * @docLink packages/factory-assets/concepts#webdav-connector
18
13
  */
19
14
  export declare class WebDAVConnector extends AbstractConnector {
20
- private readonly obscure;
21
15
  readonly name = "webdav";
22
- private rclone;
23
- constructor(obscure?: (plain: string) => Promise<string>);
24
16
  readonly filesystem: FilesystemFace;
25
17
  connect(declaration: ConnectorDeclaration, ctx: ConnectContext): Promise<ConnectorHandle>;
26
- disconnect(handle: ConnectorHandle): Promise<void>;
27
- private _sync;
18
+ disconnect(_handle: ConnectorHandle): Promise<void>;
28
19
  onHibernate(handle: ConnectorHandle): Promise<string | undefined>;
29
20
  onSessionClose(handle: ConnectorHandle): Promise<string | undefined>;
30
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../../../factory-assets/connectors/webdav/driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,cAAc,EAIf,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,iBAAiB,EAUlB,MAAM,+BAA+B,CAAC;AA0CvC;;;;;;GAMG;AACH,qBAAa,eAAgB,SAAQ,iBAAiB;IAOxC,OAAO,CAAC,QAAQ,CAAC,OAAO;IANpC,QAAQ,CAAC,IAAI,YAAY;IAEzB,OAAO,CAAC,MAAM,CAA8B;gBAIf,OAAO,GAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAmB;IAI1F,QAAQ,CAAC,UAAU,EAAE,cAAc,CAKjC;IAEI,OAAO,CAAC,WAAW,EAAE,oBAAoB,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IA4IzF,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;YAO1C,KAAK;IAwBJ,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAOjE,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CAMpF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,eAAe,CAEjD"}
1
+ {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../../../factory-assets/connectors/webdav/driver.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,cAAc,EAGf,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,iBAAiB,EAGlB,MAAM,+BAA+B,CAAC;AASvC;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,iBAAiB;IACpD,QAAQ,CAAC,IAAI,YAAY;IAEzB,QAAQ,CAAC,UAAU,EAAE,cAAc,CAGjC;IAEI,OAAO,CAAC,WAAW,EAAE,oBAAoB,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAiBzF,UAAU,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAE1C,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAKjE,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CAIpF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,eAAe,CAEjD"}