@memnexus-ai/mx-agent-cli 0.1.156 → 0.1.158

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.
@@ -0,0 +1,278 @@
1
+ /**
2
+ * leader-lock.ts — leader-session start-time mutual exclusion (Platform v2.30, #3946).
3
+ *
4
+ * ── SCOPE STATEMENT (explicit) ────────────────────────────────────────────
5
+ * This module implements leader-session START-TIME mutual exclusion ONLY: it
6
+ * refuses to launch a second `mx-agent start` leader in a worktree that already
7
+ * has a live leader. It is a file-based advisory lock in the worktree root.
8
+ *
9
+ * It does NOT address the concurrent named-memory WRITE-RACE class — that is a
10
+ * separate, already-shipped fix (#3697 / #3713, compare-and-set on named-memory
11
+ * writes). Do not conflate the two: this lock guards process launch, CAS guards
12
+ * memory content. Sub-agent teammates are spawned via the Task tool INSIDE a
13
+ * leader session, never via `mx-agent start`, so they never touch this lock
14
+ * (asserted in leader-lock.test.ts).
15
+ *
16
+ * ── Liveness discriminator ─────────────────────────────────────────────────
17
+ * A recorded PID is a live match for THIS worktree iff `/proc/<pid>` exists AND
18
+ * either `/proc/<pid>/cwd` resolves to this worktree's realpath (worktree-unique)
19
+ * OR `/proc/<pid>/environ` contains `CLAUDE_WORKTREE_PATH=<this worktree>`. We do
20
+ * NOT use cmdline (identical across teams) or tty (headless sessions have none).
21
+ *
22
+ * ── Fail-open contract ─────────────────────────────────────────────────────
23
+ * Any ambiguity (no /proc, permission errors, malformed lock) resolves to
24
+ * FAIL OPEN with a loud warning — never brick a legitimate start.
25
+ */
26
+ import { existsSync, readFileSync, realpathSync, statSync, unlinkSync, writeFileSync } from 'fs';
27
+ import { join } from 'path';
28
+ export const LOCK_FILENAME = '.mx-leader.lock';
29
+ export function lockPath(worktreePath) {
30
+ return join(worktreePath, LOCK_FILENAME);
31
+ }
32
+ /** Hard cap on lock file size. A well-formed lock is a few hundred bytes; a
33
+ * multi-megabyte file is either corruption or a crafted resource-exhaustion
34
+ * attempt. Oversize → treated as malformed (fail open), never read into memory. */
35
+ export const MAX_LOCK_BYTES = 64 * 1024;
36
+ export function readLock(worktreePath) {
37
+ const p = lockPath(worktreePath);
38
+ if (!existsSync(p))
39
+ return { present: false, lock: null };
40
+ // Size guard BEFORE reading — bound the bytes we ever pull into memory.
41
+ try {
42
+ const size = statSync(p).size;
43
+ if (size > MAX_LOCK_BYTES) {
44
+ return { present: true, lock: null, parseError: `lock file too large (${size} > ${MAX_LOCK_BYTES} bytes)` };
45
+ }
46
+ }
47
+ catch (err) {
48
+ return { present: true, lock: null, parseError: err instanceof Error ? err.message : String(err) };
49
+ }
50
+ let raw;
51
+ try {
52
+ raw = readFileSync(p, 'utf-8');
53
+ }
54
+ catch (err) {
55
+ return { present: true, lock: null, parseError: err instanceof Error ? err.message : String(err) };
56
+ }
57
+ try {
58
+ const obj = JSON.parse(raw);
59
+ if (typeof obj.team !== 'string' ||
60
+ typeof obj.worktreePath !== 'string' ||
61
+ typeof obj.wrapperPid !== 'number' ||
62
+ typeof obj.startedAt !== 'string' ||
63
+ typeof obj.version !== 'string' ||
64
+ (obj.childPid !== null && typeof obj.childPid !== 'number')) {
65
+ return { present: true, lock: null, parseError: 'lock missing required fields' };
66
+ }
67
+ return { present: true, lock: obj };
68
+ }
69
+ catch (err) {
70
+ return { present: true, lock: null, parseError: err instanceof Error ? err.message : String(err) };
71
+ }
72
+ }
73
+ function serializeLock(lock) {
74
+ return JSON.stringify(lock, null, 2) + '\n';
75
+ }
76
+ /** Force-write (overwrite) the lock. Used to patch childPid into a lock we
77
+ * already own, and as the final fail-open path. For the mutual-exclusion
78
+ * decision use {@link claimLock}, not this. */
79
+ export function writeLock(worktreePath, lock) {
80
+ writeFileSync(lockPath(worktreePath), serializeLock(lock), 'utf-8');
81
+ }
82
+ /**
83
+ * Atomically claim the lock via an exclusive create (`O_CREAT | O_EXCL`, i.e.
84
+ * `writeFileSync(..., { flag: 'wx' })`). This single filesystem operation IS the
85
+ * mutual-exclusion decision: if two `mx-agent start` invocations race, exactly
86
+ * one exclusive-create succeeds and the other gets EEXIST. No check-then-write
87
+ * TOCTOU window (that was the pre-fix bug: liveness check and lock write were
88
+ * separated by the whole fetch/rebase sequence, so both racers passed).
89
+ *
90
+ * NOTE: scope is single-host. `O_EXCL` on a POSIX filesystem is atomic locally;
91
+ * it is NOT guaranteed atomic over some network filesystems (older NFS). Agents
92
+ * run one host per worktree, so this holds. The named-memory write-race across
93
+ * hosts is a separate, shipped concern (#3697/#3713 CAS).
94
+ */
95
+ export function claimLock(worktreePath, lock) {
96
+ try {
97
+ writeFileSync(lockPath(worktreePath), serializeLock(lock), { encoding: 'utf-8', flag: 'wx' });
98
+ return { ok: true };
99
+ }
100
+ catch (err) {
101
+ const code = err.code;
102
+ if (code === 'EEXIST')
103
+ return { ok: false, reason: 'exists' };
104
+ return { ok: false, reason: 'error', error: err instanceof Error ? err.message : String(err) };
105
+ }
106
+ }
107
+ /** Read-modify-write to record the child PID once the child has spawned. */
108
+ export function updateChildPid(worktreePath, childPid) {
109
+ const { lock } = readLock(worktreePath);
110
+ if (!lock)
111
+ return; // lock vanished/corrupt — nothing to update; launch proceeds.
112
+ writeLock(worktreePath, { ...lock, childPid });
113
+ }
114
+ export function removeLock(worktreePath) {
115
+ try {
116
+ unlinkSync(lockPath(worktreePath));
117
+ }
118
+ catch {
119
+ // Already gone — fine.
120
+ }
121
+ }
122
+ function normalizeRealpath(p) {
123
+ try {
124
+ return realpathSync(p);
125
+ }
126
+ catch {
127
+ return p;
128
+ }
129
+ }
130
+ /**
131
+ * Probe a single PID against a worktree. See module header for the discriminator.
132
+ *
133
+ * Errors are classified: a missing `/proc/<pid>` (or ENOENT mid-read) means the
134
+ * process is gone → `dead`. A permission error (EACCES/EPERM) reading cwd/environ
135
+ * means we cannot verify → `indeterminate` (fail open). A live process whose
136
+ * cwd/environ point elsewhere → `dead` (not our leader).
137
+ */
138
+ export function probePid(pid, worktreeReal) {
139
+ if (!Number.isInteger(pid) || pid <= 0) {
140
+ return { pid, state: 'dead', reason: 'invalid pid' };
141
+ }
142
+ if (!existsSync('/proc')) {
143
+ return { pid, state: 'indeterminate', reason: '/proc not available' };
144
+ }
145
+ const procDir = `/proc/${pid}`;
146
+ if (!existsSync(procDir)) {
147
+ return { pid, state: 'dead', reason: 'no such process' };
148
+ }
149
+ let permissionBlocked = false;
150
+ // 1. cwd — the strongest signal (worktree-unique symlink).
151
+ let cwdReal;
152
+ try {
153
+ cwdReal = realpathSync(`${procDir}/cwd`);
154
+ if (cwdReal === worktreeReal) {
155
+ return { pid, state: 'live', matchedBy: 'cwd', cwd: cwdReal };
156
+ }
157
+ }
158
+ catch (err) {
159
+ const code = err.code;
160
+ if (code === 'ENOENT') {
161
+ return { pid, state: 'dead', reason: 'process exited during probe' };
162
+ }
163
+ if (code === 'EACCES' || code === 'EPERM') {
164
+ permissionBlocked = true;
165
+ }
166
+ }
167
+ // 2. environ — covers cases where cwd changed but the launch env is intact.
168
+ try {
169
+ const environ = readFileSync(`${procDir}/environ`, 'utf-8');
170
+ for (const entry of environ.split('\0')) {
171
+ const eq = entry.indexOf('=');
172
+ if (eq === -1)
173
+ continue;
174
+ if (entry.slice(0, eq) !== 'CLAUDE_WORKTREE_PATH')
175
+ continue;
176
+ const val = entry.slice(eq + 1);
177
+ if (val === worktreeReal || normalizeRealpath(val) === worktreeReal) {
178
+ return { pid, state: 'live', matchedBy: 'environ', cwd: cwdReal };
179
+ }
180
+ }
181
+ }
182
+ catch (err) {
183
+ const code = err.code;
184
+ if (code === 'EACCES' || code === 'EPERM') {
185
+ permissionBlocked = true;
186
+ }
187
+ // ENOENT here just means the process exited between the two reads; the cwd
188
+ // path already handled a clean exit, so fall through.
189
+ }
190
+ // Process is alive but we found no positive match. If reads were blocked by
191
+ // permissions we cannot conclude it's a different worktree → indeterminate.
192
+ if (permissionBlocked) {
193
+ return { pid, state: 'indeterminate', reason: 'process alive but /proc unreadable (permission)' };
194
+ }
195
+ return { pid, state: 'dead', reason: 'alive but different worktree', cwd: cwdReal };
196
+ }
197
+ /**
198
+ * Heartbeat freshness window. The child refreshes the lock mtime on every Bash
199
+ * PostToolUse (see deploy-verification-reminder.sh). A lock touched within this
200
+ * window is evidence a child was recently alive; we use it only to STRENGTHEN
201
+ * the stale-lock warning, never to force a refusal (clock skew / idle sessions
202
+ * must not brick a start). Primary detection is always the both-PID probe.
203
+ */
204
+ export const HEARTBEAT_FRESH_SECONDS = 300;
205
+ /**
206
+ * Evaluate a lock's liveness by probing BOTH recorded PIDs (wrapper + child).
207
+ *
208
+ * - Any PID a live match for this worktree → `live` (refuse).
209
+ * - No live match, but at least one indeterminate probe → `indeterminate` (fail open).
210
+ * - All PIDs dead/mismatched → `stale` (replace).
211
+ */
212
+ export function checkLiveness(lock, worktreePath) {
213
+ const worktreeReal = normalizeRealpath(worktreePath);
214
+ const pids = [lock.wrapperPid, lock.childPid].filter((p) => typeof p === 'number' && Number.isInteger(p) && p > 0);
215
+ const probes = pids.map(pid => probePid(pid, worktreeReal));
216
+ let lockAgeSeconds = null;
217
+ try {
218
+ const mtimeMs = statSync(lockPath(worktreePath)).mtimeMs;
219
+ lockAgeSeconds = Math.max(0, Math.round((Date.now() - mtimeMs) / 1000));
220
+ }
221
+ catch {
222
+ lockAgeSeconds = null;
223
+ }
224
+ const livePids = probes.filter(p => p.state === 'live').map(p => p.pid);
225
+ let state;
226
+ if (livePids.length > 0)
227
+ state = 'live';
228
+ else if (probes.some(p => p.state === 'indeterminate'))
229
+ state = 'indeterminate';
230
+ else
231
+ state = 'stale';
232
+ return { state, probes, livePids, lockAgeSeconds };
233
+ }
234
+ /**
235
+ * Sanitize a lock-derived string before printing it to a terminal.
236
+ *
237
+ * The lock file is attacker-influenceable (any process that can write the
238
+ * worktree can craft it). Its string fields (team, worktreePath, startedAt,
239
+ * version, and probe cwd) are echoed into the refusal/unlock evidence, which
240
+ * prints to a TTY. Without sanitization a crafted `team` could embed OSC/CSI
241
+ * escape sequences (erase-line, cursor moves, tab-title rewrite) — the reviewer
242
+ * demonstrated this. Strip C0 (0x00–0x1F) and DEL+C1 (0x7F–0x9F) control chars
243
+ * and cap the printed length.
244
+ */
245
+ export const MAX_EVIDENCE_FIELD_CHARS = 256;
246
+ export function sanitizeField(value, maxLen = MAX_EVIDENCE_FIELD_CHARS) {
247
+ // Strip C0 (0x00-0x1F), DEL (0x7F) and C1 (0x80-0x9F) — built from escape
248
+ // sequences so this source file itself carries no raw control bytes.
249
+ const CONTROL_CHARS = new RegExp("[\\u0000-\\u001F\\u007F-\\u009F]", "g");
250
+ const stripped = String(value).replace(CONTROL_CHARS, "");
251
+ return stripped.length > maxLen ? `${stripped.slice(0, maxLen)}…(truncated)` : stripped;
252
+ }
253
+ /** Human-readable evidence block shared by the refusal message and `mx-agent unlock`. */
254
+ export function formatLockEvidence(lock, result) {
255
+ const lines = [];
256
+ lines.push(` team: ${sanitizeField(lock.team)}`);
257
+ lines.push(` worktree: ${sanitizeField(lock.worktreePath)}`);
258
+ lines.push(` wrapper pid: ${lock.wrapperPid}`); // numeric — safe
259
+ lines.push(` child pid: ${lock.childPid ?? '(not yet spawned)'}`); // numeric | null — safe
260
+ lines.push(` started at: ${sanitizeField(lock.startedAt)}`);
261
+ lines.push(` version: ${sanitizeField(lock.version)}`);
262
+ if (result) {
263
+ if (result.livePids.length > 0) {
264
+ lines.push(` live pids: ${result.livePids.join(', ')}`); // numeric — safe
265
+ }
266
+ for (const probe of result.probes) {
267
+ const detail = probe.matchedBy
268
+ ? `matched by ${probe.matchedBy}${probe.cwd ? ` (cwd=${sanitizeField(probe.cwd)})` : ''}`
269
+ : probe.reason ?? '';
270
+ lines.push(` pid ${probe.pid}: ${probe.state}${detail ? ` — ${detail}` : ''}`);
271
+ }
272
+ if (result.lockAgeSeconds !== null) {
273
+ lines.push(` lock age: ${result.lockAgeSeconds}s (mtime heartbeat)`);
274
+ }
275
+ }
276
+ return lines.join('\n');
277
+ }
278
+ //# sourceMappingURL=leader-lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"leader-lock.js","sourceRoot":"","sources":["../../src/lib/leader-lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACjG,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,CAAC,MAAM,aAAa,GAAG,iBAAiB,CAAC;AAgB/C,MAAM,UAAU,QAAQ,CAAC,YAAoB;IAC3C,OAAO,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;AAC3C,CAAC;AAYD;;mFAEmF;AACnF,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,GAAG,IAAI,CAAC;AAExC,MAAM,UAAU,QAAQ,CAAC,YAAoB;IAC3C,MAAM,CAAC,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;IACjC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC1D,wEAAwE;IACxE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9B,IAAI,IAAI,GAAG,cAAc,EAAE,CAAC;YAC1B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,wBAAwB,IAAI,MAAM,cAAc,SAAS,EAAE,CAAC;QAC9G,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;IACrG,CAAC;IACD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;IACrG,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAwB,CAAC;QACnD,IACE,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;YAC5B,OAAO,GAAG,CAAC,YAAY,KAAK,QAAQ;YACpC,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ;YAClC,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ;YACjC,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;YAC/B,CAAC,GAAG,CAAC,QAAQ,KAAK,IAAI,IAAI,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,EAC3D,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,8BAA8B,EAAE,CAAC;QACnF,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAiB,EAAE,CAAC;IACpD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;IACrG,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,IAAgB;IACrC,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;AAC9C,CAAC;AAED;;+CAE+C;AAC/C,MAAM,UAAU,SAAS,CAAC,YAAoB,EAAE,IAAgB;IAC9D,aAAa,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;AACtE,CAAC;AAOD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,SAAS,CAAC,YAAoB,EAAE,IAAgB;IAC9D,IAAI,CAAC;QACH,aAAa,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9F,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;QACjD,IAAI,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QAC9D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;IACjG,CAAC;AACH,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,cAAc,CAAC,YAAoB,EAAE,QAAgB;IACnE,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;IACxC,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,8DAA8D;IACjF,SAAS,CAAC,YAAY,EAAE,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,YAAoB;IAC7C,IAAI,CAAC;QACH,UAAU,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,uBAAuB;IACzB,CAAC;AACH,CAAC;AAcD,SAAS,iBAAiB,CAAC,CAAS;IAClC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAW,EAAE,YAAoB;IACxD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;QACvC,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IACvD,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,qBAAqB,EAAE,CAAC;IACxE,CAAC;IACD,MAAM,OAAO,GAAG,SAAS,GAAG,EAAE,CAAC;IAC/B,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC3D,CAAC;IAED,IAAI,iBAAiB,GAAG,KAAK,CAAC;IAE9B,2DAA2D;IAC3D,IAAI,OAA2B,CAAC;IAChC,IAAI,CAAC;QACH,OAAO,GAAG,YAAY,CAAC,GAAG,OAAO,MAAM,CAAC,CAAC;QACzC,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;YAC7B,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;QAChE,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;QACjD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,6BAA6B,EAAE,CAAC;QACvE,CAAC;QACD,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YAC1C,iBAAiB,GAAG,IAAI,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,4EAA4E;IAC5E,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,OAAO,UAAU,EAAE,OAAO,CAAC,CAAC;QAC5D,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACxC,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC9B,IAAI,EAAE,KAAK,CAAC,CAAC;gBAAE,SAAS;YACxB,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,sBAAsB;gBAAE,SAAS;YAC5D,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YAChC,IAAI,GAAG,KAAK,YAAY,IAAI,iBAAiB,CAAC,GAAG,CAAC,KAAK,YAAY,EAAE,CAAC;gBACpE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;YACpE,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;QACjD,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YAC1C,iBAAiB,GAAG,IAAI,CAAC;QAC3B,CAAC;QACD,2EAA2E;QAC3E,sDAAsD;IACxD,CAAC;IAED,4EAA4E;IAC5E,4EAA4E;IAC5E,IAAI,iBAAiB,EAAE,CAAC;QACtB,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,iDAAiD,EAAE,CAAC;IACpG,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,8BAA8B,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;AACtF,CAAC;AAYD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,IAAgB,EAAE,YAAoB;IAClE,MAAM,YAAY,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAClD,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAC1E,CAAC;IACF,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC;IAE5D,IAAI,cAAc,GAAkB,IAAI,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC;QACzD,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,CAAC;IAAC,MAAM,CAAC;QACP,cAAc,GAAG,IAAI,CAAC;IACxB,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACxE,IAAI,KAAoB,CAAC;IACzB,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,GAAG,MAAM,CAAC;SACnC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,eAAe,CAAC;QAAE,KAAK,GAAG,eAAe,CAAC;;QAC3E,KAAK,GAAG,OAAO,CAAC;IAErB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;AACrD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAE5C,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,SAAiB,wBAAwB;IACpF,0EAA0E;IAC1E,qEAAqE;IACrE,MAAM,aAAa,GAAG,IAAI,MAAM,CAAC,kCAAkC,EAAE,GAAG,CAAC,CAAC;IAC1E,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IAC1D,OAAO,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC1F,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,kBAAkB,CAAC,IAAgB,EAAE,MAAuB;IAC1E,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,kBAAkB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzD,KAAK,CAAC,IAAI,CAAC,kBAAkB,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IACjE,KAAK,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,iBAAiB;IAClE,KAAK,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,QAAQ,IAAI,mBAAmB,EAAE,CAAC,CAAC,CAAC,wBAAwB;IAC9F,KAAK,CAAC,IAAI,CAAC,kBAAkB,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAC9D,KAAK,CAAC,IAAI,CAAC,kBAAkB,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC5D,IAAI,MAAM,EAAE,CAAC;QACX,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/B,KAAK,CAAC,IAAI,CAAC,kBAAkB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB;QAC/E,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClC,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS;gBAC5B,CAAC,CAAC,cAAc,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBACzF,CAAC,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,WAAW,KAAK,CAAC,GAAG,KAAK,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACpF,CAAC;QACD,IAAI,MAAM,CAAC,cAAc,KAAK,IAAI,EAAE,CAAC;YACnC,KAAK,CAAC,IAAI,CAAC,kBAAkB,MAAM,CAAC,cAAc,qBAAqB,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memnexus-ai/mx-agent-cli",
3
- "version": "0.1.156",
3
+ "version": "0.1.158",
4
4
  "description": "CLI for creating and managing AI agent teams",
5
5
  "type": "module",
6
6
  "bin": {