maxsimcli 2.1.1 → 2.2.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/.tsbuildinfo +1 -1
- package/dist/assets/CHANGELOG.md +7 -0
- package/dist/assets/dashboard/client/assets/index-BjfrCU-v.css +1 -0
- package/dist/assets/dashboard/client/index.html +2 -2
- package/dist/assets/dashboard/server.js +202 -1
- package/dist/install.cjs +21 -0
- package/dist/install.cjs.map +1 -1
- package/dist/install.js +25 -0
- package/dist/install.js.map +1 -1
- package/package.json +1 -1
- package/dist/assets/dashboard/client/assets/index-Dg_5QMWO.css +0 -1
- /package/dist/assets/dashboard/client/assets/{index-BtA5Kson.js → index-I1VQFVyf.js} +0 -0
|
@@ -69,6 +69,8 @@ node_tty = __toESM(node_tty);
|
|
|
69
69
|
let fs_promises = require("fs/promises");
|
|
70
70
|
let node_stream = require("node:stream");
|
|
71
71
|
let os = require("os");
|
|
72
|
+
let node_pty = require("node-pty");
|
|
73
|
+
node_pty = __toESM(node_pty);
|
|
72
74
|
|
|
73
75
|
//#region ../../node_modules/.pnpm/depd@2.0.0/node_modules/depd/index.js
|
|
74
76
|
var require_depd = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
@@ -41393,6 +41395,162 @@ function watch(paths, options = {}) {
|
|
|
41393
41395
|
return watcher;
|
|
41394
41396
|
}
|
|
41395
41397
|
|
|
41398
|
+
//#endregion
|
|
41399
|
+
//#region src/terminal/session-store.ts
|
|
41400
|
+
const MAX_SCROLLBACK = 5e4;
|
|
41401
|
+
var SessionStore = class {
|
|
41402
|
+
scrollback = [];
|
|
41403
|
+
append(data) {
|
|
41404
|
+
this.scrollback.push(data);
|
|
41405
|
+
if (this.scrollback.length > MAX_SCROLLBACK) this.scrollback = this.scrollback.slice(-MAX_SCROLLBACK);
|
|
41406
|
+
}
|
|
41407
|
+
getAll() {
|
|
41408
|
+
return this.scrollback.join("");
|
|
41409
|
+
}
|
|
41410
|
+
clear() {
|
|
41411
|
+
this.scrollback = [];
|
|
41412
|
+
}
|
|
41413
|
+
};
|
|
41414
|
+
|
|
41415
|
+
//#endregion
|
|
41416
|
+
//#region src/terminal/pty-manager.ts
|
|
41417
|
+
const DISCONNECT_TIMEOUT_MS = 6e4;
|
|
41418
|
+
const STATUS_INTERVAL_MS = 1e3;
|
|
41419
|
+
const ACTIVE_THRESHOLD_MS = 2e3;
|
|
41420
|
+
var PtyManager = class PtyManager {
|
|
41421
|
+
static instance = null;
|
|
41422
|
+
session = null;
|
|
41423
|
+
connectedClients = /* @__PURE__ */ new Set();
|
|
41424
|
+
lastOutputTime = 0;
|
|
41425
|
+
statusInterval = null;
|
|
41426
|
+
static getInstance() {
|
|
41427
|
+
if (!PtyManager.instance) PtyManager.instance = new PtyManager();
|
|
41428
|
+
return PtyManager.instance;
|
|
41429
|
+
}
|
|
41430
|
+
spawn(opts) {
|
|
41431
|
+
if (this.session) this.kill();
|
|
41432
|
+
const shell = process.platform === "win32" ? "claude.cmd" : "claude";
|
|
41433
|
+
const args = [];
|
|
41434
|
+
if (opts.skipPermissions) args.push("--dangerously-skip-permissions");
|
|
41435
|
+
const proc = node_pty.spawn(shell, args, {
|
|
41436
|
+
name: "xterm-256color",
|
|
41437
|
+
cols: opts.cols ?? 120,
|
|
41438
|
+
rows: opts.rows ?? 30,
|
|
41439
|
+
cwd: opts.cwd,
|
|
41440
|
+
env: process.env
|
|
41441
|
+
});
|
|
41442
|
+
const store = new SessionStore();
|
|
41443
|
+
this.session = {
|
|
41444
|
+
process: proc,
|
|
41445
|
+
pid: proc.pid,
|
|
41446
|
+
startTime: Date.now(),
|
|
41447
|
+
cwd: opts.cwd,
|
|
41448
|
+
skipPermissions: opts.skipPermissions,
|
|
41449
|
+
disconnectTimer: null,
|
|
41450
|
+
store
|
|
41451
|
+
};
|
|
41452
|
+
this.lastOutputTime = Date.now();
|
|
41453
|
+
proc.onData((data) => {
|
|
41454
|
+
this.lastOutputTime = Date.now();
|
|
41455
|
+
store.append(data);
|
|
41456
|
+
this.broadcastToClients({
|
|
41457
|
+
type: "output",
|
|
41458
|
+
data
|
|
41459
|
+
});
|
|
41460
|
+
});
|
|
41461
|
+
proc.onExit(({ exitCode }) => {
|
|
41462
|
+
this.broadcastToClients({
|
|
41463
|
+
type: "exit",
|
|
41464
|
+
code: exitCode
|
|
41465
|
+
});
|
|
41466
|
+
this.stopStatusBroadcast();
|
|
41467
|
+
this.session = null;
|
|
41468
|
+
});
|
|
41469
|
+
this.broadcastToClients({
|
|
41470
|
+
type: "started",
|
|
41471
|
+
pid: proc.pid
|
|
41472
|
+
});
|
|
41473
|
+
this.startStatusBroadcast();
|
|
41474
|
+
}
|
|
41475
|
+
write(data) {
|
|
41476
|
+
if (this.session) this.session.process.write(data);
|
|
41477
|
+
}
|
|
41478
|
+
resize(cols, rows) {
|
|
41479
|
+
if (this.session) this.session.process.resize(cols, rows);
|
|
41480
|
+
}
|
|
41481
|
+
kill() {
|
|
41482
|
+
if (this.session) {
|
|
41483
|
+
this.stopStatusBroadcast();
|
|
41484
|
+
try {
|
|
41485
|
+
this.session.process.kill();
|
|
41486
|
+
} catch {}
|
|
41487
|
+
if (this.session.disconnectTimer) clearTimeout(this.session.disconnectTimer);
|
|
41488
|
+
this.session = null;
|
|
41489
|
+
}
|
|
41490
|
+
}
|
|
41491
|
+
getStatus() {
|
|
41492
|
+
if (!this.session) return null;
|
|
41493
|
+
return {
|
|
41494
|
+
pid: this.session.pid,
|
|
41495
|
+
uptime: Math.floor((Date.now() - this.session.startTime) / 1e3),
|
|
41496
|
+
cwd: this.session.cwd,
|
|
41497
|
+
memoryMB: Math.round(process.memoryUsage().rss / 1024 / 1024 * 10) / 10,
|
|
41498
|
+
isActive: Date.now() - this.lastOutputTime < ACTIVE_THRESHOLD_MS,
|
|
41499
|
+
skipPermissions: this.session.skipPermissions,
|
|
41500
|
+
alive: true
|
|
41501
|
+
};
|
|
41502
|
+
}
|
|
41503
|
+
addClient(ws) {
|
|
41504
|
+
this.connectedClients.add(ws);
|
|
41505
|
+
if (this.session?.disconnectTimer) {
|
|
41506
|
+
clearTimeout(this.session.disconnectTimer);
|
|
41507
|
+
this.session.disconnectTimer = null;
|
|
41508
|
+
}
|
|
41509
|
+
if (this.session) {
|
|
41510
|
+
const scrollback = this.session.store.getAll();
|
|
41511
|
+
if (scrollback) ws.send(JSON.stringify({
|
|
41512
|
+
type: "scrollback",
|
|
41513
|
+
data: scrollback
|
|
41514
|
+
}));
|
|
41515
|
+
const status = this.getStatus();
|
|
41516
|
+
if (status) ws.send(JSON.stringify({
|
|
41517
|
+
type: "status",
|
|
41518
|
+
...status
|
|
41519
|
+
}));
|
|
41520
|
+
}
|
|
41521
|
+
}
|
|
41522
|
+
removeClient(ws) {
|
|
41523
|
+
this.connectedClients.delete(ws);
|
|
41524
|
+
if (this.connectedClients.size === 0 && this.session) this.session.disconnectTimer = setTimeout(() => {
|
|
41525
|
+
console.error("[pty] No clients connected for 60s, killing process");
|
|
41526
|
+
this.kill();
|
|
41527
|
+
}, DISCONNECT_TIMEOUT_MS);
|
|
41528
|
+
}
|
|
41529
|
+
isAlive() {
|
|
41530
|
+
return this.session !== null;
|
|
41531
|
+
}
|
|
41532
|
+
broadcastToClients(message) {
|
|
41533
|
+
const data = JSON.stringify(message);
|
|
41534
|
+
for (const client of this.connectedClients) if (client.readyState === import_websocket.default.OPEN) client.send(data);
|
|
41535
|
+
}
|
|
41536
|
+
startStatusBroadcast() {
|
|
41537
|
+
this.stopStatusBroadcast();
|
|
41538
|
+
this.statusInterval = setInterval(() => {
|
|
41539
|
+
const status = this.getStatus();
|
|
41540
|
+
if (status) this.broadcastToClients({
|
|
41541
|
+
type: "status",
|
|
41542
|
+
...status
|
|
41543
|
+
});
|
|
41544
|
+
}, STATUS_INTERVAL_MS);
|
|
41545
|
+
}
|
|
41546
|
+
stopStatusBroadcast() {
|
|
41547
|
+
if (this.statusInterval) {
|
|
41548
|
+
clearInterval(this.statusInterval);
|
|
41549
|
+
this.statusInterval = null;
|
|
41550
|
+
}
|
|
41551
|
+
}
|
|
41552
|
+
};
|
|
41553
|
+
|
|
41396
41554
|
//#endregion
|
|
41397
41555
|
//#region src/server.ts
|
|
41398
41556
|
const projectCwd = process.env.MAXSIM_PROJECT_CWD || process.cwd();
|
|
@@ -41894,10 +42052,48 @@ else app.get("/", (_req, res) => {
|
|
|
41894
42052
|
});
|
|
41895
42053
|
async function main() {
|
|
41896
42054
|
const wss = createWSS();
|
|
42055
|
+
const terminalWss = new import_websocket_server.default({ noServer: true });
|
|
42056
|
+
const ptyManager = PtyManager.getInstance();
|
|
42057
|
+
terminalWss.on("connection", (ws) => {
|
|
42058
|
+
ptyManager.addClient(ws);
|
|
42059
|
+
ws.on("message", (raw) => {
|
|
42060
|
+
try {
|
|
42061
|
+
const msg = JSON.parse(typeof raw === "string" ? raw : raw.toString());
|
|
42062
|
+
switch (msg.type) {
|
|
42063
|
+
case "input":
|
|
42064
|
+
ptyManager.write(msg.data);
|
|
42065
|
+
break;
|
|
42066
|
+
case "resize":
|
|
42067
|
+
ptyManager.resize(msg.cols, msg.rows);
|
|
42068
|
+
break;
|
|
42069
|
+
case "spawn":
|
|
42070
|
+
ptyManager.spawn({
|
|
42071
|
+
skipPermissions: !!msg.skipPermissions,
|
|
42072
|
+
cwd: projectCwd,
|
|
42073
|
+
cols: msg.cols,
|
|
42074
|
+
rows: msg.rows
|
|
42075
|
+
});
|
|
42076
|
+
break;
|
|
42077
|
+
case "kill":
|
|
42078
|
+
ptyManager.kill();
|
|
42079
|
+
break;
|
|
42080
|
+
}
|
|
42081
|
+
} catch {}
|
|
42082
|
+
});
|
|
42083
|
+
ws.on("close", () => {
|
|
42084
|
+
ptyManager.removeClient(ws);
|
|
42085
|
+
});
|
|
42086
|
+
ws.on("error", (err) => {
|
|
42087
|
+
console.error("[terminal-ws] Client error:", err.message);
|
|
42088
|
+
});
|
|
42089
|
+
});
|
|
41897
42090
|
const server = (0, node_http.createServer)(app);
|
|
41898
42091
|
server.on("upgrade", (req, socket, head) => {
|
|
41899
42092
|
const url = req.url || "/";
|
|
41900
|
-
if (url === "/
|
|
42093
|
+
if (url === "/ws/terminal" || url.startsWith("/ws/terminal?")) terminalWss.handleUpgrade(req, socket, head, (ws) => {
|
|
42094
|
+
terminalWss.emit("connection", ws, req);
|
|
42095
|
+
});
|
|
42096
|
+
else if (url === "/api/ws" || url.startsWith("/api/ws?")) wss.handleUpgrade(req, socket, head, (ws) => {
|
|
41901
42097
|
wss.emit("connection", ws, req);
|
|
41902
42098
|
});
|
|
41903
42099
|
else socket.destroy();
|
|
@@ -41916,7 +42112,9 @@ async function main() {
|
|
|
41916
42112
|
});
|
|
41917
42113
|
function shutdown() {
|
|
41918
42114
|
console.error("\n[server] Shutting down...");
|
|
42115
|
+
ptyManager.kill();
|
|
41919
42116
|
if (watcher) watcher.close().catch(() => {});
|
|
42117
|
+
terminalWss.close(() => {});
|
|
41920
42118
|
wss.close(() => {
|
|
41921
42119
|
server.close(() => {
|
|
41922
42120
|
process.exit(0);
|
|
@@ -41929,6 +42127,9 @@ async function main() {
|
|
|
41929
42127
|
}
|
|
41930
42128
|
process.on("SIGINT", shutdown);
|
|
41931
42129
|
process.on("SIGTERM", shutdown);
|
|
42130
|
+
process.on("exit", () => {
|
|
42131
|
+
ptyManager.kill();
|
|
42132
|
+
});
|
|
41932
42133
|
}
|
|
41933
42134
|
main().catch((err) => {
|
|
41934
42135
|
console.error("[server] Fatal error:", err);
|
package/dist/install.cjs
CHANGED
|
@@ -7548,6 +7548,20 @@ async function promptLocation(runtimes) {
|
|
|
7548
7548
|
}) === "global";
|
|
7549
7549
|
}
|
|
7550
7550
|
/**
|
|
7551
|
+
* Prompt whether to enable Agent Teams (Claude only, experimental feature)
|
|
7552
|
+
*/
|
|
7553
|
+
async function promptAgentTeams() {
|
|
7554
|
+
console.log();
|
|
7555
|
+
console.log(chalk.cyan(" Agent Teams") + chalk.dim(" (experimental)"));
|
|
7556
|
+
console.log(chalk.dim(" Coordinate multiple Claude Code instances working in parallel."));
|
|
7557
|
+
console.log(chalk.dim(" Enables CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS in settings.json."));
|
|
7558
|
+
console.log();
|
|
7559
|
+
return dist_default$1({
|
|
7560
|
+
message: "Enable Agent Teams?",
|
|
7561
|
+
default: false
|
|
7562
|
+
});
|
|
7563
|
+
}
|
|
7564
|
+
/**
|
|
7551
7565
|
* Install MAXSIM for all selected runtimes
|
|
7552
7566
|
*/
|
|
7553
7567
|
async function installAllRuntimes(runtimes, isGlobal, isInteractive) {
|
|
@@ -7560,8 +7574,15 @@ async function installAllRuntimes(runtimes, isGlobal, isInteractive) {
|
|
|
7560
7574
|
const primaryStatuslineResult = results.find((r) => statuslineRuntimes.includes(r.runtime));
|
|
7561
7575
|
let shouldInstallStatusline = false;
|
|
7562
7576
|
if (primaryStatuslineResult && primaryStatuslineResult.settings) shouldInstallStatusline = await handleStatusline(primaryStatuslineResult.settings, isInteractive);
|
|
7577
|
+
let enableAgentTeams = false;
|
|
7578
|
+
if (isInteractive && runtimes.includes("claude")) enableAgentTeams = await promptAgentTeams();
|
|
7563
7579
|
for (const result of results) {
|
|
7564
7580
|
const useStatusline = statuslineRuntimes.includes(result.runtime) && shouldInstallStatusline;
|
|
7581
|
+
if (result.runtime === "claude" && enableAgentTeams && result.settings) {
|
|
7582
|
+
const env = result.settings.env ?? {};
|
|
7583
|
+
env["CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS"] = "1";
|
|
7584
|
+
result.settings.env = env;
|
|
7585
|
+
}
|
|
7565
7586
|
finishInstall(result.settingsPath, result.settings, result.statuslineCommand, useStatusline, result.runtime, isGlobal);
|
|
7566
7587
|
}
|
|
7567
7588
|
}
|