openclaw-workspace-sync 2.2.0 → 2.3.1

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.
@@ -0,0 +1,42 @@
1
+ <svg id="my-svg" width="537.296875" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" height="935" viewBox="0 0 537.296875 935" role="graphics-document document" aria-roledescription="flowchart-v2" style="background-color: white;"><style>#my-svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:14px;fill:#333333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#my-svg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#my-svg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#my-svg .error-icon{fill:#50C878;}#my-svg .error-text{fill:#ffffff;stroke:#ffffff;}#my-svg .edge-thickness-normal{stroke-width:1px;}#my-svg .edge-thickness-thick{stroke-width:3.5px;}#my-svg .edge-pattern-solid{stroke-dasharray:0;}#my-svg .edge-thickness-invisible{stroke-width:0;fill:none;}#my-svg .edge-pattern-dashed{stroke-dasharray:3;}#my-svg .edge-pattern-dotted{stroke-dasharray:2;}#my-svg .marker{fill:#5C6B77;stroke:#5C6B77;}#my-svg .marker.cross{stroke:#5C6B77;}#my-svg svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:14px;}#my-svg p{margin:0;}#my-svg .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ffffff;}#my-svg .cluster-label text{fill:#333333;}#my-svg .cluster-label span{color:#333333;}#my-svg .cluster-label span p{background-color:transparent;}#my-svg .label text,#my-svg span{fill:#ffffff;color:#ffffff;}#my-svg .node rect,#my-svg .node circle,#my-svg .node ellipse,#my-svg .node polygon,#my-svg .node path{fill:#4A90D9;stroke:#2E6EB5;stroke-width:1px;}#my-svg .rough-node .label text,#my-svg .node .label text,#my-svg .image-shape .label,#my-svg .icon-shape .label{text-anchor:middle;}#my-svg .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#my-svg .rough-node .label,#my-svg .node .label,#my-svg .image-shape .label,#my-svg .icon-shape .label{text-align:center;}#my-svg .node.clickable{cursor:pointer;}#my-svg .root .anchor path{fill:#5C6B77!important;stroke-width:0;stroke:#5C6B77;}#my-svg .arrowheadPath{fill:#0b0b0b;}#my-svg .edgePath .path{stroke:#5C6B77;stroke-width:2.0px;}#my-svg .flowchart-link{stroke:#5C6B77;fill:none;}#my-svg .edgeLabel{background-color:#ffffff;text-align:center;}#my-svg .edgeLabel p{background-color:#ffffff;}#my-svg .edgeLabel rect{opacity:0.5;background-color:#ffffff;fill:#ffffff;}#my-svg .labelBkg{background-color:rgba(255, 255, 255, 0.5);}#my-svg .cluster rect{fill:#F0F4F8;stroke:#94B8D9;stroke-width:1px;}#my-svg .cluster text{fill:#333333;}#my-svg .cluster span{color:#333333;}#my-svg div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:#50C878;border:1px solid #3BA35C;border-radius:2px;pointer-events:none;z-index:100;}#my-svg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333333;}#my-svg rect.text{fill:none;stroke-width:0;}#my-svg .icon-shape,#my-svg .image-shape{background-color:#ffffff;text-align:center;}#my-svg .icon-shape p,#my-svg .image-shape p{background-color:#ffffff;padding:2px;}#my-svg .icon-shape rect,#my-svg .image-shape rect{opacity:0.5;background-color:#ffffff;fill:#ffffff;}#my-svg .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#my-svg .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#my-svg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="my-svg_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"><g class="cluster" id="REMOTE" data-look="classic"><rect style="" x="87.46484375" y="644" width="324.890625" height="283"/><g class="cluster-label" transform="translate(167.48828125, 644)"><foreignObject width="164.84375" height="21"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Your Bucket (S3 / R2 / B2)</p></span></div></foreignObject></g></g><g class="cluster" id="GW" data-look="classic"><rect style="" x="8" y="8" width="521.296875" height="131"/><g class="cluster-label" transform="translate(241.3046875, 8)"><foreignObject width="54.6875" height="21"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Gateway</p></span></div></foreignObject></g></g></g><g class="edgePaths"><path d="M124.586,104L124.586,109.833C124.586,115.667,124.586,127.333,124.586,139C124.586,150.667,124.586,162.333,135.203,173.716C145.82,185.098,167.053,196.195,177.67,201.744L188.287,207.293" id="L_WS_TAR_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_WS_TAR_0" data-points="W3sieCI6MTI0LjU4NTkzNzUsInkiOjEwNH0seyJ4IjoxMjQuNTg1OTM3NSwieSI6MTM5fSx7IngiOjEyNC41ODU5Mzc1LCJ5IjoxNzR9LHsieCI6MTkxLjgzMjAzMTI1LCJ5IjoyMDkuMTQ1NzkzNzIyNTMyMTh9XQ==" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M375.234,104L375.234,109.833C375.234,115.667,375.234,127.333,375.234,139C375.234,150.667,375.234,162.333,364.618,173.716C354.001,185.098,332.767,196.195,322.15,201.744L311.533,207.293" id="L_CFG_TAR_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_CFG_TAR_0" data-points="W3sieCI6Mzc1LjIzNDM3NSwieSI6MTA0fSx7IngiOjM3NS4yMzQzNzUsInkiOjEzOX0seyJ4IjozNzUuMjM0Mzc1LCJ5IjoxNzR9LHsieCI6MzA3Ljk4ODI4MTI1LCJ5IjoyMDkuMTQ1NzkzNzIyNTMyMTh9XQ==" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M249.91,270L249.91,277.583C249.91,285.167,249.91,300.333,249.91,314.833C249.91,329.333,249.91,343.167,249.91,350.083L249.91,357" id="L_TAR_ENC_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_TAR_ENC_0" data-points="W3sieCI6MjQ5LjkxMDE1NjI1LCJ5IjoyNzB9LHsieCI6MjQ5LjkxMDE1NjI1LCJ5IjozMTUuNX0seyJ4IjoyNDkuOTEwMTU2MjUsInkiOjM2MX1d" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M249.91,422L249.91,429.583C249.91,437.167,249.91,452.333,249.91,466.833C249.91,481.333,249.91,495.167,249.91,502.083L249.91,509" id="L_ENC_RCAT_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_ENC_RCAT_0" data-points="W3sieCI6MjQ5LjkxMDE1NjI1LCJ5Ijo0MjJ9LHsieCI6MjQ5LjkxMDE1NjI1LCJ5Ijo0NjcuNX0seyJ4IjoyNDkuOTEwMTU2MjUsInkiOjUxM31d" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M249.91,574L249.91,579.833C249.91,585.667,249.91,597.333,249.91,609C249.91,620.667,249.91,632.333,249.91,643.333C249.91,654.333,249.91,664.667,249.91,669.833L249.91,675" id="L_RCAT_SNAP_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_RCAT_SNAP_0" data-points="W3sieCI6MjQ5LjkxMDE1NjI1LCJ5Ijo1NzR9LHsieCI6MjQ5LjkxMDE1NjI1LCJ5Ijo2MDl9LHsieCI6MjQ5LjkxMDE1NjI1LCJ5Ijo2NDR9LHsieCI6MjQ5LjkxMDE1NjI1LCJ5Ijo2Nzl9XQ==" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M249.91,740L249.91,747.583C249.91,755.167,249.91,770.333,249.91,784.833C249.91,799.333,249.91,813.167,249.91,820.083L249.91,827" id="L_SNAP_OLD_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_SNAP_OLD_0" data-points="W3sieCI6MjQ5LjkxMDE1NjI1LCJ5Ijo3NDB9LHsieCI6MjQ5LjkxMDE1NjI1LCJ5Ijo3ODUuNX0seyJ4IjoyNDkuOTEwMTU2MjUsInkiOjgzMX1d" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_WS_TAR_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_CFG_TAR_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(249.91015625, 315.5)"><g class="label" data-id="L_TAR_ENC_0" transform="translate(-13.6171875, -10.5)"><foreignObject width="27.234375" height="21"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>pipe</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(249.91015625, 467.5)"><g class="label" data-id="L_ENC_RCAT_0" transform="translate(-13.6171875, -10.5)"><foreignObject width="27.234375" height="21"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>pipe</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_RCAT_SNAP_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(249.91015625, 785.5)"><g class="label" data-id="L_SNAP_OLD_0" transform="translate(-49.5078125, -10.5)"><foreignObject width="99.015625" height="21"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>retention prune</p></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="flowchart-WS-0" transform="translate(124.5859375, 73.5)"><rect class="basic label-container" style="" x="-76.5859375" y="-30.5" width="153.171875" height="61"/><g class="label" style="" transform="translate(-36.5859375, -10.5)"><rect/><foreignObject width="73.171875" height="21"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>/workspace</p></span></div></foreignObject></g></g><g class="node default" id="flowchart-CFG-1" transform="translate(375.234375, 73.5)"><rect class="basic label-container" style="" x="-114.0625" y="-30.5" width="228.125" height="61"/><g class="label" style="" transform="translate(-74.0625, -10.5)"><rect/><foreignObject width="148.125" height="21"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>config / cron / memory</p></span></div></foreignObject></g></g><g class="node default" id="flowchart-TAR-2" transform="translate(249.91015625, 239.5)"><rect class="basic label-container" style="" x="-58.078125" y="-30.5" width="116.15625" height="61"/><g class="label" style="" transform="translate(-18.078125, -10.5)"><rect/><foreignObject width="36.15625" height="21"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>tar cz</p></span></div></foreignObject></g></g><g class="node default" id="flowchart-ENC-3" transform="translate(249.91015625, 391.5)"><rect class="basic label-container" style="" x="-112.53125" y="-30.5" width="225.0625" height="61"/><g class="label" style="" transform="translate(-72.53125, -10.5)"><rect/><foreignObject width="145.0625" height="21"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>openssl enc\n(AES-256)</p></span></div></foreignObject></g></g><g class="node default" id="flowchart-RCAT-4" transform="translate(249.91015625, 543.5)"><rect class="basic label-container" style="" x="-74.3984375" y="-30.5" width="148.796875" height="61"/><g class="label" style="" transform="translate(-34.3984375, -10.5)"><rect/><foreignObject width="68.796875" height="21"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>rclone rcat</p></span></div></foreignObject></g></g><g class="node default" id="flowchart-SNAP-5" transform="translate(249.91015625, 709.5)"><rect class="basic label-container" style="" x="-122.4453125" y="-30.5" width="244.890625" height="61"/><g class="label" style="" transform="translate(-82.4453125, -10.5)"><rect/><foreignObject width="164.890625" height="21"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>backup-2026…Z.tar.gz.enc</p></span></div></foreignObject></g></g><g class="node default" id="flowchart-OLD-6" transform="translate(249.91015625, 861.5)"><rect class="basic label-container" style="" x="-88.6328125" y="-30.5" width="177.265625" height="61"/><g class="label" style="" transform="translate(-48.6328125, -10.5)"><rect/><foreignObject width="97.265625" height="21"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>older snapshots</p></span></div></foreignObject></g></g></g></g></g><style>.edgeLabel {
2
+ color: #333333 !important;
3
+ background-color: #ffffff !important;
4
+ }
5
+ .edgeLabel span {
6
+ color: #333333 !important;
7
+ fill: #333333 !important;
8
+ }
9
+ .edgeLabel p {
10
+ color: #333333 !important;
11
+ }
12
+ .labelBkg {
13
+ background-color: #ffffff !important;
14
+ }
15
+
16
+ /* Gateway subgraph — green tint */
17
+ #GW rect {
18
+ fill: #E8F5E9 !important;
19
+ stroke: #66BB6A !important;
20
+ }
21
+ #GW .cluster-label span {
22
+ color: #2E7D32 !important;
23
+ }
24
+
25
+ /* Cloud subgraph — amber tint */
26
+ #CLOUD rect {
27
+ fill: #FFF8E1 !important;
28
+ stroke: #FFB74D !important;
29
+ }
30
+ #CLOUD .cluster-label span {
31
+ color: #E65100 !important;
32
+ }
33
+
34
+ /* Local subgraph — blue tint */
35
+ #LOCAL rect {
36
+ fill: #E3F2FD !important;
37
+ stroke: #64B5F6 !important;
38
+ }
39
+ #LOCAL .cluster-label span {
40
+ color: #1565C0 !important;
41
+ }
42
+ </style></svg>
@@ -1,6 +1,10 @@
1
1
  {
2
2
  "id": "openclaw-workspace-sync",
3
3
  "uiHints": {
4
+ "sync": {
5
+ "label": "Sync Settings",
6
+ "help": "Nested sync config (preferred). Same fields as flat config: provider, mode, interval, etc."
7
+ },
4
8
  "provider": {
5
9
  "label": "Cloud Provider",
6
10
  "help": "Cloud storage provider for workspace sync"
@@ -123,12 +127,54 @@
123
127
  "label": "rclone Options",
124
128
  "help": "Key-value pairs passed directly to rclone config",
125
129
  "advanced": true
130
+ },
131
+ "backup.enabled": {
132
+ "label": "Enable Backups",
133
+ "help": "Encrypted snapshot backups to cloud storage"
134
+ },
135
+ "backup.provider": {
136
+ "label": "Backup Provider",
137
+ "help": "Cloud provider for backup storage (can differ from sync provider). Defaults to the sync provider."
138
+ },
139
+ "backup.bucket": {
140
+ "label": "Backup Bucket",
141
+ "help": "S3/R2 bucket name for backup snapshots"
142
+ },
143
+ "backup.prefix": {
144
+ "label": "Backup Prefix",
145
+ "placeholder": "habibi/",
146
+ "help": "Path prefix within the bucket for this agent's snapshots"
147
+ },
148
+ "backup.interval": {
149
+ "label": "Backup Interval (seconds)",
150
+ "placeholder": "86400",
151
+ "help": "How often to create backups (default: 86400 = daily)"
152
+ },
153
+ "backup.encrypt": {
154
+ "label": "Encrypt Backups",
155
+ "help": "Encrypt snapshots with AES-256 before upload"
156
+ },
157
+ "backup.passphrase": {
158
+ "label": "Encryption Passphrase",
159
+ "sensitive": true,
160
+ "help": "Passphrase for backup encryption. Use env var: ${BACKUP_PASSPHRASE}"
161
+ },
162
+ "backup.include": {
163
+ "label": "Backup Include",
164
+ "help": "What to include: workspace, config, cron, memory, sessions, credentials, skills, hooks, extensions, env, agents, pages, transcripts"
165
+ },
166
+ "backup.retain": {
167
+ "label": "Retention",
168
+ "help": "Number of snapshots to keep, or { daily: N, weekly: N, monthly: N }"
126
169
  }
127
170
  },
128
171
  "configSchema": {
129
172
  "type": "object",
130
- "additionalProperties": false,
131
173
  "properties": {
174
+ "sync": {
175
+ "type": "object",
176
+ "description": "Nested sync config (preferred). Contains the same fields as the flat config: provider, mode, interval, remotePath, etc."
177
+ },
132
178
  "provider": {
133
179
  "type": "string",
134
180
  "enum": [
@@ -196,6 +242,81 @@
196
242
  "copySymlinks": {
197
243
  "type": "boolean"
198
244
  },
245
+ "backup": {
246
+ "type": "object",
247
+ "additionalProperties": false,
248
+ "properties": {
249
+ "enabled": { "type": "boolean" },
250
+ "provider": {
251
+ "type": "string",
252
+ "enum": ["dropbox", "gdrive", "onedrive", "s3", "custom"]
253
+ },
254
+ "remoteName": { "type": "string" },
255
+ "configPath": { "type": "string" },
256
+ "remotePath": { "type": "string" },
257
+ "bucket": { "type": "string" },
258
+ "prefix": { "type": "string" },
259
+ "interval": { "type": "number", "minimum": 0 },
260
+ "encrypt": { "type": "boolean" },
261
+ "passphrase": { "type": "string" },
262
+ "include": {
263
+ "type": "array",
264
+ "items": {
265
+ "type": "string",
266
+ "enum": ["workspace", "config", "cron", "memory", "sessions", "credentials", "skills", "hooks", "extensions", "env", "agents", "pages", "transcripts"]
267
+ }
268
+ },
269
+ "retain": {
270
+ "description": "Number of snapshots to keep, or {daily, weekly, monthly} object for tiered retention"
271
+ },
272
+ "exclude": {
273
+ "type": "array",
274
+ "items": { "type": "string" }
275
+ },
276
+ "s3": {
277
+ "type": "object",
278
+ "properties": {
279
+ "endpoint": { "type": "string" },
280
+ "bucket": { "type": "string" },
281
+ "region": { "type": "string" },
282
+ "accessKeyId": { "type": "string" },
283
+ "secretAccessKey": { "type": "string" }
284
+ }
285
+ },
286
+ "dropbox": {
287
+ "type": "object",
288
+ "properties": {
289
+ "appFolder": { "type": "boolean" },
290
+ "appKey": { "type": "string" },
291
+ "appSecret": { "type": "string" },
292
+ "token": { "type": "string" }
293
+ }
294
+ },
295
+ "gdrive": {
296
+ "type": "object",
297
+ "properties": {
298
+ "token": { "type": "string" },
299
+ "teamDrive": { "type": "string" },
300
+ "rootFolderId": { "type": "string" }
301
+ }
302
+ },
303
+ "onedrive": {
304
+ "type": "object",
305
+ "properties": {
306
+ "token": { "type": "string" },
307
+ "driveId": { "type": "string" },
308
+ "driveType": { "type": "string", "enum": ["personal", "business", "sharepoint"] }
309
+ }
310
+ },
311
+ "custom": {
312
+ "type": "object",
313
+ "properties": {
314
+ "rcloneType": { "type": "string" },
315
+ "rcloneOptions": { "type": "object", "additionalProperties": { "type": "string" } }
316
+ }
317
+ }
318
+ }
319
+ },
199
320
  "s3": {
200
321
  "type": "object",
201
322
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "openclaw-workspace-sync",
3
- "version": "2.2.0",
4
- "description": "Workspace cloud sync via rclone — mailbox (inbox/outbox), mirror, or bisync (Dropbox, Google Drive, S3, OneDrive, 70+ providers)",
3
+ "version": "2.3.1",
4
+ "description": "Workspace cloud sync & encrypted backup via rclone — mailbox, mirror, bisync + AES-256 snapshots (Dropbox, S3, R2, 70+ providers)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -80,7 +80,7 @@ Lists files in the configured cloud storage path.
80
80
 
81
81
  ## Configuration
82
82
 
83
- Workspace sync is configured via the plugin entry in `openclaw.json`:
83
+ Workspace sync is configured via the plugin entry in `openclaw.json`. The preferred format uses nested `sync` and `backup` blocks (flat config at root level is also supported):
84
84
 
85
85
  ```json
86
86
  {
@@ -89,15 +89,17 @@ Workspace sync is configured via the plugin entry in `openclaw.json`:
89
89
  "openclaw-workspace-sync": {
90
90
  "enabled": true,
91
91
  "config": {
92
- "provider": "dropbox",
93
- "mode": "mailbox",
94
- "remotePath": "",
95
- "localPath": "/",
96
- "interval": 60,
97
- "timeout": 1800,
98
- "onSessionStart": true,
99
- "onSessionEnd": true,
100
- "exclude": [".git/**", "node_modules/**", "*.log"]
92
+ "sync": {
93
+ "provider": "dropbox",
94
+ "mode": "mailbox",
95
+ "remotePath": "",
96
+ "localPath": "/",
97
+ "interval": 60,
98
+ "timeout": 1800,
99
+ "onSessionStart": true,
100
+ "onSessionEnd": true,
101
+ "exclude": [".git/**", "node_modules/**", "*.log"]
102
+ }
101
103
  }
102
104
  }
103
105
  }
@@ -107,6 +109,8 @@ Workspace sync is configured via the plugin entry in `openclaw.json`:
107
109
 
108
110
  ### Config keys
109
111
 
112
+ These keys live under `sync` in the nested format, or at the config root in flat format.
113
+
110
114
  | Key | Default | Description |
111
115
  |-----|---------|-------------|
112
116
  | `provider` | `"off"` | `dropbox`, `gdrive`, `onedrive`, `s3`, `custom`, or `off` |
@@ -179,3 +183,46 @@ rclone ls cloud:openclaw-share
179
183
  - Only `**/.DS_Store` excluded by default — add your own excludes in config
180
184
  - Sync operations run in background (no LLM tokens used)
181
185
  - All rclone activity is logged at info level for visibility
186
+
187
+ ## Encrypted backups
188
+
189
+ Add a `backup` block to the plugin config for automated encrypted snapshots to your own cloud storage (S3, R2, B2, etc.). Backups stream directly (`tar | rclone rcat`) — no local temp files, so they work even when disk space is tight.
190
+
191
+ ### Backup commands
192
+
193
+ ```bash
194
+ openclaw workspace-sync backup now # Create a snapshot immediately
195
+ openclaw workspace-sync backup list # List available snapshots
196
+ openclaw workspace-sync backup restore # Restore latest snapshot
197
+ openclaw workspace-sync backup status # Check backup service status
198
+ ```
199
+
200
+ ### Backup config
201
+
202
+ ```json
203
+ {
204
+ "backup": {
205
+ "enabled": true,
206
+ "provider": "s3",
207
+ "bucket": "my-backups",
208
+ "prefix": "agent-name/",
209
+ "interval": 86400,
210
+ "encrypt": true,
211
+ "passphrase": "${BACKUP_PASSPHRASE}",
212
+ "include": ["workspace", "config", "cron", "memory"],
213
+ "retain": { "daily": 7, "weekly": 4 }
214
+ }
215
+ }
216
+ ```
217
+
218
+ | Key | Default | Description |
219
+ |-----|---------|-------------|
220
+ | `enabled` | `false` | Enable scheduled backups |
221
+ | `provider` | parent provider | Cloud provider (can differ from sync provider) |
222
+ | `bucket` | — | S3/R2 bucket name |
223
+ | `prefix` | `""` | Path prefix within the bucket |
224
+ | `interval` | `86400` | Backup interval in seconds (clamped to min 300) |
225
+ | `encrypt` | `false` | AES-256 client-side encryption |
226
+ | `passphrase` | — | Encryption passphrase (use env var) |
227
+ | `include` | `["workspace", "config", "cron", "memory"]` | What to back up |
228
+ | `retain` | `7` | Keep N snapshots, or `{ daily: N, weekly: N }` |