@adhdev/daemon-standalone 0.9.82-rc.167 → 0.9.82-rc.169

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-standalone",
3
- "version": "0.9.82-rc.167",
3
+ "version": "0.9.82-rc.169",
4
4
  "description": "ADHDev standalone daemon — embedded HTTP/WS server for local dashboard",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -15,7 +15,7 @@
15
15
  "bundle:vendor": "node ./scripts/vendor-runtime-deps.mjs",
16
16
  "dev": "tsx src/index.ts",
17
17
  "start": "node dist/index.js",
18
- "test": "node --import tsx --test test/*.test.ts",
18
+ "test": "node --import tsx --test test/*.test.ts && vitest run",
19
19
  "typecheck": "tsc --noEmit -p tsconfig.json",
20
20
  "prepublishOnly": "cd ../.. && npm run build -w packages/session-host-daemon && npm run build -w packages/mcp-server && npm run build -w packages/daemon-core && npm run build -w packages/web-standalone && cd packages/daemon-standalone && npm run bundle:web && npm run bundle:vendor && npm run build"
21
21
  },
@@ -52,7 +52,8 @@
52
52
  "playwright": "^1.60.0",
53
53
  "tsup": "^8.2.0",
54
54
  "tsx": "^4.19.0",
55
- "typescript": "^5.5.0"
55
+ "typescript": "^5.5.0",
56
+ "vitest": "^4.1.3"
56
57
  },
57
58
  "repository": {
58
59
  "type": "git",
@@ -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": {