@storacha/clawracha 0.0.9 → 0.0.11-rc.0
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/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +291 -234
- package/package.json +2 -2
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;AAyC7B;;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;AAyC7B;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,GAAG,EAAE,iBAAiB,QA4hBpD"}
|
package/dist/plugin.js
CHANGED
|
@@ -165,46 +165,53 @@ export default function plugin(api) {
|
|
|
165
165
|
name: "storacha-init",
|
|
166
166
|
description: "Generate an agent identity for Storacha sync",
|
|
167
167
|
handler: async (_ctx) => {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
168
|
+
try {
|
|
169
|
+
const workspace = workspaceDir;
|
|
170
|
+
if (!workspace)
|
|
171
|
+
return { text: "No workspace configured." };
|
|
172
|
+
// Check if already initialized
|
|
173
|
+
const existing = await loadDeviceConfig(workspace);
|
|
174
|
+
if (existing?.agentKey) {
|
|
175
|
+
const { Agent } = await import("@storacha/ucn/pail");
|
|
176
|
+
const agent = Agent.parse(existing.agentKey);
|
|
177
|
+
return {
|
|
178
|
+
text: [
|
|
179
|
+
"Agent already initialized.",
|
|
180
|
+
`Agent DID: \`${agent.did()}\``,
|
|
181
|
+
"",
|
|
182
|
+
existing.setupComplete
|
|
183
|
+
? "Setup is complete. Use `/storacha-status` to check sync state."
|
|
184
|
+
: "**Next step — choose one:**",
|
|
185
|
+
...(!existing.setupComplete
|
|
186
|
+
? [
|
|
187
|
+
"- **New workspace:** Have the space owner create an upload delegation for this DID, then run `/storacha-setup <upload-b64>`",
|
|
188
|
+
"- **Join existing:** Have the other device run `/storacha-grant <this-DID>`, then run `/storacha-join <upload-b64> <name-b64>`",
|
|
189
|
+
]
|
|
190
|
+
: []),
|
|
191
|
+
].join("\n"),
|
|
192
|
+
};
|
|
193
|
+
}
|
|
174
194
|
const { Agent } = await import("@storacha/ucn/pail");
|
|
175
|
-
const agent = Agent.
|
|
195
|
+
const agent = await Agent.generate();
|
|
196
|
+
const agentKey = Agent.format(agent);
|
|
197
|
+
const config = { agentKey };
|
|
198
|
+
await saveDeviceConfig(workspace, config);
|
|
176
199
|
return {
|
|
177
200
|
text: [
|
|
178
|
-
"Agent
|
|
201
|
+
"\u{1f525} Agent initialized!",
|
|
179
202
|
`Agent DID: \`${agent.did()}\``,
|
|
180
203
|
"",
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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
|
-
: []),
|
|
204
|
+
"**Next step \u2014 choose one:**",
|
|
205
|
+
"- **New workspace:** Have the space owner create an upload delegation for this DID, then run `/storacha-setup <upload-b64>`",
|
|
206
|
+
"- **Join existing workspace:** Have the other device run `/storacha-grant <this-DID>`, then run `/storacha-join <upload-b64> <name-b64>`",
|
|
190
207
|
].join("\n"),
|
|
191
208
|
};
|
|
192
209
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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
|
-
};
|
|
210
|
+
catch (err) {
|
|
211
|
+
return {
|
|
212
|
+
text: `\u274c Command failed: ${err.message}\n\`\`\`\n${err.stack ?? err}\n\`\`\``,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
208
215
|
},
|
|
209
216
|
});
|
|
210
217
|
api.registerCommand({
|
|
@@ -212,41 +219,58 @@ export default function plugin(api) {
|
|
|
212
219
|
description: "Set up a NEW Storacha workspace (first device). Usage: /storacha-setup <upload-delegation-b64>",
|
|
213
220
|
acceptsArgs: true,
|
|
214
221
|
handler: async (_ctx) => {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
222
|
+
try {
|
|
223
|
+
const workspace = workspaceDir;
|
|
224
|
+
if (!workspace)
|
|
225
|
+
return { text: "No workspace configured." };
|
|
226
|
+
const config = await loadDeviceConfig(workspace);
|
|
227
|
+
if (!config?.agentKey) {
|
|
228
|
+
return {
|
|
229
|
+
text: "Run `/storacha-init` first to generate an agent identity.",
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
if (config.setupComplete) {
|
|
233
|
+
return {
|
|
234
|
+
text: "Setup already complete. Use `/storacha-status` to check sync state.",
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
const b64 = _ctx.args?.trim();
|
|
238
|
+
if (!b64) {
|
|
239
|
+
return {
|
|
240
|
+
text: [
|
|
241
|
+
"Usage: `/storacha-setup <upload-delegation-b64>`",
|
|
242
|
+
"",
|
|
243
|
+
"This creates a **new** workspace. If you're joining an existing workspace, use `/storacha-join` instead.",
|
|
244
|
+
].join("\n"),
|
|
245
|
+
};
|
|
246
|
+
}
|
|
227
247
|
return {
|
|
228
248
|
text: [
|
|
229
|
-
"
|
|
249
|
+
"You ran '/storacha-setup' without the following command argument:",
|
|
230
250
|
"",
|
|
231
|
-
|
|
251
|
+
b64,
|
|
232
252
|
].join("\n"),
|
|
233
253
|
};
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
254
|
+
/*
|
|
255
|
+
// Validate delegation
|
|
256
|
+
const bytes = decodeDelegation(b64);
|
|
257
|
+
const { ok: delegation, error } = await extractDelegation(bytes);
|
|
258
|
+
if (!delegation) {
|
|
259
|
+
return { text: `Invalid delegation: ${error}` };
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const spaceDID = delegation.capabilities[0]?.with;
|
|
263
|
+
|
|
264
|
+
config.uploadDelegation = b64;
|
|
265
|
+
config.spaceDID = spaceDID ?? undefined;
|
|
266
|
+
config.setupComplete = true;
|
|
267
|
+
await saveDeviceConfig(workspace, config);
|
|
268
|
+
|
|
269
|
+
const { Agent } = await import("@storacha/ucn/pail");
|
|
270
|
+
const agent = Agent.parse(config.agentKey);
|
|
271
|
+
|
|
272
|
+
return {
|
|
273
|
+
text: [
|
|
250
274
|
"\u{1f525} Storacha workspace ready!",
|
|
251
275
|
`Agent DID: \`${agent.did()}\``,
|
|
252
276
|
`Space: \`${spaceDID ?? "unknown"}\``,
|
|
@@ -255,8 +279,14 @@ export default function plugin(api) {
|
|
|
255
279
|
"",
|
|
256
280
|
"To add another device, run `/storacha-grant <their-agent-DID>` here,",
|
|
257
281
|
"then `/storacha-join <upload-b64> <name-b64>` on the other device.",
|
|
258
|
-
|
|
259
|
-
|
|
282
|
+
].join("\n"),
|
|
283
|
+
};*/
|
|
284
|
+
}
|
|
285
|
+
catch (err) {
|
|
286
|
+
return {
|
|
287
|
+
text: `\u274c Command failed: ${err.message}\n\`\`\`\n${err.stack ?? err}\n\`\`\``,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
260
290
|
},
|
|
261
291
|
});
|
|
262
292
|
api.registerCommand({
|
|
@@ -264,92 +294,103 @@ export default function plugin(api) {
|
|
|
264
294
|
description: "Join an existing Storacha workspace from another device. Run /storacha-init first. Usage: /storacha-join <upload-delegation-b64> <name-delegation-b64>",
|
|
265
295
|
acceptsArgs: true,
|
|
266
296
|
handler: async (_ctx) => {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
297
|
+
try {
|
|
298
|
+
const workspace = workspaceDir;
|
|
299
|
+
if (!workspace)
|
|
300
|
+
return { text: "No workspace configured." };
|
|
301
|
+
const args = _ctx.args?.trim();
|
|
302
|
+
if (!args) {
|
|
303
|
+
return {
|
|
304
|
+
text: [
|
|
305
|
+
"Usage: `/storacha-join <upload-delegation-b64> <name-delegation-b64>`",
|
|
306
|
+
"",
|
|
307
|
+
"Get both delegations by running `/storacha-grant` on the existing device.",
|
|
308
|
+
"If you're setting up a **new** workspace, use `/storacha-setup` instead.",
|
|
309
|
+
].join("\n"),
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
const spaceIdx = args.indexOf(" ");
|
|
313
|
+
if (spaceIdx === -1) {
|
|
314
|
+
return {
|
|
315
|
+
text: "Two arguments required: `/storacha-join <upload-b64> <name-b64>`",
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
const uploadB64 = args.slice(0, spaceIdx).trim();
|
|
319
|
+
const nameB64 = args.slice(spaceIdx + 1).trim();
|
|
320
|
+
if (!uploadB64 || !nameB64) {
|
|
321
|
+
return {
|
|
322
|
+
text: "Two arguments required: `/storacha-join <upload-b64> <name-b64>`",
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
// Validate upload delegation
|
|
326
|
+
const uploadBytes = decodeDelegation(uploadB64);
|
|
327
|
+
const { ok: uploadDelegation, error: uploadErr } = await extractDelegation(uploadBytes);
|
|
328
|
+
if (!uploadDelegation) {
|
|
329
|
+
return { text: `Invalid upload delegation: ${uploadErr}` };
|
|
330
|
+
}
|
|
331
|
+
// Validate name delegation
|
|
332
|
+
const nameBytes = decodeDelegation(nameB64);
|
|
333
|
+
const { ok: nameDelegation, error: nameErr } = await extractDelegation(nameBytes);
|
|
334
|
+
if (!nameDelegation) {
|
|
335
|
+
return { text: `Invalid name delegation: ${nameErr}` };
|
|
336
|
+
}
|
|
337
|
+
const config = await loadDeviceConfig(workspace);
|
|
338
|
+
if (!config?.agentKey) {
|
|
339
|
+
return {
|
|
340
|
+
text: "Run `/storacha-init` first to generate an agent identity.",
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
if (config.setupComplete) {
|
|
344
|
+
return {
|
|
345
|
+
text: "Setup already complete. Use `/storacha-status` to check sync state.",
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
const { Agent } = await import("@storacha/ucn/pail");
|
|
349
|
+
const agent = Agent.parse(config.agentKey);
|
|
350
|
+
const spaceDID = uploadDelegation.capabilities[0]?.with;
|
|
351
|
+
config.uploadDelegation = uploadB64;
|
|
352
|
+
config.nameDelegation = nameB64;
|
|
353
|
+
config.spaceDID = spaceDID ?? undefined;
|
|
354
|
+
config.setupComplete = true;
|
|
355
|
+
await saveDeviceConfig(workspace, config);
|
|
356
|
+
// Pull remote state immediately before watcher starts
|
|
357
|
+
let pullCount = 0;
|
|
358
|
+
try {
|
|
359
|
+
const storachaClient = await createStorachaClient(config);
|
|
360
|
+
const engine = new SyncEngine(storachaClient, workspace);
|
|
361
|
+
await engine.init(config);
|
|
362
|
+
pullCount = await engine.pullRemote();
|
|
363
|
+
// Save name archive after pull
|
|
364
|
+
const nameArchive = await engine.exportNameArchive();
|
|
365
|
+
config.nameArchive = nameArchive;
|
|
366
|
+
await saveDeviceConfig(workspace, config);
|
|
367
|
+
}
|
|
368
|
+
catch (err) {
|
|
369
|
+
return {
|
|
370
|
+
text: [
|
|
371
|
+
"\u26a0\ufe0f Delegations saved but initial pull failed:",
|
|
372
|
+
`\`${err.message}\``,
|
|
373
|
+
"",
|
|
374
|
+
"Restart the gateway to retry.",
|
|
375
|
+
].join("\n"),
|
|
376
|
+
};
|
|
377
|
+
}
|
|
272
378
|
return {
|
|
273
379
|
text: [
|
|
274
|
-
"
|
|
380
|
+
"\u{1f525} Joined existing Storacha workspace!",
|
|
381
|
+
`Agent DID: \`${agent.did()}\``,
|
|
382
|
+
`Space: \`${spaceDID ?? "unknown"}\``,
|
|
383
|
+
`Pulled ${pullCount} files from remote.`,
|
|
275
384
|
"",
|
|
276
|
-
"
|
|
277
|
-
"If you're setting up a **new** workspace, use `/storacha-setup` instead.",
|
|
385
|
+
"Restart the gateway to start syncing.",
|
|
278
386
|
].join("\n"),
|
|
279
387
|
};
|
|
280
388
|
}
|
|
281
|
-
const spaceIdx = args.indexOf(" ");
|
|
282
|
-
if (spaceIdx === -1) {
|
|
283
|
-
return {
|
|
284
|
-
text: "Two arguments required: `/storacha-join <upload-b64> <name-b64>`",
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
const uploadB64 = args.slice(0, spaceIdx).trim();
|
|
288
|
-
const nameB64 = args.slice(spaceIdx + 1).trim();
|
|
289
|
-
if (!uploadB64 || !nameB64) {
|
|
290
|
-
return {
|
|
291
|
-
text: "Two arguments required: `/storacha-join <upload-b64> <name-b64>`",
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
// Validate upload delegation
|
|
295
|
-
const uploadBytes = decodeDelegation(uploadB64);
|
|
296
|
-
const { ok: uploadDelegation, error: uploadErr } = await extractDelegation(uploadBytes);
|
|
297
|
-
if (!uploadDelegation) {
|
|
298
|
-
return { text: `Invalid upload delegation: ${uploadErr}` };
|
|
299
|
-
}
|
|
300
|
-
// Validate name delegation
|
|
301
|
-
const nameBytes = decodeDelegation(nameB64);
|
|
302
|
-
const { ok: nameDelegation, error: nameErr } = await extractDelegation(nameBytes);
|
|
303
|
-
if (!nameDelegation) {
|
|
304
|
-
return { text: `Invalid name delegation: ${nameErr}` };
|
|
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
|
-
}
|
|
313
|
-
const { Agent } = await import("@storacha/ucn/pail");
|
|
314
|
-
const agent = Agent.parse(config.agentKey);
|
|
315
|
-
const spaceDID = uploadDelegation.capabilities[0]?.with;
|
|
316
|
-
config.uploadDelegation = uploadB64;
|
|
317
|
-
config.nameDelegation = nameB64;
|
|
318
|
-
config.spaceDID = spaceDID ?? undefined;
|
|
319
|
-
config.setupComplete = true;
|
|
320
|
-
await saveDeviceConfig(workspace, config);
|
|
321
|
-
// Pull remote state immediately before watcher starts
|
|
322
|
-
let pullCount = 0;
|
|
323
|
-
try {
|
|
324
|
-
const storachaClient = await createStorachaClient(config);
|
|
325
|
-
const engine = new SyncEngine(storachaClient, workspace);
|
|
326
|
-
await engine.init(config);
|
|
327
|
-
pullCount = await engine.pullRemote();
|
|
328
|
-
// Save name archive after pull
|
|
329
|
-
const nameArchive = await engine.exportNameArchive();
|
|
330
|
-
config.nameArchive = nameArchive;
|
|
331
|
-
await saveDeviceConfig(workspace, config);
|
|
332
|
-
}
|
|
333
389
|
catch (err) {
|
|
334
390
|
return {
|
|
335
|
-
text:
|
|
336
|
-
"\u26a0\ufe0f Delegations saved but initial pull failed:",
|
|
337
|
-
`\`${err.message}\``,
|
|
338
|
-
"",
|
|
339
|
-
"Restart the gateway to retry.",
|
|
340
|
-
].join("\n"),
|
|
391
|
+
text: `\u274c Command failed: ${err.message}\n\`\`\`\n${err.stack ?? err}\n\`\`\``,
|
|
341
392
|
};
|
|
342
393
|
}
|
|
343
|
-
return {
|
|
344
|
-
text: [
|
|
345
|
-
"\u{1f525} Joined existing Storacha workspace!",
|
|
346
|
-
`Agent DID: \`${agent.did()}\``,
|
|
347
|
-
`Space: \`${spaceDID ?? "unknown"}\``,
|
|
348
|
-
`Pulled ${pullCount} files from remote.`,
|
|
349
|
-
"",
|
|
350
|
-
"Restart the gateway to start syncing.",
|
|
351
|
-
].join("\n"),
|
|
352
|
-
};
|
|
353
394
|
},
|
|
354
395
|
});
|
|
355
396
|
api.registerCommand({
|
|
@@ -357,121 +398,137 @@ export default function plugin(api) {
|
|
|
357
398
|
description: "Grant another device access. Usage: /storacha-grant <target-DID>",
|
|
358
399
|
acceptsArgs: true,
|
|
359
400
|
handler: async (_ctx) => {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
const config = await loadDeviceConfig(workspace);
|
|
368
|
-
if (!config) {
|
|
369
|
-
return {
|
|
370
|
-
text: "Not initialized. Run `/storacha-init` first.",
|
|
371
|
-
};
|
|
372
|
-
}
|
|
373
|
-
const results = [];
|
|
374
|
-
// Re-delegate upload capability
|
|
375
|
-
if (config.uploadDelegation) {
|
|
376
|
-
try {
|
|
377
|
-
const storachaClient = await createStorachaClient(config);
|
|
378
|
-
const audience = { did: () => targetDID };
|
|
379
|
-
const uploadDelegation = await storachaClient.createDelegation(audience, [
|
|
380
|
-
"space/blob/add",
|
|
381
|
-
"space/index/add",
|
|
382
|
-
"upload/add",
|
|
383
|
-
"filecoin/offer",
|
|
384
|
-
]);
|
|
385
|
-
const { ok: archiveBytes } = await uploadDelegation.archive();
|
|
386
|
-
if (archiveBytes) {
|
|
387
|
-
const b64 = encodeDelegation(archiveBytes);
|
|
388
|
-
results.push("**Upload delegation:**\n```\n" + b64 + "\n```");
|
|
389
|
-
}
|
|
401
|
+
try {
|
|
402
|
+
const workspace = workspaceDir;
|
|
403
|
+
if (!workspace)
|
|
404
|
+
return { text: "No workspace configured." };
|
|
405
|
+
const targetDID = _ctx.args?.trim();
|
|
406
|
+
if (!targetDID || !targetDID.startsWith("did:")) {
|
|
407
|
+
return { text: "Usage: `/storacha-grant <did:key:z...>`" };
|
|
390
408
|
}
|
|
391
|
-
|
|
392
|
-
|
|
409
|
+
const config = await loadDeviceConfig(workspace);
|
|
410
|
+
if (!config) {
|
|
411
|
+
return {
|
|
412
|
+
text: "Not initialized. Run `/storacha-init` first.",
|
|
413
|
+
};
|
|
393
414
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
415
|
+
const results = [];
|
|
416
|
+
// Re-delegate upload capability
|
|
417
|
+
if (config.uploadDelegation) {
|
|
418
|
+
try {
|
|
419
|
+
const storachaClient = await createStorachaClient(config);
|
|
420
|
+
const audience = { did: () => targetDID };
|
|
421
|
+
const uploadDelegation = await storachaClient.createDelegation(audience, [
|
|
422
|
+
"space/blob/add",
|
|
423
|
+
"space/index/add",
|
|
424
|
+
"upload/add",
|
|
425
|
+
"filecoin/offer",
|
|
426
|
+
]);
|
|
427
|
+
const { ok: archiveBytes } = await uploadDelegation.archive();
|
|
428
|
+
if (archiveBytes) {
|
|
429
|
+
const b64 = encodeDelegation(archiveBytes);
|
|
430
|
+
results.push("**Upload delegation:**\n```\n" + b64 + "\n```");
|
|
431
|
+
}
|
|
407
432
|
}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
433
|
+
catch (err) {
|
|
434
|
+
results.push(`\u274c Failed to create upload delegation: ${err.message}`);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
results.push("\u26a0\ufe0f No upload delegation to re-delegate.");
|
|
439
|
+
}
|
|
440
|
+
// Re-delegate name (pail sync) capability
|
|
441
|
+
if (config.nameDelegation) {
|
|
442
|
+
try {
|
|
443
|
+
const { Agent, Name } = await import("@storacha/ucn/pail");
|
|
444
|
+
const agent = Agent.parse(config.agentKey);
|
|
445
|
+
let name;
|
|
446
|
+
if (config.nameArchive) {
|
|
447
|
+
const archiveBytes = decodeDelegation(config.nameArchive);
|
|
448
|
+
name = await Name.extract(agent, archiveBytes);
|
|
413
449
|
}
|
|
414
450
|
else {
|
|
415
|
-
|
|
451
|
+
const nameBytes = decodeDelegation(config.nameDelegation);
|
|
452
|
+
const { ok: nameDel } = await extractDelegation(nameBytes);
|
|
453
|
+
if (!nameDel) {
|
|
454
|
+
results.push("\u274c Failed to extract name delegation.");
|
|
455
|
+
}
|
|
456
|
+
else {
|
|
457
|
+
name = Name.from(agent, [nameDel]);
|
|
458
|
+
}
|
|
416
459
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
460
|
+
if (name) {
|
|
461
|
+
const nameDel = await name.grant(targetDID);
|
|
462
|
+
const { ok: archiveBytes } = await nameDel.archive();
|
|
463
|
+
if (archiveBytes) {
|
|
464
|
+
const b64 = encodeDelegation(archiveBytes);
|
|
465
|
+
results.push("**Name delegation:**\n```\n" + b64 + "\n```");
|
|
466
|
+
}
|
|
424
467
|
}
|
|
425
468
|
}
|
|
469
|
+
catch (err) {
|
|
470
|
+
results.push(`\u274c Failed to create name delegation: ${err.message}`);
|
|
471
|
+
}
|
|
426
472
|
}
|
|
427
|
-
|
|
428
|
-
results.push(
|
|
473
|
+
else {
|
|
474
|
+
results.push("\u26a0\ufe0f No name delegation to re-delegate.");
|
|
429
475
|
}
|
|
476
|
+
if (results.length === 0) {
|
|
477
|
+
return { text: "Nothing to grant. Set up this device first." };
|
|
478
|
+
}
|
|
479
|
+
return {
|
|
480
|
+
text: [
|
|
481
|
+
`\u{1f525} Delegations for \`${targetDID}\`:`,
|
|
482
|
+
"",
|
|
483
|
+
...results,
|
|
484
|
+
"",
|
|
485
|
+
"The target device should run:",
|
|
486
|
+
"`/storacha-join <upload-b64> <name-b64>`",
|
|
487
|
+
].join("\n"),
|
|
488
|
+
};
|
|
430
489
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
return { text: "Nothing to grant. Set up this device first." };
|
|
490
|
+
catch (err) {
|
|
491
|
+
return {
|
|
492
|
+
text: `\u274c Command failed: ${err.message}\n\`\`\`\n${err.stack ?? err}\n\`\`\``,
|
|
493
|
+
};
|
|
436
494
|
}
|
|
437
|
-
return {
|
|
438
|
-
text: [
|
|
439
|
-
`\u{1f525} Delegations for \`${targetDID}\`:`,
|
|
440
|
-
"",
|
|
441
|
-
...results,
|
|
442
|
-
"",
|
|
443
|
-
"The target device should run:",
|
|
444
|
-
"`/storacha-join <upload-b64> <name-b64>`",
|
|
445
|
-
].join("\n"),
|
|
446
|
-
};
|
|
447
495
|
},
|
|
448
496
|
});
|
|
449
497
|
api.registerCommand({
|
|
450
498
|
name: "storacha-status",
|
|
451
499
|
description: "Show Storacha sync status",
|
|
452
500
|
handler: async (_ctx) => {
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
501
|
+
try {
|
|
502
|
+
const workspace = workspaceDir;
|
|
503
|
+
if (!workspace)
|
|
504
|
+
return { text: "No workspace configured." };
|
|
505
|
+
const config = await loadDeviceConfig(workspace);
|
|
506
|
+
if (!config)
|
|
507
|
+
return {
|
|
508
|
+
text: "Not initialized. Run `/storacha-init` first.",
|
|
509
|
+
};
|
|
510
|
+
const lines = [
|
|
511
|
+
"\u{1f525} Storacha Sync Status",
|
|
512
|
+
`Agent: configured`,
|
|
513
|
+
`Upload delegation: ${config.uploadDelegation ? "\u2705" : "\u274c not set"}`,
|
|
514
|
+
`Name delegation: ${config.nameDelegation ? "\u2705" : "\u274c not set"}`,
|
|
515
|
+
`Space DID: ${config.spaceDID ?? "unknown"}`,
|
|
516
|
+
`Name Archive: ${config.nameArchive ? "saved" : "not created"}`,
|
|
517
|
+
`Setup complete: ${config.setupComplete ? "\u2705" : "\u274c"}`,
|
|
518
|
+
];
|
|
519
|
+
if (syncEngine) {
|
|
520
|
+
const status = await syncEngine.status();
|
|
521
|
+
lines.push(`Running: ${status.running}`, `Last Sync: ${status.lastSync
|
|
522
|
+
? new Date(status.lastSync).toISOString()
|
|
523
|
+
: "never"}`, `Entries: ${status.entryCount}`, `Pending: ${status.pendingChanges}`);
|
|
524
|
+
}
|
|
525
|
+
return { text: lines.join("\n") };
|
|
526
|
+
}
|
|
527
|
+
catch (err) {
|
|
458
528
|
return {
|
|
459
|
-
text:
|
|
529
|
+
text: `\u274c Command failed: ${err.message}\n\`\`\`\n${err.stack ?? err}\n\`\`\``,
|
|
460
530
|
};
|
|
461
|
-
const lines = [
|
|
462
|
-
"\u{1f525} Storacha Sync Status",
|
|
463
|
-
`Agent: configured`,
|
|
464
|
-
`Upload delegation: ${config.uploadDelegation ? "\u2705" : "\u274c not set"}`,
|
|
465
|
-
`Name delegation: ${config.nameDelegation ? "\u2705" : "\u274c not set"}`,
|
|
466
|
-
`Space DID: ${config.spaceDID ?? "unknown"}`,
|
|
467
|
-
`Name Archive: ${config.nameArchive ? "saved" : "not created"}`,
|
|
468
|
-
`Setup complete: ${config.setupComplete ? "\u2705" : "\u274c"}`,
|
|
469
|
-
];
|
|
470
|
-
if (syncEngine) {
|
|
471
|
-
const status = await syncEngine.status();
|
|
472
|
-
lines.push(`Running: ${status.running}`, `Last Sync: ${status.lastSync ? new Date(status.lastSync).toISOString() : "never"}`, `Entries: ${status.entryCount}`, `Pending: ${status.pendingChanges}`);
|
|
473
531
|
}
|
|
474
|
-
return { text: lines.join("\n") };
|
|
475
532
|
},
|
|
476
533
|
});
|
|
477
534
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storacha/clawracha",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11-rc.0",
|
|
4
4
|
"description": "OpenClaw plugin for Storacha workspace sync via UCN Pail",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"@web3-storage/pail": "0.6.3-rc.3",
|
|
37
37
|
"carstream": "^2.3.0",
|
|
38
38
|
"chokidar": "^3.6.0",
|
|
39
|
-
"multiformats": "^13.
|
|
39
|
+
"multiformats": "^13.3.6"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@ipld/unixfs": "^3.0.0",
|