@storacha/clawracha 0.0.2 → 0.0.4
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.
- package/README.md +34 -7
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +9 -3
- package/dist/watcher.d.ts +1 -1
- package/dist/watcher.d.ts.map +1 -1
- package/dist/watcher.js +24 -1
- package/openclaw.plugin.json +4 -4
- package/package.json +1 -1
- package/src/plugin.ts +12 -4
- package/src/watcher.ts +24 -1
package/README.md
CHANGED
|
@@ -21,14 +21,41 @@ openclaw plugins install @storacha/clawracha
|
|
|
21
21
|
|
|
22
22
|
## Setup
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
Setup is done via slash commands in your chat session with the agent (not CLI commands).
|
|
25
|
+
|
|
26
|
+
### New workspace (first device)
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
/storacha-init <upload-delegation-b64>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Creates a fresh workspace with a new UCN Name. You'll need an upload delegation from a Storacha space owner.
|
|
33
|
+
|
|
34
|
+
### Join an existing workspace (additional devices)
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
/storacha-join <upload-delegation-b64> <name-delegation-b64>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Joins an existing workspace from another device. Both delegations are required — get them by running `/storacha-grant` on the existing device. The join command pulls all remote files before the watcher starts, so your local workspace is fully synced from the start.
|
|
27
41
|
|
|
28
|
-
|
|
29
|
-
openclaw storacha delegate <base64-delegation>
|
|
42
|
+
### Grant access to another device
|
|
30
43
|
|
|
31
|
-
|
|
44
|
+
```
|
|
45
|
+
/storacha-grant <target-agent-DID>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Generates upload and name delegations for the target device. The target device uses these with `/storacha-join`.
|
|
49
|
+
|
|
50
|
+
### Check status
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
/storacha-status
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
After setup, restart the gateway to start syncing:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
32
59
|
openclaw gateway restart
|
|
33
60
|
```
|
|
34
61
|
|
|
@@ -108,7 +135,7 @@ The plugin provides tools for manual sync control:
|
|
|
108
135
|
|
|
109
136
|
The plugin stores data in `.storacha/` within the workspace:
|
|
110
137
|
|
|
111
|
-
- `config.json` - Agent key,
|
|
138
|
+
- `config.json` - Agent key, delegations, name archive (NOT synced)
|
|
112
139
|
- `blocks/` - Local block cache (NOT synced)
|
|
113
140
|
|
|
114
141
|
Add `.storacha/` to your `.gitignore`.
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EACV,iBAAiB,EAGlB,MAAM,qBAAqB,CAAC;AAwC7B;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,GAAG,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EACV,iBAAiB,EAGlB,MAAM,qBAAqB,CAAC;AAwC7B;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,GAAG,EAAE,iBAAiB,QA6apD"}
|
package/dist/plugin.js
CHANGED
|
@@ -44,10 +44,16 @@ async function saveDeviceConfig(workspace, config) {
|
|
|
44
44
|
* Plugin entry — called by OpenClaw when the plugin is loaded.
|
|
45
45
|
*/
|
|
46
46
|
export default function plugin(api) {
|
|
47
|
+
// Capture plugin-specific config at registration time
|
|
48
|
+
const pluginConfig = (api.pluginConfig ?? {});
|
|
47
49
|
// Register background service
|
|
48
50
|
api.registerService({
|
|
49
51
|
id: "storacha-sync",
|
|
50
52
|
async start(ctx) {
|
|
53
|
+
if (pluginConfig.enabled === false) {
|
|
54
|
+
ctx.logger.info("Storacha sync disabled via config.");
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
51
57
|
workspaceDir = ctx.workspaceDir;
|
|
52
58
|
const workspace = workspaceDir;
|
|
53
59
|
if (!workspace) {
|
|
@@ -66,8 +72,8 @@ export default function plugin(api) {
|
|
|
66
72
|
workspace,
|
|
67
73
|
config: {
|
|
68
74
|
enabled: true,
|
|
69
|
-
watchPatterns: ["**/*"],
|
|
70
|
-
ignorePatterns: [
|
|
75
|
+
watchPatterns: pluginConfig.watchPatterns ?? ["**/*"],
|
|
76
|
+
ignorePatterns: pluginConfig.ignorePatterns ?? [
|
|
71
77
|
".storacha/**",
|
|
72
78
|
"node_modules/**",
|
|
73
79
|
".git/**",
|
|
@@ -84,7 +90,7 @@ export default function plugin(api) {
|
|
|
84
90
|
await saveDeviceConfig(workspace, updatedConfig);
|
|
85
91
|
},
|
|
86
92
|
});
|
|
87
|
-
fileWatcher.start();
|
|
93
|
+
await fileWatcher.start();
|
|
88
94
|
ctx.logger.info("Started watching workspace");
|
|
89
95
|
},
|
|
90
96
|
async stop(ctx) {
|
package/dist/watcher.d.ts
CHANGED
package/dist/watcher.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAErE,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAoBD,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAmC;IAClD,OAAO,CAAC,cAAc,CAAsC;IAC5D,OAAO,CAAC,aAAa,CAA+B;IACpD,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,UAAU,CAAS;gBAEf,OAAO,EAAE,cAAc;IAKnC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmC5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAY3B;;OAEG;IACH,OAAO,CAAC,YAAY;IAmBpB;;OAEG;YACW,KAAK;IAanB;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAOlC"}
|
package/dist/watcher.js
CHANGED
|
@@ -5,7 +5,27 @@
|
|
|
5
5
|
* before triggering sync.
|
|
6
6
|
*/
|
|
7
7
|
import chokidar from "chokidar";
|
|
8
|
+
import * as fs from "node:fs/promises";
|
|
8
9
|
import * as path from "node:path";
|
|
10
|
+
/**
|
|
11
|
+
* Read .clawrachaignore from workspace root (gitignore-style).
|
|
12
|
+
* Returns parsed patterns, or empty array if file doesn't exist.
|
|
13
|
+
*/
|
|
14
|
+
async function readIgnoreFile(workspace) {
|
|
15
|
+
const ignorePath = path.join(workspace, ".clawrachaignore");
|
|
16
|
+
try {
|
|
17
|
+
const content = await fs.readFile(ignorePath, "utf-8");
|
|
18
|
+
return content
|
|
19
|
+
.split("\n")
|
|
20
|
+
.map((line) => line.trim())
|
|
21
|
+
.filter((line) => line && !line.startsWith("#"));
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
if (err.code === "ENOENT")
|
|
25
|
+
return [];
|
|
26
|
+
throw err;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
9
29
|
export class FileWatcher {
|
|
10
30
|
watcher = null;
|
|
11
31
|
pendingChanges = new Map();
|
|
@@ -19,15 +39,18 @@ export class FileWatcher {
|
|
|
19
39
|
/**
|
|
20
40
|
* Start watching the workspace
|
|
21
41
|
*/
|
|
22
|
-
start() {
|
|
42
|
+
async start() {
|
|
23
43
|
if (this.watcher)
|
|
24
44
|
return;
|
|
25
45
|
const { workspace, config } = this.options;
|
|
46
|
+
// Read workspace-level ignore file
|
|
47
|
+
const userIgnored = await readIgnoreFile(workspace);
|
|
26
48
|
// Build watch patterns
|
|
27
49
|
const watchPaths = config.watchPatterns.map((p) => path.join(workspace, p));
|
|
28
50
|
// Build ignore patterns
|
|
29
51
|
const ignored = [
|
|
30
52
|
...config.ignorePatterns,
|
|
53
|
+
...userIgnored,
|
|
31
54
|
".storacha/**", // Always ignore our own data
|
|
32
55
|
];
|
|
33
56
|
this.watcher = chokidar.watch(watchPaths, {
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"id": "
|
|
2
|
+
"id": "clawracha",
|
|
3
3
|
"name": "Storacha Workspace Sync",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.3",
|
|
5
5
|
"description": "Sync OpenClaw workspaces to Storacha via UCN Pail",
|
|
6
6
|
"entry": "./src/plugin.ts",
|
|
7
7
|
"skills": [],
|
|
8
|
-
"
|
|
8
|
+
"configSchema": {
|
|
9
9
|
"type": "object",
|
|
10
10
|
"properties": {
|
|
11
11
|
"enabled": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"watchPatterns": {
|
|
17
17
|
"type": "array",
|
|
18
18
|
"items": { "type": "string" },
|
|
19
|
-
"default": ["
|
|
19
|
+
"default": ["**/*"],
|
|
20
20
|
"description": "Glob patterns to watch for sync"
|
|
21
21
|
},
|
|
22
22
|
"ignorePatterns": {
|
package/package.json
CHANGED
package/src/plugin.ts
CHANGED
|
@@ -15,7 +15,7 @@ import type {
|
|
|
15
15
|
OpenClawPluginServiceContext,
|
|
16
16
|
AnyAgentTool,
|
|
17
17
|
} from "openclaw/plugin-sdk";
|
|
18
|
-
import type { DeviceConfig } from "./types/index.js";
|
|
18
|
+
import type { DeviceConfig, SyncPluginConfig } from "./types/index.js";
|
|
19
19
|
import { SyncEngine } from "./sync.js";
|
|
20
20
|
import { FileWatcher } from "./watcher.js";
|
|
21
21
|
import { createStorachaClient } from "./utils/client.js";
|
|
@@ -58,10 +58,18 @@ async function saveDeviceConfig(
|
|
|
58
58
|
* Plugin entry — called by OpenClaw when the plugin is loaded.
|
|
59
59
|
*/
|
|
60
60
|
export default function plugin(api: OpenClawPluginApi) {
|
|
61
|
+
// Capture plugin-specific config at registration time
|
|
62
|
+
const pluginConfig = (api.pluginConfig ?? {}) as Partial<SyncPluginConfig>;
|
|
63
|
+
|
|
61
64
|
// Register background service
|
|
62
65
|
api.registerService({
|
|
63
66
|
id: "storacha-sync",
|
|
64
67
|
async start(ctx: OpenClawPluginServiceContext) {
|
|
68
|
+
if (pluginConfig.enabled === false) {
|
|
69
|
+
ctx.logger.info("Storacha sync disabled via config.");
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
65
73
|
workspaceDir = ctx.workspaceDir;
|
|
66
74
|
const workspace = workspaceDir;
|
|
67
75
|
if (!workspace) {
|
|
@@ -85,8 +93,8 @@ export default function plugin(api: OpenClawPluginApi) {
|
|
|
85
93
|
workspace,
|
|
86
94
|
config: {
|
|
87
95
|
enabled: true,
|
|
88
|
-
watchPatterns: ["**/*"],
|
|
89
|
-
ignorePatterns: [
|
|
96
|
+
watchPatterns: pluginConfig.watchPatterns ?? ["**/*"],
|
|
97
|
+
ignorePatterns: pluginConfig.ignorePatterns ?? [
|
|
90
98
|
".storacha/**",
|
|
91
99
|
"node_modules/**",
|
|
92
100
|
".git/**",
|
|
@@ -104,7 +112,7 @@ export default function plugin(api: OpenClawPluginApi) {
|
|
|
104
112
|
},
|
|
105
113
|
});
|
|
106
114
|
|
|
107
|
-
fileWatcher.start();
|
|
115
|
+
await fileWatcher.start();
|
|
108
116
|
ctx.logger.info("Started watching workspace");
|
|
109
117
|
},
|
|
110
118
|
|
package/src/watcher.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import chokidar from "chokidar";
|
|
9
|
+
import * as fs from "node:fs/promises";
|
|
9
10
|
import * as path from "node:path";
|
|
10
11
|
import type { FileChange, SyncPluginConfig } from "./types/index.js";
|
|
11
12
|
|
|
@@ -16,6 +17,24 @@ export interface WatcherOptions {
|
|
|
16
17
|
debounceMs?: number;
|
|
17
18
|
}
|
|
18
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Read .clawrachaignore from workspace root (gitignore-style).
|
|
22
|
+
* Returns parsed patterns, or empty array if file doesn't exist.
|
|
23
|
+
*/
|
|
24
|
+
async function readIgnoreFile(workspace: string): Promise<string[]> {
|
|
25
|
+
const ignorePath = path.join(workspace, ".clawrachaignore");
|
|
26
|
+
try {
|
|
27
|
+
const content = await fs.readFile(ignorePath, "utf-8");
|
|
28
|
+
return content
|
|
29
|
+
.split("\n")
|
|
30
|
+
.map((line) => line.trim())
|
|
31
|
+
.filter((line) => line && !line.startsWith("#"));
|
|
32
|
+
} catch (err: any) {
|
|
33
|
+
if (err.code === "ENOENT") return [];
|
|
34
|
+
throw err;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
19
38
|
export class FileWatcher {
|
|
20
39
|
private watcher: chokidar.FSWatcher | null = null;
|
|
21
40
|
private pendingChanges: Map<string, FileChange> = new Map();
|
|
@@ -31,17 +50,21 @@ export class FileWatcher {
|
|
|
31
50
|
/**
|
|
32
51
|
* Start watching the workspace
|
|
33
52
|
*/
|
|
34
|
-
start(): void {
|
|
53
|
+
async start(): Promise<void> {
|
|
35
54
|
if (this.watcher) return;
|
|
36
55
|
|
|
37
56
|
const { workspace, config } = this.options;
|
|
38
57
|
|
|
58
|
+
// Read workspace-level ignore file
|
|
59
|
+
const userIgnored = await readIgnoreFile(workspace);
|
|
60
|
+
|
|
39
61
|
// Build watch patterns
|
|
40
62
|
const watchPaths = config.watchPatterns.map((p) => path.join(workspace, p));
|
|
41
63
|
|
|
42
64
|
// Build ignore patterns
|
|
43
65
|
const ignored = [
|
|
44
66
|
...config.ignorePatterns,
|
|
67
|
+
...userIgnored,
|
|
45
68
|
".storacha/**", // Always ignore our own data
|
|
46
69
|
];
|
|
47
70
|
|