agent-mp 0.3.6 → 0.3.7

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.
@@ -3,6 +3,9 @@ export declare class FixedInput {
3
3
  private history;
4
4
  private histIdx;
5
5
  private origLog;
6
+ private _pasting;
7
+ private _pasteAccum;
8
+ private _drawPending;
6
9
  private get rows();
7
10
  get cols(): number;
8
11
  private get scrollBottom();
@@ -14,6 +17,8 @@ export declare class FixedInput {
14
17
  readLine(): Promise<string>;
15
18
  println(text: string): void;
16
19
  printSeparator(): void;
20
+ /** Debounced draw: coalesces rapid calls (e.g. during paste) into a single repaint. */
21
+ private _scheduleDraw;
17
22
  /** Set DECSTBM once — only called in setup() and on resize, never during typing. */
18
23
  private _setScrollRegion;
19
24
  /** Blank every row in the reserved area. */
package/dist/ui/input.js CHANGED
@@ -20,6 +20,9 @@ export class FixedInput {
20
20
  history = [];
21
21
  histIdx = -1;
22
22
  origLog;
23
+ _pasting = false; // true while inside bracketed paste sequence
24
+ _pasteAccum = ''; // accumulates paste content between \x1b[200~ and \x1b[201~
25
+ _drawPending = false; // debounce flag
23
26
  get rows() { return process.stdout.rows || 24; }
24
27
  get cols() { return process.stdout.columns || 80; }
25
28
  // The scroll region always ends here — everything below is reserved for the box.
@@ -47,6 +50,7 @@ export class FixedInput {
47
50
  process.stdout.write(`\x1b[${this.scrollBottom};1H`);
48
51
  this._clearReserved();
49
52
  this._drawBox();
53
+ process.stdout.write('\x1b[?2004h'); // enable bracketed paste mode
50
54
  process.stdout.on('resize', () => {
51
55
  this._setScrollRegion();
52
56
  this._clearReserved();
@@ -55,6 +59,7 @@ export class FixedInput {
55
59
  }
56
60
  teardown() {
57
61
  console.log = this.origLog;
62
+ process.stdout.write('\x1b[?2004l'); // disable bracketed paste mode
58
63
  process.stdout.write('\x1b[r'); // reset scroll region
59
64
  process.stdout.write('\x1b[?25h'); // show cursor
60
65
  process.stdout.write(`\x1b[${this.rows};1H\n`);
@@ -62,6 +67,7 @@ export class FixedInput {
62
67
  redrawBox() { this._drawBox(); }
63
68
  suspend() {
64
69
  console.log = this.origLog;
70
+ process.stdout.write('\x1b[?2004l'); // disable bracketed paste while suspended
65
71
  process.stdout.write('\x1b[r');
66
72
  this._clearReserved();
67
73
  process.stdout.write(`\x1b[${this.scrollBottom};1H`);
@@ -73,6 +79,7 @@ export class FixedInput {
73
79
  this._setScrollRegion();
74
80
  this._clearReserved();
75
81
  this._drawBox();
82
+ process.stdout.write('\x1b[?2004h'); // re-enable bracketed paste mode
76
83
  };
77
84
  }
78
85
  // ── Input ──────────────────────────────────────────────────────────────────
@@ -94,6 +101,32 @@ export class FixedInput {
94
101
  const onData = (data) => {
95
102
  const hex = data.toString('hex');
96
103
  const key = data.toString();
104
+ // ── Bracketed paste: start ────────────────────────────────────
105
+ if (key.includes('\x1b[200~')) {
106
+ this._pasting = true;
107
+ this._pasteAccum = '';
108
+ // Strip the start marker and handle any content after it in the same chunk
109
+ const after = key.slice(key.indexOf('\x1b[200~') + 6);
110
+ if (after)
111
+ this._pasteAccum += after;
112
+ return;
113
+ }
114
+ // ── Bracketed paste: accumulate ───────────────────────────────
115
+ if (this._pasting) {
116
+ if (key.includes('\x1b[201~')) {
117
+ // End marker — append everything before it, then commit
118
+ const before = key.slice(0, key.indexOf('\x1b[201~'));
119
+ this._pasteAccum += before;
120
+ this.buf += this._pasteAccum;
121
+ this._pasting = false;
122
+ this._pasteAccum = '';
123
+ this._scheduleDraw();
124
+ }
125
+ else {
126
+ this._pasteAccum += key;
127
+ }
128
+ return;
129
+ }
97
130
  // ── Shift+Enter → insert newline into buffer ──────────────────
98
131
  // Different terminals send different sequences:
99
132
  if (hex === '5c0d' || // \\\r (GNOME Terminal, ThinkPad, many Linux)
@@ -103,7 +136,7 @@ export class FixedInput {
103
136
  hex === '1b4f4d' // \x1bOM DECNKP
104
137
  ) {
105
138
  this.buf += '\n';
106
- this._drawBox();
139
+ this._scheduleDraw();
107
140
  // ── Enter → submit ────────────────────────────────────────────
108
141
  }
109
142
  else if (key === '\r') {
@@ -118,7 +151,7 @@ export class FixedInput {
118
151
  else if (key === '\x7f' || key === '\x08') { // Backspace
119
152
  if (this.buf.length > 0) {
120
153
  this.buf = this.buf.slice(0, -1);
121
- this._drawBox();
154
+ this._scheduleDraw();
122
155
  }
123
156
  }
124
157
  else if (key === '\x03') { // Ctrl+C
@@ -130,13 +163,13 @@ export class FixedInput {
130
163
  }
131
164
  else if (key === '\x15') { // Ctrl+U
132
165
  this.buf = '';
133
- this._drawBox();
166
+ this._scheduleDraw();
134
167
  }
135
168
  else if (hex === '1b5b41') { // Arrow ↑
136
169
  if (this.histIdx + 1 < this.history.length) {
137
170
  this.histIdx++;
138
171
  this.buf = this.history[this.histIdx];
139
- this._drawBox();
172
+ this._scheduleDraw();
140
173
  }
141
174
  }
142
175
  else if (hex === '1b5b42') { // Arrow ↓
@@ -148,11 +181,11 @@ export class FixedInput {
148
181
  this.histIdx = -1;
149
182
  this.buf = '';
150
183
  }
151
- this._drawBox();
184
+ this._scheduleDraw();
152
185
  }
153
186
  else if (key.length >= 1 && key.charCodeAt(0) >= 32 && !key.startsWith('\x1b')) {
154
187
  this.buf += key;
155
- this._drawBox();
188
+ this._scheduleDraw();
156
189
  }
157
190
  };
158
191
  process.stdin.on('data', onData);
@@ -168,6 +201,16 @@ export class FixedInput {
168
201
  this.println(chalk.rgb(0, 120, 116)('─'.repeat(this.cols - 1)));
169
202
  }
170
203
  // ── Private drawing ────────────────────────────────────────────────────────
204
+ /** Debounced draw: coalesces rapid calls (e.g. during paste) into a single repaint. */
205
+ _scheduleDraw() {
206
+ if (this._drawPending)
207
+ return;
208
+ this._drawPending = true;
209
+ setImmediate(() => {
210
+ this._drawPending = false;
211
+ this._drawBox();
212
+ });
213
+ }
171
214
  /** Set DECSTBM once — only called in setup() and on resize, never during typing. */
172
215
  _setScrollRegion() {
173
216
  const sb = this.scrollBottom;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-mp",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "description": "Deterministic multi-agent CLI orchestrator — plan, code, review",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",