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.
@@ -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: "\r\n\x1B[31mTerminal unavailable: node-pty is not installed.\r\nRun: npm install node-pty\x1B[0m\r\n"
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) this.kill();
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 (!match) return {
42010
- success: false,
42011
- reason: "Section not found in STATE.md"
42012
- };
42013
- let sectionBody = match[2];
42014
- sectionBody = sectionBody.replace(/None yet\.?\s*\n?/gi, "").replace(/No decisions yet\.?\s*\n?/gi, "").replace(/None\.?\s*\n?/gi, "");
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
- const result = appendToStateSection(statePath, /(###?\s*(?:Decisions|Decisions Made|Accumulated.*Decisions)\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i, entry);
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
- const result = appendToStateSection(statePath, /(###?\s*(?:Blockers|Blockers\/Concerns|Concerns)\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i, `- ${text.trim()}`);
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()) console.error("[server] node-pty not available — terminal features disabled");
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()) ws.send(JSON.stringify({
42167
- type: "unavailable",
42168
- reason: "node-pty is not installed — terminal features disabled"
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
- ptyManager.spawn({
42182
- skipPermissions: !!msg.skipPermissions,
42183
- cwd: projectCwd,
42184
- cols: msg.cols,
42185
- rows: msg.rows
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
- console.error("[terminal-ws] Client error:", err.message);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "maxsimcli",
3
- "version": "2.5.2",
3
+ "version": "2.5.3",
4
4
  "private": false,
5
5
  "description": "A meta-prompting, context engineering and spec-driven development system for Claude Code, OpenCode, Gemini and Codex by MayStudios.",
6
6
  "bin": {