erosolar-cli 1.7.161 → 1.7.164

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 (53) hide show
  1. package/dist/contracts/unified-schema.json +6 -6
  2. package/dist/core/unified/tools.d.ts.map +1 -1
  3. package/dist/core/unified/tools.js +12 -34
  4. package/dist/core/unified/tools.js.map +1 -1
  5. package/dist/security/tool-security-wrapper.js +3 -3
  6. package/dist/security/tool-security-wrapper.js.map +1 -1
  7. package/dist/shell/claudeCodeStreamHandler.d.ts +145 -0
  8. package/dist/shell/claudeCodeStreamHandler.d.ts.map +1 -0
  9. package/dist/shell/claudeCodeStreamHandler.js +312 -0
  10. package/dist/shell/claudeCodeStreamHandler.js.map +1 -0
  11. package/dist/shell/inputQueueManager.d.ts +144 -0
  12. package/dist/shell/inputQueueManager.d.ts.map +1 -0
  13. package/dist/shell/inputQueueManager.js +290 -0
  14. package/dist/shell/inputQueueManager.js.map +1 -0
  15. package/dist/shell/interactiveShell.d.ts +21 -0
  16. package/dist/shell/interactiveShell.d.ts.map +1 -1
  17. package/dist/shell/interactiveShell.js +140 -51
  18. package/dist/shell/interactiveShell.js.map +1 -1
  19. package/dist/shell/streamingOutputManager.d.ts +88 -0
  20. package/dist/shell/streamingOutputManager.d.ts.map +1 -0
  21. package/dist/shell/streamingOutputManager.js +155 -0
  22. package/dist/shell/streamingOutputManager.js.map +1 -0
  23. package/dist/shell/systemPrompt.js +2 -2
  24. package/dist/shell/systemPrompt.js.map +1 -1
  25. package/dist/shell/taskCompletionDetector.d.ts.map +1 -1
  26. package/dist/shell/taskCompletionDetector.js +1 -3
  27. package/dist/shell/taskCompletionDetector.js.map +1 -1
  28. package/dist/shell/unifiedChatBox.d.ts +178 -0
  29. package/dist/shell/unifiedChatBox.d.ts.map +1 -0
  30. package/dist/shell/unifiedChatBox.js +539 -0
  31. package/dist/shell/unifiedChatBox.js.map +1 -0
  32. package/dist/tools/diffUtils.d.ts +1 -1
  33. package/dist/tools/diffUtils.d.ts.map +1 -1
  34. package/dist/tools/diffUtils.js +19 -3
  35. package/dist/tools/diffUtils.js.map +1 -1
  36. package/dist/tools/editTools.d.ts +11 -0
  37. package/dist/tools/editTools.d.ts.map +1 -1
  38. package/dist/tools/editTools.js +141 -98
  39. package/dist/tools/editTools.js.map +1 -1
  40. package/dist/tools/fileTools.d.ts.map +1 -1
  41. package/dist/tools/fileTools.js +2 -126
  42. package/dist/tools/fileTools.js.map +1 -1
  43. package/dist/tools/softwareEngineeringTools.d.ts +7 -0
  44. package/dist/tools/softwareEngineeringTools.d.ts.map +1 -0
  45. package/dist/tools/softwareEngineeringTools.js +338 -0
  46. package/dist/tools/softwareEngineeringTools.js.map +1 -0
  47. package/dist/ui/toolDisplay.d.ts.map +1 -1
  48. package/dist/ui/toolDisplay.js +1 -3
  49. package/dist/ui/toolDisplay.js.map +1 -1
  50. package/dist/ui/toolDisplayAdapter.d.ts.map +1 -1
  51. package/dist/ui/toolDisplayAdapter.js +0 -3
  52. package/dist/ui/toolDisplayAdapter.js.map +1 -1
  53. package/package.json +1 -1
@@ -0,0 +1,312 @@
1
+ /**
2
+ * ClaudeCodeStreamHandler - Complete streaming I/O handler following Claude Code's approach
3
+ *
4
+ * This module combines StreamingOutputManager and InputQueueManager to provide
5
+ * the complete Claude Code streaming experience:
6
+ *
7
+ * 1. Natural Output Flow
8
+ * - Streaming output just writes to stdout normally
9
+ * - Cursor stays where it is after each write
10
+ * - Lines scroll up naturally as new content appears
11
+ * - NO scroll regions, NO save/restore cursor during streaming
12
+ *
13
+ * 2. Readline Handles Input
14
+ * - Uses Node.js readline module
15
+ * - Input prompt naturally moves up as output streams above it
16
+ * - User can type while streaming - input is queued in memory, not rendered
17
+ *
18
+ * 3. Queue-Based Approach
19
+ * User types during streaming → Input stored in queue → Processed after streaming ends
20
+ *
21
+ * 4. The Key Insight
22
+ * The cursor is NEVER moved during streaming. Output just appends at current position.
23
+ * The "input at bottom" effect comes from:
24
+ * - New output pushes older content (including the prompt) upward
25
+ * - After streaming ends, a new prompt is shown at the bottom
26
+ */
27
+ import * as readline from 'node:readline';
28
+ import { EventEmitter } from 'node:events';
29
+ import { getStreamingOutputManager } from './streamingOutputManager.js';
30
+ import { getInputQueueManager } from './inputQueueManager.js';
31
+ /**
32
+ * Coordinates streaming output and queued input for Claude Code style UX.
33
+ */
34
+ export class ClaudeCodeStreamHandler extends EventEmitter {
35
+ outputManager;
36
+ inputManager;
37
+ writeStream;
38
+ readStream;
39
+ rl = null;
40
+ keypressHandler = null;
41
+ originalStdoutWrite = null;
42
+ isOutputSuppressed = false;
43
+ constructor(writeStream = process.stdout, readStream = process.stdin) {
44
+ super();
45
+ this.writeStream = writeStream;
46
+ this.readStream = readStream;
47
+ this.outputManager = getStreamingOutputManager();
48
+ this.inputManager = getInputQueueManager();
49
+ // Forward events
50
+ this.inputManager.on('input-queued', (input) => {
51
+ this.emit('input-queued', input);
52
+ });
53
+ }
54
+ /**
55
+ * Attach to an existing readline interface
56
+ * Call this after creating your readline.Interface
57
+ */
58
+ attachToReadline(rl) {
59
+ this.rl = rl;
60
+ this.setupKeypressCapture();
61
+ }
62
+ /**
63
+ * Set up keypress capturing for queued input during streaming
64
+ */
65
+ setupKeypressCapture() {
66
+ if (!this.readStream || !this.readStream.isTTY) {
67
+ return;
68
+ }
69
+ // Enable keypress events if not already enabled
70
+ if (this.readStream.listenerCount('keypress') === 0 && this.rl) {
71
+ readline.emitKeypressEvents(this.readStream, this.rl);
72
+ }
73
+ // Ensure raw mode for keypress events
74
+ if (this.readStream.setRawMode && !this.readStream.isRaw) {
75
+ this.readStream.setRawMode(true);
76
+ }
77
+ this.keypressHandler = (_str, key) => {
78
+ // Only capture when streaming
79
+ if (!this.outputManager.isStreaming() || !this.inputManager.isCapturing()) {
80
+ return;
81
+ }
82
+ // Handle special keys
83
+ if (key) {
84
+ // Ctrl+C - interrupt
85
+ if (key.ctrl && key.name === 'c') {
86
+ this.inputManager.handleInterrupt();
87
+ return;
88
+ }
89
+ // Enter - submit queued input
90
+ if (key.name === 'return' || key.name === 'enter') {
91
+ this.inputManager.handleSubmit();
92
+ return;
93
+ }
94
+ // Backspace
95
+ if (key.name === 'backspace') {
96
+ this.inputManager.handleBackspace();
97
+ return;
98
+ }
99
+ // Delete
100
+ if (key.name === 'delete') {
101
+ this.inputManager.handleDelete();
102
+ return;
103
+ }
104
+ // Arrow keys
105
+ if (key.name === 'left') {
106
+ this.inputManager.handleCursorLeft();
107
+ return;
108
+ }
109
+ if (key.name === 'right') {
110
+ this.inputManager.handleCursorRight();
111
+ return;
112
+ }
113
+ // Ignore other control sequences during capture
114
+ if (key.ctrl || key.meta) {
115
+ return;
116
+ }
117
+ }
118
+ // Regular character input
119
+ if (_str && _str.length > 0 && !key?.ctrl && !key?.meta) {
120
+ this.inputManager.handleChar(_str);
121
+ }
122
+ };
123
+ this.readStream.prependListener('keypress', this.keypressHandler);
124
+ }
125
+ /**
126
+ * Begin streaming mode
127
+ *
128
+ * Claude Code approach:
129
+ * - Start capturing input to queue
130
+ * - Suppress readline echo (characters typed go to queue, not screen)
131
+ * - Output flows naturally to stdout
132
+ */
133
+ startStreaming() {
134
+ if (this.outputManager.isStreaming()) {
135
+ return;
136
+ }
137
+ // Start both managers
138
+ this.outputManager.startStream();
139
+ this.inputManager.startCapturing();
140
+ // Suppress readline's output so typed characters don't appear
141
+ this.suppressReadlineOutput();
142
+ this.emit('streaming-start');
143
+ }
144
+ /**
145
+ * End streaming mode
146
+ *
147
+ * Claude Code approach:
148
+ * - Stop capturing (any remaining buffer is preserved)
149
+ * - Restore readline echo
150
+ * - Return streaming statistics
151
+ */
152
+ endStreaming() {
153
+ // Get remaining buffer before stopping capture
154
+ const remainingBuffer = this.inputManager.stopCapturing();
155
+ // If there's unsubmitted content in buffer, preserve it for next prompt
156
+ if (remainingBuffer && remainingBuffer.trim()) {
157
+ // The remaining buffer will be shown when readline prompts again
158
+ // We could queue it, but leaving it as-is is more intuitive
159
+ }
160
+ // Restore readline output
161
+ this.restoreReadlineOutput();
162
+ // End output streaming
163
+ const stats = this.outputManager.endStream();
164
+ const result = {
165
+ ...stats,
166
+ queuedInputs: this.inputManager.getQueueLength(),
167
+ };
168
+ this.emit('streaming-end', stats);
169
+ return result;
170
+ }
171
+ /**
172
+ * Write content during streaming
173
+ * Just writes naturally to stdout - no cursor manipulation
174
+ */
175
+ write(content) {
176
+ this.outputManager.writeChunk(content);
177
+ }
178
+ /**
179
+ * Write a complete line during streaming
180
+ */
181
+ writeLine(line = '') {
182
+ this.outputManager.writeLine(line);
183
+ }
184
+ /**
185
+ * Check if currently streaming
186
+ */
187
+ isStreaming() {
188
+ return this.outputManager.isStreaming();
189
+ }
190
+ /**
191
+ * Get current state
192
+ */
193
+ getState() {
194
+ const outputStats = this.outputManager.getStats();
195
+ return {
196
+ isStreaming: this.outputManager.isStreaming(),
197
+ queuedCount: this.inputManager.getQueueLength(),
198
+ charsWritten: outputStats.chars,
199
+ linesWritten: outputStats.lines,
200
+ elapsedMs: outputStats.elapsed,
201
+ };
202
+ }
203
+ /**
204
+ * Check if there are queued inputs to process
205
+ */
206
+ hasQueuedInput() {
207
+ return this.inputManager.hasQueuedInput();
208
+ }
209
+ /**
210
+ * Get the next queued input
211
+ */
212
+ getNextQueuedInput() {
213
+ return this.inputManager.dequeue();
214
+ }
215
+ /**
216
+ * Get all queued inputs
217
+ */
218
+ getAllQueuedInputs() {
219
+ return this.inputManager.getQueue();
220
+ }
221
+ /**
222
+ * Clear all queued inputs
223
+ */
224
+ clearQueue() {
225
+ this.inputManager.clearQueue();
226
+ }
227
+ /**
228
+ * Get queue summary for display
229
+ */
230
+ getQueueSummary() {
231
+ return this.inputManager.getQueueSummary();
232
+ }
233
+ /**
234
+ * Suppress readline's output during streaming
235
+ * Characters typed will be captured but not displayed
236
+ */
237
+ suppressReadlineOutput() {
238
+ if (this.isOutputSuppressed) {
239
+ return;
240
+ }
241
+ // Save original write function
242
+ this.originalStdoutWrite = this.writeStream.write.bind(this.writeStream);
243
+ // Replace with filtered version that suppresses readline echo
244
+ const outputManager = this.outputManager;
245
+ const originalWrite = this.originalStdoutWrite;
246
+ this.writeStream.write = function (chunk, encodingOrCallback, callback) {
247
+ const text = typeof chunk === 'string' ? chunk : chunk.toString();
248
+ // During streaming, only allow output from the streaming manager
249
+ // Suppress readline's echo of typed characters (single character writes)
250
+ if (outputManager.isStreaming()) {
251
+ // Allow newlines and multi-character writes (likely streaming content)
252
+ if (text.length === 1 && !text.includes('\n') && !text.includes('\r')) {
253
+ // Single character during streaming - likely user typing, suppress it
254
+ if (typeof encodingOrCallback === 'function') {
255
+ encodingOrCallback(null);
256
+ return true;
257
+ }
258
+ if (callback) {
259
+ callback(null);
260
+ }
261
+ return true;
262
+ }
263
+ }
264
+ // Pass through everything else
265
+ return originalWrite(chunk, encodingOrCallback, callback);
266
+ };
267
+ this.isOutputSuppressed = true;
268
+ }
269
+ /**
270
+ * Restore readline's normal output
271
+ */
272
+ restoreReadlineOutput() {
273
+ if (!this.isOutputSuppressed || !this.originalStdoutWrite) {
274
+ return;
275
+ }
276
+ this.writeStream.write = this.originalStdoutWrite;
277
+ this.originalStdoutWrite = null;
278
+ this.isOutputSuppressed = false;
279
+ }
280
+ /**
281
+ * Cleanup when done
282
+ */
283
+ dispose() {
284
+ // Restore output if suppressed
285
+ this.restoreReadlineOutput();
286
+ // Remove keypress handler
287
+ if (this.keypressHandler && this.readStream) {
288
+ this.readStream.off('keypress', this.keypressHandler);
289
+ this.keypressHandler = null;
290
+ }
291
+ // Clear queue
292
+ this.inputManager.clearQueue();
293
+ this.rl = null;
294
+ }
295
+ }
296
+ /**
297
+ * Singleton instance for global use
298
+ */
299
+ let globalInstance = null;
300
+ export function getClaudeCodeStreamHandler() {
301
+ if (!globalInstance) {
302
+ globalInstance = new ClaudeCodeStreamHandler();
303
+ }
304
+ return globalInstance;
305
+ }
306
+ export function resetClaudeCodeStreamHandler() {
307
+ if (globalInstance) {
308
+ globalInstance.dispose();
309
+ }
310
+ globalInstance = null;
311
+ }
312
+ //# sourceMappingURL=claudeCodeStreamHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudeCodeStreamHandler.js","sourceRoot":"","sources":["../../src/shell/claudeCodeStreamHandler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * InputQueueManager - Queue-based input handling for Claude Code style streaming
3
+ *
4
+ * Key principles from Claude Code:
5
+ * 1. Readline handles input - Uses Node.js readline module
6
+ * 2. User can type while streaming - Input is queued in memory, not rendered
7
+ * 3. Queue-based approach: User types → stored in queue → processed after streaming ends
8
+ *
9
+ * The key insight is that the cursor is never moved during streaming.
10
+ * Input is captured "invisibly" while streaming, then processed when streaming ends.
11
+ */
12
+ import { EventEmitter } from 'node:events';
13
+ export interface QueuedInput {
14
+ id: string;
15
+ text: string;
16
+ timestamp: number;
17
+ type: 'message' | 'command' | 'interrupt';
18
+ }
19
+ export interface InputQueueState {
20
+ isCapturing: boolean;
21
+ buffer: string;
22
+ cursorPosition: number;
23
+ queue: QueuedInput[];
24
+ }
25
+ export interface InputQueueEvents {
26
+ 'input-queued': (input: QueuedInput) => void;
27
+ 'input-processed': (input: QueuedInput) => void;
28
+ 'queue-cleared': () => void;
29
+ 'capture-start': () => void;
30
+ 'capture-end': () => void;
31
+ }
32
+ /**
33
+ * Manages input queuing during streaming output.
34
+ *
35
+ * When streaming is active:
36
+ * - Captures keystrokes into a buffer
37
+ * - On Enter, queues the input for later processing
38
+ * - Provides methods to process queue after streaming ends
39
+ */
40
+ export declare class InputQueueManager extends EventEmitter {
41
+ private state;
42
+ private inputIdCounter;
43
+ private readonly maxQueueSize;
44
+ private readonly maxBufferLength;
45
+ constructor(options?: {
46
+ maxQueueSize?: number;
47
+ maxBufferLength?: number;
48
+ });
49
+ /**
50
+ * Start capturing input (during streaming)
51
+ * Input will be buffered and queued, not immediately processed
52
+ */
53
+ startCapturing(): void;
54
+ /**
55
+ * Stop capturing input (after streaming ends)
56
+ * Returns any remaining buffer content
57
+ */
58
+ stopCapturing(): string;
59
+ /**
60
+ * Check if currently capturing input
61
+ */
62
+ isCapturing(): boolean;
63
+ /**
64
+ * Handle a character input
65
+ * During capturing, adds to buffer; otherwise ignored
66
+ */
67
+ handleChar(char: string): void;
68
+ /**
69
+ * Handle backspace
70
+ */
71
+ handleBackspace(): void;
72
+ /**
73
+ * Handle delete key
74
+ */
75
+ handleDelete(): void;
76
+ /**
77
+ * Handle cursor left
78
+ */
79
+ handleCursorLeft(): void;
80
+ /**
81
+ * Handle cursor right
82
+ */
83
+ handleCursorRight(): void;
84
+ /**
85
+ * Handle Enter - queue the current buffer
86
+ * Returns the queued input or null if buffer was empty
87
+ */
88
+ handleSubmit(): QueuedInput | null;
89
+ /**
90
+ * Handle Ctrl+C during capture - queue an interrupt
91
+ */
92
+ handleInterrupt(): QueuedInput;
93
+ /**
94
+ * Get current buffer contents (for display purposes)
95
+ */
96
+ getBuffer(): string;
97
+ /**
98
+ * Get current cursor position
99
+ */
100
+ getCursorPosition(): number;
101
+ /**
102
+ * Get the number of queued inputs
103
+ */
104
+ getQueueLength(): number;
105
+ /**
106
+ * Check if there are queued inputs
107
+ */
108
+ hasQueuedInput(): boolean;
109
+ /**
110
+ * Get the next queued input without removing it
111
+ */
112
+ peekQueue(): QueuedInput | undefined;
113
+ /**
114
+ * Get and remove the next queued input
115
+ */
116
+ dequeue(): QueuedInput | undefined;
117
+ /**
118
+ * Get all queued inputs (copy)
119
+ */
120
+ getQueue(): QueuedInput[];
121
+ /**
122
+ * Clear all queued inputs
123
+ */
124
+ clearQueue(): void;
125
+ /**
126
+ * Clear the current buffer
127
+ */
128
+ clearBuffer(): void;
129
+ /**
130
+ * Set the buffer content directly (for paste handling)
131
+ */
132
+ setBuffer(content: string, cursorPos?: number): void;
133
+ /**
134
+ * Get queue summary for display
135
+ */
136
+ getQueueSummary(): string;
137
+ /**
138
+ * Get full state (for debugging)
139
+ */
140
+ getState(): InputQueueState;
141
+ }
142
+ export declare function getInputQueueManager(): InputQueueManager;
143
+ export declare function resetInputQueueManager(): void;
144
+ //# sourceMappingURL=inputQueueManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inputQueueManager.d.ts","sourceRoot":"","sources":["../../src/shell/inputQueueManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;CAC3C;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IAC7C,iBAAiB,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IAChD,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,qBAAa,iBAAkB,SAAQ,YAAY;IACjD,OAAO,CAAC,KAAK,CAKX;IAEF,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;gBAE7B,OAAO,GAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAO;IAM7E;;;OAGG;IACH,cAAc,IAAI,IAAI;IAYtB;;;OAGG;IACH,aAAa,IAAI,MAAM;IAWvB;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;;OAGG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAkB9B;;OAEG;IACH,eAAe,IAAI,IAAI;IAWvB;;OAEG;IACH,YAAY,IAAI,IAAI;IAUpB;;OAEG;IACH,gBAAgB,IAAI,IAAI;IAKxB;;OAEG;IACH,iBAAiB,IAAI,IAAI;IAKzB;;;OAGG;IACH,YAAY,IAAI,WAAW,GAAG,IAAI;IAoClC;;OAEG;IACH,eAAe,IAAI,WAAW;IAiB9B;;OAEG;IACH,SAAS,IAAI,MAAM;IAInB;;OAEG;IACH,iBAAiB,IAAI,MAAM;IAI3B;;OAEG;IACH,cAAc,IAAI,MAAM;IAIxB;;OAEG;IACH,cAAc,IAAI,OAAO;IAIzB;;OAEG;IACH,SAAS,IAAI,WAAW,GAAG,SAAS;IAIpC;;OAEG;IACH,OAAO,IAAI,WAAW,GAAG,SAAS;IAQlC;;OAEG;IACH,QAAQ,IAAI,WAAW,EAAE;IAIzB;;OAEG;IACH,UAAU,IAAI,IAAI;IASlB;;OAEG;IACH,WAAW,IAAI,IAAI;IAKnB;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAKpD;;OAEG;IACH,eAAe,IAAI,MAAM;IAwBzB;;OAEG;IACH,QAAQ,IAAI,eAAe;CAG5B;AAOD,wBAAgB,oBAAoB,IAAI,iBAAiB,CAKxD;AAED,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C"}