@storacha/clawracha 0.0.7 → 0.0.9

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 CHANGED
@@ -23,21 +23,31 @@ openclaw plugins install @storacha/clawracha
23
23
 
24
24
  Setup is done via slash commands in your chat session with the agent (not CLI commands).
25
25
 
26
- ### New workspace (first device)
26
+ ### Step 1: Initialize the agent
27
27
 
28
28
  ```
29
- /storacha-init <upload-delegation-b64>
29
+ /storacha-init
30
30
  ```
31
31
 
32
- Creates a fresh workspace with a new UCN Name. You'll need an upload delegation from a Storacha space owner.
32
+ Generates an agent identity and displays the Agent DID. You'll need this DID to create delegations.
33
33
 
34
- ### Join an existing workspace (additional devices)
34
+ ### Step 2: Choose your path
35
+
36
+ **New workspace (first device):**
37
+
38
+ ```
39
+ /storacha-setup <upload-delegation-b64>
40
+ ```
41
+
42
+ Have the space owner create an upload delegation for your Agent DID, then import it. Creates a fresh UCN Name and starts syncing.
43
+
44
+ **Join an existing workspace (additional devices):**
35
45
 
36
46
  ```
37
47
  /storacha-join <upload-delegation-b64> <name-delegation-b64>
38
48
  ```
39
49
 
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.
50
+ Get both delegations 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.
41
51
 
42
52
  ### Grant access to another device
43
53
 
@@ -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,QA6apD"}
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;AAyC7B;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,GAAG,EAAE,iBAAiB,QAyepD"}
package/dist/plugin.js CHANGED
@@ -10,6 +10,7 @@ import * as fs from "node:fs/promises";
10
10
  import * as path from "node:path";
11
11
  import { extract as extractDelegation } from "@storacha/client/delegation";
12
12
  import { SyncEngine } from "./sync.js";
13
+ import { decodeDelegation, encodeDelegation } from "./utils/delegation.js";
13
14
  import { FileWatcher } from "./watcher.js";
14
15
  import { createStorachaClient } from "./utils/client.js";
15
16
  // Global state
@@ -62,7 +63,7 @@ export default function plugin(api) {
62
63
  }
63
64
  const deviceConfig = await loadDeviceConfig(workspace);
64
65
  if (!deviceConfig || !deviceConfig.setupComplete) {
65
- ctx.logger.info("Setup not complete. Run /storacha-init or /storacha-join first.");
66
+ ctx.logger.info("Setup not complete. Run /storacha-init first, then /storacha-setup or /storacha-join.");
66
67
  return;
67
68
  }
68
69
  const storachaClient = await createStorachaClient(deviceConfig);
@@ -114,7 +115,7 @@ export default function plugin(api) {
114
115
  content: [
115
116
  {
116
117
  type: "text",
117
- text: "Sync not initialized. Run /storacha-init or /storacha-join first.",
118
+ text: "Sync not initialized. Run /storacha-init first, then /storacha-setup or /storacha-join.",
118
119
  },
119
120
  ],
120
121
  details: null,
@@ -140,7 +141,7 @@ export default function plugin(api) {
140
141
  content: [
141
142
  {
142
143
  type: "text",
143
- text: "Sync not initialized. Run /storacha-init or /storacha-join first.",
144
+ text: "Sync not initialized. Run /storacha-init first, then /storacha-setup or /storacha-join.",
144
145
  },
145
146
  ],
146
147
  details: null,
@@ -162,42 +163,91 @@ export default function plugin(api) {
162
163
  // --- Slash Commands ---
163
164
  api.registerCommand({
164
165
  name: "storacha-init",
165
- description: "Initialize a NEW Storacha workspace (first device). Usage: /storacha-init <upload-delegation-b64>",
166
+ description: "Generate an agent identity for Storacha sync",
167
+ handler: async (_ctx) => {
168
+ const workspace = workspaceDir;
169
+ if (!workspace)
170
+ return { text: "No workspace configured." };
171
+ // Check if already initialized
172
+ const existing = await loadDeviceConfig(workspace);
173
+ if (existing?.agentKey) {
174
+ const { Agent } = await import("@storacha/ucn/pail");
175
+ const agent = Agent.parse(existing.agentKey);
176
+ return {
177
+ text: [
178
+ "Agent already initialized.",
179
+ `Agent DID: \`${agent.did()}\``,
180
+ "",
181
+ existing.setupComplete
182
+ ? "Setup is complete. Use `/storacha-status` to check sync state."
183
+ : "**Next step — choose one:**",
184
+ ...(!existing.setupComplete
185
+ ? [
186
+ "- **New workspace:** Have the space owner create an upload delegation for this DID, then run `/storacha-setup <upload-b64>`",
187
+ "- **Join existing:** Have the other device run `/storacha-grant <this-DID>`, then run `/storacha-join <upload-b64> <name-b64>`",
188
+ ]
189
+ : []),
190
+ ].join("\n"),
191
+ };
192
+ }
193
+ const { Agent } = await import("@storacha/ucn/pail");
194
+ const agent = await Agent.generate();
195
+ const agentKey = Agent.format(agent);
196
+ const config = { agentKey };
197
+ await saveDeviceConfig(workspace, config);
198
+ return {
199
+ text: [
200
+ "\u{1f525} Agent initialized!",
201
+ `Agent DID: \`${agent.did()}\``,
202
+ "",
203
+ "**Next step \u2014 choose one:**",
204
+ "- **New workspace:** Have the space owner create an upload delegation for this DID, then run `/storacha-setup <upload-b64>`",
205
+ "- **Join existing workspace:** Have the other device run `/storacha-grant <this-DID>`, then run `/storacha-join <upload-b64> <name-b64>`",
206
+ ].join("\n"),
207
+ };
208
+ },
209
+ });
210
+ api.registerCommand({
211
+ name: "storacha-setup",
212
+ description: "Set up a NEW Storacha workspace (first device). Usage: /storacha-setup <upload-delegation-b64>",
166
213
  acceptsArgs: true,
167
214
  handler: async (_ctx) => {
168
215
  const workspace = workspaceDir;
169
216
  if (!workspace)
170
217
  return { text: "No workspace configured." };
218
+ const config = await loadDeviceConfig(workspace);
219
+ if (!config?.agentKey) {
220
+ return { text: "Run `/storacha-init` first to generate an agent identity." };
221
+ }
222
+ if (config.setupComplete) {
223
+ return { text: "Setup already complete. Use `/storacha-status` to check sync state." };
224
+ }
171
225
  const b64 = _ctx.args?.trim();
172
226
  if (!b64) {
173
227
  return {
174
228
  text: [
175
- "Usage: `/storacha-init <upload-delegation-b64>`",
229
+ "Usage: `/storacha-setup <upload-delegation-b64>`",
176
230
  "",
177
- "This creates a **new** workspace. If you're syncing from an existing device, use `/storacha-join` instead.",
231
+ "This creates a **new** workspace. If you're joining an existing workspace, use `/storacha-join` instead.",
178
232
  ].join("\n"),
179
233
  };
180
234
  }
181
235
  // Validate delegation
182
- const bytes = Buffer.from(b64, "base64");
236
+ const bytes = decodeDelegation(b64);
183
237
  const { ok: delegation, error } = await extractDelegation(bytes);
184
238
  if (!delegation) {
185
239
  return { text: `Invalid delegation: ${error}` };
186
240
  }
187
- const { Agent } = await import("@storacha/ucn/pail");
188
- const agent = await Agent.generate();
189
- const agentKey = Agent.format(agent);
190
241
  const spaceDID = delegation.capabilities[0]?.with;
191
- const config = {
192
- agentKey,
193
- uploadDelegation: b64,
194
- spaceDID: spaceDID ?? undefined,
195
- setupComplete: true,
196
- };
242
+ config.uploadDelegation = b64;
243
+ config.spaceDID = spaceDID ?? undefined;
244
+ config.setupComplete = true;
197
245
  await saveDeviceConfig(workspace, config);
246
+ const { Agent } = await import("@storacha/ucn/pail");
247
+ const agent = Agent.parse(config.agentKey);
198
248
  return {
199
249
  text: [
200
- "\u{1f525} Storacha workspace initialized!",
250
+ "\u{1f525} Storacha workspace ready!",
201
251
  `Agent DID: \`${agent.did()}\``,
202
252
  `Space: \`${spaceDID ?? "unknown"}\``,
203
253
  "",
@@ -211,7 +261,7 @@ export default function plugin(api) {
211
261
  });
212
262
  api.registerCommand({
213
263
  name: "storacha-join",
214
- description: "Join an existing Storacha workspace from another device. Usage: /storacha-join <upload-delegation-b64> <name-delegation-b64>",
264
+ description: "Join an existing Storacha workspace from another device. Run /storacha-init first. Usage: /storacha-join <upload-delegation-b64> <name-delegation-b64>",
215
265
  acceptsArgs: true,
216
266
  handler: async (_ctx) => {
217
267
  const workspace = workspaceDir;
@@ -224,7 +274,7 @@ export default function plugin(api) {
224
274
  "Usage: `/storacha-join <upload-delegation-b64> <name-delegation-b64>`",
225
275
  "",
226
276
  "Get both delegations by running `/storacha-grant` on the existing device.",
227
- "If you're setting up a **new** workspace, use `/storacha-init` instead.",
277
+ "If you're setting up a **new** workspace, use `/storacha-setup` instead.",
228
278
  ].join("\n"),
229
279
  };
230
280
  }
@@ -242,28 +292,31 @@ export default function plugin(api) {
242
292
  };
243
293
  }
244
294
  // Validate upload delegation
245
- const uploadBytes = Buffer.from(uploadB64, "base64");
295
+ const uploadBytes = decodeDelegation(uploadB64);
246
296
  const { ok: uploadDelegation, error: uploadErr } = await extractDelegation(uploadBytes);
247
297
  if (!uploadDelegation) {
248
298
  return { text: `Invalid upload delegation: ${uploadErr}` };
249
299
  }
250
300
  // Validate name delegation
251
- const nameBytes = Buffer.from(nameB64, "base64");
301
+ const nameBytes = decodeDelegation(nameB64);
252
302
  const { ok: nameDelegation, error: nameErr } = await extractDelegation(nameBytes);
253
303
  if (!nameDelegation) {
254
304
  return { text: `Invalid name delegation: ${nameErr}` };
255
305
  }
306
+ const config = await loadDeviceConfig(workspace);
307
+ if (!config?.agentKey) {
308
+ return { text: "Run `/storacha-init` first to generate an agent identity." };
309
+ }
310
+ if (config.setupComplete) {
311
+ return { text: "Setup already complete. Use `/storacha-status` to check sync state." };
312
+ }
256
313
  const { Agent } = await import("@storacha/ucn/pail");
257
- const agent = await Agent.generate();
258
- const agentKey = Agent.format(agent);
314
+ const agent = Agent.parse(config.agentKey);
259
315
  const spaceDID = uploadDelegation.capabilities[0]?.with;
260
- const config = {
261
- agentKey,
262
- uploadDelegation: uploadB64,
263
- nameDelegation: nameB64,
264
- spaceDID: spaceDID ?? undefined,
265
- setupComplete: true,
266
- };
316
+ config.uploadDelegation = uploadB64;
317
+ config.nameDelegation = nameB64;
318
+ config.spaceDID = spaceDID ?? undefined;
319
+ config.setupComplete = true;
267
320
  await saveDeviceConfig(workspace, config);
268
321
  // Pull remote state immediately before watcher starts
269
322
  let pullCount = 0;
@@ -314,7 +367,7 @@ export default function plugin(api) {
314
367
  const config = await loadDeviceConfig(workspace);
315
368
  if (!config) {
316
369
  return {
317
- text: "Not initialized. Run `/storacha-init` or `/storacha-join` first.",
370
+ text: "Not initialized. Run `/storacha-init` first.",
318
371
  };
319
372
  }
320
373
  const results = [];
@@ -331,7 +384,7 @@ export default function plugin(api) {
331
384
  ]);
332
385
  const { ok: archiveBytes } = await uploadDelegation.archive();
333
386
  if (archiveBytes) {
334
- const b64 = Buffer.from(archiveBytes).toString("base64");
387
+ const b64 = encodeDelegation(archiveBytes);
335
388
  results.push("**Upload delegation:**\n```\n" + b64 + "\n```");
336
389
  }
337
390
  }
@@ -349,11 +402,11 @@ export default function plugin(api) {
349
402
  const agent = Agent.parse(config.agentKey);
350
403
  let name;
351
404
  if (config.nameArchive) {
352
- const archiveBytes = Buffer.from(config.nameArchive, "base64");
405
+ const archiveBytes = decodeDelegation(config.nameArchive);
353
406
  name = await Name.extract(agent, archiveBytes);
354
407
  }
355
408
  else {
356
- const nameBytes = Buffer.from(config.nameDelegation, "base64");
409
+ const nameBytes = decodeDelegation(config.nameDelegation);
357
410
  const { ok: nameDel } = await extractDelegation(nameBytes);
358
411
  if (!nameDel) {
359
412
  results.push("\u274c Failed to extract name delegation.");
@@ -366,7 +419,7 @@ export default function plugin(api) {
366
419
  const nameDel = await name.grant(targetDID);
367
420
  const { ok: archiveBytes } = await nameDel.archive();
368
421
  if (archiveBytes) {
369
- const b64 = Buffer.from(archiveBytes).toString("base64");
422
+ const b64 = encodeDelegation(archiveBytes);
370
423
  results.push("**Name delegation:**\n```\n" + b64 + "\n```");
371
424
  }
372
425
  }
@@ -403,7 +456,7 @@ export default function plugin(api) {
403
456
  const config = await loadDeviceConfig(workspace);
404
457
  if (!config)
405
458
  return {
406
- text: "Not initialized. Run /storacha-init or /storacha-join first.",
459
+ text: "Not initialized. Run `/storacha-init` first.",
407
460
  };
408
461
  const lines = [
409
462
  "\u{1f525} Storacha Sync Status",
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,OAAO,KAAK,EACV,SAAS,EACT,UAAU,EAEV,YAAY,EACb,MAAM,kBAAkB,CAAC;AAS1B,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAExE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,qBAAa,UAAU;IACrB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,IAAI,CAAyB;IACrC,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,cAAc,CAAS;gBAEnB,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAMrD;;OAEG;IACG,IAAI,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAgC/C;;OAEG;IACG,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAe1D;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkD3B;;OAEG;YACW,iBAAiB;IAc/B;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC;IAc5C;;OAEG;YACW,kBAAkB;IAWhC;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IA0B7B,MAAM,IAAI,OAAO,CAAC,SAAS,CAAC;IAW5B,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;YAM5B,WAAW;CAK1B"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,OAAO,KAAK,EACV,SAAS,EACT,UAAU,EAEV,YAAY,EACb,MAAM,kBAAkB,CAAC;AAS1B,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAExE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG1C,qBAAa,UAAU;IACrB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,IAAI,CAAyB;IACrC,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,cAAc,CAAS;gBAEnB,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAMrD;;OAEG;IACG,IAAI,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAgC/C;;OAEG;IACG,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAe1D;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkD3B;;OAEG;YACW,iBAAiB;IAc/B;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC;IAc5C;;OAEG;YACW,kBAAkB;IAWhC;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IA0B7B,MAAM,IAAI,OAAO,CAAC,SAAS,CAAC;IAW5B,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;YAM5B,WAAW;CAK1B"}
package/dist/sync.js CHANGED
@@ -16,6 +16,7 @@ import { applyRemoteChanges } from "./handlers/remote.js";
16
16
  import { processChanges } from "./handlers/process.js";
17
17
  import { diffRemoteChanges } from "./utils/differ.js";
18
18
  import { makeTempCar } from "./utils/tempcar.js";
19
+ import { decodeDelegation, encodeDelegation } from "./utils/delegation.js";
19
20
  export class SyncEngine {
20
21
  workspace;
21
22
  blocks;
@@ -38,13 +39,13 @@ export class SyncEngine {
38
39
  const agent = Agent.parse(config.agentKey);
39
40
  if (config.nameArchive) {
40
41
  // Restore from previously saved archive (has full state)
41
- const archiveBytes = Buffer.from(config.nameArchive, "base64");
42
+ const archiveBytes = decodeDelegation(config.nameArchive);
42
43
  this.name = await Name.extract(agent, archiveBytes);
43
44
  }
44
45
  else if (config.nameDelegation) {
45
46
  // Reconstruct from delegation (granted by another device)
46
47
  const { extract } = await import("@storacha/client/delegation");
47
- const nameBytes = Buffer.from(config.nameDelegation, "base64");
48
+ const nameBytes = decodeDelegation(config.nameDelegation);
48
49
  const { ok: delegation } = await extract(nameBytes);
49
50
  if (!delegation)
50
51
  throw new Error("Failed to extract name delegation");
@@ -205,7 +206,7 @@ export class SyncEngine {
205
206
  if (!this.name)
206
207
  throw new Error("Sync engine not initialized");
207
208
  const bytes = await this.name.archive();
208
- return Buffer.from(bytes).toString("base64");
209
+ return encodeDelegation(bytes);
209
210
  }
210
211
  async storeBlocks(blocks) {
211
212
  for (const block of blocks) {
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/utils/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE/C;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,MAAM,CAAC,CA8BjB"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/utils/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE/C;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,MAAM,CAAC,CA8BjB"}
@@ -8,6 +8,7 @@ import { Agent as PailAgent } from "@storacha/ucn/pail";
8
8
  import { create as createClient } from "@storacha/client";
9
9
  import { StoreMemory } from "@storacha/client/stores/memory";
10
10
  import { extract } from "@storacha/client/delegation";
11
+ import { decodeDelegation } from "./delegation.js";
11
12
  /**
12
13
  * Build a Storacha Client from device config.
13
14
  * Requires agentKey and uploadDelegation to be present.
@@ -22,7 +23,7 @@ export async function createStorachaClient(config) {
22
23
  store: new StoreMemory(),
23
24
  });
24
25
  // Import the upload delegation (space → agent)
25
- const uploadBytes = Buffer.from(config.uploadDelegation, "base64");
26
+ const uploadBytes = decodeDelegation(config.uploadDelegation);
26
27
  const { ok: uploadDelegation, error: uploadErr } = await extract(uploadBytes);
27
28
  if (!uploadDelegation) {
28
29
  throw new Error(`Failed to extract upload delegation: ${uploadErr}`);
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Delegation encoding/decoding utilities.
3
+ *
4
+ * Delegations are serialized as CIDv1 with the CAR codec (0x0202)
5
+ * and identity multihash, encoded as base64. This matches the format
6
+ * used by the Storacha CLI (`storacha delegation create --base64`).
7
+ */
8
+ /**
9
+ * Encode delegation archive bytes as a CID string (base64).
10
+ * archive bytes → CIDv1(CAR, identity) → base64 string
11
+ */
12
+ export declare function encodeDelegation(archiveBytes: Uint8Array): string;
13
+ /**
14
+ * Decode a delegation CID string back to archive bytes.
15
+ * base64 string → CID → identity multihash digest → bytes
16
+ */
17
+ export declare function decodeDelegation(encoded: string): Uint8Array;
18
+ //# sourceMappingURL=delegation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegation.d.ts","sourceRoot":"","sources":["../../src/utils/delegation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,UAAU,GAAG,MAAM,CAGjE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,CAQ5D"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Delegation encoding/decoding utilities.
3
+ *
4
+ * Delegations are serialized as CIDv1 with the CAR codec (0x0202)
5
+ * and identity multihash, encoded as base64. This matches the format
6
+ * used by the Storacha CLI (`storacha delegation create --base64`).
7
+ */
8
+ import { CID } from "multiformats/cid";
9
+ import { base64 } from "multiformats/bases/base64";
10
+ import { identity } from "multiformats/hashes/identity";
11
+ /** CAR codec code (multicodec 0x0202) */
12
+ const CAR_CODE = 0x0202;
13
+ /**
14
+ * Encode delegation archive bytes as a CID string (base64).
15
+ * archive bytes → CIDv1(CAR, identity) → base64 string
16
+ */
17
+ export function encodeDelegation(archiveBytes) {
18
+ const cid = CID.createV1(CAR_CODE, identity.digest(archiveBytes));
19
+ return cid.toString(base64);
20
+ }
21
+ /**
22
+ * Decode a delegation CID string back to archive bytes.
23
+ * base64 string → CID → identity multihash digest → bytes
24
+ */
25
+ export function decodeDelegation(encoded) {
26
+ const cid = CID.parse(encoded, base64);
27
+ if (cid.multihash.code !== identity.code) {
28
+ throw new Error("Invalid delegation encoding: expected identity multihash");
29
+ }
30
+ return cid.multihash.digest;
31
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storacha/clawracha",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "OpenClaw plugin for Storacha workspace sync via UCN Pail",
5
5
  "type": "module",
6
6
  "files": [