muuuuse 0.2.0 → 1.3.1
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/README.md +43 -55
- package/bin/muuse.js +0 -0
- package/package.json +8 -3
- package/src/agents.js +100 -6
- package/src/cli.js +51 -124
- package/src/runtime.js +457 -496
- package/src/util.js +44 -47
package/src/util.js
CHANGED
|
@@ -5,18 +5,17 @@ const path = require("node:path");
|
|
|
5
5
|
const { spawnSync } = require("node:child_process");
|
|
6
6
|
|
|
7
7
|
const BRAND = "🔌Muuuuse";
|
|
8
|
-
const POLL_MS =
|
|
9
|
-
const CONTROLLER_WAIT_MS = 1000;
|
|
8
|
+
const POLL_MS = 250;
|
|
10
9
|
const SESSION_MATCH_WINDOW_MS = 5 * 60 * 1000;
|
|
11
10
|
const MAX_RELAY_CHARS = 4000;
|
|
12
11
|
|
|
13
12
|
const FLAG_ALIASES = new Map([
|
|
14
13
|
["--max-relays", "maxRelays"],
|
|
15
|
-
["--
|
|
16
|
-
["--
|
|
14
|
+
["--no-preset", "noPreset"],
|
|
15
|
+
["--session", "session"],
|
|
17
16
|
]);
|
|
18
17
|
|
|
19
|
-
const
|
|
18
|
+
const BOOLEAN_FLAGS = new Set(["noPreset"]);
|
|
20
19
|
|
|
21
20
|
function shellEscape(value) {
|
|
22
21
|
return `'${String(value).replace(/'/g, `'\\''`)}'`;
|
|
@@ -121,10 +120,6 @@ function readCommandVersion(command, args = ["--version"]) {
|
|
|
121
120
|
return (result.stdout || result.stderr || "").trim().split("\n")[0] || null;
|
|
122
121
|
}
|
|
123
122
|
|
|
124
|
-
function findFirstExisting(paths) {
|
|
125
|
-
return paths.find((candidate) => fs.existsSync(candidate)) || null;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
123
|
function stripAnsi(text) {
|
|
129
124
|
return String(text || "").replace(
|
|
130
125
|
// eslint-disable-next-line no-control-regex
|
|
@@ -172,10 +167,27 @@ function slugifySegment(value) {
|
|
|
172
167
|
.replace(/^-+|-+$/g, "") || "default";
|
|
173
168
|
}
|
|
174
169
|
|
|
170
|
+
function hashText(text) {
|
|
171
|
+
return createHash("sha1").update(String(text || "")).digest("hex");
|
|
172
|
+
}
|
|
173
|
+
|
|
175
174
|
function getStateRoot() {
|
|
176
175
|
return ensureDir(path.join(os.homedir(), ".muuuuse"));
|
|
177
176
|
}
|
|
178
177
|
|
|
178
|
+
function getDefaultSessionName(currentPath = process.cwd()) {
|
|
179
|
+
const resolvedPath = (() => {
|
|
180
|
+
try {
|
|
181
|
+
return fs.realpathSync(currentPath);
|
|
182
|
+
} catch (error) {
|
|
183
|
+
return path.resolve(currentPath);
|
|
184
|
+
}
|
|
185
|
+
})();
|
|
186
|
+
|
|
187
|
+
const label = slugifySegment(path.basename(resolvedPath));
|
|
188
|
+
return `${label}-${hashText(resolvedPath).slice(0, 8)}`;
|
|
189
|
+
}
|
|
190
|
+
|
|
179
191
|
function getSessionDir(sessionName) {
|
|
180
192
|
return ensureDir(path.join(getStateRoot(), "sessions", slugifySegment(sessionName)));
|
|
181
193
|
}
|
|
@@ -188,29 +200,18 @@ function getSeatPaths(sessionName, seatId) {
|
|
|
188
200
|
const dir = getSeatDir(sessionName, seatId);
|
|
189
201
|
return {
|
|
190
202
|
dir,
|
|
191
|
-
metaPath: path.join(dir, "meta.json"),
|
|
192
|
-
daemonPath: path.join(dir, "daemon.json"),
|
|
193
|
-
commandsPath: path.join(dir, "commands.jsonl"),
|
|
194
203
|
eventsPath: path.join(dir, "events.jsonl"),
|
|
195
|
-
|
|
204
|
+
metaPath: path.join(dir, "meta.json"),
|
|
196
205
|
statusPath: path.join(dir, "status.json"),
|
|
197
206
|
};
|
|
198
207
|
}
|
|
199
208
|
|
|
200
|
-
function getControllerPath(sessionName) {
|
|
201
|
-
return path.join(getSessionDir(sessionName), "controller.json");
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
function hashText(text) {
|
|
205
|
-
return createHash("sha1").update(String(text || "")).digest("hex");
|
|
206
|
-
}
|
|
207
|
-
|
|
208
209
|
function parseFlags(argv) {
|
|
209
210
|
const positionals = [];
|
|
210
211
|
const flags = {
|
|
211
|
-
step: [],
|
|
212
212
|
maxRelays: Number.POSITIVE_INFINITY,
|
|
213
|
-
|
|
213
|
+
noPreset: false,
|
|
214
|
+
session: null,
|
|
214
215
|
};
|
|
215
216
|
|
|
216
217
|
for (let index = 0; index < argv.length; index += 1) {
|
|
@@ -226,6 +227,11 @@ function parseFlags(argv) {
|
|
|
226
227
|
throw new Error(`Unknown flag: ${rawFlag}`);
|
|
227
228
|
}
|
|
228
229
|
|
|
230
|
+
if (BOOLEAN_FLAGS.has(key)) {
|
|
231
|
+
flags[key] = true;
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
|
|
229
235
|
const next = inlineValue !== undefined ? inlineValue : argv[index + 1];
|
|
230
236
|
if (inlineValue === undefined) {
|
|
231
237
|
index += 1;
|
|
@@ -235,18 +241,12 @@ function parseFlags(argv) {
|
|
|
235
241
|
throw new Error(`Missing value for ${rawFlag}`);
|
|
236
242
|
}
|
|
237
243
|
|
|
238
|
-
if (MULTI_FLAGS.has(key)) {
|
|
239
|
-
flags[key].push(next);
|
|
240
|
-
continue;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
244
|
flags[key] = next;
|
|
244
245
|
}
|
|
245
246
|
|
|
246
247
|
flags.maxRelays = flags.maxRelays === Number.POSITIVE_INFINITY
|
|
247
248
|
? Number.POSITIVE_INFINITY
|
|
248
249
|
: toInt(flags.maxRelays, Number.POSITIVE_INFINITY);
|
|
249
|
-
flags.seedSeat = toInt(flags.seedSeat, 1);
|
|
250
250
|
|
|
251
251
|
return {
|
|
252
252
|
positionals,
|
|
@@ -256,33 +256,31 @@ function parseFlags(argv) {
|
|
|
256
256
|
|
|
257
257
|
function usage() {
|
|
258
258
|
return [
|
|
259
|
-
`${BRAND}
|
|
259
|
+
`${BRAND} wraps two local programs and bounces final blocks between them.`,
|
|
260
260
|
"",
|
|
261
261
|
"Usage:",
|
|
262
|
-
" muuuuse 1",
|
|
263
|
-
" muuuuse 2",
|
|
264
|
-
" muuuuse 3
|
|
265
|
-
" muuuuse
|
|
266
|
-
" muuuuse live",
|
|
262
|
+
" muuuuse 1 <program...>",
|
|
263
|
+
" muuuuse 2 <program...>",
|
|
264
|
+
" muuuuse 3 stop",
|
|
265
|
+
" muuuuse 3 status",
|
|
267
266
|
" muuuuse doctor",
|
|
268
267
|
"",
|
|
269
|
-
"
|
|
270
|
-
"
|
|
271
|
-
"
|
|
272
|
-
"
|
|
273
|
-
"
|
|
268
|
+
"Examples:",
|
|
269
|
+
" muuuuse 1 codex",
|
|
270
|
+
" muuuuse 2 gemini",
|
|
271
|
+
" muuuuse 3 stop",
|
|
272
|
+
" muuuuse 1 bash -lc 'while read line; do printf \"script one: %s\\n\\n\" \"$line\"; done'",
|
|
274
273
|
"",
|
|
275
274
|
"Notes:",
|
|
276
|
-
" -
|
|
277
|
-
" -
|
|
278
|
-
" -
|
|
279
|
-
" -
|
|
275
|
+
" - Seats auto-pair by current working directory by default.",
|
|
276
|
+
" - Use `--session <name>` on seats and seat 3 if you want an explicit shared lane.",
|
|
277
|
+
" - Known presets (`codex`, `claude`, `gemini`) expand to recommended launch flags.",
|
|
278
|
+
" - Any other program runs as-is inside the current terminal under a PTY wrapper.",
|
|
280
279
|
].join("\n");
|
|
281
280
|
}
|
|
282
281
|
|
|
283
282
|
module.exports = {
|
|
284
283
|
BRAND,
|
|
285
|
-
CONTROLLER_WAIT_MS,
|
|
286
284
|
MAX_RELAY_CHARS,
|
|
287
285
|
POLL_MS,
|
|
288
286
|
SESSION_MATCH_WINDOW_MS,
|
|
@@ -290,8 +288,7 @@ module.exports = {
|
|
|
290
288
|
commandExists,
|
|
291
289
|
createId,
|
|
292
290
|
ensureDir,
|
|
293
|
-
|
|
294
|
-
getControllerPath,
|
|
291
|
+
getDefaultSessionName,
|
|
295
292
|
getFileSize,
|
|
296
293
|
getSeatDir,
|
|
297
294
|
getSeatPaths,
|