maxsimcli 2.5.2 → 2.5.3
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/assets/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [2.5.3](https://github.com/maystudios/maxsim/compare/v2.5.2...v2.5.3) (2026-02-25)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **dashboard:** make state section append robust and add server logging ([dd19326](https://github.com/maystudios/maxsim/commit/dd193265ac694c1fe522a4b20da0e55245ca0b73))
|
|
7
|
+
|
|
1
8
|
## [2.5.2](https://github.com/maystudios/maxsim/compare/v2.5.1...v2.5.2) (2026-02-25)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -32444,7 +32444,7 @@ var require_websocket = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
32444
32444
|
const tls = require("tls");
|
|
32445
32445
|
const { randomBytes, createHash: createHash$1 } = require("crypto");
|
|
32446
32446
|
const { Duplex: Duplex$2, Readable: Readable$1 } = require("stream");
|
|
32447
|
-
const { URL } = require("url");
|
|
32447
|
+
const { URL: URL$1 } = require("url");
|
|
32448
32448
|
const PerMessageDeflate = require_permessage_deflate();
|
|
32449
32449
|
const Receiver = require_receiver();
|
|
32450
32450
|
const Sender = require_sender();
|
|
@@ -32973,9 +32973,9 @@ var require_websocket = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
32973
32973
|
websocket._closeTimeout = opts.closeTimeout;
|
|
32974
32974
|
if (!protocolVersions.includes(opts.protocolVersion)) throw new RangeError(`Unsupported protocol version: ${opts.protocolVersion} (supported versions: ${protocolVersions.join(", ")})`);
|
|
32975
32975
|
let parsedUrl;
|
|
32976
|
-
if (address instanceof URL) parsedUrl = address;
|
|
32976
|
+
if (address instanceof URL$1) parsedUrl = address;
|
|
32977
32977
|
else try {
|
|
32978
|
-
parsedUrl = new URL(address);
|
|
32978
|
+
parsedUrl = new URL$1(address);
|
|
32979
32979
|
} catch (e) {
|
|
32980
32980
|
throw new SyntaxError(`Invalid URL: ${address}`);
|
|
32981
32981
|
}
|
|
@@ -33077,7 +33077,7 @@ var require_websocket = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
33077
33077
|
req.abort();
|
|
33078
33078
|
let addr;
|
|
33079
33079
|
try {
|
|
33080
|
-
addr = new URL(location, address);
|
|
33080
|
+
addr = new URL$1(location, address);
|
|
33081
33081
|
} catch (e) {
|
|
33082
33082
|
emitErrorAndClose(websocket, /* @__PURE__ */ new SyntaxError(`Invalid URL: ${location}`));
|
|
33083
33083
|
return;
|
|
@@ -41425,12 +41425,24 @@ var SessionStore = class {
|
|
|
41425
41425
|
//#endregion
|
|
41426
41426
|
//#region src/terminal/pty-manager.ts
|
|
41427
41427
|
let pty = null;
|
|
41428
|
+
let ptyLoadError = null;
|
|
41428
41429
|
try {
|
|
41429
41430
|
pty = require("node-pty");
|
|
41430
|
-
} catch {
|
|
41431
|
+
} catch (err) {
|
|
41432
|
+
ptyLoadError = err instanceof Error ? err.message : String(err);
|
|
41433
|
+
}
|
|
41431
41434
|
const DISCONNECT_TIMEOUT_MS = 6e4;
|
|
41432
41435
|
const STATUS_INTERVAL_MS = 1e3;
|
|
41433
41436
|
const ACTIVE_THRESHOLD_MS = 2e3;
|
|
41437
|
+
const logDir$1 = node_path.join(node_path.dirname(new URL(require("url").pathToFileURL(__filename).href).pathname.replace(/^\/([A-Z]:)/i, "$1")), "..", "logs");
|
|
41438
|
+
function ptyLog(level, ...args) {
|
|
41439
|
+
try {
|
|
41440
|
+
node_fs.mkdirSync(logDir$1, { recursive: true });
|
|
41441
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
41442
|
+
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
41443
|
+
node_fs.appendFileSync(node_path.join(logDir$1, `dashboard-${ts.slice(0, 10)}.log`), `[${ts}] [${level}] [pty-manager] ${msg}\n`);
|
|
41444
|
+
} catch {}
|
|
41445
|
+
}
|
|
41434
41446
|
var PtyManager = class PtyManager {
|
|
41435
41447
|
static instance = null;
|
|
41436
41448
|
session = null;
|
|
@@ -41443,16 +41455,21 @@ var PtyManager = class PtyManager {
|
|
|
41443
41455
|
}
|
|
41444
41456
|
spawn(opts) {
|
|
41445
41457
|
if (!pty) {
|
|
41458
|
+
ptyLog("ERROR", `node-pty not available: ${ptyLoadError}`);
|
|
41446
41459
|
this.broadcastToClients({
|
|
41447
41460
|
type: "output",
|
|
41448
|
-
data:
|
|
41461
|
+
data: `\r\n\x1b[31mTerminal unavailable: node-pty is not installed.\r\nError: ${ptyLoadError}\r\nRun: npm install node-pty\x1b[0m\r\n`
|
|
41449
41462
|
});
|
|
41450
41463
|
return;
|
|
41451
41464
|
}
|
|
41452
|
-
if (this.session)
|
|
41465
|
+
if (this.session) {
|
|
41466
|
+
ptyLog("INFO", "Killing existing session before spawn");
|
|
41467
|
+
this.kill();
|
|
41468
|
+
}
|
|
41453
41469
|
const shell = process.platform === "win32" ? "claude.cmd" : "claude";
|
|
41454
41470
|
const args = [];
|
|
41455
41471
|
if (opts.skipPermissions) args.push("--dangerously-skip-permissions");
|
|
41472
|
+
ptyLog("INFO", `Spawning: shell=${shell}, args=${JSON.stringify(args)}, cwd=${opts.cwd}, cols=${opts.cols ?? 120}, rows=${opts.rows ?? 30}`);
|
|
41456
41473
|
const proc = pty.spawn(shell, args, {
|
|
41457
41474
|
name: "xterm-256color",
|
|
41458
41475
|
cols: opts.cols ?? 120,
|
|
@@ -41460,6 +41477,7 @@ var PtyManager = class PtyManager {
|
|
|
41460
41477
|
cwd: opts.cwd,
|
|
41461
41478
|
env: process.env
|
|
41462
41479
|
});
|
|
41480
|
+
ptyLog("INFO", `Process spawned with pid=${proc.pid}`);
|
|
41463
41481
|
const store = new SessionStore();
|
|
41464
41482
|
this.session = {
|
|
41465
41483
|
process: proc,
|
|
@@ -41480,6 +41498,7 @@ var PtyManager = class PtyManager {
|
|
|
41480
41498
|
});
|
|
41481
41499
|
});
|
|
41482
41500
|
proc.onExit(({ exitCode }) => {
|
|
41501
|
+
ptyLog("INFO", `Process exited with code=${exitCode}`);
|
|
41483
41502
|
this.broadcastToClients({
|
|
41484
41503
|
type: "exit",
|
|
41485
41504
|
code: exitCode
|
|
@@ -41577,7 +41596,18 @@ var PtyManager = class PtyManager {
|
|
|
41577
41596
|
|
|
41578
41597
|
//#endregion
|
|
41579
41598
|
//#region src/server.ts
|
|
41599
|
+
const dashboardDir = node_path.dirname(new URL(require("url").pathToFileURL(__filename).href).pathname.replace(/^\/([A-Z]:)/i, "$1"));
|
|
41600
|
+
const logDir = node_path.join(dashboardDir, "logs");
|
|
41601
|
+
node_fs.mkdirSync(logDir, { recursive: true });
|
|
41602
|
+
const logFile = node_path.join(logDir, `dashboard-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.log`);
|
|
41603
|
+
const logStream = node_fs.createWriteStream(logFile, { flags: "a" });
|
|
41604
|
+
function log(level, tag, ...args) {
|
|
41605
|
+
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [${level}] [${tag}] ${args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ")}\n`;
|
|
41606
|
+
logStream.write(line);
|
|
41607
|
+
if (level === "ERROR") console.error(`[${tag}]`, ...args);
|
|
41608
|
+
}
|
|
41580
41609
|
const projectCwd = process.env.MAXSIM_PROJECT_CWD || process.cwd();
|
|
41610
|
+
log("INFO", "server", `Starting dashboard server, projectCwd=${projectCwd}`);
|
|
41581
41611
|
const clientDir = node_path.join(__dirname, "client");
|
|
41582
41612
|
function isWithinPlanning(cwd, targetPath) {
|
|
41583
41613
|
const planningDir = node_path.resolve(cwd, ".planning");
|
|
@@ -42003,17 +42033,15 @@ None yet.
|
|
|
42003
42033
|
`;
|
|
42004
42034
|
node_fs.writeFileSync(statePath, template, "utf-8");
|
|
42005
42035
|
}
|
|
42006
|
-
function appendToStateSection(statePath, sectionPattern, entry) {
|
|
42007
|
-
let content = node_fs.readFileSync(statePath, "utf-8");
|
|
42036
|
+
function appendToStateSection(statePath, sectionPattern, entry, fallbackSection) {
|
|
42037
|
+
let content = node_fs.readFileSync(statePath, "utf-8").replace(/\r\n/g, "\n");
|
|
42008
42038
|
const match = content.match(sectionPattern);
|
|
42009
|
-
if (
|
|
42010
|
-
|
|
42011
|
-
|
|
42012
|
-
|
|
42013
|
-
|
|
42014
|
-
|
|
42015
|
-
sectionBody = sectionBody.trimEnd() + "\n" + entry + "\n";
|
|
42016
|
-
content = content.replace(sectionPattern, (_m, header) => `${header}${sectionBody}`);
|
|
42039
|
+
if (match) {
|
|
42040
|
+
let sectionBody = match[2];
|
|
42041
|
+
sectionBody = sectionBody.replace(/None yet\.?\s*\n?/gi, "").replace(/No decisions yet\.?\s*\n?/gi, "").replace(/None\.?\s*\n?/gi, "");
|
|
42042
|
+
sectionBody = sectionBody.trimEnd() + "\n" + entry + "\n";
|
|
42043
|
+
content = content.replace(sectionPattern, (_m, header) => `${header}${sectionBody}`);
|
|
42044
|
+
} else content = content.trimEnd() + "\n\n" + fallbackSection + "\n" + entry + "\n";
|
|
42017
42045
|
suppressPath(statePath);
|
|
42018
42046
|
node_fs.writeFileSync(statePath, content, "utf-8");
|
|
42019
42047
|
return { success: true };
|
|
@@ -42024,8 +42052,7 @@ app.post("/api/state/decision", (req, res) => {
|
|
|
42024
42052
|
const { phase, text } = req.body;
|
|
42025
42053
|
if (!text?.trim()) return res.status(400).json({ error: "text is required" });
|
|
42026
42054
|
const entry = `- [Phase ${phase?.trim() || "?"}]: ${text.trim()}`;
|
|
42027
|
-
|
|
42028
|
-
if (!result.success) return res.status(404).json({ error: result.reason });
|
|
42055
|
+
appendToStateSection(statePath, /(###?\s*(?:Decisions|Decisions Made|Accumulated.*Decisions)\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i, entry, "### Decisions");
|
|
42029
42056
|
return res.json({
|
|
42030
42057
|
added: true,
|
|
42031
42058
|
decision: entry
|
|
@@ -42036,8 +42063,7 @@ app.post("/api/state/blocker", (req, res) => {
|
|
|
42036
42063
|
ensureStateMd(statePath);
|
|
42037
42064
|
const { text } = req.body;
|
|
42038
42065
|
if (!text?.trim()) return res.status(400).json({ error: "text is required" });
|
|
42039
|
-
|
|
42040
|
-
if (!result.success) return res.status(404).json({ error: result.reason });
|
|
42066
|
+
appendToStateSection(statePath, /(###?\s*(?:Blockers|Blockers\/Concerns|Concerns)\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i, `- ${text.trim()}`, "### Blockers/Concerns");
|
|
42041
42067
|
return res.json({
|
|
42042
42068
|
added: true,
|
|
42043
42069
|
blocker: text.trim()
|
|
@@ -42160,13 +42186,18 @@ async function main() {
|
|
|
42160
42186
|
const wss = createWSS();
|
|
42161
42187
|
const terminalWss = new import_websocket_server.default({ noServer: true });
|
|
42162
42188
|
const ptyManager = PtyManager.getInstance();
|
|
42163
|
-
if (!ptyManager.isAvailable())
|
|
42189
|
+
if (!ptyManager.isAvailable()) log("WARN", "server", "node-pty not available — terminal features disabled");
|
|
42190
|
+
else log("INFO", "server", "node-pty available — terminal features enabled");
|
|
42164
42191
|
terminalWss.on("connection", (ws) => {
|
|
42192
|
+
log("INFO", "terminal-ws", "Client connected");
|
|
42165
42193
|
ptyManager.addClient(ws);
|
|
42166
|
-
if (!ptyManager.isAvailable())
|
|
42167
|
-
|
|
42168
|
-
|
|
42169
|
-
|
|
42194
|
+
if (!ptyManager.isAvailable()) {
|
|
42195
|
+
ws.send(JSON.stringify({
|
|
42196
|
+
type: "unavailable",
|
|
42197
|
+
reason: "node-pty is not installed — terminal features disabled"
|
|
42198
|
+
}));
|
|
42199
|
+
log("WARN", "terminal-ws", "Sent unavailable to client — node-pty missing");
|
|
42200
|
+
}
|
|
42170
42201
|
ws.on("message", (raw) => {
|
|
42171
42202
|
try {
|
|
42172
42203
|
const msg = JSON.parse(typeof raw === "string" ? raw : raw.toString());
|
|
@@ -42175,27 +42206,44 @@ async function main() {
|
|
|
42175
42206
|
ptyManager.write(msg.data);
|
|
42176
42207
|
break;
|
|
42177
42208
|
case "resize":
|
|
42209
|
+
log("INFO", "terminal-ws", `Resize: ${msg.cols}x${msg.rows}`);
|
|
42178
42210
|
ptyManager.resize(msg.cols, msg.rows);
|
|
42179
42211
|
break;
|
|
42180
42212
|
case "spawn":
|
|
42181
|
-
|
|
42182
|
-
|
|
42183
|
-
|
|
42184
|
-
|
|
42185
|
-
|
|
42186
|
-
|
|
42213
|
+
log("INFO", "terminal-ws", `Spawn requested: skipPermissions=${!!msg.skipPermissions}, cwd=${projectCwd}`);
|
|
42214
|
+
try {
|
|
42215
|
+
ptyManager.spawn({
|
|
42216
|
+
skipPermissions: !!msg.skipPermissions,
|
|
42217
|
+
cwd: projectCwd,
|
|
42218
|
+
cols: msg.cols,
|
|
42219
|
+
rows: msg.rows
|
|
42220
|
+
});
|
|
42221
|
+
log("INFO", "terminal-ws", `Spawn succeeded, pid=${ptyManager.getStatus()?.pid}`);
|
|
42222
|
+
} catch (err) {
|
|
42223
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
42224
|
+
log("ERROR", "terminal-ws", `Spawn failed: ${errMsg}`);
|
|
42225
|
+
ws.send(JSON.stringify({
|
|
42226
|
+
type: "output",
|
|
42227
|
+
data: `\r\n\x1b[31mFailed to start terminal: ${errMsg}\x1b[0m\r\n`
|
|
42228
|
+
}));
|
|
42229
|
+
}
|
|
42187
42230
|
break;
|
|
42188
42231
|
case "kill":
|
|
42232
|
+
log("INFO", "terminal-ws", "Kill requested");
|
|
42189
42233
|
ptyManager.kill();
|
|
42190
42234
|
break;
|
|
42235
|
+
default: log("WARN", "terminal-ws", `Unknown message type: ${msg.type}`);
|
|
42191
42236
|
}
|
|
42192
|
-
} catch {
|
|
42237
|
+
} catch (err) {
|
|
42238
|
+
log("ERROR", "terminal-ws", `Message handling error: ${err instanceof Error ? err.message : String(err)}`);
|
|
42239
|
+
}
|
|
42193
42240
|
});
|
|
42194
42241
|
ws.on("close", () => {
|
|
42242
|
+
log("INFO", "terminal-ws", "Client disconnected");
|
|
42195
42243
|
ptyManager.removeClient(ws);
|
|
42196
42244
|
});
|
|
42197
42245
|
ws.on("error", (err) => {
|
|
42198
|
-
|
|
42246
|
+
log("ERROR", "terminal-ws", `Client error: ${err.message}`);
|
|
42199
42247
|
});
|
|
42200
42248
|
});
|
|
42201
42249
|
const server = (0, node_http.createServer)(app);
|
|
@@ -42218,7 +42266,9 @@ async function main() {
|
|
|
42218
42266
|
const port = await esm_default(3333);
|
|
42219
42267
|
const url = `http://localhost:${port}`;
|
|
42220
42268
|
server.listen(port, () => {
|
|
42269
|
+
log("INFO", "server", `Dashboard ready at ${url}, log file: ${logFile}`);
|
|
42221
42270
|
console.error(`Dashboard ready at ${url}`);
|
|
42271
|
+
console.error(`Logs: ${logFile}`);
|
|
42222
42272
|
open$1(url).catch(() => {});
|
|
42223
42273
|
});
|
|
42224
42274
|
function shutdown() {
|
package/package.json
CHANGED