@adhdev/daemon-standalone 0.9.82-rc.2 → 0.9.82-rc.200

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/mcp-server",
3
- "version": "0.9.81",
3
+ "version": "0.9.82",
4
4
  "description": "ADHDev MCP server \u2014 expose IDE agents as MCP tools",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -82,7 +82,8 @@ function formatXtermViewportPlain(terminal, rows) {
82
82
  const lines = [];
83
83
  for (let i = start; i < end; i++) {
84
84
  const line = buffer.getLine(i);
85
- lines.push(line ? line.translateToString(true) : "");
85
+ const raw = line ? line.translateToString(false) : "";
86
+ lines.push(raw.replace(/\s+$/, ""));
86
87
  }
87
88
  let first = 0;
88
89
  let last = lines.length;
@@ -145,6 +146,9 @@ function createXtermMirror(options) {
145
146
  if (serializer) return serializeXtermViewport(terminal, serializer, currentRows);
146
147
  return formatXtermViewportPlain(terminal, currentRows);
147
148
  },
149
+ formatPlainText() {
150
+ return formatXtermViewportPlain(terminal, currentRows).replace(/\r\n/g, "\n");
151
+ },
148
152
  getCursorPosition() {
149
153
  const buffer = terminal.buffer.active;
150
154
  return {
@@ -177,6 +181,9 @@ function normalizeGhosttyBinding(mod) {
177
181
  formatVT() {
178
182
  return viewportSnapshot.formatVT();
179
183
  },
184
+ formatPlainText() {
185
+ return viewportSnapshot.formatPlainText();
186
+ },
180
187
  getCursorPosition() {
181
188
  if (typeof handle.getCursorPosition === "function") return handle.getCursorPosition();
182
189
  return viewportSnapshot.getCursorPosition();
@@ -225,6 +232,10 @@ var PtySessionRuntime = class {
225
232
  ptyProcess = null;
226
233
  screenMirror = null;
227
234
  pendingQueryScanTail = "";
235
+ terminalModeScanTail = "";
236
+ altScreen = false;
237
+ pasteMode = false;
238
+ scrollRegion;
228
239
  onDataCallback;
229
240
  onExitCallback;
230
241
  constructor(options) {
@@ -232,6 +243,7 @@ var PtySessionRuntime = class {
232
243
  this.payload = options.payload;
233
244
  this.cols = (0, import_session_host_core.resolveSessionHostCols)(options.payload.cols);
234
245
  this.rows = (0, import_session_host_core.resolveSessionHostRows)(options.payload.rows);
246
+ this.scrollRegion = { top: 0, bot: this.rows - 1 };
235
247
  this.onDataCallback = options.onData;
236
248
  this.onExitCallback = options.onExit;
237
249
  }
@@ -263,6 +275,7 @@ var PtySessionRuntime = class {
263
275
  });
264
276
  this.ptyProcess.onData((data) => {
265
277
  this.screenMirror?.write(data);
278
+ this.trackTerminalModes(data);
266
279
  this.respondToTerminalQueries(data);
267
280
  this.onDataCallback(data);
268
281
  });
@@ -271,6 +284,7 @@ var PtySessionRuntime = class {
271
284
  this.screenMirror?.dispose();
272
285
  this.screenMirror = null;
273
286
  this.pendingQueryScanTail = "";
287
+ this.terminalModeScanTail = "";
274
288
  this.onExitCallback(exitCode ?? null);
275
289
  });
276
290
  return this.ptyProcess.pid;
@@ -282,6 +296,12 @@ var PtySessionRuntime = class {
282
296
  resize(cols, rows) {
283
297
  if (!this.ptyProcess) throw new Error(`Session not running: ${this.sessionId}`);
284
298
  this.ptyProcess.resize(cols, rows);
299
+ this.cols = Math.max(1, cols | 0);
300
+ this.rows = Math.max(1, rows | 0);
301
+ this.scrollRegion = {
302
+ top: Math.min(this.scrollRegion.top, this.rows - 1),
303
+ bot: Math.min(Math.max(this.scrollRegion.top, this.scrollRegion.bot), this.rows - 1)
304
+ };
285
305
  this.screenMirror?.resize(cols, rows);
286
306
  }
287
307
  stop() {
@@ -305,6 +325,55 @@ var PtySessionRuntime = class {
305
325
  getSnapshotText() {
306
326
  return this.screenMirror?.formatVT() || "";
307
327
  }
328
+ getTerminalSnapshot() {
329
+ if (!this.ptyProcess || !this.screenMirror) {
330
+ throw new Error(`Session not running: ${this.sessionId}`);
331
+ }
332
+ const cursor = this.screenMirror.getCursorPosition();
333
+ return {
334
+ text: this.screenMirror.formatPlainText(),
335
+ state: {
336
+ cursor: {
337
+ row: Math.max(0, cursor.row | 0),
338
+ col: Math.max(0, cursor.col | 0)
339
+ },
340
+ altScreen: this.altScreen,
341
+ pasteMode: this.pasteMode,
342
+ rawMode: true,
343
+ scrollRegion: { ...this.scrollRegion },
344
+ cols: this.cols,
345
+ rows: this.rows
346
+ }
347
+ };
348
+ }
349
+ trackTerminalModes(data) {
350
+ if (!data) return;
351
+ const combined = this.terminalModeScanTail + data;
352
+ const privateMode = /\x1b\[\?([0-9;]*)([hl])/g;
353
+ let privateMatch;
354
+ while ((privateMatch = privateMode.exec(combined)) !== null) {
355
+ const enabled = privateMatch[2] === "h";
356
+ for (const mode of privateMatch[1].split(";")) {
357
+ if (mode === "47" || mode === "1047" || mode === "1049") this.altScreen = enabled;
358
+ if (mode === "2004") this.pasteMode = enabled;
359
+ }
360
+ }
361
+ const scrollRegion = /\x1b\[(\d*)(?:;(\d*))?r/g;
362
+ let scrollMatch;
363
+ while ((scrollMatch = scrollRegion.exec(combined)) !== null) {
364
+ const top = scrollMatch[1] ? Number.parseInt(scrollMatch[1], 10) - 1 : 0;
365
+ const bot = scrollMatch[2] ? Number.parseInt(scrollMatch[2], 10) - 1 : this.rows - 1;
366
+ this.scrollRegion = {
367
+ top: Math.max(0, Math.min(this.rows - 1, top)),
368
+ bot: Math.max(0, Math.min(this.rows - 1, bot))
369
+ };
370
+ if (this.scrollRegion.bot < this.scrollRegion.top) {
371
+ this.scrollRegion = { top: 0, bot: this.rows - 1 };
372
+ }
373
+ }
374
+ const lastEscape = combined.lastIndexOf("\x1B");
375
+ this.terminalModeScanTail = lastEscape >= 0 && combined.length - lastEscape < 64 ? combined.slice(lastEscape) : "";
376
+ }
308
377
  respondToTerminalQueries(data) {
309
378
  if (!this.ptyProcess || !this.screenMirror || !data) return;
310
379
  const combined = this.pendingQueryScanTail + data;
@@ -518,6 +587,8 @@ var SessionHostServer = class _SessionHostServer extends import_events.EventEmit
518
587
  }
519
588
  case "get_snapshot":
520
589
  return { success: true, result: this.getSnapshot(request.payload.sessionId, request.payload.sinceSeq) };
590
+ case "get_terminal_snapshot":
591
+ return { success: true, result: this.requireRuntime(request.payload.sessionId).getTerminalSnapshot() };
521
592
  case "get_host_diagnostics":
522
593
  return { success: true, result: this.getHostDiagnostics(request.payload) };
523
594
  case "clear_session_buffer": {
@@ -758,7 +829,12 @@ var SessionHostServer = class _SessionHostServer extends import_events.EventEmit
758
829
  const record = this.registry.getSession(sessionId);
759
830
  if (!record) return;
760
831
  const snapshot = this.getSnapshot(sessionId);
761
- this.storage.save(record, snapshot);
832
+ try {
833
+ this.storage.save(record, snapshot);
834
+ } catch (error) {
835
+ const code = typeof error?.code === "string" ? error.code : "persist_failed";
836
+ console.error(`[session-host] Persist failed for ${sessionId}: ${code}: ${error?.message || error}`);
837
+ }
762
838
  }
763
839
  getSessionHostRecoveryLabel(record) {
764
840
  const recoveryState = typeof record.meta?.runtimeRecoveryState === "string" ? String(record.meta.runtimeRecoveryState).trim() : "";