@marshell/cli 0.7.4 → 0.7.5
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/bridge.js +1 -0
- package/dist/cli.js +10 -4
- package/dist/relay-cron.js +38 -5
- package/dist/relay-state.js +50 -3
- package/package.json +1 -1
package/dist/bridge.js
CHANGED
|
@@ -408,6 +408,7 @@ async function handleInbound(networkUrl, msg, options) {
|
|
|
408
408
|
});
|
|
409
409
|
if (pending) {
|
|
410
410
|
await (0, pending_1.clearPending)(msg.from);
|
|
411
|
+
await (0, relay_state_1.clearWaitingReported)(msg.from);
|
|
411
412
|
}
|
|
412
413
|
await (0, relay_state_1.markRelayed)([msg.id]);
|
|
413
414
|
}
|
package/dist/cli.js
CHANGED
|
@@ -24,7 +24,7 @@ function printHelp() {
|
|
|
24
24
|
" marshell inbox [--json] [--wait <seconds>] [--from <name>]",
|
|
25
25
|
" marshell history [--with <name>] [--limit <n>] [--json]",
|
|
26
26
|
" marshell listen [--json] [--notify <cmd>] (deliver-only listener)",
|
|
27
|
-
" marshell relay cron [--include-untracked] [--json]",
|
|
27
|
+
" marshell relay cron [--quiet] [--include-untracked] [--json]",
|
|
28
28
|
" marshell pending list|clear [--peer <name>] [--json]",
|
|
29
29
|
" marshell --help",
|
|
30
30
|
"",
|
|
@@ -370,13 +370,14 @@ async function cmdInbox(args) {
|
|
|
370
370
|
async function cmdRelay(args) {
|
|
371
371
|
const sub = args[0];
|
|
372
372
|
if (sub !== "cron") {
|
|
373
|
-
printError("Usage: marshell relay cron [--include-untracked] [--json]");
|
|
373
|
+
printError("Usage: marshell relay cron [--quiet] [--include-untracked] [--json]");
|
|
374
374
|
}
|
|
375
375
|
const json = hasFlag(args, "--json");
|
|
376
|
+
const quiet = hasFlag(args, "--quiet");
|
|
376
377
|
const pendingOnly = !hasFlag(args, "--include-untracked");
|
|
377
378
|
const config = await (0, config_1.readConfig)();
|
|
378
379
|
const networkUrl = (0, config_1.getNetworkUrl)(config);
|
|
379
|
-
const result = await (0, relay_cron_1.runRelayCron)({ networkUrl, pendingOnly });
|
|
380
|
+
const result = await (0, relay_cron_1.runRelayCron)({ networkUrl, pendingOnly, quiet });
|
|
380
381
|
if (json) {
|
|
381
382
|
printJson({
|
|
382
383
|
...result,
|
|
@@ -384,6 +385,9 @@ async function cmdRelay(args) {
|
|
|
384
385
|
});
|
|
385
386
|
return;
|
|
386
387
|
}
|
|
388
|
+
if (!result.notify) {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
387
391
|
if (result.relayed.length > 0) {
|
|
388
392
|
if (result.pending_count === 0 && !pendingOnly) {
|
|
389
393
|
process.stdout.write(`${result.relayed.length} new inbound message(s):\n\n`);
|
|
@@ -391,7 +395,9 @@ async function cmdRelay(args) {
|
|
|
391
395
|
process.stdout.write(`${(0, relay_cron_1.formatRelayOutput)(result.relayed)}\n`);
|
|
392
396
|
return;
|
|
393
397
|
}
|
|
394
|
-
|
|
398
|
+
if (result.message) {
|
|
399
|
+
process.stdout.write(`${result.message}\n`);
|
|
400
|
+
}
|
|
395
401
|
}
|
|
396
402
|
async function cmdPending(args) {
|
|
397
403
|
const json = hasFlag(args, "--json");
|
package/dist/relay-cron.js
CHANGED
|
@@ -17,6 +17,7 @@ function formatRelayOutput(items) {
|
|
|
17
17
|
return items.map(formatItem).join("\n\n---\n\n");
|
|
18
18
|
}
|
|
19
19
|
async function runRelayCron(options) {
|
|
20
|
+
const quiet = options.quiet ?? false;
|
|
20
21
|
const pending = await (0, pending_1.listPending)();
|
|
21
22
|
const pendingMap = new Map(pending.map((p) => [p.peer.toLowerCase(), p]));
|
|
22
23
|
if (options.pendingOnly && pending.length === 0) {
|
|
@@ -24,7 +25,10 @@ async function runRelayCron(options) {
|
|
|
24
25
|
pending_count: 0,
|
|
25
26
|
relayed: [],
|
|
26
27
|
skipped_relayed: 0,
|
|
27
|
-
message:
|
|
28
|
+
message: quiet
|
|
29
|
+
? undefined
|
|
30
|
+
: "No pending tracked sends — list is empty.",
|
|
31
|
+
notify: !quiet,
|
|
28
32
|
};
|
|
29
33
|
}
|
|
30
34
|
const inbox = await (0, network_1.fetchInbox)(options.networkUrl, { peek: true });
|
|
@@ -55,17 +59,46 @@ async function runRelayCron(options) {
|
|
|
55
59
|
}
|
|
56
60
|
for (const peer of peersToClear) {
|
|
57
61
|
await (0, pending_1.clearPending)(peer);
|
|
62
|
+
await (0, relay_state_1.clearWaitingReported)(peer);
|
|
63
|
+
}
|
|
64
|
+
if (items.length > 0) {
|
|
65
|
+
return {
|
|
66
|
+
pending_count: pending.length,
|
|
67
|
+
relayed: items,
|
|
68
|
+
skipped_relayed: skippedRelayed,
|
|
69
|
+
notify: true,
|
|
70
|
+
};
|
|
58
71
|
}
|
|
59
72
|
let message;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
73
|
+
let notify = !quiet;
|
|
74
|
+
if (pending.length > 0) {
|
|
75
|
+
const waitingPeers = [];
|
|
76
|
+
for (const entry of pending) {
|
|
77
|
+
const shouldReport = await (0, relay_state_1.shouldReportWaiting)(entry.peer, entry.sentAt);
|
|
78
|
+
if (shouldReport) {
|
|
79
|
+
waitingPeers.push(entry.peer);
|
|
80
|
+
await (0, relay_state_1.markWaitingReported)(entry.peer, entry.sentAt);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (waitingPeers.length > 0) {
|
|
84
|
+
message = `Waiting for replies from: ${waitingPeers.join(", ")}`;
|
|
85
|
+
notify = true;
|
|
86
|
+
}
|
|
87
|
+
else if (quiet) {
|
|
88
|
+
message = undefined;
|
|
89
|
+
notify = false;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
message = `Still waiting for: ${pending.map((p) => p.peer).join(", ")}`;
|
|
93
|
+
notify = true;
|
|
94
|
+
}
|
|
63
95
|
}
|
|
64
96
|
return {
|
|
65
97
|
pending_count: pending.length,
|
|
66
|
-
relayed:
|
|
98
|
+
relayed: [],
|
|
67
99
|
skipped_relayed: skippedRelayed,
|
|
68
100
|
message,
|
|
101
|
+
notify,
|
|
69
102
|
};
|
|
70
103
|
}
|
|
71
104
|
function buildItem(msg, pending, kind) {
|
package/dist/relay-state.js
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.filterUnrelayed = filterUnrelayed;
|
|
4
4
|
exports.markRelayed = markRelayed;
|
|
5
|
+
exports.shouldReportWaiting = shouldReportWaiting;
|
|
6
|
+
exports.markWaitingReported = markWaitingReported;
|
|
7
|
+
exports.clearWaitingReported = clearWaitingReported;
|
|
5
8
|
const promises_1 = require("node:fs/promises");
|
|
6
9
|
const node_path_1 = require("node:path");
|
|
7
10
|
const node_os_1 = require("node:os");
|
|
@@ -9,21 +12,36 @@ const MAX_IDS = 500;
|
|
|
9
12
|
function statePath() {
|
|
10
13
|
return (0, node_path_1.join)((0, node_os_1.homedir)(), ".marshell", "relay-state.json");
|
|
11
14
|
}
|
|
15
|
+
function emptyState() {
|
|
16
|
+
return {
|
|
17
|
+
relayedIds: [],
|
|
18
|
+
waitingReported: {},
|
|
19
|
+
updatedAt: new Date().toISOString(),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
12
22
|
async function readState() {
|
|
13
23
|
try {
|
|
14
24
|
const raw = await (0, promises_1.readFile)(statePath(), "utf8");
|
|
15
|
-
|
|
25
|
+
const parsed = JSON.parse(raw);
|
|
26
|
+
return {
|
|
27
|
+
relayedIds: parsed.relayedIds ?? [],
|
|
28
|
+
waitingReported: parsed.waitingReported ?? {},
|
|
29
|
+
updatedAt: parsed.updatedAt ?? new Date().toISOString(),
|
|
30
|
+
};
|
|
16
31
|
}
|
|
17
32
|
catch (error) {
|
|
18
33
|
const maybeCode = error.code;
|
|
19
34
|
if (maybeCode === "ENOENT") {
|
|
20
|
-
return
|
|
35
|
+
return emptyState();
|
|
21
36
|
}
|
|
22
37
|
throw error;
|
|
23
38
|
}
|
|
24
39
|
}
|
|
25
40
|
async function writeState(state) {
|
|
26
41
|
await (0, promises_1.mkdir)((0, node_path_1.join)((0, node_os_1.homedir)(), ".marshell"), { recursive: true });
|
|
42
|
+
await writeStateFile(state);
|
|
43
|
+
}
|
|
44
|
+
async function writeStateFile(state) {
|
|
27
45
|
await (0, promises_1.writeFile)(statePath(), `${JSON.stringify(state, null, 2)}\n`, "utf8");
|
|
28
46
|
}
|
|
29
47
|
async function filterUnrelayed(messages) {
|
|
@@ -37,8 +55,37 @@ async function markRelayed(ids) {
|
|
|
37
55
|
const state = await readState();
|
|
38
56
|
const merged = [...new Set([...state.relayedIds, ...ids])];
|
|
39
57
|
const trimmed = merged.length > MAX_IDS ? merged.slice(merged.length - MAX_IDS) : merged;
|
|
40
|
-
await
|
|
58
|
+
await writeStateFile({
|
|
59
|
+
...state,
|
|
41
60
|
relayedIds: trimmed,
|
|
42
61
|
updatedAt: new Date().toISOString(),
|
|
43
62
|
});
|
|
44
63
|
}
|
|
64
|
+
/** True if we should tell the human we're waiting on this peer (once per pending). */
|
|
65
|
+
async function shouldReportWaiting(peer, pendingSentAt) {
|
|
66
|
+
const state = await readState();
|
|
67
|
+
const key = peer.toLowerCase();
|
|
68
|
+
return state.waitingReported[key] !== pendingSentAt;
|
|
69
|
+
}
|
|
70
|
+
async function markWaitingReported(peer, pendingSentAt) {
|
|
71
|
+
const state = await readState();
|
|
72
|
+
const key = peer.toLowerCase();
|
|
73
|
+
await writeStateFile({
|
|
74
|
+
...state,
|
|
75
|
+
waitingReported: { ...state.waitingReported, [key]: pendingSentAt },
|
|
76
|
+
updatedAt: new Date().toISOString(),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
async function clearWaitingReported(peer) {
|
|
80
|
+
const state = await readState();
|
|
81
|
+
const key = peer.toLowerCase();
|
|
82
|
+
if (!(key in state.waitingReported))
|
|
83
|
+
return;
|
|
84
|
+
const next = { ...state.waitingReported };
|
|
85
|
+
delete next[key];
|
|
86
|
+
await writeStateFile({
|
|
87
|
+
...state,
|
|
88
|
+
waitingReported: next,
|
|
89
|
+
updatedAt: new Date().toISOString(),
|
|
90
|
+
});
|
|
91
|
+
}
|