mnemospark 0.8.3 → 0.9.1
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 +3 -1
- package/dist/cli.js +137 -29
- package/dist/cli.js.map +1 -1
- package/dist/index.js +137 -29
- package/dist/index.js.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/skills/mnemospark/SKILL.md +2 -2
- package/skills/mnemospark/references/commands.md +1 -1
package/README.md
CHANGED
|
@@ -59,9 +59,11 @@ Use via `/mnemospark_cloud ...` in OpenClaw chat.
|
|
|
59
59
|
### Get a storage quote
|
|
60
60
|
|
|
61
61
|
```text
|
|
62
|
-
/mnemospark_cloud price-storage --wallet-address <addr> --object-id <id> --object-id-hash <sha256> --gb <gb> --provider
|
|
62
|
+
/mnemospark_cloud price-storage --wallet-address <addr> --object-id <id> --object-id-hash <sha256> --gb <gb> --provider aws --region us-east-1
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
+
Use other regions by changing `--provider` and `--region` (defaults: `aws` / `us-east-1`).
|
|
66
|
+
|
|
65
67
|
### Upload using quote
|
|
66
68
|
|
|
67
69
|
```text
|
package/dist/cli.js
CHANGED
|
@@ -2973,10 +2973,12 @@ import {
|
|
|
2973
2973
|
randomBytes as randomBytesNode,
|
|
2974
2974
|
randomUUID as randomUUID3
|
|
2975
2975
|
} from "crypto";
|
|
2976
|
-
import { createReadStream as createReadStream2, statfsSync } from "fs";
|
|
2976
|
+
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, statfsSync } from "fs";
|
|
2977
2977
|
import { lstat, mkdir as mkdir5, readFile as readFile3, readdir as readdir2, rm, stat as stat2, writeFile as writeFile3 } from "fs/promises";
|
|
2978
|
-
import { homedir as homedir6 } from "os";
|
|
2978
|
+
import { homedir as homedir6, tmpdir } from "os";
|
|
2979
2979
|
import { basename as basename2, dirname as dirname5, join as join8, resolve as resolve2 } from "path";
|
|
2980
|
+
import { Readable } from "stream";
|
|
2981
|
+
import { finished } from "stream/promises";
|
|
2980
2982
|
import { privateKeyToAccount as privateKeyToAccount5 } from "viem/accounts";
|
|
2981
2983
|
|
|
2982
2984
|
// src/cloud-ls-format.ts
|
|
@@ -3374,6 +3376,7 @@ async function createCloudDatastore(homeDir) {
|
|
|
3374
3376
|
addOperationsColumn("subagent_session_id", "TEXT");
|
|
3375
3377
|
addOperationsColumn("timeout_seconds", "INTEGER");
|
|
3376
3378
|
addOperationsColumn("cancel_requested_at", "TEXT");
|
|
3379
|
+
addOperationsColumn("result_text", "TEXT");
|
|
3377
3380
|
nextDb.prepare(
|
|
3378
3381
|
`INSERT INTO schema_migrations(version, applied_at)
|
|
3379
3382
|
VALUES(?, ?)
|
|
@@ -3565,8 +3568,8 @@ async function createCloudDatastore(homeDir) {
|
|
|
3565
3568
|
const ts = nowIso();
|
|
3566
3569
|
const terminalStatuses = /* @__PURE__ */ new Set(["succeeded", "failed", "cancelled", "timed_out"]);
|
|
3567
3570
|
db.prepare(
|
|
3568
|
-
`INSERT INTO operations(operation_id, type, object_id, quote_id, trace_id, orchestrator, subagent_session_id, timeout_seconds, cancel_requested_at, status, error_code, error_message, started_at, finished_at, created_at, updated_at)
|
|
3569
|
-
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3571
|
+
`INSERT INTO operations(operation_id, type, object_id, quote_id, trace_id, orchestrator, subagent_session_id, timeout_seconds, cancel_requested_at, status, error_code, error_message, result_text, started_at, finished_at, created_at, updated_at)
|
|
3572
|
+
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3570
3573
|
ON CONFLICT(operation_id) DO UPDATE SET
|
|
3571
3574
|
type=excluded.type,
|
|
3572
3575
|
object_id=COALESCE(excluded.object_id, operations.object_id),
|
|
@@ -3579,6 +3582,7 @@ async function createCloudDatastore(homeDir) {
|
|
|
3579
3582
|
status=excluded.status,
|
|
3580
3583
|
error_code=excluded.error_code,
|
|
3581
3584
|
error_message=excluded.error_message,
|
|
3585
|
+
result_text=COALESCE(excluded.result_text, operations.result_text),
|
|
3582
3586
|
started_at=COALESCE(excluded.started_at, operations.started_at),
|
|
3583
3587
|
finished_at=COALESCE(excluded.finished_at, operations.finished_at),
|
|
3584
3588
|
updated_at=excluded.updated_at`
|
|
@@ -3595,6 +3599,7 @@ async function createCloudDatastore(homeDir) {
|
|
|
3595
3599
|
row.status,
|
|
3596
3600
|
row.error_code,
|
|
3597
3601
|
row.error_message,
|
|
3602
|
+
row.result_text ?? null,
|
|
3598
3603
|
row.status === "started" ? ts : null,
|
|
3599
3604
|
terminalStatuses.has(row.status) ? ts : null,
|
|
3600
3605
|
ts,
|
|
@@ -3604,7 +3609,7 @@ async function createCloudDatastore(homeDir) {
|
|
|
3604
3609
|
},
|
|
3605
3610
|
findOperationById: async (operationId) => safe(() => {
|
|
3606
3611
|
const row = db.prepare(
|
|
3607
|
-
`SELECT operation_id, type, object_id, quote_id, trace_id, orchestrator, subagent_session_id, timeout_seconds, cancel_requested_at, status, error_code, error_message, started_at, finished_at, updated_at
|
|
3612
|
+
`SELECT operation_id, type, object_id, quote_id, trace_id, orchestrator, subagent_session_id, timeout_seconds, cancel_requested_at, status, error_code, error_message, result_text, started_at, finished_at, updated_at
|
|
3608
3613
|
FROM operations
|
|
3609
3614
|
WHERE operation_id = ?
|
|
3610
3615
|
LIMIT 1`
|
|
@@ -3763,6 +3768,7 @@ var DEFAULT_BACKUP_DIR = join8(homedir6(), BACKUP_DIR_SUBPATH);
|
|
|
3763
3768
|
var BLOCKRUN_WALLET_KEY_SUBPATH = join8(".openclaw", "blockrun", "wallet.key");
|
|
3764
3769
|
var MNEMOSPARK_WALLET_KEY_SUBPATH = join8(".openclaw", "mnemospark", "wallet", "wallet.key");
|
|
3765
3770
|
var INLINE_UPLOAD_MAX_BYTES = 45e5;
|
|
3771
|
+
var NODE_FS_MAX_READFILE_BYTES = 2147483648;
|
|
3766
3772
|
var PAYMENT_CRON_SCHEDULE = "0 0 1 * *";
|
|
3767
3773
|
var TAR_OVERHEAD_BYTES = 10 * 1024 * 1024;
|
|
3768
3774
|
var QUOTE_VALIDITY_USER_NOTE = "Quotes are valid for one hour. Please run price-storage again if you need a new quote.";
|
|
@@ -3809,8 +3815,8 @@ var CLOUD_HELP_TEXT = [
|
|
|
3809
3815
|
" Purpose: create a local tar+gzip archive under ~/.openclaw/mnemospark/backup (filename from sanitized friendly name) and record metadata in SQLite for later price-storage and upload.",
|
|
3810
3816
|
" Required: " + REQUIRED_BACKUP,
|
|
3811
3817
|
"",
|
|
3812
|
-
"\u2022 `/mnemospark_cloud price-storage --wallet-address <addr> --object-id <id> --object-id-hash <hash> --gb <gb> --provider
|
|
3813
|
-
" Purpose: request a storage quote before upload.",
|
|
3818
|
+
"\u2022 `/mnemospark_cloud price-storage --wallet-address <addr> --object-id <id> --object-id-hash <hash> --gb <gb> --provider aws --region us-east-1`",
|
|
3819
|
+
" Purpose: request a storage quote before upload (defaults shown; override `--provider` / `--region` for other regions).",
|
|
3814
3820
|
" Required: " + REQUIRED_PRICE_STORAGE,
|
|
3815
3821
|
"",
|
|
3816
3822
|
"\u2022 `/mnemospark_cloud upload --quote-id <quote-id> --wallet-address <addr> --object-id <id> --object-id-hash <hash> [--name <friendly-name>] [--async] [--orchestrator <inline|subagent>] [--timeout-seconds <n>]`",
|
|
@@ -4686,6 +4692,39 @@ function encryptAesGcm(plaintext, key, randomFn = randomBytesNode) {
|
|
|
4686
4692
|
const tag = cipher.getAuthTag();
|
|
4687
4693
|
return Buffer.concat([nonce, ciphertext, tag]);
|
|
4688
4694
|
}
|
|
4695
|
+
async function encryptPlaintextFileToAesGcmPath(plaintextPath, dek, outPath, randomFn = randomBytesNode) {
|
|
4696
|
+
if (dek.length !== 32) {
|
|
4697
|
+
throw new Error("Expected 32-byte AES key");
|
|
4698
|
+
}
|
|
4699
|
+
const nonce = randomFn(AES_GCM_NONCE_BYTES);
|
|
4700
|
+
const cipher = createCipheriv("aes-256-gcm", dek, nonce);
|
|
4701
|
+
const writeStream = createWriteStream2(outPath, { flags: "w" });
|
|
4702
|
+
writeStream.write(nonce);
|
|
4703
|
+
try {
|
|
4704
|
+
for await (const chunk of createReadStream2(plaintextPath)) {
|
|
4705
|
+
const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
4706
|
+
const out = cipher.update(buf);
|
|
4707
|
+
if (out.length) {
|
|
4708
|
+
await new Promise((resolve3, reject) => {
|
|
4709
|
+
writeStream.write(out, (err) => err ? reject(err) : resolve3());
|
|
4710
|
+
});
|
|
4711
|
+
}
|
|
4712
|
+
}
|
|
4713
|
+
const final = cipher.final();
|
|
4714
|
+
const tag = cipher.getAuthTag();
|
|
4715
|
+
await new Promise((resolve3, reject) => {
|
|
4716
|
+
writeStream.write(final, (err) => err ? reject(err) : resolve3());
|
|
4717
|
+
});
|
|
4718
|
+
await new Promise((resolve3, reject) => {
|
|
4719
|
+
writeStream.write(tag, (err) => err ? reject(err) : resolve3());
|
|
4720
|
+
});
|
|
4721
|
+
writeStream.end();
|
|
4722
|
+
await finished(writeStream);
|
|
4723
|
+
} catch (err) {
|
|
4724
|
+
writeStream.destroy();
|
|
4725
|
+
throw err;
|
|
4726
|
+
}
|
|
4727
|
+
}
|
|
4689
4728
|
async function loadOrCreateKek(walletAddress, homeDir) {
|
|
4690
4729
|
const keyPath = resolveWalletKekPath(walletAddress, homeDir);
|
|
4691
4730
|
await mkdir5(dirname5(keyPath), { recursive: true });
|
|
@@ -4702,11 +4741,42 @@ async function loadOrCreateKek(walletAddress, homeDir) {
|
|
|
4702
4741
|
return { kek: generated, keyPath };
|
|
4703
4742
|
}
|
|
4704
4743
|
async function prepareUploadPayload(archivePath, walletAddress, homeDir) {
|
|
4705
|
-
const
|
|
4744
|
+
const archiveStat = await stat2(archivePath);
|
|
4745
|
+
if (!archiveStat.isFile()) {
|
|
4746
|
+
throw new Error(`Cannot read backup archive: not a file (${archivePath}).`);
|
|
4747
|
+
}
|
|
4706
4748
|
const { kek, keyPath } = await loadOrCreateKek(walletAddress, homeDir);
|
|
4707
4749
|
const dek = randomBytesNode(32);
|
|
4708
|
-
const encryptedContent = encryptAesGcm(plaintext, dek);
|
|
4709
4750
|
const wrappedDek = encryptAesGcm(dek, kek);
|
|
4751
|
+
if (archiveStat.size >= NODE_FS_MAX_READFILE_BYTES) {
|
|
4752
|
+
const encryptedTempPath = join8(tmpdir(), `mnemospark-upload-${randomUUID3()}.enc`);
|
|
4753
|
+
try {
|
|
4754
|
+
await encryptPlaintextFileToAesGcmPath(archivePath, dek, encryptedTempPath);
|
|
4755
|
+
const encStat = await stat2(encryptedTempPath);
|
|
4756
|
+
const payloadHash2 = await sha256File(encryptedTempPath);
|
|
4757
|
+
const payload2 = {
|
|
4758
|
+
mode: "presigned",
|
|
4759
|
+
content_base64: void 0,
|
|
4760
|
+
content_sha256: payloadHash2,
|
|
4761
|
+
content_length_bytes: encStat.size,
|
|
4762
|
+
wrapped_dek: wrappedDek.toString("base64"),
|
|
4763
|
+
encryption_algorithm: "AES-256-GCM",
|
|
4764
|
+
bucket_name_hint: bucketNameForWallet(walletAddress),
|
|
4765
|
+
key_store_path_hint: keyPath
|
|
4766
|
+
};
|
|
4767
|
+
return {
|
|
4768
|
+
payload: payload2,
|
|
4769
|
+
encryptedContent: null,
|
|
4770
|
+
encryptedTempPath
|
|
4771
|
+
};
|
|
4772
|
+
} catch (err) {
|
|
4773
|
+
await rm(encryptedTempPath, { force: true }).catch(() => {
|
|
4774
|
+
});
|
|
4775
|
+
throw err;
|
|
4776
|
+
}
|
|
4777
|
+
}
|
|
4778
|
+
const plaintext = await readFile3(archivePath);
|
|
4779
|
+
const encryptedContent = encryptAesGcm(plaintext, dek);
|
|
4710
4780
|
const payloadHash = sha256Buffer(encryptedContent);
|
|
4711
4781
|
const payload = {
|
|
4712
4782
|
mode: encryptedContent.length <= INLINE_UPLOAD_MAX_BYTES ? "inline" : "presigned",
|
|
@@ -4723,7 +4793,17 @@ async function prepareUploadPayload(archivePath, walletAddress, homeDir) {
|
|
|
4723
4793
|
encryptedContent
|
|
4724
4794
|
};
|
|
4725
4795
|
}
|
|
4726
|
-
|
|
4796
|
+
function presignedPutBodyInit(encryptedContent, encryptedTempPath) {
|
|
4797
|
+
if (encryptedTempPath?.trim()) {
|
|
4798
|
+
const body = Readable.toWeb(createReadStream2(encryptedTempPath));
|
|
4799
|
+
return { body, duplex: "half" };
|
|
4800
|
+
}
|
|
4801
|
+
if (encryptedContent) {
|
|
4802
|
+
return { body: new Uint8Array(encryptedContent) };
|
|
4803
|
+
}
|
|
4804
|
+
throw new Error("Cannot upload storage object: missing encrypted payload body.");
|
|
4805
|
+
}
|
|
4806
|
+
async function uploadPresignedObjectIfNeeded(uploadResponse, uploadMode, encryptedContent, encryptedTempPath, fetchImpl = fetch) {
|
|
4727
4807
|
if (!uploadResponse.upload_url) {
|
|
4728
4808
|
if (uploadMode === "presigned") {
|
|
4729
4809
|
throw new Error("Cannot upload storage object: missing presigned upload URL.");
|
|
@@ -4734,24 +4814,33 @@ async function uploadPresignedObjectIfNeeded(uploadResponse, uploadMode, encrypt
|
|
|
4734
4814
|
if (!headers.has("content-type")) {
|
|
4735
4815
|
headers.set("content-type", "application/octet-stream");
|
|
4736
4816
|
}
|
|
4737
|
-
const
|
|
4738
|
-
const
|
|
4817
|
+
const { body, duplex } = presignedPutBodyInit(encryptedContent, encryptedTempPath);
|
|
4818
|
+
const firstInit = {
|
|
4739
4819
|
method: "PUT",
|
|
4740
4820
|
headers,
|
|
4741
|
-
body
|
|
4821
|
+
body,
|
|
4742
4822
|
redirect: "manual"
|
|
4743
|
-
}
|
|
4823
|
+
};
|
|
4824
|
+
if (duplex) {
|
|
4825
|
+
firstInit.duplex = duplex;
|
|
4826
|
+
}
|
|
4827
|
+
const firstAttempt = await fetchImpl(uploadResponse.upload_url, firstInit);
|
|
4744
4828
|
if (firstAttempt.ok) {
|
|
4745
4829
|
return;
|
|
4746
4830
|
}
|
|
4747
4831
|
if ((firstAttempt.status === 307 || firstAttempt.status === 308) && firstAttempt.headers.has("location")) {
|
|
4748
4832
|
const location = firstAttempt.headers.get("location")?.trim();
|
|
4749
4833
|
if (location) {
|
|
4750
|
-
const
|
|
4834
|
+
const retryBody = presignedPutBodyInit(encryptedContent, encryptedTempPath);
|
|
4835
|
+
const retryInit = {
|
|
4751
4836
|
method: "PUT",
|
|
4752
4837
|
headers,
|
|
4753
|
-
body:
|
|
4754
|
-
}
|
|
4838
|
+
body: retryBody.body
|
|
4839
|
+
};
|
|
4840
|
+
if (retryBody.duplex) {
|
|
4841
|
+
retryInit.duplex = retryBody.duplex;
|
|
4842
|
+
}
|
|
4843
|
+
const redirectedAttempt = await fetchImpl(location, retryInit);
|
|
4755
4844
|
if (redirectedAttempt.ok) {
|
|
4756
4845
|
return;
|
|
4757
4846
|
}
|
|
@@ -4879,9 +4968,11 @@ function formatPriceStorageUserMessage(quote, localArchiveHint) {
|
|
|
4879
4968
|
function quoteLookupMatchesPriceStorageResponse(lookup, quote) {
|
|
4880
4969
|
return lookup.quoteId === quote.quote_id && lookup.walletAddress.trim().toLowerCase() === quote.addr.trim().toLowerCase() && lookup.objectId === quote.object_id && lookup.objectIdHash.toLowerCase() === quote.object_id_hash.toLowerCase() && lookup.storagePrice === quote.storage_price && lookup.provider === quote.provider && lookup.location === quote.location;
|
|
4881
4970
|
}
|
|
4971
|
+
var DEFAULT_BACKUP_QUOTE_PROVIDER = "aws";
|
|
4972
|
+
var DEFAULT_BACKUP_QUOTE_REGION = "us-east-1";
|
|
4882
4973
|
function formatBackupSuccessUserMessage(result, walletAddress, friendlyName) {
|
|
4883
4974
|
const hash = result.objectIdHash.replace(/\s/g, "");
|
|
4884
|
-
const priceStorageLine = `/mnemospark_cloud price-storage --wallet-address \`${walletAddress}\` --object-id \`${result.objectId}\` --object-id-hash \`${hash}\` --gb \`${result.objectSizeGb}\` --provider
|
|
4975
|
+
const priceStorageLine = `/mnemospark_cloud price-storage --wallet-address \`${walletAddress}\` --object-id \`${result.objectId}\` --object-id-hash \`${hash}\` --gb \`${result.objectSizeGb}\` --provider ${DEFAULT_BACKUP_QUOTE_PROVIDER} --region ${DEFAULT_BACKUP_QUOTE_REGION}`;
|
|
4885
4976
|
return [
|
|
4886
4977
|
`Backup archive: \`${result.archivePath}\``,
|
|
4887
4978
|
"",
|
|
@@ -4890,10 +4981,12 @@ function formatBackupSuccessUserMessage(result, walletAddress, friendlyName) {
|
|
|
4890
4981
|
`object-id-hash: ${hash}`,
|
|
4891
4982
|
`object-size: ${result.objectSizeGb}`,
|
|
4892
4983
|
"",
|
|
4893
|
-
"Next, request a storage quote.
|
|
4984
|
+
"Next, request a storage quote.",
|
|
4894
4985
|
"",
|
|
4895
4986
|
priceStorageLine,
|
|
4896
4987
|
"",
|
|
4988
|
+
`The default region is ${DEFAULT_BACKUP_QUOTE_REGION}. Change the command parameters to switch regions (not required).`,
|
|
4989
|
+
"",
|
|
4897
4990
|
"Region examples (merge into the command above):",
|
|
4898
4991
|
"North America: `--provider aws --region us-east-1`",
|
|
4899
4992
|
"Europe: `--provider aws --region eu-north-1`",
|
|
@@ -5407,8 +5500,8 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5407
5500
|
const datastore = await createCloudDatastore(mnemosparkHomeDir);
|
|
5408
5501
|
const terminalOperationStatuses = /* @__PURE__ */ new Set(["succeeded", "failed", "cancelled", "timed_out"]);
|
|
5409
5502
|
const isTerminalOperationStatus = (status) => terminalOperationStatuses.has(status);
|
|
5410
|
-
const formatOperationStatus = (operation) =>
|
|
5411
|
-
|
|
5503
|
+
const formatOperationStatus = (operation) => {
|
|
5504
|
+
const meta = [
|
|
5412
5505
|
`operation-id: ${operation.operation_id}`,
|
|
5413
5506
|
`type: ${operation.type}`,
|
|
5414
5507
|
`status: ${operation.status}`,
|
|
@@ -5419,9 +5512,15 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5419
5512
|
operation.timeout_seconds ? `timeout-seconds: ${operation.timeout_seconds}` : null,
|
|
5420
5513
|
operation.error_code ? `error-code: ${operation.error_code}` : null,
|
|
5421
5514
|
operation.error_message ? `error-message: ${operation.error_message}` : null
|
|
5422
|
-
].filter((v) => Boolean(v)).join("\n")
|
|
5423
|
-
|
|
5424
|
-
|
|
5515
|
+
].filter((v) => Boolean(v)).join("\n");
|
|
5516
|
+
const withResult = operation.status === "succeeded" && operation.result_text?.trim() ? `${meta}
|
|
5517
|
+
|
|
5518
|
+
${operation.result_text}` : meta;
|
|
5519
|
+
return {
|
|
5520
|
+
text: withResult,
|
|
5521
|
+
isError: operation.status === "failed" || operation.status === "cancelled" || operation.status === "timed_out"
|
|
5522
|
+
};
|
|
5523
|
+
};
|
|
5425
5524
|
if (parsed.mode === "op-status") {
|
|
5426
5525
|
let operation = await datastore.findOperationById(parsed.operationId);
|
|
5427
5526
|
if (!operation) {
|
|
@@ -5758,7 +5857,7 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5758
5857
|
mnemosparkHomeDir
|
|
5759
5858
|
);
|
|
5760
5859
|
},
|
|
5761
|
-
onCompleted: async (sessionId) => {
|
|
5860
|
+
onCompleted: async (sessionId, result) => {
|
|
5762
5861
|
await datastore.upsertOperation({
|
|
5763
5862
|
operation_id: operationId,
|
|
5764
5863
|
type: opType,
|
|
@@ -5770,7 +5869,8 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5770
5869
|
timeout_seconds: timeoutSeconds,
|
|
5771
5870
|
status: "succeeded",
|
|
5772
5871
|
error_code: null,
|
|
5773
|
-
error_message: null
|
|
5872
|
+
error_message: null,
|
|
5873
|
+
result_text: result.isError ? null : result.text
|
|
5774
5874
|
});
|
|
5775
5875
|
await emitOperationEventBestEffort(
|
|
5776
5876
|
"operation.completed",
|
|
@@ -5947,7 +6047,8 @@ operation-id: ${operationId}`,
|
|
|
5947
6047
|
orchestrator: "inline",
|
|
5948
6048
|
status: result.isError ? "failed" : "succeeded",
|
|
5949
6049
|
error_code: result.isError ? "ASYNC_FAILED" : null,
|
|
5950
|
-
error_message: result.isError ? result.text : null
|
|
6050
|
+
error_message: result.isError ? result.text : null,
|
|
6051
|
+
result_text: result.isError ? null : result.text
|
|
5951
6052
|
});
|
|
5952
6053
|
await emitOperationEventBestEffort(
|
|
5953
6054
|
"operation.completed",
|
|
@@ -6027,7 +6128,7 @@ operation-id: ${operationId}`,
|
|
|
6027
6128
|
await emitCloudEventBestEffort(
|
|
6028
6129
|
"backup.completed",
|
|
6029
6130
|
{
|
|
6030
|
-
operation_id: randomUUID3(),
|
|
6131
|
+
operation_id: executionContext.forcedOperationId?.trim() || randomUUID3(),
|
|
6031
6132
|
object_id: result.objectId,
|
|
6032
6133
|
status: "succeeded",
|
|
6033
6134
|
details: {
|
|
@@ -6152,6 +6253,7 @@ operation-id: ${operationId}`,
|
|
|
6152
6253
|
executionContext.forcedOperationId ?? idempotencyKeyFn(),
|
|
6153
6254
|
executionContext.forcedTraceId
|
|
6154
6255
|
);
|
|
6256
|
+
let preparedPayload;
|
|
6155
6257
|
try {
|
|
6156
6258
|
const loggedQuote = await datastore.findQuoteById(parsed.uploadRequest.quote_id);
|
|
6157
6259
|
if (!loggedQuote) {
|
|
@@ -6223,7 +6325,7 @@ operation-id: ${operationId}`,
|
|
|
6223
6325
|
isError: true
|
|
6224
6326
|
};
|
|
6225
6327
|
}
|
|
6226
|
-
|
|
6328
|
+
preparedPayload = await prepareUploadPayload(
|
|
6227
6329
|
archivePath,
|
|
6228
6330
|
parsed.uploadRequest.wallet_address,
|
|
6229
6331
|
mnemosparkHomeDir
|
|
@@ -6267,6 +6369,7 @@ operation-id: ${operationId}`,
|
|
|
6267
6369
|
uploadResponse,
|
|
6268
6370
|
preparedPayload.payload.mode,
|
|
6269
6371
|
preparedPayload.encryptedContent,
|
|
6372
|
+
preparedPayload.encryptedTempPath,
|
|
6270
6373
|
fetchImpl
|
|
6271
6374
|
);
|
|
6272
6375
|
let finalizedUploadResponse = uploadResponse;
|
|
@@ -6404,6 +6507,11 @@ operation-id: ${operationId}`,
|
|
|
6404
6507
|
text: uploadErrorMessage ?? "Cannot upload storage object",
|
|
6405
6508
|
isError: true
|
|
6406
6509
|
};
|
|
6510
|
+
} finally {
|
|
6511
|
+
if (preparedPayload?.encryptedTempPath) {
|
|
6512
|
+
await rm(preparedPayload.encryptedTempPath, { force: true }).catch(() => {
|
|
6513
|
+
});
|
|
6514
|
+
}
|
|
6407
6515
|
}
|
|
6408
6516
|
}
|
|
6409
6517
|
if (parsed.mode === "ls") {
|