spawn-term 3.0.4 → 3.0.6

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.
Files changed (57) hide show
  1. package/dist/cjs/components/App.js +28 -56
  2. package/dist/cjs/components/App.js.map +1 -1
  3. package/dist/cjs/components/ErrorFooter.js +120 -0
  4. package/dist/cjs/components/ErrorFooter.js.map +1 -0
  5. package/dist/cjs/components/ExpandedOutput.js +0 -2
  6. package/dist/cjs/components/ExpandedOutput.js.map +1 -1
  7. package/dist/cjs/components/StatusBar.js +22 -33
  8. package/dist/cjs/components/StatusBar.js.map +1 -1
  9. package/dist/cjs/index-esm.js +4 -0
  10. package/dist/cjs/index-esm.js.map +1 -1
  11. package/dist/cjs/lib/TerminalBuffer.js +139 -0
  12. package/dist/cjs/lib/TerminalBuffer.js.map +1 -0
  13. package/dist/cjs/session.js +129 -56
  14. package/dist/cjs/session.js.map +1 -1
  15. package/dist/cjs/src/components/ErrorFooter.d.ts +11 -0
  16. package/dist/cjs/src/index-esm.d.ts +1 -0
  17. package/dist/cjs/src/lib/TerminalBuffer.d.ts +32 -0
  18. package/dist/cjs/src/state/processStore.d.ts +14 -7
  19. package/dist/cjs/src/types.d.ts +2 -0
  20. package/dist/cjs/state/processStore.js +79 -26
  21. package/dist/cjs/state/processStore.js.map +1 -1
  22. package/dist/cjs/types.js.map +1 -1
  23. package/dist/esm/components/App.js +28 -56
  24. package/dist/esm/components/App.js.map +1 -1
  25. package/dist/esm/components/ErrorFooter.js +95 -0
  26. package/dist/esm/components/ErrorFooter.js.map +1 -0
  27. package/dist/esm/components/ExpandedOutput.js +0 -2
  28. package/dist/esm/components/ExpandedOutput.js.map +1 -1
  29. package/dist/esm/components/StatusBar.js +22 -33
  30. package/dist/esm/components/StatusBar.js.map +1 -1
  31. package/dist/esm/index-esm.js +1 -0
  32. package/dist/esm/index-esm.js.map +1 -1
  33. package/dist/esm/lib/TerminalBuffer.js +62 -0
  34. package/dist/esm/lib/TerminalBuffer.js.map +1 -0
  35. package/dist/esm/session.js +112 -35
  36. package/dist/esm/session.js.map +1 -1
  37. package/dist/esm/src/components/ErrorFooter.d.ts +11 -0
  38. package/dist/esm/src/index-esm.d.ts +1 -0
  39. package/dist/esm/src/lib/TerminalBuffer.d.ts +32 -0
  40. package/dist/esm/src/state/processStore.d.ts +14 -7
  41. package/dist/esm/src/types.d.ts +2 -0
  42. package/dist/esm/state/processStore.js +53 -22
  43. package/dist/esm/state/processStore.js.map +1 -1
  44. package/dist/esm/types.js.map +1 -1
  45. package/package.json +2 -1
  46. package/dist/cjs/components/ErrorDetailModal.js +0 -115
  47. package/dist/cjs/components/ErrorDetailModal.js.map +0 -1
  48. package/dist/cjs/components/ErrorListModal.js +0 -135
  49. package/dist/cjs/components/ErrorListModal.js.map +0 -1
  50. package/dist/cjs/src/components/ErrorDetailModal.d.ts +0 -8
  51. package/dist/cjs/src/components/ErrorListModal.d.ts +0 -8
  52. package/dist/esm/components/ErrorDetailModal.js +0 -99
  53. package/dist/esm/components/ErrorDetailModal.js.map +0 -1
  54. package/dist/esm/components/ErrorListModal.js +0 -116
  55. package/dist/esm/components/ErrorListModal.js.map +0 -1
  56. package/dist/esm/src/components/ErrorDetailModal.d.ts +0 -8
  57. package/dist/esm/src/components/ErrorListModal.d.ts +0 -8
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "TerminalBuffer", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return TerminalBuffer;
9
+ }
10
+ });
11
+ var _headless = /*#__PURE__*/ _interop_require_wildcard(require("@xterm/headless"));
12
+ function _class_call_check(instance, Constructor) {
13
+ if (!(instance instanceof Constructor)) {
14
+ throw new TypeError("Cannot call a class as a function");
15
+ }
16
+ }
17
+ function _defineProperties(target, props) {
18
+ for(var i = 0; i < props.length; i++){
19
+ var descriptor = props[i];
20
+ descriptor.enumerable = descriptor.enumerable || false;
21
+ descriptor.configurable = true;
22
+ if ("value" in descriptor) descriptor.writable = true;
23
+ Object.defineProperty(target, descriptor.key, descriptor);
24
+ }
25
+ }
26
+ function _create_class(Constructor, protoProps, staticProps) {
27
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
28
+ if (staticProps) _defineProperties(Constructor, staticProps);
29
+ return Constructor;
30
+ }
31
+ function _getRequireWildcardCache(nodeInterop) {
32
+ if (typeof WeakMap !== "function") return null;
33
+ var cacheBabelInterop = new WeakMap();
34
+ var cacheNodeInterop = new WeakMap();
35
+ return (_getRequireWildcardCache = function(nodeInterop) {
36
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
37
+ })(nodeInterop);
38
+ }
39
+ function _interop_require_wildcard(obj, nodeInterop) {
40
+ if (!nodeInterop && obj && obj.__esModule) {
41
+ return obj;
42
+ }
43
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
44
+ return {
45
+ default: obj
46
+ };
47
+ }
48
+ var cache = _getRequireWildcardCache(nodeInterop);
49
+ if (cache && cache.has(obj)) {
50
+ return cache.get(obj);
51
+ }
52
+ var newObj = {
53
+ __proto__: null
54
+ };
55
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
56
+ for(var key in obj){
57
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
58
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
59
+ if (desc && (desc.get || desc.set)) {
60
+ Object.defineProperty(newObj, key, desc);
61
+ } else {
62
+ newObj[key] = obj[key];
63
+ }
64
+ }
65
+ }
66
+ newObj.default = obj;
67
+ if (cache) {
68
+ cache.set(obj, newObj);
69
+ }
70
+ return newObj;
71
+ }
72
+ var _xterm_default;
73
+ // Handle both ESM and CJS module formats
74
+ var Terminal = _headless.Terminal || ((_xterm_default = _headless.default) === null || _xterm_default === void 0 ? void 0 : _xterm_default.Terminal);
75
+ var TerminalBuffer = /*#__PURE__*/ function() {
76
+ "use strict";
77
+ function TerminalBuffer(cols) {
78
+ var scrollback = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 10000;
79
+ _class_call_check(this, TerminalBuffer);
80
+ this.terminal = new Terminal({
81
+ cols: cols,
82
+ rows: 50,
83
+ scrollback: scrollback,
84
+ allowProposedApi: true
85
+ });
86
+ }
87
+ var _proto = TerminalBuffer.prototype;
88
+ /**
89
+ * Write raw data to the terminal buffer.
90
+ * The terminal interprets all ANSI sequences automatically.
91
+ */ _proto.write = function write(data) {
92
+ var str = typeof data === 'string' ? data : data.toString('utf8');
93
+ this.terminal.write(str);
94
+ };
95
+ /**
96
+ * Resize the terminal width.
97
+ */ _proto.resize = function resize(cols) {
98
+ this.terminal.resize(cols, this.terminal.rows);
99
+ };
100
+ /**
101
+ * Extract the rendered lines from the terminal buffer.
102
+ * This returns the actual visible content after all ANSI sequences
103
+ * have been processed.
104
+ */ _proto.getLines = function getLines() {
105
+ var buffer = this.terminal.buffer.active;
106
+ var lines = [];
107
+ for(var i = 0; i < buffer.length; i++){
108
+ var line = buffer.getLine(i);
109
+ if (line) {
110
+ // translateToString(trimRight) - trim trailing whitespace
111
+ // Also trim leading whitespace - tools like ncu/npm use cursor positioning
112
+ // which creates lines with leading spaces when interpreted by xterm
113
+ lines.push(line.translateToString(true).trimStart());
114
+ }
115
+ }
116
+ // Trim trailing empty lines
117
+ while(lines.length > 0 && lines[lines.length - 1] === ''){
118
+ lines.pop();
119
+ }
120
+ return lines;
121
+ };
122
+ /**
123
+ * Clean up terminal resources.
124
+ */ _proto.dispose = function dispose() {
125
+ this.terminal.dispose();
126
+ };
127
+ _create_class(TerminalBuffer, [
128
+ {
129
+ key: "lineCount",
130
+ get: /**
131
+ * Get the number of rendered lines.
132
+ */ function get() {
133
+ return this.getLines().length;
134
+ }
135
+ }
136
+ ]);
137
+ return TerminalBuffer;
138
+ }();
139
+ /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/lib/TerminalBuffer.ts"],"sourcesContent":["import * as xterm from '@xterm/headless';\n\n// Handle both ESM and CJS module formats\nconst Terminal = (xterm as { Terminal: typeof xterm.Terminal; default?: { Terminal: typeof xterm.Terminal } }).Terminal || (xterm as { default?: { Terminal: typeof xterm.Terminal } }).default?.Terminal;\n\n/**\n * Wrapper around @xterm/headless Terminal that provides a virtual terminal buffer.\n * Interprets ANSI escape sequences (cursor movement, line clearing, etc.) to produce\n * the actual rendered output rather than raw intermediate states.\n */\nexport class TerminalBuffer {\n private terminal: InstanceType<typeof Terminal>;\n\n constructor(cols: number, scrollback = 10000) {\n this.terminal = new Terminal({\n cols,\n rows: 50, // Visible rows (doesn't matter much for headless)\n scrollback,\n allowProposedApi: true,\n });\n }\n\n /**\n * Write raw data to the terminal buffer.\n * The terminal interprets all ANSI sequences automatically.\n */\n write(data: string | Buffer): void {\n const str = typeof data === 'string' ? data : data.toString('utf8');\n this.terminal.write(str);\n }\n\n /**\n * Resize the terminal width.\n */\n resize(cols: number): void {\n this.terminal.resize(cols, this.terminal.rows);\n }\n\n /**\n * Extract the rendered lines from the terminal buffer.\n * This returns the actual visible content after all ANSI sequences\n * have been processed.\n */\n getLines(): string[] {\n const buffer = this.terminal.buffer.active;\n const lines: string[] = [];\n\n for (let i = 0; i < buffer.length; i++) {\n const line = buffer.getLine(i);\n if (line) {\n // translateToString(trimRight) - trim trailing whitespace\n // Also trim leading whitespace - tools like ncu/npm use cursor positioning\n // which creates lines with leading spaces when interpreted by xterm\n lines.push(line.translateToString(true).trimStart());\n }\n }\n\n // Trim trailing empty lines\n while (lines.length > 0 && lines[lines.length - 1] === '') {\n lines.pop();\n }\n\n return lines;\n }\n\n /**\n * Get the number of rendered lines.\n */\n get lineCount(): number {\n return this.getLines().length;\n }\n\n /**\n * Clean up terminal resources.\n */\n dispose(): void {\n this.terminal.dispose();\n }\n}\n"],"names":["TerminalBuffer","Terminal","xterm","default","cols","scrollback","terminal","rows","allowProposedApi","write","data","str","toString","resize","getLines","buffer","active","lines","i","length","line","getLine","push","translateToString","trimStart","pop","dispose","lineCount"],"mappings":";;;;+BAUaA;;;eAAAA;;;gEAVU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAGoG;AAD3H,yCAAyC;AACzC,IAAMC,WAAW,AAACC,UAA6FD,QAAQ,MAAI,iBAAA,AAACC,UAA4DC,OAAO,cAApE,qCAAA,eAAsEF,QAAQ;AAOlM,IAAA,AAAMD,+BAAN;;aAAMA,eAGCI,IAAY;YAAEC,aAAAA,iEAAa;gCAH5BL;QAIT,IAAI,CAACM,QAAQ,GAAG,IAAIL,SAAS;YAC3BG,MAAAA;YACAG,MAAM;YACNF,YAAAA;YACAG,kBAAkB;QACpB;;iBATSR;IAYX;;;GAGC,GACDS,OAAAA,KAGC,GAHDA,SAAAA,MAAMC,IAAqB;QACzB,IAAMC,MAAM,OAAOD,SAAS,WAAWA,OAAOA,KAAKE,QAAQ,CAAC;QAC5D,IAAI,CAACN,QAAQ,CAACG,KAAK,CAACE;IACtB;IAEA;;GAEC,GACDE,OAAAA,MAEC,GAFDA,SAAAA,OAAOT,IAAY;QACjB,IAAI,CAACE,QAAQ,CAACO,MAAM,CAACT,MAAM,IAAI,CAACE,QAAQ,CAACC,IAAI;IAC/C;IAEA;;;;GAIC,GACDO,OAAAA,QAoBC,GApBDA,SAAAA;QACE,IAAMC,SAAS,IAAI,CAACT,QAAQ,CAACS,MAAM,CAACC,MAAM;QAC1C,IAAMC,QAAkB,EAAE;QAE1B,IAAK,IAAIC,IAAI,GAAGA,IAAIH,OAAOI,MAAM,EAAED,IAAK;YACtC,IAAME,OAAOL,OAAOM,OAAO,CAACH;YAC5B,IAAIE,MAAM;gBACR,0DAA0D;gBAC1D,2EAA2E;gBAC3E,oEAAoE;gBACpEH,MAAMK,IAAI,CAACF,KAAKG,iBAAiB,CAAC,MAAMC,SAAS;YACnD;QACF;QAEA,4BAA4B;QAC5B,MAAOP,MAAME,MAAM,GAAG,KAAKF,KAAK,CAACA,MAAME,MAAM,GAAG,EAAE,KAAK,GAAI;YACzDF,MAAMQ,GAAG;QACX;QAEA,OAAOR;IACT;IASA;;GAEC,GACDS,OAAAA,OAEC,GAFDA,SAAAA;QACE,IAAI,CAACpB,QAAQ,CAACoB,OAAO;IACvB;kBAnEW1B;;YA0DP2B,KAAAA;iBAAJ,AAHA;;GAEC,GACD;gBACE,OAAO,IAAI,CAACb,QAAQ,GAAGK,MAAM;YAC/B;;;WA5DWnB"}
@@ -16,16 +16,28 @@ var _onone = /*#__PURE__*/ _interop_require_default(require("on-one"));
16
16
  var _queuecb = /*#__PURE__*/ _interop_require_default(require("queue-cb"));
17
17
  var _Appts = /*#__PURE__*/ _interop_require_default(require("./components/App.js"));
18
18
  var _constantsts = require("./constants.js");
19
- var _addLinests = /*#__PURE__*/ _interop_require_default(require("./lib/addLines.js"));
20
19
  var _concatWritablets = /*#__PURE__*/ _interop_require_default(require("./lib/concatWritable.js"));
21
20
  var _formatArgumentsts = /*#__PURE__*/ _interop_require_default(require("./lib/formatArguments.js"));
21
+ var _TerminalBufferts = require("./lib/TerminalBuffer.js");
22
22
  var _processStorets = require("./state/processStore.js");
23
- var _typests = require("./types.js");
24
23
  function _class_call_check(instance, Constructor) {
25
24
  if (!(instance instanceof Constructor)) {
26
25
  throw new TypeError("Cannot call a class as a function");
27
26
  }
28
27
  }
28
+ function _define_property(obj, key, value) {
29
+ if (key in obj) {
30
+ Object.defineProperty(obj, key, {
31
+ value: value,
32
+ enumerable: true,
33
+ configurable: true,
34
+ writable: true
35
+ });
36
+ } else {
37
+ obj[key] = value;
38
+ }
39
+ return obj;
40
+ }
29
41
  function _interop_require_default(obj) {
30
42
  return obj && obj.__esModule ? obj : {
31
43
  default: obj
@@ -72,6 +84,45 @@ function _interop_require_wildcard(obj, nodeInterop) {
72
84
  }
73
85
  return newObj;
74
86
  }
87
+ function _object_spread(target) {
88
+ for(var i = 1; i < arguments.length; i++){
89
+ var source = arguments[i] != null ? arguments[i] : {};
90
+ var ownKeys = Object.keys(source);
91
+ if (typeof Object.getOwnPropertySymbols === "function") {
92
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
93
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
94
+ }));
95
+ }
96
+ ownKeys.forEach(function(key) {
97
+ _define_property(target, key, source[key]);
98
+ });
99
+ }
100
+ return target;
101
+ }
102
+ function ownKeys(object, enumerableOnly) {
103
+ var keys = Object.keys(object);
104
+ if (Object.getOwnPropertySymbols) {
105
+ var symbols = Object.getOwnPropertySymbols(object);
106
+ if (enumerableOnly) {
107
+ symbols = symbols.filter(function(sym) {
108
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
109
+ });
110
+ }
111
+ keys.push.apply(keys, symbols);
112
+ }
113
+ return keys;
114
+ }
115
+ function _object_spread_props(target, source) {
116
+ source = source != null ? source : {};
117
+ if (Object.getOwnPropertyDescriptors) {
118
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
119
+ } else {
120
+ ownKeys(Object(source)).forEach(function(key) {
121
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
122
+ });
123
+ }
124
+ return target;
125
+ }
75
126
  function _object_without_properties(source, excluded) {
76
127
  if (source == null) return {};
77
128
  var target = _object_without_properties_loose(source, excluded);
@@ -111,13 +162,21 @@ var SessionImpl = /*#__PURE__*/ function() {
111
162
  this.store = new _processStorets.ProcessStore(options);
112
163
  var _options_interactive;
113
164
  this.isInteractive = (_options_interactive = options.interactive) !== null && _options_interactive !== void 0 ? _options_interactive : false;
114
- // Render Ink app immediately
115
- this.inkApp = (0, _ink.render)(/*#__PURE__*/ (0, _jsxruntime.jsx)(_Appts.default, {
116
- store: this.store
117
- }), {
118
- incrementalRendering: true,
119
- maxFps: _constantsts.DEFAULT_MAX_FPS
120
- });
165
+ // Use a very wide buffer to prevent line wrapping in xterm
166
+ // Actual display truncation is handled by Ink components
167
+ this.terminalWidth = 10000;
168
+ // Only render Ink when stdout is a real terminal
169
+ // When piped (e.g., nested spawn-term), skip Ink to avoid cursor positioning artifacts
170
+ if (process.stdout.isTTY) {
171
+ // Note: incrementalRendering disabled to prevent corruption when content shifts vertically
172
+ // (e.g., error footer appearing, processes completing, scroll position changes)
173
+ this.inkApp = (0, _ink.render)(/*#__PURE__*/ (0, _jsxruntime.jsx)(_Appts.default, {
174
+ store: this.store
175
+ }), {
176
+ incrementalRendering: false,
177
+ maxFps: _constantsts.DEFAULT_MAX_FPS
178
+ });
179
+ }
121
180
  }
122
181
  var _proto = SessionImpl.prototype;
123
182
  _proto.spawn = function spawn(command, args, spawnOptions, options, callback) {
@@ -130,8 +189,28 @@ var SessionImpl = /*#__PURE__*/ function() {
130
189
  "stdio"
131
190
  ]);
132
191
  if (stdio === 'inherit') {
192
+ // When Ink is not rendering (stdout not a TTY), pass output directly to stdout
193
+ if (!this.inkApp) {
194
+ var cp = (0, _crossspawncb.crossSpawn)(command, args, _object_spread_props(_object_spread({}, csOptions), {
195
+ stdio: 'inherit'
196
+ }));
197
+ _crossspawncb.default.worker(cp, csOptions, function(err) {
198
+ var res = err ? err : {};
199
+ res.stdout = null;
200
+ res.stderr = null;
201
+ res.output = [
202
+ null,
203
+ null,
204
+ null
205
+ ];
206
+ err ? callback(err) : callback(null, res);
207
+ });
208
+ return;
209
+ }
133
210
  this.runningCount++;
134
211
  var id = _crypto.default.randomUUID();
212
+ // Create terminal buffer for ANSI sequence interpretation
213
+ var terminalBuffer = new _TerminalBufferts.TerminalBuffer(this.terminalWidth);
135
214
  this.store.addProcess({
136
215
  id: id,
137
216
  title: [
@@ -139,55 +218,49 @@ var SessionImpl = /*#__PURE__*/ function() {
139
218
  ].concat((0, _formatArgumentsts.default)(args)).join(' '),
140
219
  state: 'running',
141
220
  lines: [],
221
+ terminalBuffer: terminalBuffer,
142
222
  group: options.group,
143
223
  expanded: options.expanded
144
224
  });
145
- var cp = (0, _crossspawncb.crossSpawn)(command, args, csOptions);
146
- var outputs = {
147
- stdout: null,
148
- stderr: null
149
- };
150
- var queue = new _queuecb.default();
151
- if (cp.stdout) {
152
- outputs.stdout = (0, _addLinests.default)(function(lines) {
153
- _this.store.appendLines(id, lines.map(function(text) {
154
- return {
155
- type: _typests.LineType.stdout,
156
- text: text
157
- };
158
- }));
225
+ var cp1 = (0, _crossspawncb.crossSpawn)(command, args, csOptions);
226
+ // Pipe stdout and stderr directly to terminal buffer
227
+ // Both streams go to the same buffer to maintain correct ordering
228
+ if (cp1.stdout) {
229
+ cp1.stdout.on('data', function(chunk) {
230
+ terminalBuffer.write(chunk);
231
+ _this.store.notify();
159
232
  });
160
- queue.defer(_onone.default.bind(null, cp.stdout.pipe(outputs.stdout), [
233
+ }
234
+ if (cp1.stderr) {
235
+ cp1.stderr.on('data', function(chunk) {
236
+ terminalBuffer.write(chunk);
237
+ _this.store.notify();
238
+ });
239
+ }
240
+ // Wait for process to complete
241
+ var queue = new _queuecb.default();
242
+ if (cp1.stdout) {
243
+ queue.defer(_onone.default.bind(null, cp1.stdout, [
161
244
  'error',
162
245
  'end',
163
- 'close',
164
- 'finish'
246
+ 'close'
165
247
  ]));
166
248
  }
167
- if (cp.stderr) {
168
- outputs.stderr = (0, _addLinests.default)(function(lines) {
169
- _this.store.appendLines(id, lines.map(function(text) {
170
- return {
171
- type: _typests.LineType.stderr,
172
- text: text
173
- };
174
- }));
175
- });
176
- queue.defer(_onone.default.bind(null, cp.stderr.pipe(outputs.stderr), [
249
+ if (cp1.stderr) {
250
+ queue.defer(_onone.default.bind(null, cp1.stderr, [
177
251
  'error',
178
252
  'end',
179
- 'close',
180
- 'finish'
253
+ 'close'
181
254
  ]));
182
255
  }
183
- queue.defer(_crossspawncb.default.worker.bind(null, cp, csOptions));
256
+ queue.defer(_crossspawncb.default.worker.bind(null, cp1, csOptions));
184
257
  queue.await(function(err) {
185
258
  var res = err ? err : {};
186
- res.stdout = outputs.stdout ? outputs.stdout.output : null;
187
- res.stderr = outputs.stderr ? outputs.stderr.output : null;
259
+ res.stdout = null; // Not collecting raw output in inherit mode
260
+ res.stderr = null;
188
261
  res.output = [
189
- res.stdout,
190
- res.stderr,
262
+ null,
263
+ null,
191
264
  null
192
265
  ];
193
266
  _this.store.updateProcess(id, {
@@ -198,39 +271,39 @@ var SessionImpl = /*#__PURE__*/ function() {
198
271
  });
199
272
  } else {
200
273
  // Non-inherit mode: collect output but don't display in UI
201
- var cp1 = (0, _crossspawncb.crossSpawn)(command, args, csOptions);
202
- var outputs1 = {
274
+ var cp2 = (0, _crossspawncb.crossSpawn)(command, args, csOptions);
275
+ var outputs = {
203
276
  stdout: null,
204
277
  stderr: null
205
278
  };
206
279
  var queue1 = new _queuecb.default();
207
- if (cp1.stdout) {
208
- outputs1.stdout = (0, _concatWritablets.default)(function(output) {
209
- outputs1.stdout.output = output.toString(encoding || 'utf8');
280
+ if (cp2.stdout) {
281
+ outputs.stdout = (0, _concatWritablets.default)(function(output) {
282
+ outputs.stdout.output = output.toString(encoding || 'utf8');
210
283
  });
211
- queue1.defer(_onone.default.bind(null, cp1.stdout.pipe(outputs1.stdout), [
284
+ queue1.defer(_onone.default.bind(null, cp2.stdout.pipe(outputs.stdout), [
212
285
  'error',
213
286
  'end',
214
287
  'close',
215
288
  'finish'
216
289
  ]));
217
290
  }
218
- if (cp1.stderr) {
219
- outputs1.stderr = (0, _concatWritablets.default)(function(output) {
220
- outputs1.stderr.output = output.toString(encoding || 'utf8');
291
+ if (cp2.stderr) {
292
+ outputs.stderr = (0, _concatWritablets.default)(function(output) {
293
+ outputs.stderr.output = output.toString(encoding || 'utf8');
221
294
  });
222
- queue1.defer(_onone.default.bind(null, cp1.stderr.pipe(outputs1.stderr), [
295
+ queue1.defer(_onone.default.bind(null, cp2.stderr.pipe(outputs.stderr), [
223
296
  'error',
224
297
  'end',
225
298
  'close',
226
299
  'finish'
227
300
  ]));
228
301
  }
229
- queue1.defer(_crossspawncb.default.worker.bind(null, cp1, csOptions));
302
+ queue1.defer(_crossspawncb.default.worker.bind(null, cp2, csOptions));
230
303
  queue1.await(function(err) {
231
304
  var res = err ? err : {};
232
- res.stdout = outputs1.stdout ? outputs1.stdout.output : null;
233
- res.stderr = outputs1.stderr ? outputs1.stderr.output : null;
305
+ res.stdout = outputs.stdout ? outputs.stdout.output : null;
306
+ res.stderr = outputs.stderr ? outputs.stderr.output : null;
234
307
  res.output = [
235
308
  res.stdout,
236
309
  res.stderr,
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/session.tsx"],"sourcesContent":["import spawn, { crossSpawn, type SpawnResult } from 'cross-spawn-cb';\nimport crypto from 'crypto';\nimport { render } from 'ink';\nimport oo from 'on-one';\nimport Queue from 'queue-cb';\n\nimport App from './components/App.ts';\nimport { DEFAULT_MAX_FPS } from './constants.ts';\nimport addLines from './lib/addLines.ts';\nimport concatWritable from './lib/concatWritable.ts';\nimport formatArguments from './lib/formatArguments.ts';\nimport { ProcessStore } from './state/processStore.ts';\nimport type { ProcessOptions, SessionOptions, SpawnError, SpawnOptions, TerminalCallback } from './types.ts';\nimport { LineType } from './types.ts';\n\nexport interface Session {\n spawn(command: string, args: string[], spawnOptions: SpawnOptions, options: ProcessOptions, callback: TerminalCallback): void;\n close(): void;\n waitAndClose(callback?: () => void): void;\n}\n\nclass SessionImpl implements Session {\n private store: ProcessStore;\n private inkApp: ReturnType<typeof render> | null = null;\n private runningCount = 0;\n private closed = false;\n private waitCallbacks: (() => void)[] = [];\n private isInteractive: boolean;\n\n constructor(options: SessionOptions = {}) {\n this.store = new ProcessStore(options);\n this.isInteractive = options.interactive ?? false;\n\n // Render Ink app immediately\n this.inkApp = render(<App store={this.store} />, {\n incrementalRendering: true,\n maxFps: DEFAULT_MAX_FPS,\n });\n }\n\n spawn(command: string, args: string[], spawnOptions: SpawnOptions, options: ProcessOptions, callback: TerminalCallback): void {\n if (this.closed) {\n throw new Error('Session is closed');\n }\n\n const { encoding, stdio, ...csOptions } = spawnOptions;\n\n if (stdio === 'inherit') {\n this.runningCount++;\n const id = crypto.randomUUID();\n this.store.addProcess({\n id,\n title: [command].concat(formatArguments(args)).join(' '),\n state: 'running',\n lines: [],\n group: options.group,\n expanded: options.expanded,\n });\n\n const cp = crossSpawn(command, args, csOptions);\n const outputs = { stdout: null as ReturnType<typeof addLines> | null, stderr: null as ReturnType<typeof addLines> | null };\n\n const queue = new Queue();\n if (cp.stdout) {\n outputs.stdout = addLines((lines) => {\n this.store.appendLines(\n id,\n lines.map((text) => ({ type: LineType.stdout, text }))\n );\n });\n queue.defer(oo.bind(null, cp.stdout.pipe(outputs.stdout), ['error', 'end', 'close', 'finish']));\n }\n if (cp.stderr) {\n outputs.stderr = addLines((lines) => {\n this.store.appendLines(\n id,\n lines.map((text) => ({ type: LineType.stderr, text }))\n );\n });\n queue.defer(oo.bind(null, cp.stderr.pipe(outputs.stderr), ['error', 'end', 'close', 'finish']));\n }\n queue.defer(spawn.worker.bind(null, cp, csOptions));\n queue.await((err?: SpawnError) => {\n const res = (err ? err : {}) as SpawnResult;\n res.stdout = outputs.stdout ? (outputs.stdout as unknown as { output: string }).output : null;\n res.stderr = outputs.stderr ? (outputs.stderr as unknown as { output: string }).output : null;\n res.output = [res.stdout, res.stderr, null];\n this.store.updateProcess(id, { state: err ? 'error' : 'success' });\n\n this.onProcessComplete();\n err ? callback(err) : callback(null, res);\n });\n } else {\n // Non-inherit mode: collect output but don't display in UI\n const cp = crossSpawn(command, args, csOptions);\n const outputs = { stdout: null as ReturnType<typeof concatWritable> | null, stderr: null as ReturnType<typeof concatWritable> | null };\n\n const queue = new Queue();\n if (cp.stdout) {\n outputs.stdout = concatWritable((output) => {\n (outputs.stdout as unknown as { output: string }).output = output.toString(encoding || 'utf8');\n });\n queue.defer(oo.bind(null, cp.stdout.pipe(outputs.stdout), ['error', 'end', 'close', 'finish']));\n }\n if (cp.stderr) {\n outputs.stderr = concatWritable((output) => {\n (outputs.stderr as unknown as { output: string }).output = output.toString(encoding || 'utf8');\n });\n queue.defer(oo.bind(null, cp.stderr.pipe(outputs.stderr), ['error', 'end', 'close', 'finish']));\n }\n queue.defer(spawn.worker.bind(null, cp, csOptions));\n queue.await((err?: SpawnError) => {\n const res = (err ? err : {}) as SpawnResult;\n res.stdout = outputs.stdout ? (outputs.stdout as unknown as { output: string }).output : null;\n res.stderr = outputs.stderr ? (outputs.stderr as unknown as { output: string }).output : null;\n res.output = [res.stdout, res.stderr, null];\n err ? callback(err) : callback(null, res);\n });\n }\n }\n\n close(): void {\n if (this.closed) return;\n this.closed = true;\n this.cleanup();\n }\n\n waitAndClose(callback?: () => void): void {\n if (this.closed) {\n callback?.();\n return;\n }\n\n if (callback) this.waitCallbacks.push(callback);\n\n if (this.runningCount === 0) {\n if (this.isInteractive) {\n // In interactive mode, wait for user to quit (press 'q')\n const unsubscribe = this.store.subscribe(() => {\n if (this.store.getShouldExit()) {\n unsubscribe();\n this.closeAndCallWaitCallbacks();\n }\n });\n } else {\n this.closeAndCallWaitCallbacks();\n }\n }\n // If runningCount > 0, will close when it hits 0 in onProcessComplete\n }\n\n private onProcessComplete(): void {\n this.runningCount--;\n if (this.runningCount === 0 && this.waitCallbacks.length > 0) {\n if (this.isInteractive) {\n // In interactive mode, wait for user to quit (press 'q')\n const unsubscribe = this.store.subscribe(() => {\n if (this.store.getShouldExit()) {\n unsubscribe();\n this.closeAndCallWaitCallbacks();\n }\n });\n } else {\n this.closeAndCallWaitCallbacks();\n }\n }\n }\n\n private closeAndCallWaitCallbacks(): void {\n if (this.closed) return;\n this.closed = true;\n this.cleanup(() => {\n for (const cb of this.waitCallbacks) cb();\n this.waitCallbacks = [];\n });\n }\n\n private cleanup(onComplete?: () => void): void {\n // Signal exit to React component\n this.store.signalExit(() => {\n this.store.reset();\n process.stdout.write('\\x1b[?25h'); // show cursor\n });\n\n // Wait for Ink to finish\n if (this.inkApp) {\n this.inkApp\n .waitUntilExit()\n .then(() => {\n const cb = this.store.getExitCallback();\n cb?.();\n onComplete?.();\n })\n .catch(() => {\n const cb = this.store.getExitCallback();\n cb?.();\n onComplete?.();\n });\n this.inkApp = null;\n } else {\n onComplete?.();\n }\n }\n}\n\nexport function createSession(options: SessionOptions = {}): Session {\n return new SessionImpl(options);\n}\n"],"names":["createSession","SessionImpl","options","inkApp","runningCount","closed","waitCallbacks","store","ProcessStore","isInteractive","interactive","render","App","incrementalRendering","maxFps","DEFAULT_MAX_FPS","spawn","command","args","spawnOptions","callback","Error","encoding","stdio","csOptions","id","crypto","randomUUID","addProcess","title","concat","formatArguments","join","state","lines","group","expanded","cp","crossSpawn","outputs","stdout","stderr","queue","Queue","addLines","appendLines","map","text","type","LineType","defer","oo","bind","pipe","worker","await","err","res","output","updateProcess","onProcessComplete","concatWritable","toString","close","cleanup","waitAndClose","push","unsubscribe","subscribe","getShouldExit","closeAndCallWaitCallbacks","length","cb","onComplete","signalExit","reset","process","write","waitUntilExit","then","getExitCallback","catch"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/session.tsx"],"sourcesContent":["import spawn, { crossSpawn, type SpawnResult } from 'cross-spawn-cb';\nimport crypto from 'crypto';\nimport { render } from 'ink';\nimport oo from 'on-one';\nimport Queue from 'queue-cb';\n\nimport App from './components/App.ts';\nimport { DEFAULT_MAX_FPS } from './constants.ts';\nimport concatWritable from './lib/concatWritable.ts';\nimport formatArguments from './lib/formatArguments.ts';\nimport { TerminalBuffer } from './lib/TerminalBuffer.ts';\nimport { ProcessStore } from './state/processStore.ts';\nimport type { ProcessOptions, SessionOptions, SpawnError, SpawnOptions, TerminalCallback } from './types.ts';\n\nexport interface Session {\n spawn(command: string, args: string[], spawnOptions: SpawnOptions, options: ProcessOptions, callback: TerminalCallback): void;\n close(): void;\n waitAndClose(callback?: () => void): void;\n}\n\nclass SessionImpl implements Session {\n private store: ProcessStore;\n private inkApp: ReturnType<typeof render> | null = null;\n private runningCount = 0;\n private closed = false;\n private waitCallbacks: (() => void)[] = [];\n private isInteractive: boolean;\n private terminalWidth: number;\n\n constructor(options: SessionOptions = {}) {\n this.store = new ProcessStore(options);\n this.isInteractive = options.interactive ?? false;\n // Use a very wide buffer to prevent line wrapping in xterm\n // Actual display truncation is handled by Ink components\n this.terminalWidth = 10000;\n\n // Only render Ink when stdout is a real terminal\n // When piped (e.g., nested spawn-term), skip Ink to avoid cursor positioning artifacts\n if (process.stdout.isTTY) {\n // Note: incrementalRendering disabled to prevent corruption when content shifts vertically\n // (e.g., error footer appearing, processes completing, scroll position changes)\n this.inkApp = render(<App store={this.store} />, {\n incrementalRendering: false,\n maxFps: DEFAULT_MAX_FPS,\n });\n }\n }\n\n spawn(command: string, args: string[], spawnOptions: SpawnOptions, options: ProcessOptions, callback: TerminalCallback): void {\n if (this.closed) {\n throw new Error('Session is closed');\n }\n\n const { encoding, stdio, ...csOptions } = spawnOptions;\n\n if (stdio === 'inherit') {\n // When Ink is not rendering (stdout not a TTY), pass output directly to stdout\n if (!this.inkApp) {\n const cp = crossSpawn(command, args, { ...csOptions, stdio: 'inherit' });\n spawn.worker(cp, csOptions, (err?: SpawnError) => {\n const res = (err ? err : {}) as SpawnResult;\n res.stdout = null;\n res.stderr = null;\n res.output = [null, null, null];\n err ? callback(err) : callback(null, res);\n });\n return;\n }\n\n this.runningCount++;\n const id = crypto.randomUUID();\n\n // Create terminal buffer for ANSI sequence interpretation\n const terminalBuffer = new TerminalBuffer(this.terminalWidth);\n\n this.store.addProcess({\n id,\n title: [command].concat(formatArguments(args)).join(' '),\n state: 'running',\n lines: [],\n terminalBuffer,\n group: options.group,\n expanded: options.expanded,\n });\n\n const cp = crossSpawn(command, args, csOptions);\n\n // Pipe stdout and stderr directly to terminal buffer\n // Both streams go to the same buffer to maintain correct ordering\n if (cp.stdout) {\n cp.stdout.on('data', (chunk: Buffer) => {\n terminalBuffer.write(chunk);\n this.store.notify();\n });\n }\n if (cp.stderr) {\n cp.stderr.on('data', (chunk: Buffer) => {\n terminalBuffer.write(chunk);\n this.store.notify();\n });\n }\n\n // Wait for process to complete\n const queue = new Queue();\n if (cp.stdout) {\n queue.defer(oo.bind(null, cp.stdout, ['error', 'end', 'close']));\n }\n if (cp.stderr) {\n queue.defer(oo.bind(null, cp.stderr, ['error', 'end', 'close']));\n }\n queue.defer(spawn.worker.bind(null, cp, csOptions));\n queue.await((err?: SpawnError) => {\n const res = (err ? err : {}) as SpawnResult;\n res.stdout = null; // Not collecting raw output in inherit mode\n res.stderr = null;\n res.output = [null, null, null];\n this.store.updateProcess(id, { state: err ? 'error' : 'success' });\n\n this.onProcessComplete();\n err ? callback(err) : callback(null, res);\n });\n } else {\n // Non-inherit mode: collect output but don't display in UI\n const cp = crossSpawn(command, args, csOptions);\n const outputs = { stdout: null as ReturnType<typeof concatWritable> | null, stderr: null as ReturnType<typeof concatWritable> | null };\n\n const queue = new Queue();\n if (cp.stdout) {\n outputs.stdout = concatWritable((output) => {\n (outputs.stdout as unknown as { output: string }).output = output.toString(encoding || 'utf8');\n });\n queue.defer(oo.bind(null, cp.stdout.pipe(outputs.stdout), ['error', 'end', 'close', 'finish']));\n }\n if (cp.stderr) {\n outputs.stderr = concatWritable((output) => {\n (outputs.stderr as unknown as { output: string }).output = output.toString(encoding || 'utf8');\n });\n queue.defer(oo.bind(null, cp.stderr.pipe(outputs.stderr), ['error', 'end', 'close', 'finish']));\n }\n queue.defer(spawn.worker.bind(null, cp, csOptions));\n queue.await((err?: SpawnError) => {\n const res = (err ? err : {}) as SpawnResult;\n res.stdout = outputs.stdout ? (outputs.stdout as unknown as { output: string }).output : null;\n res.stderr = outputs.stderr ? (outputs.stderr as unknown as { output: string }).output : null;\n res.output = [res.stdout, res.stderr, null];\n err ? callback(err) : callback(null, res);\n });\n }\n }\n\n close(): void {\n if (this.closed) return;\n this.closed = true;\n this.cleanup();\n }\n\n waitAndClose(callback?: () => void): void {\n if (this.closed) {\n callback?.();\n return;\n }\n\n if (callback) this.waitCallbacks.push(callback);\n\n if (this.runningCount === 0) {\n if (this.isInteractive) {\n // In interactive mode, wait for user to quit (press 'q')\n const unsubscribe = this.store.subscribe(() => {\n if (this.store.getShouldExit()) {\n unsubscribe();\n this.closeAndCallWaitCallbacks();\n }\n });\n } else {\n this.closeAndCallWaitCallbacks();\n }\n }\n // If runningCount > 0, will close when it hits 0 in onProcessComplete\n }\n\n private onProcessComplete(): void {\n this.runningCount--;\n if (this.runningCount === 0 && this.waitCallbacks.length > 0) {\n if (this.isInteractive) {\n // In interactive mode, wait for user to quit (press 'q')\n const unsubscribe = this.store.subscribe(() => {\n if (this.store.getShouldExit()) {\n unsubscribe();\n this.closeAndCallWaitCallbacks();\n }\n });\n } else {\n this.closeAndCallWaitCallbacks();\n }\n }\n }\n\n private closeAndCallWaitCallbacks(): void {\n if (this.closed) return;\n this.closed = true;\n this.cleanup(() => {\n for (const cb of this.waitCallbacks) cb();\n this.waitCallbacks = [];\n });\n }\n\n private cleanup(onComplete?: () => void): void {\n // Signal exit to React component\n this.store.signalExit(() => {\n this.store.reset();\n process.stdout.write('\\x1b[?25h'); // show cursor\n });\n\n // Wait for Ink to finish\n if (this.inkApp) {\n this.inkApp\n .waitUntilExit()\n .then(() => {\n const cb = this.store.getExitCallback();\n cb?.();\n onComplete?.();\n })\n .catch(() => {\n const cb = this.store.getExitCallback();\n cb?.();\n onComplete?.();\n });\n this.inkApp = null;\n } else {\n onComplete?.();\n }\n }\n}\n\nexport function createSession(options: SessionOptions = {}): Session {\n return new SessionImpl(options);\n}\n"],"names":["createSession","SessionImpl","options","inkApp","runningCount","closed","waitCallbacks","store","ProcessStore","isInteractive","interactive","terminalWidth","process","stdout","isTTY","render","App","incrementalRendering","maxFps","DEFAULT_MAX_FPS","spawn","command","args","spawnOptions","callback","Error","encoding","stdio","csOptions","cp","crossSpawn","worker","err","res","stderr","output","id","crypto","randomUUID","terminalBuffer","TerminalBuffer","addProcess","title","concat","formatArguments","join","state","lines","group","expanded","on","chunk","write","notify","queue","Queue","defer","oo","bind","await","updateProcess","onProcessComplete","outputs","concatWritable","toString","pipe","close","cleanup","waitAndClose","push","unsubscribe","subscribe","getShouldExit","closeAndCallWaitCallbacks","length","cb","onComplete","signalExit","reset","waitUntilExit","then","getExitCallback","catch"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { Line } from '../types.js';
2
+ type ErrorGroup = {
3
+ processName: string;
4
+ lines: Line[];
5
+ };
6
+ type Props = {
7
+ errors: ErrorGroup[];
8
+ isExpanded: boolean;
9
+ };
10
+ declare const _default: import("react").NamedExoticComponent<Props>;
11
+ export default _default;
@@ -1,5 +1,6 @@
1
1
  export { default as figures } from './lib/figures.js';
2
2
  export { default as formatArguments } from './lib/formatArguments.js';
3
+ export { TerminalBuffer } from './lib/TerminalBuffer.js';
3
4
  export * from './types.js';
4
5
  import type { createSession as createSessionType, Session } from './createSessionWrapper.js';
5
6
  export type { Session };
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Wrapper around @xterm/headless Terminal that provides a virtual terminal buffer.
3
+ * Interprets ANSI escape sequences (cursor movement, line clearing, etc.) to produce
4
+ * the actual rendered output rather than raw intermediate states.
5
+ */
6
+ export declare class TerminalBuffer {
7
+ private terminal;
8
+ constructor(cols: number, scrollback?: number);
9
+ /**
10
+ * Write raw data to the terminal buffer.
11
+ * The terminal interprets all ANSI sequences automatically.
12
+ */
13
+ write(data: string | Buffer): void;
14
+ /**
15
+ * Resize the terminal width.
16
+ */
17
+ resize(cols: number): void;
18
+ /**
19
+ * Extract the rendered lines from the terminal buffer.
20
+ * This returns the actual visible content after all ANSI sequences
21
+ * have been processed.
22
+ */
23
+ getLines(): string[];
24
+ /**
25
+ * Get the number of rendered lines.
26
+ */
27
+ get lineCount(): number;
28
+ /**
29
+ * Clean up terminal resources.
30
+ */
31
+ dispose(): void;
32
+ }
@@ -1,6 +1,6 @@
1
1
  import type { ChildProcess, Line, SessionOptions } from '../types.js';
2
2
  type Listener = () => void;
3
- type Mode = 'normal' | 'interactive' | 'errorList' | 'errorDetail';
3
+ type Mode = 'normal' | 'interactive';
4
4
  export declare class ProcessStore {
5
5
  private processes;
6
6
  private completedIds;
@@ -9,10 +9,11 @@ export declare class ProcessStore {
9
9
  private exitCallback;
10
10
  private mode;
11
11
  private selectedIndex;
12
- private selectedErrorIndex;
13
12
  private expandedId;
14
13
  private scrollOffset;
15
14
  private listScrollOffset;
15
+ private errorFooterExpanded;
16
+ private bufferVersion;
16
17
  private header;
17
18
  private showStatusBar;
18
19
  private isInteractive;
@@ -29,10 +30,11 @@ export declare class ProcessStore {
29
30
  getErrorLineCount: () => number;
30
31
  getMode: () => Mode;
31
32
  getSelectedIndex: () => number;
32
- getSelectedErrorIndex: () => number;
33
33
  getExpandedId: () => string | null;
34
34
  getScrollOffset: () => number;
35
35
  getListScrollOffset: () => number;
36
+ getErrorFooterExpanded: () => boolean;
37
+ getBufferVersion: () => number;
36
38
  getHeader: () => string | undefined;
37
39
  getShowStatusBar: () => boolean;
38
40
  getIsInteractive: () => boolean;
@@ -41,14 +43,19 @@ export declare class ProcessStore {
41
43
  updateProcess(id: string, update: Partial<ChildProcess>): void;
42
44
  appendLines(id: string, newLines: Line[]): void;
43
45
  getProcess(id: string): ChildProcess | undefined;
46
+ getProcessLines(id: string): Line[];
47
+ getProcessLineCount(id: string): number;
44
48
  setMode(mode: Mode): void;
45
49
  selectNext(visibleCount?: number): void;
46
50
  selectPrev(visibleCount?: number): void;
47
51
  private adjustListScroll;
48
52
  getSelectedProcess(): ChildProcess | undefined;
49
- selectNextError(): void;
50
- selectPrevError(): void;
51
- getSelectedError(): ChildProcess | undefined;
53
+ toggleErrorFooter(): void;
54
+ expandErrorFooter(): void;
55
+ getErrorLines(): Array<{
56
+ processName: string;
57
+ lines: Line[];
58
+ }>;
52
59
  toggleExpand(): void;
53
60
  collapse(): void;
54
61
  scrollDown(maxVisible: number): void;
@@ -57,6 +64,6 @@ export declare class ProcessStore {
57
64
  getShouldExit: () => boolean;
58
65
  getExitCallback: () => (() => void) | null;
59
66
  reset(): void;
60
- private notify;
67
+ notify(): void;
61
68
  }
62
69
  export {};
@@ -19,11 +19,13 @@ export type Line = {
19
19
  text: string;
20
20
  };
21
21
  export type State = 'running' | 'error' | 'success';
22
+ import type { TerminalBuffer } from './lib/TerminalBuffer.js';
22
23
  export type ChildProcess = {
23
24
  id: string;
24
25
  group?: string;
25
26
  title: string;
26
27
  state: State;
27
28
  lines: Line[];
29
+ terminalBuffer?: TerminalBuffer;
28
30
  expanded?: boolean;
29
31
  };