@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 +15 -5
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +89 -36
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +4 -3
- package/dist/utils/client.d.ts.map +1 -1
- package/dist/utils/client.js +2 -1
- package/dist/utils/delegation.d.ts +18 -0
- package/dist/utils/delegation.d.ts.map +1 -0
- package/dist/utils/delegation.js +31 -0
- package/package.json +1 -1
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
|
-
###
|
|
26
|
+
### Step 1: Initialize the agent
|
|
27
27
|
|
|
28
28
|
```
|
|
29
|
-
/storacha-init
|
|
29
|
+
/storacha-init
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
Generates an agent identity and displays the Agent DID. You'll need this DID to create delegations.
|
|
33
33
|
|
|
34
|
-
###
|
|
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
|
-
|
|
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
|
|
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;
|
|
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
|
|
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
|
|
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
|
|
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: "
|
|
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-
|
|
229
|
+
"Usage: `/storacha-setup <upload-delegation-b64>`",
|
|
176
230
|
"",
|
|
177
|
-
"This creates a **new** workspace. If you're
|
|
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 =
|
|
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
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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
|
|
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-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
258
|
-
const agentKey = Agent.format(agent);
|
|
314
|
+
const agent = Agent.parse(config.agentKey);
|
|
259
315
|
const spaceDID = uploadDelegation.capabilities[0]?.with;
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
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`
|
|
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 =
|
|
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 =
|
|
405
|
+
const archiveBytes = decodeDelegation(config.nameArchive);
|
|
353
406
|
name = await Name.extract(agent, archiveBytes);
|
|
354
407
|
}
|
|
355
408
|
else {
|
|
356
|
-
const nameBytes =
|
|
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 =
|
|
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
|
|
459
|
+
text: "Not initialized. Run `/storacha-init` first.",
|
|
407
460
|
};
|
|
408
461
|
const lines = [
|
|
409
462
|
"\u{1f525} Storacha Sync Status",
|
package/dist/sync.d.ts.map
CHANGED
|
@@ -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;
|
|
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 =
|
|
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 =
|
|
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
|
|
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;
|
|
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"}
|
package/dist/utils/client.js
CHANGED
|
@@ -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 =
|
|
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
|
+
}
|