@mutmutco/cli 2.62.0 → 2.64.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/index.cjs +2 -308
- package/dist/main.cjs +4830 -9597
- package/package.json +1 -1
- package/dist/saga.cjs +0 -5245
package/dist/index.cjs
CHANGED
|
@@ -1,28 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __esm = (fn, res, err) => function __init() {
|
|
6
|
-
if (err) throw err[0];
|
|
7
|
-
try {
|
|
8
|
-
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
9
|
-
} catch (e) {
|
|
10
|
-
throw err = [e], e;
|
|
11
|
-
}
|
|
12
|
-
};
|
|
13
|
-
var __export = (target, all) => {
|
|
14
|
-
for (var name in all)
|
|
15
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
// ../infra/compat.mjs
|
|
19
|
-
var init_compat = __esm({
|
|
20
|
-
"../infra/compat.mjs"() {
|
|
21
|
-
"use strict";
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
3
|
|
|
25
4
|
// src/client-version.ts
|
|
5
|
+
var import_node_fs = require("node:fs");
|
|
6
|
+
var import_node_path = require("node:path");
|
|
26
7
|
function resolveClientVersionManifestCandidates(distDir = __dirname) {
|
|
27
8
|
return [
|
|
28
9
|
(0, import_node_path.join)(distDir, "..", "..", ".claude-plugin", "plugin.json"),
|
|
@@ -46,287 +27,8 @@ function resolveClientVersion() {
|
|
|
46
27
|
}
|
|
47
28
|
return "0.0.0";
|
|
48
29
|
}
|
|
49
|
-
var import_node_fs, import_node_path;
|
|
50
|
-
var init_client_version = __esm({
|
|
51
|
-
"src/client-version.ts"() {
|
|
52
|
-
"use strict";
|
|
53
|
-
import_node_fs = require("node:fs");
|
|
54
|
-
import_node_path = require("node:path");
|
|
55
|
-
init_compat();
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// src/stdin-inject.ts
|
|
60
|
-
function setInjectedStdin(payload) {
|
|
61
|
-
injectedStdin = payload;
|
|
62
|
-
}
|
|
63
|
-
function stdinHasPipedInput(statFd = () => (0, import_node_fs2.fstatSync)(0), getIsTTY = () => process.stdin.isTTY) {
|
|
64
|
-
try {
|
|
65
|
-
const stat = statFd();
|
|
66
|
-
if (stat.isFIFO() || stat.isFile()) return true;
|
|
67
|
-
if (stat.isCharacterDevice()) return false;
|
|
68
|
-
if (stat.isSocket()) return false;
|
|
69
|
-
if (getIsTTY() === true) return false;
|
|
70
|
-
return true;
|
|
71
|
-
} catch {
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
async function readStdin(opts = {}) {
|
|
76
|
-
if (injectedStdin !== void 0) return injectedStdin;
|
|
77
|
-
if (!stdinHasPipedInput()) return "";
|
|
78
|
-
const maxBytes = opts.maxBytes ?? STDIN_MAX_BYTES;
|
|
79
|
-
const timeoutMs = opts.timeoutMs ?? STDIN_DRAIN_TIMEOUT_MS;
|
|
80
|
-
const chunks = [];
|
|
81
|
-
let total = 0;
|
|
82
|
-
const drain = (async () => {
|
|
83
|
-
for await (const chunk of process.stdin) {
|
|
84
|
-
const buf = chunk;
|
|
85
|
-
const room = maxBytes - total;
|
|
86
|
-
if (buf.length >= room) {
|
|
87
|
-
chunks.push(buf.subarray(0, room));
|
|
88
|
-
total = maxBytes;
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
|
-
chunks.push(buf);
|
|
92
|
-
total += buf.length;
|
|
93
|
-
}
|
|
94
|
-
})().catch(() => {
|
|
95
|
-
});
|
|
96
|
-
let timer;
|
|
97
|
-
const timeout = new Promise((resolve) => {
|
|
98
|
-
timer = setTimeout(resolve, timeoutMs);
|
|
99
|
-
});
|
|
100
|
-
try {
|
|
101
|
-
await Promise.race([drain, timeout]);
|
|
102
|
-
} finally {
|
|
103
|
-
if (timer) clearTimeout(timer);
|
|
104
|
-
try {
|
|
105
|
-
process.stdin.unref();
|
|
106
|
-
} catch {
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return Buffer.concat(chunks).toString("utf8");
|
|
110
|
-
}
|
|
111
|
-
var import_node_fs2, injectedStdin, STDIN_MAX_BYTES, STDIN_DRAIN_TIMEOUT_MS;
|
|
112
|
-
var init_stdin_inject = __esm({
|
|
113
|
-
"src/stdin-inject.ts"() {
|
|
114
|
-
"use strict";
|
|
115
|
-
import_node_fs2 = require("node:fs");
|
|
116
|
-
STDIN_MAX_BYTES = 8 * 1024 * 1024;
|
|
117
|
-
STDIN_DRAIN_TIMEOUT_MS = 5e3;
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
// src/daemon-protocol.ts
|
|
122
|
-
function daemonDir(env = process.env) {
|
|
123
|
-
return env.MMI_CLI_DAEMON_DIR || (0, import_node_path2.join)((0, import_node_os.homedir)(), ".mmi");
|
|
124
|
-
}
|
|
125
|
-
function tokenPath(env = process.env) {
|
|
126
|
-
return (0, import_node_path2.join)(daemonDir(env), "daemon-token");
|
|
127
|
-
}
|
|
128
|
-
function readDaemonToken(env = process.env) {
|
|
129
|
-
try {
|
|
130
|
-
const t = (0, import_node_fs3.readFileSync)(tokenPath(env), "utf8").trim();
|
|
131
|
-
return t.length > 0 ? t : void 0;
|
|
132
|
-
} catch {
|
|
133
|
-
return void 0;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
function socketPath(env = process.env, platform = process.platform, user) {
|
|
137
|
-
if (env.MMI_CLI_DAEMON_SOCKET) return env.MMI_CLI_DAEMON_SOCKET;
|
|
138
|
-
let name = user;
|
|
139
|
-
if (!name) {
|
|
140
|
-
try {
|
|
141
|
-
name = (0, import_node_os.userInfo)().username;
|
|
142
|
-
} catch {
|
|
143
|
-
name = env.USERNAME || env.USER || "default";
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
const hash = (0, import_node_crypto.createHash)("sha256").update(name).digest("hex").slice(0, 12);
|
|
147
|
-
return platform === "win32" ? `\\\\.\\pipe\\mmi-cli-${hash}` : (0, import_node_path2.join)(daemonDir(env), `mmi-cli-${hash}.sock`);
|
|
148
|
-
}
|
|
149
|
-
function argvReadsStdin(args) {
|
|
150
|
-
for (let i = 0; i < args.length; i++) {
|
|
151
|
-
const a = args[i];
|
|
152
|
-
if (a.endsWith("-file=-")) return true;
|
|
153
|
-
if (a.endsWith("-file") && args[i + 1] === "-") return true;
|
|
154
|
-
}
|
|
155
|
-
return false;
|
|
156
|
-
}
|
|
157
|
-
function daemonEligible(args) {
|
|
158
|
-
const verb2 = args[1] ?? "";
|
|
159
|
-
return args[0] === "saga" && HOT_VERBS.has(verb2) && !CONTINUITY_HOT_VERBS.has(verb2) && !args.includes("--run") && !args.includes("--help") && !args.includes("-h") && !argvReadsStdin(args);
|
|
160
|
-
}
|
|
161
|
-
function buildStamp(version, bundleMtimeMs) {
|
|
162
|
-
return `${version}#${Math.trunc(bundleMtimeMs)}`;
|
|
163
|
-
}
|
|
164
|
-
function parseLine(line) {
|
|
165
|
-
try {
|
|
166
|
-
const v = JSON.parse(line);
|
|
167
|
-
return v && typeof v === "object" ? v : void 0;
|
|
168
|
-
} catch {
|
|
169
|
-
return void 0;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
var import_node_crypto, import_node_fs3, import_node_os, import_node_path2, DEFAULT_IDLE_EXIT_MS, DEFAULT_CONNECT_TIMEOUT_MS, DEFAULT_RESPONSE_TIMEOUT_MS, HOT_VERBS, CONTINUITY_HOT_VERBS, STDIN_VERBS, encodeLine, MAX_FRAME_LENGTH, LineBuffer;
|
|
173
|
-
var init_daemon_protocol = __esm({
|
|
174
|
-
"src/daemon-protocol.ts"() {
|
|
175
|
-
"use strict";
|
|
176
|
-
import_node_crypto = require("node:crypto");
|
|
177
|
-
import_node_fs3 = require("node:fs");
|
|
178
|
-
import_node_os = require("node:os");
|
|
179
|
-
import_node_path2 = require("node:path");
|
|
180
|
-
DEFAULT_IDLE_EXIT_MS = 30 * 6e4;
|
|
181
|
-
DEFAULT_CONNECT_TIMEOUT_MS = 200;
|
|
182
|
-
DEFAULT_RESPONSE_TIMEOUT_MS = 2e3;
|
|
183
|
-
HOT_VERBS = /* @__PURE__ */ new Set(["note", "probe", "capture", "session", "head-update"]);
|
|
184
|
-
CONTINUITY_HOT_VERBS = /* @__PURE__ */ new Set(["note", "probe", "capture", "session", "head-update"]);
|
|
185
|
-
STDIN_VERBS = /* @__PURE__ */ new Set(["capture", "session"]);
|
|
186
|
-
encodeLine = (obj) => `${JSON.stringify(obj)}
|
|
187
|
-
`;
|
|
188
|
-
MAX_FRAME_LENGTH = 1024 * 1024;
|
|
189
|
-
LineBuffer = class {
|
|
190
|
-
constructor(maxFrameLength = MAX_FRAME_LENGTH) {
|
|
191
|
-
this.maxFrameLength = maxFrameLength;
|
|
192
|
-
}
|
|
193
|
-
maxFrameLength;
|
|
194
|
-
buf = "";
|
|
195
|
-
push(chunk) {
|
|
196
|
-
this.buf += chunk;
|
|
197
|
-
const parts = this.buf.split("\n");
|
|
198
|
-
this.buf = parts.pop() ?? "";
|
|
199
|
-
if (this.buf.length > this.maxFrameLength || parts.some((p) => p.length > this.maxFrameLength)) {
|
|
200
|
-
this.buf = "";
|
|
201
|
-
throw new RangeError("daemon frame too long");
|
|
202
|
-
}
|
|
203
|
-
return parts.filter((p) => p.length > 0);
|
|
204
|
-
}
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
// src/daemon-client.ts
|
|
210
|
-
var daemon_client_exports = {};
|
|
211
|
-
__export(daemon_client_exports, {
|
|
212
|
-
clientStamp: () => clientStamp,
|
|
213
|
-
spawnDaemon: () => spawnDaemon,
|
|
214
|
-
tryDaemonRun: () => tryDaemonRun
|
|
215
|
-
});
|
|
216
|
-
function clientStamp() {
|
|
217
|
-
let mtime = 0;
|
|
218
|
-
try {
|
|
219
|
-
mtime = (0, import_node_fs4.statSync)((0, import_node_path3.join)(__dirname, "index.cjs")).mtimeMs;
|
|
220
|
-
} catch {
|
|
221
|
-
}
|
|
222
|
-
return buildStamp(resolveClientVersion(), mtime);
|
|
223
|
-
}
|
|
224
|
-
function spawnDaemon() {
|
|
225
|
-
try {
|
|
226
|
-
(0, import_node_child_process.spawn)(process.execPath, [process.argv[1], "daemon", "--run"], {
|
|
227
|
-
detached: true,
|
|
228
|
-
stdio: "ignore",
|
|
229
|
-
windowsHide: true,
|
|
230
|
-
cwd: (0, import_node_os2.tmpdir)()
|
|
231
|
-
}).unref();
|
|
232
|
-
} catch {
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
function requestOnce(req, path, connectTimeoutMs, responseTimeoutMs) {
|
|
236
|
-
return new Promise((resolve) => {
|
|
237
|
-
let socket;
|
|
238
|
-
try {
|
|
239
|
-
socket = (0, import_node_net.connect)(path);
|
|
240
|
-
} catch {
|
|
241
|
-
return resolve(void 0);
|
|
242
|
-
}
|
|
243
|
-
let done = false;
|
|
244
|
-
let responseTimer;
|
|
245
|
-
const connectTimer = setTimeout(() => finish(void 0), connectTimeoutMs);
|
|
246
|
-
function finish(v) {
|
|
247
|
-
if (done) return;
|
|
248
|
-
done = true;
|
|
249
|
-
clearTimeout(connectTimer);
|
|
250
|
-
if (responseTimer) clearTimeout(responseTimer);
|
|
251
|
-
try {
|
|
252
|
-
socket.destroy();
|
|
253
|
-
} catch {
|
|
254
|
-
}
|
|
255
|
-
resolve(v);
|
|
256
|
-
}
|
|
257
|
-
const lb = new LineBuffer();
|
|
258
|
-
socket.setEncoding("utf8");
|
|
259
|
-
socket.on("connect", () => {
|
|
260
|
-
clearTimeout(connectTimer);
|
|
261
|
-
responseTimer = setTimeout(() => finish(void 0), responseTimeoutMs);
|
|
262
|
-
socket.write(encodeLine(req));
|
|
263
|
-
});
|
|
264
|
-
socket.on("data", (chunk) => {
|
|
265
|
-
let lines;
|
|
266
|
-
try {
|
|
267
|
-
lines = lb.push(chunk);
|
|
268
|
-
} catch {
|
|
269
|
-
return finish(void 0);
|
|
270
|
-
}
|
|
271
|
-
if (lines.length) finish(parseLine(lines[0]));
|
|
272
|
-
});
|
|
273
|
-
socket.on("error", () => finish(void 0));
|
|
274
|
-
socket.on("close", () => finish(void 0));
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
async function tryDaemonRun(args, deps = {}) {
|
|
278
|
-
const env = deps.env ?? process.env;
|
|
279
|
-
if (env.MMI_CLI_NO_DAEMON) return { handled: false };
|
|
280
|
-
if (!daemonEligible(args)) return { handled: false };
|
|
281
|
-
const respawn = deps.spawnDaemon ?? spawnDaemon;
|
|
282
|
-
let stdin;
|
|
283
|
-
try {
|
|
284
|
-
if (STDIN_VERBS.has(args[1] ?? "")) {
|
|
285
|
-
stdin = await (deps.readInput ?? readStdin)();
|
|
286
|
-
setInjectedStdin(stdin);
|
|
287
|
-
}
|
|
288
|
-
const req = {
|
|
289
|
-
args,
|
|
290
|
-
cwd: process.cwd(),
|
|
291
|
-
stamp: deps.stamp ?? clientStamp(),
|
|
292
|
-
token: deps.token ?? readDaemonToken(env) ?? "",
|
|
293
|
-
...stdin !== void 0 ? { stdin } : {}
|
|
294
|
-
};
|
|
295
|
-
const resp = await requestOnce(
|
|
296
|
-
req,
|
|
297
|
-
deps.path ?? socketPath(env),
|
|
298
|
-
deps.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS,
|
|
299
|
-
deps.responseTimeoutMs ?? DEFAULT_RESPONSE_TIMEOUT_MS
|
|
300
|
-
);
|
|
301
|
-
if (!resp || resp.restart) {
|
|
302
|
-
respawn();
|
|
303
|
-
return { handled: false, stdin };
|
|
304
|
-
}
|
|
305
|
-
if (resp.decline || typeof resp.code !== "number") return { handled: false, stdin };
|
|
306
|
-
if (resp.stdout) (deps.out ?? ((s) => process.stdout.write(s)))(resp.stdout);
|
|
307
|
-
if (resp.stderr) (deps.errOut ?? ((s) => process.stderr.write(s)))(resp.stderr);
|
|
308
|
-
return { handled: true, code: resp.code };
|
|
309
|
-
} catch {
|
|
310
|
-
return { handled: false, stdin };
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
var import_node_net, import_node_child_process, import_node_fs4, import_node_os2, import_node_path3;
|
|
314
|
-
var init_daemon_client = __esm({
|
|
315
|
-
"src/daemon-client.ts"() {
|
|
316
|
-
"use strict";
|
|
317
|
-
import_node_net = require("node:net");
|
|
318
|
-
import_node_child_process = require("node:child_process");
|
|
319
|
-
import_node_fs4 = require("node:fs");
|
|
320
|
-
import_node_os2 = require("node:os");
|
|
321
|
-
import_node_path3 = require("node:path");
|
|
322
|
-
init_client_version();
|
|
323
|
-
init_stdin_inject();
|
|
324
|
-
init_daemon_protocol();
|
|
325
|
-
}
|
|
326
|
-
});
|
|
327
30
|
|
|
328
31
|
// src/boot.ts
|
|
329
|
-
init_client_version();
|
|
330
32
|
function requireSibling(name) {
|
|
331
33
|
try {
|
|
332
34
|
return require(name);
|
|
@@ -340,14 +42,6 @@ function requireSibling(name) {
|
|
|
340
42
|
var verb = process.argv[2];
|
|
341
43
|
if (process.argv.length === 3 && (verb === "--version" || verb === "-V")) {
|
|
342
44
|
console.log(resolveClientVersion());
|
|
343
|
-
} else if (verb === "saga") {
|
|
344
|
-
void Promise.resolve().then(() => (init_daemon_client(), daemon_client_exports)).then(async (c) => {
|
|
345
|
-
const r = await c.tryDaemonRun(process.argv.slice(2)).catch(() => ({ handled: false }));
|
|
346
|
-
if (r.handled) process.exitCode = r.code;
|
|
347
|
-
else requireSibling("./saga.cjs")?.runSagaCli("stdin" in r ? r.stdin : void 0);
|
|
348
|
-
});
|
|
349
|
-
} else if (verb === "daemon" && process.argv[3] === "--run" && process.argv.length === 4) {
|
|
350
|
-
requireSibling("./saga.cjs")?.runDaemon();
|
|
351
45
|
} else {
|
|
352
46
|
requireSibling("./main.cjs");
|
|
353
47
|
}
|