@memnexus-ai/mx-agent-cli 0.1.167 → 0.1.168
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/__tests__/config-command.test.d.ts +9 -0
- package/dist/__tests__/config-command.test.d.ts.map +1 -0
- package/dist/__tests__/config-command.test.js +55 -0
- package/dist/__tests__/config-command.test.js.map +1 -0
- package/dist/__tests__/coordination-client.test.d.ts +9 -0
- package/dist/__tests__/coordination-client.test.d.ts.map +1 -0
- package/dist/__tests__/coordination-client.test.js +72 -0
- package/dist/__tests__/coordination-client.test.js.map +1 -0
- package/dist/__tests__/coordination-command.test.d.ts +9 -0
- package/dist/__tests__/coordination-command.test.d.ts.map +1 -0
- package/dist/__tests__/coordination-command.test.js +108 -0
- package/dist/__tests__/coordination-command.test.js.map +1 -0
- package/dist/__tests__/coordination-fallback.test.d.ts +9 -0
- package/dist/__tests__/coordination-fallback.test.d.ts.map +1 -0
- package/dist/__tests__/coordination-fallback.test.js +158 -0
- package/dist/__tests__/coordination-fallback.test.js.map +1 -0
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +5 -1
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/coordination.d.ts +49 -0
- package/dist/commands/coordination.d.ts.map +1 -0
- package/dist/commands/coordination.js +128 -0
- package/dist/commands/coordination.js.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/coordination-client.d.ts +74 -0
- package/dist/lib/coordination-client.d.ts.map +1 -0
- package/dist/lib/coordination-client.js +83 -0
- package/dist/lib/coordination-client.js.map +1 -0
- package/dist/lib/coordination-fallback.d.ts +75 -0
- package/dist/lib/coordination-fallback.d.ts.map +1 -0
- package/dist/lib/coordination-fallback.js +224 -0
- package/dist/lib/coordination-fallback.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* coordination-fallback -- FR-8 degraded-mode durable fallback for enqueue.
|
|
3
|
+
*
|
|
4
|
+
* When the coordination service is unreachable, `mx-agent escalate` writes the
|
|
5
|
+
* message ONLY to a local durable file in the worktree (never a network call),
|
|
6
|
+
* so the entry is non-lossy. On the next successful CLI invocation the file is
|
|
7
|
+
* flushed into the service under a single-flusher lease, each entry carrying an
|
|
8
|
+
* idempotency key so a re-run (or interrupted flush) is a server-side no-op.
|
|
9
|
+
*
|
|
10
|
+
* Hardening (KI-COORD-SF2): the fallback file is opened O_NOFOLLOW + O_CREAT,
|
|
11
|
+
* mode 0600, with per-entry atomic append (one line < PIPE_BUF under O_APPEND is
|
|
12
|
+
* atomic on POSIX). A pre-planted symlink is rejected (ELOOP).
|
|
13
|
+
*
|
|
14
|
+
* Part of PR-B / FR-8 of the agent coordination queue PRD.
|
|
15
|
+
*/
|
|
16
|
+
import { openSync, writeSync, closeSync, fstatSync, fchmodSync, readFileSync, writeFileSync, existsSync, statSync, unlinkSync, constants as fsConstants, } from 'fs';
|
|
17
|
+
import { join } from 'path';
|
|
18
|
+
import { createHash } from 'crypto';
|
|
19
|
+
export const FALLBACK_FILENAME = '.mx-coordination-fallback.jsonl';
|
|
20
|
+
export const LEASE_FILENAME = '.mx-coordination-fallback.lock';
|
|
21
|
+
export const CORRUPT_FILENAME = '.mx-coordination-fallback.corrupt.jsonl';
|
|
22
|
+
export function corruptPath(root = worktreeRoot()) {
|
|
23
|
+
return join(root, CORRUPT_FILENAME);
|
|
24
|
+
}
|
|
25
|
+
export function worktreeRoot() {
|
|
26
|
+
return process.env.CLAUDE_WORKTREE_PATH || process.cwd();
|
|
27
|
+
}
|
|
28
|
+
export function fallbackPath(root = worktreeRoot()) {
|
|
29
|
+
return join(root, FALLBACK_FILENAME);
|
|
30
|
+
}
|
|
31
|
+
export function leasePath(root = worktreeRoot()) {
|
|
32
|
+
return join(root, LEASE_FILENAME);
|
|
33
|
+
}
|
|
34
|
+
/** Idempotency key = team + localTimestamp + contentHash (matches the flush spec). */
|
|
35
|
+
export function idempotencyKeyFor(team, localTimestamp, body) {
|
|
36
|
+
const contentHash = createHash('sha256').update(body, 'utf8').digest('hex');
|
|
37
|
+
return `${team}:${localTimestamp}:${contentHash}`;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Append one entry to the fallback file with a single atomic write. Opens
|
|
41
|
+
* O_NOFOLLOW so a pre-planted symlink is rejected, O_CREAT|O_APPEND mode 0600.
|
|
42
|
+
*/
|
|
43
|
+
export function appendFallbackEntry(entry, path = fallbackPath()) {
|
|
44
|
+
const localTimestamp = entry.localTimestamp ?? new Date().toISOString();
|
|
45
|
+
const full = {
|
|
46
|
+
...entry,
|
|
47
|
+
localTimestamp,
|
|
48
|
+
idempotencyKey: idempotencyKeyFor(entry.team, localTimestamp, entry.body),
|
|
49
|
+
};
|
|
50
|
+
const flags = fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_APPEND | fsConstants.O_NOFOLLOW;
|
|
51
|
+
const fd = openSync(path, flags, 0o600);
|
|
52
|
+
try {
|
|
53
|
+
// Tighten a pre-existing loose file (MINOR-5): if the file existed with
|
|
54
|
+
// group/other bits, fchmod it back to 0600 before writing the secret body.
|
|
55
|
+
const mode = fstatSync(fd).mode & 0o777;
|
|
56
|
+
if (mode & 0o077)
|
|
57
|
+
fchmodSync(fd, 0o600);
|
|
58
|
+
writeSync(fd, `${JSON.stringify(full)}\n`);
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
closeSync(fd);
|
|
62
|
+
}
|
|
63
|
+
return full;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Read fallback entries, SKIP-AND-QUARANTINE corrupt lines (MAJOR-4): a single
|
|
67
|
+
* JSON-invalid line must not wedge the whole queue. Bad lines are appended to a
|
|
68
|
+
* sibling `.corrupt.jsonl` (0600) for manual inspection and a warning is printed
|
|
69
|
+
* to stderr; valid lines are returned. `corruptFile` is injectable for tests.
|
|
70
|
+
*/
|
|
71
|
+
export function readFallbackEntries(path = fallbackPath(), corruptFile = corruptPath()) {
|
|
72
|
+
if (!existsSync(path))
|
|
73
|
+
return [];
|
|
74
|
+
const raw = readFileSync(path, 'utf8');
|
|
75
|
+
const good = [];
|
|
76
|
+
const corrupt = [];
|
|
77
|
+
for (const line of raw.split('\n')) {
|
|
78
|
+
const trimmed = line.trim();
|
|
79
|
+
if (!trimmed)
|
|
80
|
+
continue;
|
|
81
|
+
try {
|
|
82
|
+
good.push(JSON.parse(trimmed));
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
corrupt.push(trimmed);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (corrupt.length > 0) {
|
|
89
|
+
const noun = `corrupt fallback entr${corrupt.length === 1 ? 'y' : 'ies'}`;
|
|
90
|
+
try {
|
|
91
|
+
// Same O_NOFOLLOW protection as the main file: never follow a pre-planted
|
|
92
|
+
// symlink at the quarantine path.
|
|
93
|
+
const flags = fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_APPEND | fsConstants.O_NOFOLLOW;
|
|
94
|
+
const fd = openSync(corruptFile, flags, 0o600);
|
|
95
|
+
try {
|
|
96
|
+
const mode = fstatSync(fd).mode & 0o777;
|
|
97
|
+
if (mode & 0o077)
|
|
98
|
+
fchmodSync(fd, 0o600);
|
|
99
|
+
writeSync(fd, corrupt.join('\n') + '\n');
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
closeSync(fd);
|
|
103
|
+
}
|
|
104
|
+
process.stderr.write(`WARNING: ${corrupt.length} ${noun} quarantined to ${corruptFile} — inspect manually\n`);
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
// Quarantine path is a symlink or unwritable — never follow, never crash.
|
|
108
|
+
// Surface the lost lines INLINE so nothing is silently dropped.
|
|
109
|
+
const code = err.code ?? 'error';
|
|
110
|
+
process.stderr.write(`WARNING: could not quarantine ${corrupt.length} ${noun} (${code}) to ${corruptFile} — NOT written; inline: ${corrupt.join(' | ')}\n`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return good;
|
|
114
|
+
}
|
|
115
|
+
function writeFallbackEntries(entries, path) {
|
|
116
|
+
if (entries.length === 0) {
|
|
117
|
+
if (existsSync(path))
|
|
118
|
+
unlinkSync(path);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
writeFileSync(path, entries.map((e) => JSON.stringify(e)).join('\n') + '\n', { mode: 0o600 });
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Acquire the single-flusher lease (exclusive create). If a lease exists but is
|
|
125
|
+
* stale (older than staleMs), steal it — a crashed flusher must not wedge the
|
|
126
|
+
* queue. Returns true if acquired.
|
|
127
|
+
*/
|
|
128
|
+
export function acquireLease(path = leasePath(), staleMs = 30_000) {
|
|
129
|
+
const flags = fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL | fsConstants.O_NOFOLLOW;
|
|
130
|
+
const tryCreate = () => {
|
|
131
|
+
try {
|
|
132
|
+
const fd = openSync(path, flags, 0o600);
|
|
133
|
+
writeSync(fd, JSON.stringify({ pid: process.pid, ts: new Date().toISOString() }));
|
|
134
|
+
closeSync(fd);
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
if (err.code === 'EEXIST')
|
|
139
|
+
return false;
|
|
140
|
+
throw err;
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
if (tryCreate())
|
|
144
|
+
return true;
|
|
145
|
+
// Lease exists — steal it if stale.
|
|
146
|
+
try {
|
|
147
|
+
const age = Date.now() - statSync(path).mtimeMs;
|
|
148
|
+
if (age > staleMs) {
|
|
149
|
+
unlinkSync(path);
|
|
150
|
+
return tryCreate();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
/* raced away — fall through to not-acquired */
|
|
155
|
+
}
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
export function releaseLease(path = leasePath()) {
|
|
159
|
+
try {
|
|
160
|
+
if (existsSync(path))
|
|
161
|
+
unlinkSync(path);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
/* best effort */
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Flush queued-locally entries into the service under the single-flusher lease.
|
|
169
|
+
* Each entry is enqueued with its idempotency key; a re-flush of an already-sent
|
|
170
|
+
* entry is a server-side dedup no-op (the service treats dedup as
|
|
171
|
+
* fail-open-with-audit, which makes re-flush safe by design). Stops early if the
|
|
172
|
+
* service is still unreachable, leaving remaining entries on disk.
|
|
173
|
+
*/
|
|
174
|
+
export async function flushFallback(client, opts = {}) {
|
|
175
|
+
const fp = opts.fallbackPath ?? fallbackPath();
|
|
176
|
+
const lp = opts.leasePath ?? leasePath();
|
|
177
|
+
const cp = opts.corruptPath ?? `${fp.replace(/\.jsonl$/, '')}.corrupt.jsonl`;
|
|
178
|
+
const entries = readFallbackEntries(fp, cp);
|
|
179
|
+
if (entries.length === 0)
|
|
180
|
+
return { flushed: 0, remaining: 0, skipped: false };
|
|
181
|
+
if (!acquireLease(lp, opts.staleMs)) {
|
|
182
|
+
return { flushed: 0, remaining: entries.length, skipped: true };
|
|
183
|
+
}
|
|
184
|
+
let flushed = 0;
|
|
185
|
+
try {
|
|
186
|
+
// Re-read under the lease so we do not clobber entries a prior holder wrote.
|
|
187
|
+
const held = readFallbackEntries(fp, cp);
|
|
188
|
+
const remaining = [];
|
|
189
|
+
let stillDown = false;
|
|
190
|
+
for (const entry of held) {
|
|
191
|
+
if (stillDown) {
|
|
192
|
+
remaining.push(entry);
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
try {
|
|
196
|
+
const req = {
|
|
197
|
+
to: entry.to,
|
|
198
|
+
priority: entry.priority,
|
|
199
|
+
body: entry.body,
|
|
200
|
+
from: entry.from ?? entry.team,
|
|
201
|
+
idempotencyKey: entry.idempotencyKey,
|
|
202
|
+
};
|
|
203
|
+
await client.enqueue(req);
|
|
204
|
+
flushed++;
|
|
205
|
+
}
|
|
206
|
+
catch (err) {
|
|
207
|
+
if (err?.name === 'ServiceUnreachableError') {
|
|
208
|
+
// Still down — keep this and all following entries for the next flush.
|
|
209
|
+
stillDown = true;
|
|
210
|
+
remaining.push(entry);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
throw err; // a real HTTP error is not a transient outage
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
writeFallbackEntries(remaining, fp);
|
|
218
|
+
return { flushed, remaining: remaining.length, skipped: false };
|
|
219
|
+
}
|
|
220
|
+
finally {
|
|
221
|
+
releaseLease(lp);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=coordination-fallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordination-fallback.js","sourceRoot":"","sources":["../../src/lib/coordination-fallback.ts"],"names":[],"mappings":"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"}
|