@storacha/clawracha 0.0.1 → 0.0.3

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 (43) hide show
  1. package/README.md +34 -7
  2. package/dist/handlers/apply.d.ts +18 -0
  3. package/dist/handlers/apply.d.ts.map +1 -0
  4. package/dist/handlers/apply.js +50 -0
  5. package/dist/handlers/process.d.ts +15 -0
  6. package/dist/handlers/process.d.ts.map +1 -0
  7. package/dist/handlers/process.js +82 -0
  8. package/dist/handlers/remote.d.ts +15 -0
  9. package/dist/handlers/remote.d.ts.map +1 -0
  10. package/dist/handlers/remote.js +48 -0
  11. package/dist/index.d.ts +3 -3
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +3 -3
  14. package/dist/mdsync/index.d.ts +45 -0
  15. package/dist/mdsync/index.d.ts.map +1 -0
  16. package/dist/mdsync/index.js +365 -0
  17. package/dist/plugin.d.ts.map +1 -1
  18. package/dist/plugin.js +233 -29
  19. package/dist/sync.d.ts +12 -5
  20. package/dist/sync.d.ts.map +1 -1
  21. package/dist/sync.js +82 -157
  22. package/dist/types/index.d.ts +58 -0
  23. package/dist/types/index.d.ts.map +1 -0
  24. package/dist/types/index.js +4 -0
  25. package/dist/utils/client.d.ts +14 -0
  26. package/dist/utils/client.d.ts.map +1 -0
  27. package/dist/utils/client.js +38 -0
  28. package/dist/utils/differ.d.ts +29 -0
  29. package/dist/utils/differ.d.ts.map +1 -0
  30. package/dist/utils/differ.js +47 -0
  31. package/dist/utils/encoder.d.ts +16 -0
  32. package/dist/utils/encoder.d.ts.map +1 -0
  33. package/dist/utils/encoder.js +51 -0
  34. package/dist/utils/tempcar.d.ts +22 -0
  35. package/dist/utils/tempcar.d.ts.map +1 -0
  36. package/dist/utils/tempcar.js +44 -0
  37. package/dist/watcher.d.ts +2 -2
  38. package/dist/watcher.d.ts.map +1 -1
  39. package/dist/watcher.js +24 -1
  40. package/openclaw.plugin.json +2 -2
  41. package/package.json +1 -1
  42. package/src/plugin.ts +12 -4
  43. package/src/watcher.ts +24 -1
@@ -0,0 +1,44 @@
1
+ import * as fs from "node:fs/promises";
2
+ import { createReadStream, createWriteStream } from "node:fs";
3
+ import * as os from "node:os";
4
+ import * as path from "node:path";
5
+ import * as stream from "node:stream";
6
+ import { CarWriter } from "@ipld/car/writer";
7
+ export const makeTempCar = async () => {
8
+ const dir = await fs.mkdtemp(path.join(os.tmpdir(), "sync-clawracha-"));
9
+ const cleanup = async () => await fs.rm(dir, { recursive: true });
10
+ const file = path.join(dir, "blocks.car");
11
+ // CarWriter.createAppender() creates a headerless/rootless CAR
12
+ // which is fine for uploadCAR (the client handles it)
13
+ const { writer, out } = CarWriter.createAppender();
14
+ // Pipe the output to a file
15
+ const fsWriteStream = createWriteStream(file);
16
+ const pipePromise = stream.promises.pipeline(stream.Readable.from(out), fsWriteStream);
17
+ let didWrite = false;
18
+ const put = async (block) => {
19
+ didWrite = true;
20
+ await writer.put({ cid: block.cid, bytes: block.bytes });
21
+ };
22
+ const switchToReadable = async () => {
23
+ try {
24
+ await writer.close();
25
+ await pipePromise;
26
+ if (!didWrite) {
27
+ await cleanup();
28
+ return null;
29
+ }
30
+ return {
31
+ readable: {
32
+ stream: () => stream.Readable.toWeb(createReadStream(file)),
33
+ },
34
+ cleanup,
35
+ };
36
+ }
37
+ catch (err) {
38
+ console.error("Error switching to readable:", err);
39
+ await cleanup();
40
+ throw err;
41
+ }
42
+ };
43
+ return { put, switchToReadable, cleanup };
44
+ };
package/dist/watcher.d.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * Uses chokidar to watch for file changes and batches them
5
5
  * before triggering sync.
6
6
  */
7
- import type { FileChange, SyncPluginConfig } from "./types.js";
7
+ import type { FileChange, SyncPluginConfig } from "./types/index.js";
8
8
  export interface WatcherOptions {
9
9
  workspace: string;
10
10
  config: SyncPluginConfig;
@@ -21,7 +21,7 @@ export declare class FileWatcher {
21
21
  /**
22
22
  * Start watching the workspace
23
23
  */
24
- start(): void;
24
+ start(): Promise<void>;
25
25
  /**
26
26
  * Stop watching
27
27
  */
@@ -1 +1 @@
1
- {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE/D,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;AAED,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;IACH,KAAK,IAAI,IAAI;IA+Bb;;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"}
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, {
@@ -5,7 +5,7 @@
5
5
  "description": "Sync OpenClaw workspaces to Storacha via UCN Pail",
6
6
  "entry": "./src/plugin.ts",
7
7
  "skills": [],
8
- "config": {
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": ["**/*.md"],
19
+ "default": ["**/*"],
20
20
  "description": "Glob patterns to watch for sync"
21
21
  },
22
22
  "ignorePatterns": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storacha/clawracha",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "OpenClaw plugin for Storacha workspace sync via UCN Pail",
5
5
  "type": "module",
6
6
  "main": "dist/plugin.js",
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