mnemospark 0.5.0 → 0.7.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/cli.js +201 -405
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +201 -405
- package/dist/index.js.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -2
- package/skills/mnemospark/references/state-and-logs.md +17 -13
- package/skills/mnemospark/references/troubleshooting.md +4 -2
- package/skills/mnemospark/scripts/debug-operation.sh +1 -7
package/dist/cli.js
CHANGED
|
@@ -1602,8 +1602,8 @@ import { homedir as homedir2 } from "os";
|
|
|
1602
1602
|
import { basename, dirname as dirname2, join as join3 } from "path";
|
|
1603
1603
|
import { pipeline } from "stream/promises";
|
|
1604
1604
|
var BASE_DIR = join3(homedir2(), ".openclaw", "mnemospark");
|
|
1605
|
-
var MAX_BYTES =
|
|
1606
|
-
var KEEP_ROTATED =
|
|
1605
|
+
var MAX_BYTES = 15 * 1024 * 1024;
|
|
1606
|
+
var KEEP_ROTATED = 12;
|
|
1607
1607
|
function resolvePath(fileName, homeDir) {
|
|
1608
1608
|
const baseDir = homeDir ? join3(homeDir, ".openclaw", "mnemospark") : BASE_DIR;
|
|
1609
1609
|
return join3(baseDir, fileName);
|
|
@@ -1694,10 +1694,11 @@ function logProxyEvent(level, event, fields = {}) {
|
|
|
1694
1694
|
console.info(message);
|
|
1695
1695
|
}
|
|
1696
1696
|
function emitProxyEvent(eventType, status, correlation, details = {}) {
|
|
1697
|
-
void appendJsonlEvent("
|
|
1697
|
+
void appendJsonlEvent("events.jsonl", {
|
|
1698
1698
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1699
1699
|
event_type: eventType,
|
|
1700
1700
|
status,
|
|
1701
|
+
source: "proxy",
|
|
1701
1702
|
trace_id: correlation.trace_id,
|
|
1702
1703
|
operation_id: correlation.operation_id,
|
|
1703
1704
|
quote_id: correlation.quote_id ?? null,
|
|
@@ -2890,7 +2891,14 @@ import { CronExpressionParser } from "cron-parser";
|
|
|
2890
2891
|
var LS_NAME_DISPLAY_MAX = 72;
|
|
2891
2892
|
var LS_PAY_DISPLAY_MAX = 28;
|
|
2892
2893
|
var LS_CRON_ID_MAX = 14;
|
|
2893
|
-
var
|
|
2894
|
+
var LS_S3_COL_WIDTH = 12;
|
|
2895
|
+
var LS_NEXT_COL_WIDTH = Math.max(LS_S3_COL_WIDTH, "NEXT PAYMENT DATE".length);
|
|
2896
|
+
var HDR_SIZE = "SIZE";
|
|
2897
|
+
var HDR_S3_TIME = "S3_TIME";
|
|
2898
|
+
var HDR_CRON_JOB = "CRON JOB";
|
|
2899
|
+
var HDR_NEXT_PAYMENT = "NEXT PAYMENT DATE";
|
|
2900
|
+
var HDR_AMOUNT_DUE = "AMOUNT DUE";
|
|
2901
|
+
var HDR_FILE_OR_KEY = "FILE NAME OR OBJECT-KEY";
|
|
2894
2902
|
var MONTHS_SHORT = [
|
|
2895
2903
|
"Jan",
|
|
2896
2904
|
"Feb",
|
|
@@ -2905,14 +2913,14 @@ var MONTHS_SHORT = [
|
|
|
2905
2913
|
"Nov",
|
|
2906
2914
|
"Dec"
|
|
2907
2915
|
];
|
|
2908
|
-
function formatLsTimeFieldUtc(iso, now) {
|
|
2909
|
-
const placeholder = " - ".slice(0,
|
|
2916
|
+
function formatLsTimeFieldUtc(iso, now, fieldWidth = LS_S3_COL_WIDTH) {
|
|
2917
|
+
const placeholder = " - ".slice(0, fieldWidth);
|
|
2910
2918
|
if (!iso) {
|
|
2911
|
-
return placeholder.padEnd(
|
|
2919
|
+
return placeholder.padEnd(fieldWidth, " ");
|
|
2912
2920
|
}
|
|
2913
2921
|
const d = new Date(iso);
|
|
2914
2922
|
if (Number.isNaN(d.getTime())) {
|
|
2915
|
-
return placeholder.padEnd(
|
|
2923
|
+
return placeholder.padEnd(fieldWidth, " ");
|
|
2916
2924
|
}
|
|
2917
2925
|
const mon = MONTHS_SHORT[d.getUTCMonth()] ?? "???";
|
|
2918
2926
|
const day = String(d.getUTCDate()).padStart(2, " ");
|
|
@@ -2926,7 +2934,7 @@ function formatLsTimeFieldUtc(iso, now) {
|
|
|
2926
2934
|
} else {
|
|
2927
2935
|
core = `${mon} ${day} ${y}`;
|
|
2928
2936
|
}
|
|
2929
|
-
return core.padEnd(
|
|
2937
|
+
return core.padEnd(fieldWidth, " ");
|
|
2930
2938
|
}
|
|
2931
2939
|
function truncateEnd(value, max) {
|
|
2932
2940
|
if (value.length <= max) {
|
|
@@ -2966,18 +2974,26 @@ function formatPaymentCell(amount, network, maxWidth) {
|
|
|
2966
2974
|
return truncateEnd(s, maxWidth).padStart(maxWidth, " ");
|
|
2967
2975
|
}
|
|
2968
2976
|
function formatNextCronUtc(schedule, cronStatus, now) {
|
|
2969
|
-
const blank = " - ".slice(0,
|
|
2977
|
+
const blank = " - ".slice(0, LS_NEXT_COL_WIDTH).padEnd(LS_NEXT_COL_WIDTH, " ");
|
|
2970
2978
|
if (cronStatus !== "active") {
|
|
2971
2979
|
return blank;
|
|
2972
2980
|
}
|
|
2973
2981
|
try {
|
|
2974
2982
|
const expr = CronExpressionParser.parse(schedule, { tz: "UTC", currentDate: now });
|
|
2975
2983
|
const next = expr.next().toDate();
|
|
2976
|
-
return formatLsTimeFieldUtc(next.toISOString(), now);
|
|
2984
|
+
return formatLsTimeFieldUtc(next.toISOString(), now, LS_NEXT_COL_WIDTH);
|
|
2977
2985
|
} catch {
|
|
2978
|
-
return "?".padEnd(
|
|
2986
|
+
return "?".padEnd(LS_NEXT_COL_WIDTH, " ");
|
|
2979
2987
|
}
|
|
2980
2988
|
}
|
|
2989
|
+
function buildLsProseIntro(bucket) {
|
|
2990
|
+
return [
|
|
2991
|
+
"\u2601\uFE0F mnemospark cloud files",
|
|
2992
|
+
`S3 bucket: ${bucket}`,
|
|
2993
|
+
"The columns: CRON JOB, NEXT PAYMENT DATE, AMOUNT DUE, FILE NAME are from this host's mnemospark SQLite catalog",
|
|
2994
|
+
"mnemospark cloud only stores the OBJECT-KEY for privacy"
|
|
2995
|
+
];
|
|
2996
|
+
}
|
|
2981
2997
|
async function prepareRows(objects, walletAddress, datastore, now) {
|
|
2982
2998
|
const sorted = [...objects].sort((a, b) => {
|
|
2983
2999
|
const ta = a.last_modified ? Date.parse(a.last_modified) : Number.NaN;
|
|
@@ -3000,9 +3016,9 @@ async function prepareRows(objects, walletAddress, datastore, now) {
|
|
|
3000
3016
|
const friendly = await datastore.findLatestFriendlyNameForObjectKey(walletAddress, obj.key);
|
|
3001
3017
|
const cp = await datastore.findCronAndPaymentForObjectKey(walletAddress, obj.key);
|
|
3002
3018
|
const sizeStr = formatBytesForDisplay(obj.size_bytes);
|
|
3003
|
-
const s3time = formatLsTimeFieldUtc(obj.last_modified, now);
|
|
3019
|
+
const s3time = formatLsTimeFieldUtc(obj.last_modified, now, LS_S3_COL_WIDTH);
|
|
3004
3020
|
let cronIdDisp = null;
|
|
3005
|
-
let nextRun = " - ".slice(0,
|
|
3021
|
+
let nextRun = " - ".slice(0, LS_NEXT_COL_WIDTH).padEnd(LS_NEXT_COL_WIDTH, " ");
|
|
3006
3022
|
let payCell = "";
|
|
3007
3023
|
if (cp) {
|
|
3008
3024
|
cronIdDisp = cp.cronId;
|
|
@@ -3013,10 +3029,6 @@ async function prepareRows(objects, walletAddress, datastore, now) {
|
|
|
3013
3029
|
}
|
|
3014
3030
|
const nameRaw = friendly ? `${friendly} (${obj.key})` : obj.key;
|
|
3015
3031
|
rows.push({
|
|
3016
|
-
perm: "----------",
|
|
3017
|
-
ln: " 1",
|
|
3018
|
-
user: "- ",
|
|
3019
|
-
grp: "- ",
|
|
3020
3032
|
sizeStr,
|
|
3021
3033
|
s3time,
|
|
3022
3034
|
cronIdRaw: cronIdDisp,
|
|
@@ -3028,68 +3040,57 @@ async function prepareRows(objects, walletAddress, datastore, now) {
|
|
|
3028
3040
|
return rows;
|
|
3029
3041
|
}
|
|
3030
3042
|
function columnWidths(rows) {
|
|
3031
|
-
let sizeW =
|
|
3032
|
-
let
|
|
3033
|
-
let
|
|
3043
|
+
let sizeW = HDR_SIZE.length;
|
|
3044
|
+
let s3W = Math.max(LS_S3_COL_WIDTH, HDR_S3_TIME.length);
|
|
3045
|
+
let nextW = LS_NEXT_COL_WIDTH;
|
|
3046
|
+
let cronW = HDR_CRON_JOB.length;
|
|
3047
|
+
let payW = HDR_AMOUNT_DUE.length;
|
|
3034
3048
|
for (const r of rows) {
|
|
3035
3049
|
sizeW = Math.max(sizeW, r.sizeStr.length);
|
|
3050
|
+
s3W = Math.max(s3W, r.s3time.length);
|
|
3051
|
+
nextW = Math.max(nextW, r.nextRun.length);
|
|
3036
3052
|
const cid = r.cronIdRaw ? truncateEnd(r.cronIdRaw, LS_CRON_ID_MAX) : "";
|
|
3037
3053
|
cronW = Math.max(cronW, cid.length || 1);
|
|
3038
3054
|
payW = Math.max(payW, r.payRaw.length);
|
|
3039
3055
|
}
|
|
3040
|
-
cronW = Math.min(Math.max(cronW,
|
|
3041
|
-
payW = Math.min(Math.max(payW,
|
|
3042
|
-
return { sizeW, cronW, payW };
|
|
3056
|
+
cronW = Math.min(Math.max(cronW, HDR_CRON_JOB.length), LS_CRON_ID_MAX);
|
|
3057
|
+
payW = Math.min(Math.max(payW, HDR_AMOUNT_DUE.length), LS_PAY_DISPLAY_MAX);
|
|
3058
|
+
return { sizeW, s3W, cronW, nextW, payW };
|
|
3043
3059
|
}
|
|
3044
3060
|
function renderRow(r, w) {
|
|
3045
3061
|
const cronPadded = formatCronIdCell(r.cronIdRaw, w.cronW);
|
|
3046
|
-
const sizePadded = r.sizeStr.padStart(w.sizeW, " ");
|
|
3047
|
-
const payPadded = r.payRaw.padStart(w.payW, " ");
|
|
3048
3062
|
return [
|
|
3049
|
-
r.
|
|
3050
|
-
r.
|
|
3051
|
-
r.user,
|
|
3052
|
-
r.grp,
|
|
3053
|
-
sizePadded,
|
|
3054
|
-
r.s3time,
|
|
3063
|
+
r.sizeStr.padStart(w.sizeW, " "),
|
|
3064
|
+
r.s3time.padEnd(w.s3W, " "),
|
|
3055
3065
|
cronPadded,
|
|
3056
|
-
r.nextRun,
|
|
3057
|
-
|
|
3066
|
+
r.nextRun.padEnd(w.nextW, " "),
|
|
3067
|
+
r.payRaw.padStart(w.payW, " "),
|
|
3058
3068
|
r.nameRaw
|
|
3059
3069
|
].join(" ");
|
|
3060
3070
|
}
|
|
3061
3071
|
function renderHeader(w) {
|
|
3062
3072
|
return [
|
|
3063
|
-
"
|
|
3064
|
-
"
|
|
3065
|
-
"
|
|
3066
|
-
"
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
"CRON".padStart(w.cronW, " "),
|
|
3070
|
-
"NEXT ".slice(0, LS_TIME_FIELD_WIDTH).padEnd(LS_TIME_FIELD_WIDTH, " "),
|
|
3071
|
-
"PAY".padStart(w.payW, " "),
|
|
3072
|
-
"NAME"
|
|
3073
|
+
HDR_SIZE.padStart(w.sizeW, " "),
|
|
3074
|
+
HDR_S3_TIME.padEnd(w.s3W, " "),
|
|
3075
|
+
HDR_CRON_JOB.padStart(w.cronW, " "),
|
|
3076
|
+
HDR_NEXT_PAYMENT.padEnd(w.nextW, " "),
|
|
3077
|
+
HDR_AMOUNT_DUE.padStart(w.payW, " "),
|
|
3078
|
+
HDR_FILE_OR_KEY
|
|
3073
3079
|
].join(" ");
|
|
3074
3080
|
}
|
|
3075
3081
|
async function buildMnemosparkLsMessage(result, ctx) {
|
|
3076
3082
|
const now = ctx.now ?? /* @__PURE__ */ new Date();
|
|
3077
3083
|
if (isStorageLsListResponse(result)) {
|
|
3078
|
-
const
|
|
3079
|
-
const legend2 = "Legend: S3_TIME and NEXT are UTC. NEXT is the next cron fire from the stored expression.";
|
|
3080
|
-
const bucketLine = `bucket: ${result.bucket}`;
|
|
3081
|
-
const sortLine = "sorted by: S3 last_modified descending (missing dates last), then key ascending.";
|
|
3084
|
+
const intro = buildLsProseIntro(result.bucket);
|
|
3082
3085
|
if (result.objects.length === 0) {
|
|
3083
|
-
|
|
3084
|
-
return lines.join("\n");
|
|
3086
|
+
return [...intro, "", "No objects in this bucket."].join("\n");
|
|
3085
3087
|
}
|
|
3086
3088
|
const rows = await prepareRows(result.objects, ctx.walletAddress, ctx.datastore, now);
|
|
3087
3089
|
const w2 = columnWidths(rows);
|
|
3088
3090
|
const header2 = renderHeader(w2);
|
|
3089
3091
|
const bodyLines = rows.map((r) => renderRow(r, w2));
|
|
3090
|
-
const totalLine = `total ${String(result.objects.length)}`;
|
|
3091
3092
|
const truncLine = result.is_truncated ? "List truncated; more objects in bucket." : null;
|
|
3092
|
-
const prose2 = [
|
|
3093
|
+
const prose2 = [...intro, ...truncLine ? [truncLine] : []].join("\n");
|
|
3093
3094
|
const fence2 = ["```", [header2, ...bodyLines].join("\n"), "```"].join("\n");
|
|
3094
3095
|
return `${prose2}
|
|
3095
3096
|
|
|
@@ -3101,10 +3102,10 @@ ${fence2}`;
|
|
|
3101
3102
|
);
|
|
3102
3103
|
const cp = await ctx.datastore.findCronAndPaymentForObjectKey(ctx.walletAddress, result.key);
|
|
3103
3104
|
const sizeStr = formatBytesForDisplay(result.size_bytes);
|
|
3104
|
-
const s3time = formatLsTimeFieldUtc(void 0, now);
|
|
3105
|
+
const s3time = formatLsTimeFieldUtc(void 0, now, LS_S3_COL_WIDTH);
|
|
3105
3106
|
let payCell = formatPaymentCell(null, null, LS_PAY_DISPLAY_MAX);
|
|
3106
3107
|
let cronIdDisp = null;
|
|
3107
|
-
let nextRun = " - ".slice(0,
|
|
3108
|
+
let nextRun = " - ".slice(0, LS_NEXT_COL_WIDTH).padEnd(LS_NEXT_COL_WIDTH, " ");
|
|
3108
3109
|
if (cp) {
|
|
3109
3110
|
cronIdDisp = cp.cronId;
|
|
3110
3111
|
nextRun = formatNextCronUtc(cp.schedule, cp.cronStatus, now);
|
|
@@ -3116,10 +3117,6 @@ ${fence2}`;
|
|
|
3116
3117
|
8
|
|
3117
3118
|
);
|
|
3118
3119
|
const prep = {
|
|
3119
|
-
perm: "----------",
|
|
3120
|
-
ln: " 1",
|
|
3121
|
-
user: "- ",
|
|
3122
|
-
grp: "- ",
|
|
3123
3120
|
sizeStr,
|
|
3124
3121
|
s3time,
|
|
3125
3122
|
cronIdRaw: cronIdDisp,
|
|
@@ -3130,11 +3127,10 @@ ${fence2}`;
|
|
|
3130
3127
|
const w = columnWidths([prep]);
|
|
3131
3128
|
const header = renderHeader(w);
|
|
3132
3129
|
const line = renderRow(prep, w);
|
|
3133
|
-
const
|
|
3134
|
-
const legend = "Legend: S3_TIME and NEXT are UTC.";
|
|
3135
|
-
const prose = [disclaimer, legend, `bucket: ${result.bucket}`, ""].join("\n");
|
|
3130
|
+
const prose = buildLsProseIntro(result.bucket).join("\n");
|
|
3136
3131
|
const fence = ["```", [header, line].join("\n"), "```"].join("\n");
|
|
3137
3132
|
return `${prose}
|
|
3133
|
+
|
|
3138
3134
|
${fence}`;
|
|
3139
3135
|
}
|
|
3140
3136
|
|
|
@@ -3645,7 +3641,6 @@ async function createCloudDatastore(homeDir) {
|
|
|
3645
3641
|
var SUPPORTED_BACKUP_PLATFORMS = /* @__PURE__ */ new Set(["darwin", "linux"]);
|
|
3646
3642
|
var BACKUP_DIR_SUBPATH = join8(".openclaw", "mnemospark", "backup");
|
|
3647
3643
|
var DEFAULT_BACKUP_DIR = join8(homedir6(), BACKUP_DIR_SUBPATH);
|
|
3648
|
-
var OBJECT_LOG_SUBPATH = join8(".openclaw", "mnemospark", "object.log");
|
|
3649
3644
|
var CRON_TABLE_SUBPATH = join8(".openclaw", "mnemospark", "crontab.txt");
|
|
3650
3645
|
var BLOCKRUN_WALLET_KEY_SUBPATH = join8(".openclaw", "blockrun", "wallet.key");
|
|
3651
3646
|
var MNEMOSPARK_WALLET_KEY_SUBPATH = join8(".openclaw", "mnemospark", "wallet", "wallet.key");
|
|
@@ -3653,8 +3648,10 @@ var INLINE_UPLOAD_MAX_BYTES = 45e5;
|
|
|
3653
3648
|
var PAYMENT_REMINDER_INTERVAL_DAYS = 30;
|
|
3654
3649
|
var PAYMENT_DELETE_DEADLINE_DAYS = 32;
|
|
3655
3650
|
var PAYMENT_CRON_SCHEDULE = "0 0 1 * *";
|
|
3656
|
-
var CRON_LOG_ROW_PREFIX = "cron";
|
|
3657
3651
|
var TAR_OVERHEAD_BYTES = 10 * 1024 * 1024;
|
|
3652
|
+
var QUOTE_VALIDITY_USER_NOTE = "Quotes are valid for one hour. Please run price-storage again if you need a new quote.";
|
|
3653
|
+
var MNEMOSPARK_SUPPORT_EMAIL = "pluggedin@mnemospark.ai";
|
|
3654
|
+
var CLOUD_HELP_FOOTER_STATE = "Local state: mnemospark records quotes, objects, payments, cron jobs, friendly names, and operation metadata in ~/.openclaw/mnemospark/state.db (SQLite). For troubleshooting and correlation, commands and the HTTP proxy append structured JSON lines to ~/.openclaw/mnemospark/events.jsonl. Monthly storage billing jobs are listed in ~/.openclaw/mnemospark/crontab.txt for your system scheduler.";
|
|
3658
3655
|
var REQUIRED_PRICE_STORAGE = "--wallet-address, --object-id, --object-id-hash, --gb, --provider, --region";
|
|
3659
3656
|
var REQUIRED_UPLOAD = "--quote-id, --wallet-address, --object-id, --object-id-hash";
|
|
3660
3657
|
var REQUIRED_PAYMENT_SETTLE = "--quote-id and --wallet-address";
|
|
@@ -3683,12 +3680,14 @@ function expandTilde(path) {
|
|
|
3683
3680
|
return path;
|
|
3684
3681
|
}
|
|
3685
3682
|
var CLOUD_HELP_TEXT = [
|
|
3686
|
-
"\u2601\uFE0F **mnemospark
|
|
3683
|
+
"\u2601\uFE0F **mnemospark - Wallet and go.** \u{1F499}",
|
|
3684
|
+
"",
|
|
3685
|
+
"**Cloud Commands**",
|
|
3687
3686
|
"",
|
|
3688
3687
|
"\u2022 `/mnemospark_cloud` or `/mnemospark_cloud help` \u2014 show this message",
|
|
3689
3688
|
"",
|
|
3690
3689
|
"\u2022 `/mnemospark_cloud backup <file|directory> [--name <friendly-name>] [--async] [--orchestrator <inline|subagent>] [--timeout-seconds <n>]`",
|
|
3691
|
-
" Purpose: create a local tar+gzip backup
|
|
3690
|
+
" Purpose: create a local tar+gzip archive under ~/.openclaw/mnemospark/backup and record metadata in SQLite for later price-storage and upload.",
|
|
3692
3691
|
" Required: <file|directory>",
|
|
3693
3692
|
"",
|
|
3694
3693
|
"\u2022 `/mnemospark_cloud price-storage --wallet-address <addr> --object-id <id> --object-id-hash <hash> --gb <gb> --provider <provider> --region <region>`",
|
|
@@ -3737,7 +3736,9 @@ var CLOUD_HELP_TEXT = [
|
|
|
3737
3736
|
"\u2022 `/mnemospark_cloud op-status --operation-id <id>`",
|
|
3738
3737
|
"\u2022 `/mnemospark_cloud op-status --operation-id <id> --cancel`",
|
|
3739
3738
|
"",
|
|
3740
|
-
|
|
3739
|
+
CLOUD_HELP_FOOTER_STATE,
|
|
3740
|
+
"",
|
|
3741
|
+
"Commands price-storage, upload, ls, download, delete, and payment-settle require --wallet-address."
|
|
3741
3742
|
].join("\n");
|
|
3742
3743
|
var UnsupportedBackupPlatformError = class extends Error {
|
|
3743
3744
|
constructor(platform) {
|
|
@@ -4110,19 +4111,9 @@ function parseCloudArgs(args) {
|
|
|
4110
4111
|
}
|
|
4111
4112
|
return { mode: "unknown" };
|
|
4112
4113
|
}
|
|
4113
|
-
function resolveObjectLogPath(homeDir) {
|
|
4114
|
-
return join8(homeDir ?? homedir6(), OBJECT_LOG_SUBPATH);
|
|
4115
|
-
}
|
|
4116
4114
|
function resolveCronTablePath(homeDir) {
|
|
4117
4115
|
return join8(homeDir ?? homedir6(), CRON_TABLE_SUBPATH);
|
|
4118
4116
|
}
|
|
4119
|
-
async function appendObjectLogLine(line, homeDir) {
|
|
4120
|
-
const objectLogPath = resolveObjectLogPath(homeDir);
|
|
4121
|
-
await mkdir5(dirname5(objectLogPath), { recursive: true });
|
|
4122
|
-
await appendFile2(objectLogPath, `${line}
|
|
4123
|
-
`, "utf-8");
|
|
4124
|
-
return objectLogPath;
|
|
4125
|
-
}
|
|
4126
4117
|
async function calculateInputSizeBytes(targetPath) {
|
|
4127
4118
|
const targetStats = await lstat(targetPath);
|
|
4128
4119
|
if (targetStats.isFile() || targetStats.isSymbolicLink()) {
|
|
@@ -4219,38 +4210,17 @@ async function buildBackupObject(targetPathArg, options = {}) {
|
|
|
4219
4210
|
const archiveStats = await stat2(archivePath);
|
|
4220
4211
|
const objectIdHash = await sha256File(archivePath);
|
|
4221
4212
|
const objectSizeGb = toGbString(archiveStats.size);
|
|
4222
|
-
const objectLogPath = await appendObjectLogLine(
|
|
4223
|
-
`${objectId},${objectIdHash},${objectSizeGb}`,
|
|
4224
|
-
options.homeDir
|
|
4225
|
-
);
|
|
4226
4213
|
return {
|
|
4227
4214
|
objectId,
|
|
4228
4215
|
objectIdHash,
|
|
4229
4216
|
objectSizeGb,
|
|
4230
|
-
archivePath
|
|
4231
|
-
objectLogPath
|
|
4217
|
+
archivePath
|
|
4232
4218
|
};
|
|
4233
4219
|
} catch (error) {
|
|
4234
4220
|
await rm(archivePath, { force: true }).catch(() => void 0);
|
|
4235
4221
|
throw error;
|
|
4236
4222
|
}
|
|
4237
4223
|
}
|
|
4238
|
-
async function appendPriceStorageQuoteLog(quote, homeDir) {
|
|
4239
|
-
return appendObjectLogLine(
|
|
4240
|
-
[
|
|
4241
|
-
quote.timestamp,
|
|
4242
|
-
quote.quote_id,
|
|
4243
|
-
quote.storage_price.toString(),
|
|
4244
|
-
quote.addr,
|
|
4245
|
-
quote.object_id,
|
|
4246
|
-
quote.object_id_hash,
|
|
4247
|
-
quote.object_size_gb.toString(),
|
|
4248
|
-
quote.provider,
|
|
4249
|
-
quote.location
|
|
4250
|
-
].join(","),
|
|
4251
|
-
homeDir
|
|
4252
|
-
);
|
|
4253
|
-
}
|
|
4254
4224
|
function formatTimestamp(date) {
|
|
4255
4225
|
const pad = (value) => value.toString().padStart(2, "0");
|
|
4256
4226
|
return [
|
|
@@ -4267,55 +4237,6 @@ function formatTimestamp(date) {
|
|
|
4267
4237
|
pad(date.getSeconds())
|
|
4268
4238
|
].join("");
|
|
4269
4239
|
}
|
|
4270
|
-
function parseLoggedPriceStorageQuote(line) {
|
|
4271
|
-
const parts = line.split(",");
|
|
4272
|
-
if (parts.length < 9) {
|
|
4273
|
-
return null;
|
|
4274
|
-
}
|
|
4275
|
-
const quoteId = parts[1]?.trim() ?? "";
|
|
4276
|
-
const storagePriceRaw = parts[2]?.trim() ?? "";
|
|
4277
|
-
const walletAddress = parts[3]?.trim() ?? "";
|
|
4278
|
-
const objectId = parts[4]?.trim() ?? "";
|
|
4279
|
-
const objectIdHash = parts[5]?.trim() ?? "";
|
|
4280
|
-
const provider = parts[7]?.trim() ?? "";
|
|
4281
|
-
const location = parts[8]?.trim() ?? "";
|
|
4282
|
-
const storagePrice = Number.parseFloat(storagePriceRaw);
|
|
4283
|
-
if (!quoteId || !walletAddress || !objectId || !objectIdHash || !provider || !location) {
|
|
4284
|
-
return null;
|
|
4285
|
-
}
|
|
4286
|
-
if (!Number.isFinite(storagePrice) || storagePrice <= 0) {
|
|
4287
|
-
return null;
|
|
4288
|
-
}
|
|
4289
|
-
return {
|
|
4290
|
-
quoteId,
|
|
4291
|
-
storagePrice,
|
|
4292
|
-
walletAddress,
|
|
4293
|
-
objectId,
|
|
4294
|
-
objectIdHash,
|
|
4295
|
-
provider,
|
|
4296
|
-
location
|
|
4297
|
-
};
|
|
4298
|
-
}
|
|
4299
|
-
function parseLoggedStoragePaymentCron(line) {
|
|
4300
|
-
const parts = line.split(",");
|
|
4301
|
-
if (parts.length < 5) {
|
|
4302
|
-
return null;
|
|
4303
|
-
}
|
|
4304
|
-
if ((parts[0]?.trim() ?? "").toLowerCase() !== CRON_LOG_ROW_PREFIX) {
|
|
4305
|
-
return null;
|
|
4306
|
-
}
|
|
4307
|
-
const cronId = parts[2]?.trim() ?? "";
|
|
4308
|
-
const objectId = parts[3]?.trim() ?? "";
|
|
4309
|
-
const objectKey = parts[4]?.trim() ?? "";
|
|
4310
|
-
if (!cronId || !objectId || !objectKey) {
|
|
4311
|
-
return null;
|
|
4312
|
-
}
|
|
4313
|
-
return {
|
|
4314
|
-
cronId,
|
|
4315
|
-
objectId,
|
|
4316
|
-
objectKey
|
|
4317
|
-
};
|
|
4318
|
-
}
|
|
4319
4240
|
function parseStoragePaymentCronJobLine(line) {
|
|
4320
4241
|
const trimmed = line.trim();
|
|
4321
4242
|
if (!trimmed) {
|
|
@@ -4361,31 +4282,11 @@ function parseStoragePaymentCronJobLine(line) {
|
|
|
4361
4282
|
location
|
|
4362
4283
|
};
|
|
4363
4284
|
}
|
|
4364
|
-
async function
|
|
4365
|
-
const
|
|
4366
|
-
let content;
|
|
4367
|
-
try {
|
|
4368
|
-
content = await readFile3(objectLogPath, "utf-8");
|
|
4369
|
-
} catch (error) {
|
|
4370
|
-
if (error.code === "ENOENT") {
|
|
4371
|
-
return null;
|
|
4372
|
-
}
|
|
4373
|
-
throw error;
|
|
4374
|
-
}
|
|
4375
|
-
const lines = content.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
4376
|
-
for (let idx = lines.length - 1; idx >= 0; idx -= 1) {
|
|
4377
|
-
const parsed = parseLoggedPriceStorageQuote(lines[idx]);
|
|
4378
|
-
if (parsed && parsed.quoteId === quoteId) {
|
|
4379
|
-
return parsed;
|
|
4380
|
-
}
|
|
4381
|
-
}
|
|
4382
|
-
return null;
|
|
4383
|
-
}
|
|
4384
|
-
async function findLoggedStoragePaymentCronByObjectKey(objectKey, homeDir) {
|
|
4385
|
-
const objectLogPath = resolveObjectLogPath(homeDir);
|
|
4285
|
+
async function findCronJobInCrontabByObjectKey(objectKey, homeDir) {
|
|
4286
|
+
const cronTablePath = resolveCronTablePath(homeDir);
|
|
4386
4287
|
let content;
|
|
4387
4288
|
try {
|
|
4388
|
-
content = await readFile3(
|
|
4289
|
+
content = await readFile3(cronTablePath, "utf-8");
|
|
4389
4290
|
} catch (error) {
|
|
4390
4291
|
if (error.code === "ENOENT") {
|
|
4391
4292
|
return null;
|
|
@@ -4394,9 +4295,13 @@ async function findLoggedStoragePaymentCronByObjectKey(objectKey, homeDir) {
|
|
|
4394
4295
|
}
|
|
4395
4296
|
const lines = content.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
4396
4297
|
for (let idx = lines.length - 1; idx >= 0; idx -= 1) {
|
|
4397
|
-
const parsed =
|
|
4298
|
+
const parsed = parseStoragePaymentCronJobLine(lines[idx]);
|
|
4398
4299
|
if (parsed && parsed.objectKey === objectKey) {
|
|
4399
|
-
return
|
|
4300
|
+
return {
|
|
4301
|
+
cronId: parsed.cronId,
|
|
4302
|
+
objectId: parsed.objectId,
|
|
4303
|
+
objectKey: parsed.objectKey
|
|
4304
|
+
};
|
|
4400
4305
|
}
|
|
4401
4306
|
}
|
|
4402
4307
|
return null;
|
|
@@ -4420,20 +4325,6 @@ function buildStoragePaymentCronCommand(job) {
|
|
|
4420
4325
|
quoteCronArgument(job.storagePrice)
|
|
4421
4326
|
].join(" ");
|
|
4422
4327
|
}
|
|
4423
|
-
async function appendStoragePaymentCronLog(cronJob, homeDir) {
|
|
4424
|
-
return appendObjectLogLine(
|
|
4425
|
-
[
|
|
4426
|
-
CRON_LOG_ROW_PREFIX,
|
|
4427
|
-
cronJob.createdAt,
|
|
4428
|
-
cronJob.cronId,
|
|
4429
|
-
cronJob.objectId,
|
|
4430
|
-
cronJob.objectKey,
|
|
4431
|
-
cronJob.quoteId,
|
|
4432
|
-
cronJob.storagePrice.toString()
|
|
4433
|
-
].join(","),
|
|
4434
|
-
homeDir
|
|
4435
|
-
);
|
|
4436
|
-
}
|
|
4437
4328
|
async function appendStoragePaymentCronJob(cronJob, homeDir) {
|
|
4438
4329
|
const cronTablePath = resolveCronTablePath(homeDir);
|
|
4439
4330
|
await mkdir5(dirname5(cronTablePath), { recursive: true });
|
|
@@ -4500,7 +4391,6 @@ async function createStoragePaymentCronJob(upload, storagePrice, homeDir, nowDat
|
|
|
4500
4391
|
location: upload.location
|
|
4501
4392
|
};
|
|
4502
4393
|
await appendStoragePaymentCronJob(cronJob, homeDir);
|
|
4503
|
-
await appendStoragePaymentCronLog(cronJob, homeDir);
|
|
4504
4394
|
return cronJob;
|
|
4505
4395
|
}
|
|
4506
4396
|
async function readWalletKeyIfPresent(walletPath) {
|
|
@@ -4630,24 +4520,6 @@ async function uploadPresignedObjectIfNeeded(uploadResponse, uploadMode, encrypt
|
|
|
4630
4520
|
`Presigned upload failed with status ${firstAttempt.status}${details ? `: ${details}` : ""}`
|
|
4631
4521
|
);
|
|
4632
4522
|
}
|
|
4633
|
-
async function appendStorageUploadLog(upload, homeDir, nowDateFn = () => /* @__PURE__ */ new Date()) {
|
|
4634
|
-
return appendObjectLogLine(
|
|
4635
|
-
[
|
|
4636
|
-
formatTimestamp(nowDateFn()),
|
|
4637
|
-
upload.quote_id,
|
|
4638
|
-
upload.addr,
|
|
4639
|
-
upload.addr_hash ?? "",
|
|
4640
|
-
upload.trans_id ?? "",
|
|
4641
|
-
upload.storage_price?.toString() ?? "",
|
|
4642
|
-
upload.object_id,
|
|
4643
|
-
upload.object_key,
|
|
4644
|
-
upload.provider,
|
|
4645
|
-
upload.bucket_name,
|
|
4646
|
-
upload.location
|
|
4647
|
-
].join(","),
|
|
4648
|
-
homeDir
|
|
4649
|
-
);
|
|
4650
|
-
}
|
|
4651
4523
|
async function maybeCleanupLocalBackupArchive(archivePath) {
|
|
4652
4524
|
const flag = process.env.MNEMOSPARK_DELETE_BACKUP_AFTER_UPLOAD;
|
|
4653
4525
|
if (!flag) {
|
|
@@ -4663,10 +4535,18 @@ async function maybeCleanupLocalBackupArchive(archivePath) {
|
|
|
4663
4535
|
}
|
|
4664
4536
|
}
|
|
4665
4537
|
function formatStorageUploadUserMessage(upload, cronJobId) {
|
|
4538
|
+
const lsLine = `/mnemospark_cloud ls --wallet-address \`${upload.addr}\``;
|
|
4666
4539
|
return [
|
|
4667
4540
|
`Your file \`${upload.object_id}\` with key \`${upload.object_key}\` has been stored using \`${upload.provider}\` in \`${upload.bucket_name}\` \`${upload.location}\``,
|
|
4668
|
-
|
|
4669
|
-
|
|
4541
|
+
"",
|
|
4542
|
+
`A cron job \`${cronJobId}\` has been configured to send payment monthly (on the 1st) for storage services. If payment is not sent, your \`${upload.object_id}\` will be deleted after the ${PAYMENT_DELETE_DEADLINE_DAYS}-day deadline (${PAYMENT_REMINDER_INTERVAL_DAYS}-day billing interval + 2-day grace period).`,
|
|
4543
|
+
"",
|
|
4544
|
+
"To view your cloud storage run the command:",
|
|
4545
|
+
"",
|
|
4546
|
+
lsLine,
|
|
4547
|
+
"",
|
|
4548
|
+
"Thank you for using mnemospark!",
|
|
4549
|
+
`Reach out if you need anything: ${MNEMOSPARK_SUPPORT_EMAIL}`
|
|
4670
4550
|
].join("\n");
|
|
4671
4551
|
}
|
|
4672
4552
|
function formatStorageDeleteUserMessage(objectKey, cronId, cronDeleted) {
|
|
@@ -4713,9 +4593,39 @@ function extractLsErrorMessage(error) {
|
|
|
4713
4593
|
return null;
|
|
4714
4594
|
}
|
|
4715
4595
|
function formatPriceStorageUserMessage(quote) {
|
|
4596
|
+
const uploadLine = `/mnemospark_cloud upload --quote-id \`${quote.quote_id}\` --wallet-address \`${quote.addr}\` --object-id \`${quote.object_id}\` --object-id-hash \`${quote.object_id_hash}\``;
|
|
4597
|
+
return [
|
|
4598
|
+
`Your storage quote \`${quote.quote_id}\`: storage price \`${quote.storage_price}\` for \`${quote.object_id}\` with file size \`${quote.object_size_gb}\` in \`${quote.provider}\` \`${quote.location}\`.`,
|
|
4599
|
+
"",
|
|
4600
|
+
"If you accept this quote, run:",
|
|
4601
|
+
"",
|
|
4602
|
+
uploadLine,
|
|
4603
|
+
"",
|
|
4604
|
+
QUOTE_VALIDITY_USER_NOTE
|
|
4605
|
+
].join("\n");
|
|
4606
|
+
}
|
|
4607
|
+
function quoteLookupMatchesPriceStorageResponse(lookup, quote) {
|
|
4608
|
+
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;
|
|
4609
|
+
}
|
|
4610
|
+
function formatBackupSuccessUserMessage(result) {
|
|
4611
|
+
const hash = result.objectIdHash.replace(/\s/g, "");
|
|
4612
|
+
const priceStorageLine = `/mnemospark_cloud price-storage --wallet-address <wallet-address> --object-id \`${result.objectId}\` --object-id-hash \`${hash}\` --gb \`${result.objectSizeGb}\` --provider <provider> --region <region>`;
|
|
4716
4613
|
return [
|
|
4717
|
-
`
|
|
4718
|
-
|
|
4614
|
+
`Backup archive: \`${result.archivePath}\``,
|
|
4615
|
+
"",
|
|
4616
|
+
`object-id: ${result.objectId}`,
|
|
4617
|
+
`object-id-hash: ${hash}`,
|
|
4618
|
+
`object-size: ${result.objectSizeGb}`,
|
|
4619
|
+
"",
|
|
4620
|
+
"Next, request a storage quote. Replace `<wallet-address>`, `<provider>`, and `<region>` (one line):",
|
|
4621
|
+
"",
|
|
4622
|
+
priceStorageLine,
|
|
4623
|
+
"",
|
|
4624
|
+
"Region examples (merge into the command above):",
|
|
4625
|
+
"North America: `--provider aws --region us-east-1`",
|
|
4626
|
+
"Europe: `--provider aws --region eu-north-1`",
|
|
4627
|
+
"South America: `--provider aws --region sa-east-1`",
|
|
4628
|
+
"Asia Pacific: `--provider aws --region ap-northeast-1`"
|
|
4719
4629
|
].join("\n");
|
|
4720
4630
|
}
|
|
4721
4631
|
function createInProcessSubagentOrchestrator() {
|
|
@@ -4842,7 +4752,7 @@ function createCloudCommand(options = {}) {
|
|
|
4842
4752
|
requestStorageDownloadFn: options.requestStorageDownloadFn ?? requestStorageDownloadViaProxy,
|
|
4843
4753
|
requestStorageDeleteFn: options.requestStorageDeleteFn ?? requestStorageDeleteViaProxy,
|
|
4844
4754
|
requestPaymentSettleViaProxyFn: options.requestPaymentSettleViaProxyFn ?? requestPaymentSettleViaProxy,
|
|
4845
|
-
|
|
4755
|
+
mnemosparkHomeDir: options.mnemosparkHomeDir ?? options.backupOptions?.homeDir,
|
|
4846
4756
|
backupOptions: options.backupOptions,
|
|
4847
4757
|
proxyQuoteOptions: options.proxyQuoteOptions,
|
|
4848
4758
|
proxyUploadOptions: options.proxyUploadOptions,
|
|
@@ -4858,42 +4768,7 @@ function createCloudCommand(options = {}) {
|
|
|
4858
4768
|
}
|
|
4859
4769
|
};
|
|
4860
4770
|
}
|
|
4861
|
-
async function
|
|
4862
|
-
const manifestPath = join8(homeDir ?? homedir6(), ".openclaw", "mnemospark", "manifest.jsonl");
|
|
4863
|
-
let manifestRaw;
|
|
4864
|
-
try {
|
|
4865
|
-
manifestRaw = await readFile3(manifestPath, "utf-8");
|
|
4866
|
-
} catch {
|
|
4867
|
-
return { objectKey: null, matchCount: 0 };
|
|
4868
|
-
}
|
|
4869
|
-
const wallet = params.walletAddress.trim().toLowerCase();
|
|
4870
|
-
const name = params.friendlyName.trim();
|
|
4871
|
-
const atMs = params.at ? Date.parse(params.at) : Number.NaN;
|
|
4872
|
-
const hasAt = Number.isFinite(atMs);
|
|
4873
|
-
const rows = manifestRaw.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((line) => {
|
|
4874
|
-
try {
|
|
4875
|
-
return JSON.parse(line);
|
|
4876
|
-
} catch {
|
|
4877
|
-
return null;
|
|
4878
|
-
}
|
|
4879
|
-
}).filter((row) => Boolean(row)).filter((row) => {
|
|
4880
|
-
if (!row.object_key || !row.friendly_name || !row.wallet_address || !row.created_at)
|
|
4881
|
-
return false;
|
|
4882
|
-
if (row.friendly_name !== name) return false;
|
|
4883
|
-
if (row.wallet_address.trim().toLowerCase() !== wallet) return false;
|
|
4884
|
-
if (params.latest || !hasAt) return true;
|
|
4885
|
-
const createdAtMs = Date.parse(row.created_at);
|
|
4886
|
-
return Number.isFinite(createdAtMs) && createdAtMs <= atMs;
|
|
4887
|
-
}).sort((a, b) => Date.parse(b.created_at ?? "") - Date.parse(a.created_at ?? ""));
|
|
4888
|
-
if (rows.length === 0) {
|
|
4889
|
-
return { objectKey: null, matchCount: 0 };
|
|
4890
|
-
}
|
|
4891
|
-
if (!params.latest && !hasAt && rows.length > 1) {
|
|
4892
|
-
return { objectKey: null, matchCount: rows.length };
|
|
4893
|
-
}
|
|
4894
|
-
return { objectKey: rows[0].object_key ?? null, matchCount: rows.length };
|
|
4895
|
-
}
|
|
4896
|
-
async function resolveNameSelectorIfNeeded(datastore, request, selector, homeDir) {
|
|
4771
|
+
async function resolveNameSelectorIfNeeded(datastore, request, selector) {
|
|
4897
4772
|
if (!selector) {
|
|
4898
4773
|
const walletAddress = request.wallet_address?.trim();
|
|
4899
4774
|
if (!walletAddress) {
|
|
@@ -4917,11 +4792,12 @@ async function resolveNameSelectorIfNeeded(datastore, request, selector, homeDir
|
|
|
4917
4792
|
}
|
|
4918
4793
|
return { request: parsedRequest2 };
|
|
4919
4794
|
}
|
|
4920
|
-
let sqliteUnavailable = false;
|
|
4921
4795
|
try {
|
|
4922
4796
|
await datastore.ensureReady();
|
|
4923
4797
|
} catch {
|
|
4924
|
-
|
|
4798
|
+
return {
|
|
4799
|
+
error: "Cannot resolve --name: local SQLite (~/.openclaw/mnemospark/state.db) is unavailable. Use --object-key or restore SQLite access."
|
|
4800
|
+
};
|
|
4925
4801
|
}
|
|
4926
4802
|
const matches = await datastore.countFriendlyNameMatches(request.wallet_address, selector.name);
|
|
4927
4803
|
if (matches > 1 && !selector.latest && !selector.at) {
|
|
@@ -4935,28 +4811,7 @@ async function resolveNameSelectorIfNeeded(datastore, request, selector, homeDir
|
|
|
4935
4811
|
latest: selector.latest,
|
|
4936
4812
|
at: selector.at
|
|
4937
4813
|
});
|
|
4938
|
-
|
|
4939
|
-
let degradedWarning;
|
|
4940
|
-
if (!resolvedObjectKey && sqliteUnavailable) {
|
|
4941
|
-
const manifestResolved = await resolveFriendlyNameFromManifest(
|
|
4942
|
-
{
|
|
4943
|
-
walletAddress: request.wallet_address,
|
|
4944
|
-
friendlyName: selector.name,
|
|
4945
|
-
latest: selector.latest,
|
|
4946
|
-
at: selector.at
|
|
4947
|
-
},
|
|
4948
|
-
homeDir
|
|
4949
|
-
);
|
|
4950
|
-
if (manifestResolved.matchCount > 1 && !selector.latest && !selector.at) {
|
|
4951
|
-
return {
|
|
4952
|
-
error: `Multiple objects match --name ${selector.name}. Add --latest or --at <timestamp>.`
|
|
4953
|
-
};
|
|
4954
|
-
}
|
|
4955
|
-
resolvedObjectKey = manifestResolved.objectKey;
|
|
4956
|
-
if (resolvedObjectKey) {
|
|
4957
|
-
degradedWarning = "SQLite friendly-name index unavailable; resolved --name via manifest.jsonl fallback.";
|
|
4958
|
-
}
|
|
4959
|
-
}
|
|
4814
|
+
const resolvedObjectKey = resolved?.objectKey ?? null;
|
|
4960
4815
|
if (!resolvedObjectKey) {
|
|
4961
4816
|
return { error: `No object found for --name ${selector.name}.` };
|
|
4962
4817
|
}
|
|
@@ -4967,10 +4822,7 @@ async function resolveNameSelectorIfNeeded(datastore, request, selector, homeDir
|
|
|
4967
4822
|
if (!parsedRequest) {
|
|
4968
4823
|
return { error: "Cannot resolve storage object request." };
|
|
4969
4824
|
}
|
|
4970
|
-
return {
|
|
4971
|
-
request: parsedRequest,
|
|
4972
|
-
degradedWarning
|
|
4973
|
-
};
|
|
4825
|
+
return { request: parsedRequest };
|
|
4974
4826
|
}
|
|
4975
4827
|
function toStorageObjectRequestOrError(request, missingKeyMessage) {
|
|
4976
4828
|
const key = request.object_key?.trim();
|
|
@@ -4993,7 +4845,8 @@ async function emitCloudEvent(eventType, details, homeDir) {
|
|
|
4993
4845
|
{
|
|
4994
4846
|
...details,
|
|
4995
4847
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4996
|
-
event_type: eventType
|
|
4848
|
+
event_type: eventType,
|
|
4849
|
+
source: "command"
|
|
4997
4850
|
},
|
|
4998
4851
|
homeDir
|
|
4999
4852
|
);
|
|
@@ -5010,6 +4863,7 @@ function toOperationEventPayload(eventType, context) {
|
|
|
5010
4863
|
trace_id: context.traceId,
|
|
5011
4864
|
event_type: eventType,
|
|
5012
4865
|
status: context.status,
|
|
4866
|
+
source: "command",
|
|
5013
4867
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5014
4868
|
wallet_address: context.walletAddress ?? void 0,
|
|
5015
4869
|
object_id: context.objectId ?? void 0,
|
|
@@ -5025,10 +4879,7 @@ function toOperationEventPayload(eventType, context) {
|
|
|
5025
4879
|
}
|
|
5026
4880
|
async function emitOperationEvent(eventType, context, homeDir) {
|
|
5027
4881
|
const payload = toOperationEventPayload(eventType, context);
|
|
5028
|
-
await
|
|
5029
|
-
appendJsonlEvent("events.jsonl", payload, homeDir),
|
|
5030
|
-
appendJsonlEvent("proxy-events.jsonl", payload, homeDir)
|
|
5031
|
-
]);
|
|
4882
|
+
await appendJsonlEvent("events.jsonl", payload, homeDir);
|
|
5032
4883
|
}
|
|
5033
4884
|
async function emitOperationEventBestEffort(eventType, context, homeDir) {
|
|
5034
4885
|
try {
|
|
@@ -5054,7 +4905,7 @@ function parseTransIdFromPaymentSettleBody(bodyText) {
|
|
|
5054
4905
|
return null;
|
|
5055
4906
|
}
|
|
5056
4907
|
}
|
|
5057
|
-
async function resolveAmountForPaymentSettle(quoteId, storagePriceFromFlag, datastore
|
|
4908
|
+
async function resolveAmountForPaymentSettle(quoteId, storagePriceFromFlag, datastore) {
|
|
5058
4909
|
if (storagePriceFromFlag !== void 0 && Number.isFinite(storagePriceFromFlag)) {
|
|
5059
4910
|
return storagePriceFromFlag;
|
|
5060
4911
|
}
|
|
@@ -5062,10 +4913,6 @@ async function resolveAmountForPaymentSettle(quoteId, storagePriceFromFlag, data
|
|
|
5062
4913
|
if (quoteLookup && Number.isFinite(quoteLookup.storagePrice)) {
|
|
5063
4914
|
return quoteLookup.storagePrice;
|
|
5064
4915
|
}
|
|
5065
|
-
const logged = await findLoggedPriceStorageQuote(quoteId, homeDir);
|
|
5066
|
-
if (logged && Number.isFinite(logged.storagePrice)) {
|
|
5067
|
-
return logged.storagePrice;
|
|
5068
|
-
}
|
|
5069
4916
|
const payment = await datastore.findPaymentByQuoteId(quoteId);
|
|
5070
4917
|
if (payment && Number.isFinite(payment.amount)) {
|
|
5071
4918
|
return payment.amount;
|
|
@@ -5101,18 +4948,19 @@ async function emitPaymentSettleClientObservationBestEffort(params) {
|
|
|
5101
4948
|
homeDir
|
|
5102
4949
|
);
|
|
5103
4950
|
await appendJsonlEvent(
|
|
5104
|
-
"
|
|
4951
|
+
"events.jsonl",
|
|
5105
4952
|
{
|
|
5106
4953
|
ts,
|
|
5107
4954
|
event_type: "payment.settle",
|
|
5108
4955
|
status: "start",
|
|
4956
|
+
source: "command",
|
|
5109
4957
|
trace_id: correlation.traceId,
|
|
5110
4958
|
operation_id: correlation.operationId,
|
|
5111
4959
|
quote_id: quoteId,
|
|
5112
4960
|
wallet_address: walletAddress,
|
|
5113
4961
|
object_id: objectId ?? null,
|
|
5114
4962
|
object_key: objectKey ?? null,
|
|
5115
|
-
details: {
|
|
4963
|
+
details: { client_observation: true }
|
|
5116
4964
|
},
|
|
5117
4965
|
homeDir
|
|
5118
4966
|
);
|
|
@@ -5134,18 +4982,20 @@ async function emitPaymentSettleClientObservationBestEffort(params) {
|
|
|
5134
4982
|
homeDir
|
|
5135
4983
|
);
|
|
5136
4984
|
await appendJsonlEvent(
|
|
5137
|
-
"
|
|
4985
|
+
"events.jsonl",
|
|
5138
4986
|
{
|
|
5139
4987
|
ts,
|
|
5140
4988
|
event_type: "payment.settle",
|
|
5141
4989
|
status: "result",
|
|
4990
|
+
source: "command",
|
|
5142
4991
|
trace_id: correlation.traceId,
|
|
5143
4992
|
operation_id: correlation.operationId,
|
|
5144
4993
|
quote_id: quoteId,
|
|
5145
4994
|
wallet_address: walletAddress,
|
|
5146
4995
|
object_id: objectId ?? null,
|
|
5147
4996
|
object_key: objectKey ?? null,
|
|
5148
|
-
|
|
4997
|
+
http_status: httpStatus ?? null,
|
|
4998
|
+
details: { client_observation: true }
|
|
5149
4999
|
},
|
|
5150
5000
|
homeDir
|
|
5151
5001
|
);
|
|
@@ -5154,7 +5004,7 @@ async function emitPaymentSettleClientObservationBestEffort(params) {
|
|
|
5154
5004
|
}
|
|
5155
5005
|
async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
5156
5006
|
const parsed = parseCloudArgs(ctx.args);
|
|
5157
|
-
const
|
|
5007
|
+
const mnemosparkHomeDir = options.mnemosparkHomeDir;
|
|
5158
5008
|
const backupBuilder = options.buildBackupObjectFn;
|
|
5159
5009
|
const requestPriceStorageQuote = options.requestPriceStorageQuoteFn;
|
|
5160
5010
|
const requestStorageUpload = options.requestStorageUploadFn;
|
|
@@ -5241,7 +5091,7 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5241
5091
|
isError: true
|
|
5242
5092
|
};
|
|
5243
5093
|
}
|
|
5244
|
-
const datastore = await createCloudDatastore(
|
|
5094
|
+
const datastore = await createCloudDatastore(mnemosparkHomeDir);
|
|
5245
5095
|
const terminalOperationStatuses = /* @__PURE__ */ new Set(["succeeded", "failed", "cancelled", "timed_out"]);
|
|
5246
5096
|
const isTerminalOperationStatus = (status) => terminalOperationStatuses.has(status);
|
|
5247
5097
|
const formatOperationStatus = (operation) => ({
|
|
@@ -5303,7 +5153,7 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5303
5153
|
subagentSessionId: operation.subagent_session_id,
|
|
5304
5154
|
timeoutSeconds: operation.timeout_seconds
|
|
5305
5155
|
},
|
|
5306
|
-
|
|
5156
|
+
mnemosparkHomeDir
|
|
5307
5157
|
);
|
|
5308
5158
|
const cancelResult = await subagentOrchestrator.cancel(
|
|
5309
5159
|
operation.subagent_session_id,
|
|
@@ -5340,7 +5190,7 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5340
5190
|
errorCode: "ASYNC_CANCELLED",
|
|
5341
5191
|
errorMessage: "Operation cancelled by user request."
|
|
5342
5192
|
},
|
|
5343
|
-
|
|
5193
|
+
mnemosparkHomeDir
|
|
5344
5194
|
);
|
|
5345
5195
|
}
|
|
5346
5196
|
}
|
|
@@ -5359,7 +5209,7 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5359
5209
|
const req = parsed.paymentSettleRequest;
|
|
5360
5210
|
let walletKey;
|
|
5361
5211
|
try {
|
|
5362
|
-
walletKey = await resolveWalletKey(
|
|
5212
|
+
walletKey = await resolveWalletKey(mnemosparkHomeDir);
|
|
5363
5213
|
} catch (err) {
|
|
5364
5214
|
const message = err instanceof Error ? err.message : String(err);
|
|
5365
5215
|
return { text: message.trim() || "Cannot resolve wallet key.", isError: true };
|
|
@@ -5382,7 +5232,7 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5382
5232
|
walletAddress: req.wallet_address,
|
|
5383
5233
|
objectId,
|
|
5384
5234
|
objectKey,
|
|
5385
|
-
homeDir:
|
|
5235
|
+
homeDir: mnemosparkHomeDir
|
|
5386
5236
|
});
|
|
5387
5237
|
let settleResult;
|
|
5388
5238
|
try {
|
|
@@ -5395,8 +5245,7 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5395
5245
|
const amountErr = await resolveAmountForPaymentSettle(
|
|
5396
5246
|
req.quote_id,
|
|
5397
5247
|
req.storage_price,
|
|
5398
|
-
datastore
|
|
5399
|
-
objectLogHomeDir
|
|
5248
|
+
datastore
|
|
5400
5249
|
);
|
|
5401
5250
|
await datastore.upsertPayment({
|
|
5402
5251
|
quote_id: req.quote_id,
|
|
@@ -5420,16 +5269,11 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5420
5269
|
objectId,
|
|
5421
5270
|
objectKey,
|
|
5422
5271
|
outcomeStatus: "failed",
|
|
5423
|
-
homeDir:
|
|
5272
|
+
homeDir: mnemosparkHomeDir
|
|
5424
5273
|
});
|
|
5425
5274
|
return { text: `Payment settle failed: ${msg}`, isError: true };
|
|
5426
5275
|
}
|
|
5427
|
-
const amount = await resolveAmountForPaymentSettle(
|
|
5428
|
-
req.quote_id,
|
|
5429
|
-
req.storage_price,
|
|
5430
|
-
datastore,
|
|
5431
|
-
objectLogHomeDir
|
|
5432
|
-
);
|
|
5276
|
+
const amount = await resolveAmountForPaymentSettle(req.quote_id, req.storage_price, datastore);
|
|
5433
5277
|
const transId = settleResult.status === 200 ? parseTransIdFromPaymentSettleBody(settleResult.bodyText ?? "") : null;
|
|
5434
5278
|
if (settleResult.status === 200) {
|
|
5435
5279
|
await datastore.upsertPayment({
|
|
@@ -5454,7 +5298,7 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5454
5298
|
objectKey,
|
|
5455
5299
|
httpStatus: settleResult.status,
|
|
5456
5300
|
outcomeStatus: "succeeded",
|
|
5457
|
-
homeDir:
|
|
5301
|
+
homeDir: mnemosparkHomeDir
|
|
5458
5302
|
});
|
|
5459
5303
|
return {
|
|
5460
5304
|
text: transId ? `Payment settled for quote ${req.quote_id} (trans_id: ${transId}).` : `Payment settled for quote ${req.quote_id}.`
|
|
@@ -5482,7 +5326,7 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5482
5326
|
objectKey,
|
|
5483
5327
|
httpStatus: settleResult.status,
|
|
5484
5328
|
outcomeStatus: "failed",
|
|
5485
|
-
homeDir:
|
|
5329
|
+
homeDir: mnemosparkHomeDir
|
|
5486
5330
|
});
|
|
5487
5331
|
const bodySnippet = settleResult.bodyText?.trim();
|
|
5488
5332
|
const detail = bodySnippet && bodySnippet.length > 500 ? `${bodySnippet.slice(0, 500)}\u2026` : bodySnippet;
|
|
@@ -5524,7 +5368,7 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5524
5368
|
await emitOperationEventBestEffort(
|
|
5525
5369
|
"operation.dispatched",
|
|
5526
5370
|
{ ...eventContextBase, status: "started" },
|
|
5527
|
-
|
|
5371
|
+
mnemosparkHomeDir
|
|
5528
5372
|
);
|
|
5529
5373
|
const syncArgs = stripAsyncControlFlags(ctx.args);
|
|
5530
5374
|
if (orchestratorMode === "subagent") {
|
|
@@ -5576,7 +5420,7 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5576
5420
|
subagentSessionId: sessionId,
|
|
5577
5421
|
progressMessage: "subagent running"
|
|
5578
5422
|
},
|
|
5579
|
-
|
|
5423
|
+
mnemosparkHomeDir
|
|
5580
5424
|
);
|
|
5581
5425
|
},
|
|
5582
5426
|
onProgress: async (sessionId, message) => {
|
|
@@ -5588,7 +5432,7 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5588
5432
|
subagentSessionId: sessionId,
|
|
5589
5433
|
progressMessage: message
|
|
5590
5434
|
},
|
|
5591
|
-
|
|
5435
|
+
mnemosparkHomeDir
|
|
5592
5436
|
);
|
|
5593
5437
|
},
|
|
5594
5438
|
onCompleted: async (sessionId) => {
|
|
@@ -5612,7 +5456,7 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5612
5456
|
status: "succeeded",
|
|
5613
5457
|
subagentSessionId: sessionId
|
|
5614
5458
|
},
|
|
5615
|
-
|
|
5459
|
+
mnemosparkHomeDir
|
|
5616
5460
|
);
|
|
5617
5461
|
},
|
|
5618
5462
|
onFailed: async (sessionId, details) => {
|
|
@@ -5638,7 +5482,7 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5638
5482
|
errorCode: details.code,
|
|
5639
5483
|
errorMessage: details.message
|
|
5640
5484
|
},
|
|
5641
|
-
|
|
5485
|
+
mnemosparkHomeDir
|
|
5642
5486
|
);
|
|
5643
5487
|
},
|
|
5644
5488
|
onCancelled: async (sessionId, reason) => {
|
|
@@ -5665,7 +5509,7 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5665
5509
|
errorCode: "ASYNC_CANCELLED",
|
|
5666
5510
|
errorMessage: reason ?? "Operation cancelled."
|
|
5667
5511
|
},
|
|
5668
|
-
|
|
5512
|
+
mnemosparkHomeDir
|
|
5669
5513
|
);
|
|
5670
5514
|
},
|
|
5671
5515
|
onTimedOut: async (sessionId) => {
|
|
@@ -5691,7 +5535,7 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5691
5535
|
errorCode: "ASYNC_TIMEOUT",
|
|
5692
5536
|
errorMessage: "Operation timed out."
|
|
5693
5537
|
},
|
|
5694
|
-
|
|
5538
|
+
mnemosparkHomeDir
|
|
5695
5539
|
);
|
|
5696
5540
|
}
|
|
5697
5541
|
}
|
|
@@ -5743,7 +5587,7 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5743
5587
|
errorCode: "ASYNC_DISPATCH_FAILED",
|
|
5744
5588
|
errorMessage: dispatchMessage
|
|
5745
5589
|
},
|
|
5746
|
-
|
|
5590
|
+
mnemosparkHomeDir
|
|
5747
5591
|
);
|
|
5748
5592
|
return {
|
|
5749
5593
|
text: `Cannot dispatch subagent operation: ${dispatchMessage}
|
|
@@ -5790,7 +5634,7 @@ operation-id: ${operationId}`,
|
|
|
5790
5634
|
errorCode: result.isError ? "ASYNC_FAILED" : null,
|
|
5791
5635
|
errorMessage: result.isError ? result.text : null
|
|
5792
5636
|
},
|
|
5793
|
-
|
|
5637
|
+
mnemosparkHomeDir
|
|
5794
5638
|
);
|
|
5795
5639
|
}).catch(async (err) => {
|
|
5796
5640
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
@@ -5813,7 +5657,7 @@ operation-id: ${operationId}`,
|
|
|
5813
5657
|
errorCode: "ASYNC_EXCEPTION",
|
|
5814
5658
|
errorMessage
|
|
5815
5659
|
},
|
|
5816
|
-
|
|
5660
|
+
mnemosparkHomeDir
|
|
5817
5661
|
);
|
|
5818
5662
|
});
|
|
5819
5663
|
return {
|
|
@@ -5833,9 +5677,14 @@ operation-id: ${operationId}`,
|
|
|
5833
5677
|
operation_id: randomUUID3(),
|
|
5834
5678
|
object_id: result.objectId,
|
|
5835
5679
|
status: "succeeded",
|
|
5836
|
-
details: {
|
|
5680
|
+
details: {
|
|
5681
|
+
friendly_name: parsed.friendlyName ?? basename2(parsed.backupTarget),
|
|
5682
|
+
archive_path: result.archivePath,
|
|
5683
|
+
object_id_hash: result.objectIdHash.replace(/\s/g, ""),
|
|
5684
|
+
object_size_gb: result.objectSizeGb
|
|
5685
|
+
}
|
|
5837
5686
|
},
|
|
5838
|
-
|
|
5687
|
+
mnemosparkHomeDir
|
|
5839
5688
|
);
|
|
5840
5689
|
await datastore.upsertObject({
|
|
5841
5690
|
object_id: result.objectId,
|
|
@@ -5859,11 +5708,7 @@ operation-id: ${operationId}`,
|
|
|
5859
5708
|
});
|
|
5860
5709
|
}
|
|
5861
5710
|
return {
|
|
5862
|
-
text:
|
|
5863
|
-
`object-id: ${result.objectId}`,
|
|
5864
|
-
`object-id-hash: ${result.objectIdHash.replace(/\s/g, "")}`,
|
|
5865
|
-
`object-size: ${result.objectSizeGb}`
|
|
5866
|
-
].join("\n")
|
|
5711
|
+
text: formatBackupSuccessUserMessage(result)
|
|
5867
5712
|
};
|
|
5868
5713
|
} catch (err) {
|
|
5869
5714
|
if (err instanceof UnsupportedBackupPlatformError) {
|
|
@@ -5885,7 +5730,7 @@ operation-id: ${operationId}`,
|
|
|
5885
5730
|
...options.proxyQuoteOptions,
|
|
5886
5731
|
correlation
|
|
5887
5732
|
});
|
|
5888
|
-
await
|
|
5733
|
+
await datastore.ensureReady();
|
|
5889
5734
|
await datastore.upsertObject({
|
|
5890
5735
|
object_id: quote.object_id,
|
|
5891
5736
|
object_key: null,
|
|
@@ -5905,6 +5750,13 @@ operation-id: ${operationId}`,
|
|
|
5905
5750
|
network: null,
|
|
5906
5751
|
status: "quoted"
|
|
5907
5752
|
});
|
|
5753
|
+
const verified = await datastore.findQuoteById(quote.quote_id);
|
|
5754
|
+
if (!verified || !quoteLookupMatchesPriceStorageResponse(verified, quote)) {
|
|
5755
|
+
return {
|
|
5756
|
+
text: "Cannot price storage: quote was not saved to local SQLite (~/.openclaw/mnemospark/state.db). Check disk permissions or MNEMOSPARK_DISABLE_SQLITE.",
|
|
5757
|
+
isError: true
|
|
5758
|
+
};
|
|
5759
|
+
}
|
|
5908
5760
|
await emitCloudEventBestEffort(
|
|
5909
5761
|
"price-storage.completed",
|
|
5910
5762
|
{
|
|
@@ -5915,7 +5767,7 @@ operation-id: ${operationId}`,
|
|
|
5915
5767
|
quote_id: quote.quote_id,
|
|
5916
5768
|
status: "succeeded"
|
|
5917
5769
|
},
|
|
5918
|
-
|
|
5770
|
+
mnemosparkHomeDir
|
|
5919
5771
|
);
|
|
5920
5772
|
return {
|
|
5921
5773
|
text: formatPriceStorageUserMessage(quote)
|
|
@@ -5930,7 +5782,7 @@ operation-id: ${operationId}`,
|
|
|
5930
5782
|
object_id: parsed.priceStorageRequest.object_id,
|
|
5931
5783
|
status: "failed"
|
|
5932
5784
|
},
|
|
5933
|
-
|
|
5785
|
+
mnemosparkHomeDir
|
|
5934
5786
|
);
|
|
5935
5787
|
const message = err instanceof Error ? err.message : typeof err === "string" ? err : String(err);
|
|
5936
5788
|
return {
|
|
@@ -5945,10 +5797,10 @@ operation-id: ${operationId}`,
|
|
|
5945
5797
|
executionContext.forcedTraceId
|
|
5946
5798
|
);
|
|
5947
5799
|
try {
|
|
5948
|
-
const loggedQuote = await datastore.findQuoteById(parsed.uploadRequest.quote_id)
|
|
5800
|
+
const loggedQuote = await datastore.findQuoteById(parsed.uploadRequest.quote_id);
|
|
5949
5801
|
if (!loggedQuote) {
|
|
5950
5802
|
return {
|
|
5951
|
-
text: "Cannot upload storage object: quote-id not found in
|
|
5803
|
+
text: "Cannot upload storage object: quote-id not found in local SQLite. Run /mnemospark_cloud price-storage first (quotes expire after about one hour on the server).",
|
|
5952
5804
|
isError: true
|
|
5953
5805
|
};
|
|
5954
5806
|
}
|
|
@@ -5984,7 +5836,7 @@ operation-id: ${operationId}`,
|
|
|
5984
5836
|
isError: true
|
|
5985
5837
|
};
|
|
5986
5838
|
}
|
|
5987
|
-
const walletKey = await resolveWalletKey(
|
|
5839
|
+
const walletKey = await resolveWalletKey(mnemosparkHomeDir);
|
|
5988
5840
|
const walletAccount = privateKeyToAccount5(walletKey);
|
|
5989
5841
|
if (walletAccount.address.toLowerCase() !== parsed.uploadRequest.wallet_address.toLowerCase()) {
|
|
5990
5842
|
return {
|
|
@@ -5995,7 +5847,7 @@ operation-id: ${operationId}`,
|
|
|
5995
5847
|
const preparedPayload = await prepareUploadPayload(
|
|
5996
5848
|
archivePath,
|
|
5997
5849
|
parsed.uploadRequest.wallet_address,
|
|
5998
|
-
|
|
5850
|
+
mnemosparkHomeDir
|
|
5999
5851
|
);
|
|
6000
5852
|
const idempotencyKey = uploadCorrelation.operationId;
|
|
6001
5853
|
const shouldSettleBeforeUpload = requestStorageUpload !== requestStorageUploadViaProxy;
|
|
@@ -6061,13 +5913,12 @@ operation-id: ${operationId}`,
|
|
|
6061
5913
|
);
|
|
6062
5914
|
}
|
|
6063
5915
|
}
|
|
6064
|
-
await appendStorageUploadLog(finalizedUploadResponse, objectLogHomeDir, nowDateFn);
|
|
6065
5916
|
const cronStoragePriceCandidate = finalizedUploadResponse.storage_price ?? loggedQuote.storagePrice;
|
|
6066
5917
|
const cronStoragePrice = Number.isFinite(cronStoragePriceCandidate) && cronStoragePriceCandidate > 0 ? cronStoragePriceCandidate : loggedQuote.storagePrice;
|
|
6067
5918
|
const cronJob = await createStoragePaymentCronJob(
|
|
6068
5919
|
finalizedUploadResponse,
|
|
6069
5920
|
cronStoragePrice,
|
|
6070
|
-
|
|
5921
|
+
mnemosparkHomeDir,
|
|
6071
5922
|
nowDateFn
|
|
6072
5923
|
);
|
|
6073
5924
|
await datastore.upsertObject({
|
|
@@ -6120,7 +5971,7 @@ operation-id: ${operationId}`,
|
|
|
6120
5971
|
friendlyNameVerified = false;
|
|
6121
5972
|
}
|
|
6122
5973
|
if (!friendlyNameVerified) {
|
|
6123
|
-
const warning = "SQLite friendly-name write verification failed;
|
|
5974
|
+
const warning = "SQLite friendly-name write verification failed; --name lookups may not resolve until SQLite is healthy.";
|
|
6124
5975
|
await emitCloudEventBestEffort(
|
|
6125
5976
|
"friendly_name.write_verification_failed",
|
|
6126
5977
|
{
|
|
@@ -6133,27 +5984,12 @@ operation-id: ${operationId}`,
|
|
|
6133
5984
|
friendly_name: normalizedFriendlyName,
|
|
6134
5985
|
warning
|
|
6135
5986
|
},
|
|
6136
|
-
|
|
5987
|
+
mnemosparkHomeDir
|
|
6137
5988
|
);
|
|
6138
5989
|
if (process.env.MNEMOSPARK_SQLITE_STRICT === "1") {
|
|
6139
5990
|
throw new Error(warning);
|
|
6140
5991
|
}
|
|
6141
5992
|
}
|
|
6142
|
-
try {
|
|
6143
|
-
await appendJsonlEvent(
|
|
6144
|
-
"manifest.jsonl",
|
|
6145
|
-
{
|
|
6146
|
-
friendly_name: normalizedFriendlyName,
|
|
6147
|
-
object_id: finalizedUploadResponse.object_id,
|
|
6148
|
-
object_key: finalizedUploadResponse.object_key,
|
|
6149
|
-
quote_id: finalizedUploadResponse.quote_id,
|
|
6150
|
-
wallet_address: finalizedUploadResponse.addr,
|
|
6151
|
-
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
6152
|
-
},
|
|
6153
|
-
objectLogHomeDir
|
|
6154
|
-
);
|
|
6155
|
-
} catch {
|
|
6156
|
-
}
|
|
6157
5993
|
}
|
|
6158
5994
|
await emitCloudEventBestEffort(
|
|
6159
5995
|
"upload.completed",
|
|
@@ -6166,7 +6002,7 @@ operation-id: ${operationId}`,
|
|
|
6166
6002
|
quote_id: finalizedUploadResponse.quote_id,
|
|
6167
6003
|
status: "succeeded"
|
|
6168
6004
|
},
|
|
6169
|
-
|
|
6005
|
+
mnemosparkHomeDir
|
|
6170
6006
|
);
|
|
6171
6007
|
await maybeCleanupLocalBackupArchive(archivePath);
|
|
6172
6008
|
return {
|
|
@@ -6183,7 +6019,7 @@ operation-id: ${operationId}`,
|
|
|
6183
6019
|
quote_id: parsed.uploadRequest.quote_id,
|
|
6184
6020
|
status: "failed"
|
|
6185
6021
|
},
|
|
6186
|
-
|
|
6022
|
+
mnemosparkHomeDir
|
|
6187
6023
|
);
|
|
6188
6024
|
const uploadErrorMessage = extractUploadErrorMessage(error);
|
|
6189
6025
|
return {
|
|
@@ -6196,24 +6032,12 @@ operation-id: ${operationId}`,
|
|
|
6196
6032
|
const resolved = await resolveNameSelectorIfNeeded(
|
|
6197
6033
|
datastore,
|
|
6198
6034
|
parsed.storageObjectRequest,
|
|
6199
|
-
parsed.nameSelector
|
|
6200
|
-
objectLogHomeDir
|
|
6035
|
+
parsed.nameSelector
|
|
6201
6036
|
);
|
|
6202
6037
|
if (resolved.error || !resolved.request) {
|
|
6203
6038
|
return { text: resolved.error ?? "Cannot resolve storage object request.", isError: true };
|
|
6204
6039
|
}
|
|
6205
6040
|
const resolvedRequest = resolved.request;
|
|
6206
|
-
if (resolved.degradedWarning) {
|
|
6207
|
-
await emitCloudEventBestEffort(
|
|
6208
|
-
"name_resolution.degraded",
|
|
6209
|
-
{
|
|
6210
|
-
wallet_address: resolvedRequest.wallet_address,
|
|
6211
|
-
object_key: resolvedRequest.object_key ?? null,
|
|
6212
|
-
warning: resolved.degradedWarning
|
|
6213
|
-
},
|
|
6214
|
-
objectLogHomeDir
|
|
6215
|
-
);
|
|
6216
|
-
}
|
|
6217
6041
|
const objectKeyForLs = resolvedRequest.object_key?.trim();
|
|
6218
6042
|
const isBucketList = !objectKeyForLs;
|
|
6219
6043
|
const correlation = buildRequestCorrelation();
|
|
@@ -6256,16 +6080,14 @@ operation-id: ${operationId}`,
|
|
|
6256
6080
|
status: "succeeded",
|
|
6257
6081
|
list_mode: isBucketList
|
|
6258
6082
|
},
|
|
6259
|
-
|
|
6083
|
+
mnemosparkHomeDir
|
|
6260
6084
|
);
|
|
6261
6085
|
const lsText = await buildMnemosparkLsMessage(lsResult, {
|
|
6262
6086
|
walletAddress: resolvedRequest.wallet_address,
|
|
6263
6087
|
datastore
|
|
6264
6088
|
});
|
|
6265
6089
|
return {
|
|
6266
|
-
text:
|
|
6267
|
-
|
|
6268
|
-
${lsText}` : lsText
|
|
6090
|
+
text: lsText
|
|
6269
6091
|
};
|
|
6270
6092
|
} catch (error) {
|
|
6271
6093
|
const lsErrorMessage = extractLsErrorMessage(error) ?? "Cannot list storage object";
|
|
@@ -6288,7 +6110,7 @@ ${lsText}` : lsText
|
|
|
6288
6110
|
status: "failed",
|
|
6289
6111
|
list_mode: isBucketList
|
|
6290
6112
|
},
|
|
6291
|
-
|
|
6113
|
+
mnemosparkHomeDir
|
|
6292
6114
|
);
|
|
6293
6115
|
return {
|
|
6294
6116
|
text: lsErrorMessage,
|
|
@@ -6300,8 +6122,7 @@ ${lsText}` : lsText
|
|
|
6300
6122
|
const resolved = await resolveNameSelectorIfNeeded(
|
|
6301
6123
|
datastore,
|
|
6302
6124
|
parsed.storageObjectRequest,
|
|
6303
|
-
parsed.nameSelector
|
|
6304
|
-
objectLogHomeDir
|
|
6125
|
+
parsed.nameSelector
|
|
6305
6126
|
);
|
|
6306
6127
|
if (resolved.error || !resolved.request) {
|
|
6307
6128
|
return { text: resolved.error ?? "Cannot resolve storage object request.", isError: true };
|
|
@@ -6314,17 +6135,6 @@ ${lsText}` : lsText
|
|
|
6314
6135
|
return { text: narrowed.error, isError: true };
|
|
6315
6136
|
}
|
|
6316
6137
|
const resolvedRequest = narrowed.request;
|
|
6317
|
-
if (resolved.degradedWarning) {
|
|
6318
|
-
await emitCloudEventBestEffort(
|
|
6319
|
-
"name_resolution.degraded",
|
|
6320
|
-
{
|
|
6321
|
-
wallet_address: resolvedRequest.wallet_address,
|
|
6322
|
-
object_key: resolvedRequest.object_key,
|
|
6323
|
-
warning: resolved.degradedWarning
|
|
6324
|
-
},
|
|
6325
|
-
objectLogHomeDir
|
|
6326
|
-
);
|
|
6327
|
-
}
|
|
6328
6138
|
const correlation = buildRequestCorrelation(
|
|
6329
6139
|
executionContext.forcedOperationId,
|
|
6330
6140
|
executionContext.forcedTraceId
|
|
@@ -6367,12 +6177,11 @@ ${lsText}` : lsText
|
|
|
6367
6177
|
object_key: resolvedRequest.object_key,
|
|
6368
6178
|
status: "succeeded"
|
|
6369
6179
|
},
|
|
6370
|
-
|
|
6180
|
+
mnemosparkHomeDir
|
|
6371
6181
|
);
|
|
6372
6182
|
const downloadText = `File ${resolvedRequest.object_key} downloaded to ${downloadResult.file_path}`;
|
|
6373
6183
|
return {
|
|
6374
|
-
text:
|
|
6375
|
-
${downloadText}` : downloadText
|
|
6184
|
+
text: downloadText
|
|
6376
6185
|
};
|
|
6377
6186
|
} catch {
|
|
6378
6187
|
await datastore.upsertOperation({
|
|
@@ -6393,7 +6202,7 @@ ${downloadText}` : downloadText
|
|
|
6393
6202
|
object_key: resolvedRequest.object_key,
|
|
6394
6203
|
status: "failed"
|
|
6395
6204
|
},
|
|
6396
|
-
|
|
6205
|
+
mnemosparkHomeDir
|
|
6397
6206
|
);
|
|
6398
6207
|
return {
|
|
6399
6208
|
text: "Cannot download file",
|
|
@@ -6405,8 +6214,7 @@ ${downloadText}` : downloadText
|
|
|
6405
6214
|
const resolved = await resolveNameSelectorIfNeeded(
|
|
6406
6215
|
datastore,
|
|
6407
6216
|
parsed.storageObjectRequest,
|
|
6408
|
-
parsed.nameSelector
|
|
6409
|
-
objectLogHomeDir
|
|
6217
|
+
parsed.nameSelector
|
|
6410
6218
|
);
|
|
6411
6219
|
if (resolved.error || !resolved.request) {
|
|
6412
6220
|
return { text: resolved.error ?? "Cannot resolve storage object request.", isError: true };
|
|
@@ -6419,17 +6227,6 @@ ${downloadText}` : downloadText
|
|
|
6419
6227
|
return { text: narrowedDelete.error, isError: true };
|
|
6420
6228
|
}
|
|
6421
6229
|
const resolvedRequest = narrowedDelete.request;
|
|
6422
|
-
if (resolved.degradedWarning) {
|
|
6423
|
-
await emitCloudEventBestEffort(
|
|
6424
|
-
"name_resolution.degraded",
|
|
6425
|
-
{
|
|
6426
|
-
wallet_address: resolvedRequest.wallet_address,
|
|
6427
|
-
object_key: resolvedRequest.object_key,
|
|
6428
|
-
warning: resolved.degradedWarning
|
|
6429
|
-
},
|
|
6430
|
-
objectLogHomeDir
|
|
6431
|
-
);
|
|
6432
|
-
}
|
|
6433
6230
|
const correlation = buildRequestCorrelation();
|
|
6434
6231
|
const operationId = correlation.operationId;
|
|
6435
6232
|
const existingObjectByKey = await datastore.findObjectByObjectKey(resolvedRequest.object_key);
|
|
@@ -6451,7 +6248,7 @@ ${downloadText}` : downloadText
|
|
|
6451
6248
|
object_key: resolvedRequest.object_key,
|
|
6452
6249
|
status: "failed"
|
|
6453
6250
|
},
|
|
6454
|
-
|
|
6251
|
+
mnemosparkHomeDir
|
|
6455
6252
|
);
|
|
6456
6253
|
return {
|
|
6457
6254
|
text: "Cannot delete file",
|
|
@@ -6470,15 +6267,15 @@ ${downloadText}` : downloadText
|
|
|
6470
6267
|
};
|
|
6471
6268
|
}
|
|
6472
6269
|
if (!cronEntry) {
|
|
6473
|
-
cronEntry = await
|
|
6270
|
+
cronEntry = await findCronJobInCrontabByObjectKey(
|
|
6474
6271
|
resolvedRequest.object_key,
|
|
6475
|
-
|
|
6272
|
+
mnemosparkHomeDir
|
|
6476
6273
|
);
|
|
6477
6274
|
}
|
|
6478
6275
|
if (cronEntry) {
|
|
6479
6276
|
const fileCronDeleted = await removeStoragePaymentCronJob(
|
|
6480
6277
|
cronEntry.cronId,
|
|
6481
|
-
|
|
6278
|
+
mnemosparkHomeDir
|
|
6482
6279
|
);
|
|
6483
6280
|
const dbCronDeleted = await datastore.removeCronJob(cronEntry.cronId);
|
|
6484
6281
|
cronDeleted = fileCronDeleted || dbCronDeleted;
|
|
@@ -6509,7 +6306,7 @@ ${downloadText}` : downloadText
|
|
|
6509
6306
|
object_key: resolvedRequest.object_key,
|
|
6510
6307
|
status: "succeeded"
|
|
6511
6308
|
},
|
|
6512
|
-
|
|
6309
|
+
mnemosparkHomeDir
|
|
6513
6310
|
);
|
|
6514
6311
|
const deleteText = formatStorageDeleteUserMessage(
|
|
6515
6312
|
resolvedRequest.object_key,
|
|
@@ -6517,8 +6314,7 @@ ${downloadText}` : downloadText
|
|
|
6517
6314
|
cronDeleted
|
|
6518
6315
|
);
|
|
6519
6316
|
return {
|
|
6520
|
-
text:
|
|
6521
|
-
${deleteText}` : deleteText
|
|
6317
|
+
text: deleteText
|
|
6522
6318
|
};
|
|
6523
6319
|
}
|
|
6524
6320
|
return {
|