erosolar-cli 2.1.33 → 2.1.35
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/dist/core/agent.d.ts.map +1 -1
- package/dist/core/agent.js +2 -1
- package/dist/core/agent.js.map +1 -1
- package/dist/shell/interactiveShell.d.ts.map +1 -1
- package/dist/shell/interactiveShell.js +39 -17
- package/dist/shell/interactiveShell.js.map +1 -1
- package/package.json +1 -1
- package/dist/ui/DisplayEventQueue.d.ts +0 -99
- package/dist/ui/DisplayEventQueue.d.ts.map +0 -1
- package/dist/ui/DisplayEventQueue.js +0 -167
- package/dist/ui/DisplayEventQueue.js.map +0 -1
- package/dist/ui/SequentialRenderer.d.ts +0 -69
- package/dist/ui/SequentialRenderer.d.ts.map +0 -1
- package/dist/ui/SequentialRenderer.js +0 -137
- package/dist/ui/SequentialRenderer.js.map +0 -1
- package/dist/ui/writeLock.d.ts +0 -65
- package/dist/ui/writeLock.d.ts.map +0 -1
- package/dist/ui/writeLock.js +0 -114
- package/dist/ui/writeLock.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "erosolar-cli",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.35",
|
|
4
4
|
"description": "Unified AI agent framework for the command line - Multi-provider support with schema-driven tools, code intelligence, and transparent reasoning",
|
|
5
5
|
"main": "dist/bin/erosolar.js",
|
|
6
6
|
"type": "module",
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DisplayEventQueue - Unified event queue for sequential, non-overlapping UI rendering
|
|
3
|
-
*
|
|
4
|
-
* Architecture:
|
|
5
|
-
* - All display events (banners, responses, tool calls, etc.) go through this queue
|
|
6
|
-
* - Events are processed sequentially to prevent overlap
|
|
7
|
-
* - Chat box position is tracked and content always stays above it
|
|
8
|
-
* - No simultaneous writes - everything is coordinated
|
|
9
|
-
*
|
|
10
|
-
* Key principles:
|
|
11
|
-
* 1. Single event at a time - no concurrent rendering
|
|
12
|
-
* 2. Content flows top-to-bottom in order
|
|
13
|
-
* 3. Chat box stays at bottom, never overlaps content
|
|
14
|
-
* 4. All events complete before next one starts
|
|
15
|
-
*/
|
|
16
|
-
export type DisplayEventType = 'banner' | 'assistant-response' | 'assistant-streaming' | 'tool-call' | 'tool-result' | 'thought-block' | 'error' | 'info' | 'status';
|
|
17
|
-
export interface DisplayEvent {
|
|
18
|
-
type: DisplayEventType;
|
|
19
|
-
content: string;
|
|
20
|
-
metadata?: {
|
|
21
|
-
isFinal?: boolean;
|
|
22
|
-
wasStreamed?: boolean;
|
|
23
|
-
toolName?: string;
|
|
24
|
-
success?: boolean;
|
|
25
|
-
[key: string]: any;
|
|
26
|
-
};
|
|
27
|
-
timestamp: number;
|
|
28
|
-
id: string;
|
|
29
|
-
}
|
|
30
|
-
export interface DisplayEventHandler {
|
|
31
|
-
(event: DisplayEvent): void | Promise<void>;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Unified display event queue that ensures sequential rendering
|
|
35
|
-
*/
|
|
36
|
-
export declare class DisplayEventQueue {
|
|
37
|
-
private queue;
|
|
38
|
-
private processing;
|
|
39
|
-
private handlers;
|
|
40
|
-
private eventCounter;
|
|
41
|
-
private lastContentRow;
|
|
42
|
-
private chatBoxHeight;
|
|
43
|
-
constructor();
|
|
44
|
-
/**
|
|
45
|
-
* Enqueue a display event for sequential rendering
|
|
46
|
-
*/
|
|
47
|
-
enqueue(type: DisplayEventType, content: string, metadata?: Record<string, any>): string;
|
|
48
|
-
/**
|
|
49
|
-
* Register a handler for a specific event type
|
|
50
|
-
*/
|
|
51
|
-
registerHandler(type: DisplayEventType, handler: DisplayEventHandler): void;
|
|
52
|
-
/**
|
|
53
|
-
* Process the event queue sequentially
|
|
54
|
-
*/
|
|
55
|
-
private processQueue;
|
|
56
|
-
/**
|
|
57
|
-
* Process a single event with proper locking
|
|
58
|
-
*/
|
|
59
|
-
private processEvent;
|
|
60
|
-
/**
|
|
61
|
-
* Update chat box height tracking
|
|
62
|
-
*/
|
|
63
|
-
updateChatBoxHeight(height: number): void;
|
|
64
|
-
/**
|
|
65
|
-
* Update last content row position
|
|
66
|
-
*/
|
|
67
|
-
updateContentRow(row: number): void;
|
|
68
|
-
/**
|
|
69
|
-
* Get the safe row for chat box (below all content)
|
|
70
|
-
*/
|
|
71
|
-
getChatBoxStartRow(terminalRows: number): number;
|
|
72
|
-
/**
|
|
73
|
-
* Clear the queue (useful for interrupts)
|
|
74
|
-
*/
|
|
75
|
-
clear(): void;
|
|
76
|
-
/**
|
|
77
|
-
* Get queue length
|
|
78
|
-
*/
|
|
79
|
-
get length(): number;
|
|
80
|
-
/**
|
|
81
|
-
* Check if queue is processing
|
|
82
|
-
*/
|
|
83
|
-
get isProcessing(): boolean;
|
|
84
|
-
/**
|
|
85
|
-
* Wait for queue to finish processing
|
|
86
|
-
*/
|
|
87
|
-
waitForCompletion(): Promise<void>;
|
|
88
|
-
/**
|
|
89
|
-
* Register default handlers (can be overridden)
|
|
90
|
-
*/
|
|
91
|
-
private registerDefaultHandlers;
|
|
92
|
-
/**
|
|
93
|
-
* Utility delay function
|
|
94
|
-
*/
|
|
95
|
-
private delay;
|
|
96
|
-
}
|
|
97
|
-
export declare function getDisplayEventQueue(): DisplayEventQueue;
|
|
98
|
-
export declare function resetDisplayEventQueue(): void;
|
|
99
|
-
//# sourceMappingURL=DisplayEventQueue.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DisplayEventQueue.d.ts","sourceRoot":"","sources":["../../src/ui/DisplayEventQueue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,MAAM,MAAM,gBAAgB,GACxB,QAAQ,GACR,oBAAoB,GACpB,qBAAqB,GACrB,WAAW,GACX,aAAa,GACb,eAAe,GACf,OAAO,GACP,MAAM,GACN,QAAQ,CAAC;AAEb,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE;QACT,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;IACF,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,mBAAmB;IAClC,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,KAAK,CAAsB;IACnC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAoD;IACpE,OAAO,CAAC,YAAY,CAAK;IAGzB,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,aAAa,CAAK;;IAO1B;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM;IAmBxF;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,mBAAmB,GAAG,IAAI;IAI3E;;OAEG;YACW,YAAY;IAsB1B;;OAEG;YACW,YAAY;IAa1B;;OAEG;IACH,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIzC;;OAEG;IACH,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAInC;;OAEG;IACH,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAShD;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;OAEG;IACH,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAMxC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAK/B;;OAEG;IACH,OAAO,CAAC,KAAK;CAGd;AAOD,wBAAgB,oBAAoB,IAAI,iBAAiB,CAKxD;AAED,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C"}
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DisplayEventQueue - Unified event queue for sequential, non-overlapping UI rendering
|
|
3
|
-
*
|
|
4
|
-
* Architecture:
|
|
5
|
-
* - All display events (banners, responses, tool calls, etc.) go through this queue
|
|
6
|
-
* - Events are processed sequentially to prevent overlap
|
|
7
|
-
* - Chat box position is tracked and content always stays above it
|
|
8
|
-
* - No simultaneous writes - everything is coordinated
|
|
9
|
-
*
|
|
10
|
-
* Key principles:
|
|
11
|
-
* 1. Single event at a time - no concurrent rendering
|
|
12
|
-
* 2. Content flows top-to-bottom in order
|
|
13
|
-
* 3. Chat box stays at bottom, never overlaps content
|
|
14
|
-
* 4. All events complete before next one starts
|
|
15
|
-
*/
|
|
16
|
-
import { writeLock } from './writeLock.js';
|
|
17
|
-
/**
|
|
18
|
-
* Unified display event queue that ensures sequential rendering
|
|
19
|
-
*/
|
|
20
|
-
export class DisplayEventQueue {
|
|
21
|
-
queue = [];
|
|
22
|
-
processing = false;
|
|
23
|
-
handlers = new Map();
|
|
24
|
-
eventCounter = 0;
|
|
25
|
-
// Track the last content position to ensure chat box stays below
|
|
26
|
-
lastContentRow = 1;
|
|
27
|
-
chatBoxHeight = 0;
|
|
28
|
-
constructor() {
|
|
29
|
-
// Initialize with default handlers
|
|
30
|
-
this.registerDefaultHandlers();
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Enqueue a display event for sequential rendering
|
|
34
|
-
*/
|
|
35
|
-
enqueue(type, content, metadata) {
|
|
36
|
-
const event = {
|
|
37
|
-
type,
|
|
38
|
-
content,
|
|
39
|
-
metadata,
|
|
40
|
-
timestamp: Date.now(),
|
|
41
|
-
id: `evt-${++this.eventCounter}`,
|
|
42
|
-
};
|
|
43
|
-
this.queue.push(event);
|
|
44
|
-
// Start processing if not already running
|
|
45
|
-
if (!this.processing) {
|
|
46
|
-
void this.processQueue();
|
|
47
|
-
}
|
|
48
|
-
return event.id;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Register a handler for a specific event type
|
|
52
|
-
*/
|
|
53
|
-
registerHandler(type, handler) {
|
|
54
|
-
this.handlers.set(type, handler);
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Process the event queue sequentially
|
|
58
|
-
*/
|
|
59
|
-
async processQueue() {
|
|
60
|
-
if (this.processing || this.queue.length === 0) {
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
this.processing = true;
|
|
64
|
-
try {
|
|
65
|
-
while (this.queue.length > 0) {
|
|
66
|
-
const event = this.queue.shift();
|
|
67
|
-
if (!event)
|
|
68
|
-
continue;
|
|
69
|
-
await this.processEvent(event);
|
|
70
|
-
// Small delay to ensure rendering completes
|
|
71
|
-
await this.delay(10);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
finally {
|
|
75
|
-
this.processing = false;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Process a single event with proper locking
|
|
80
|
-
*/
|
|
81
|
-
async processEvent(event) {
|
|
82
|
-
const handler = this.handlers.get(event.type);
|
|
83
|
-
if (!handler) {
|
|
84
|
-
console.warn(`No handler registered for event type: ${event.type}`);
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
// Use write lock to ensure no concurrent writes
|
|
88
|
-
await writeLock.withLockAsync(async () => {
|
|
89
|
-
await handler(event);
|
|
90
|
-
}, `event-${event.type}-${event.id}`);
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Update chat box height tracking
|
|
94
|
-
*/
|
|
95
|
-
updateChatBoxHeight(height) {
|
|
96
|
-
this.chatBoxHeight = height;
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Update last content row position
|
|
100
|
-
*/
|
|
101
|
-
updateContentRow(row) {
|
|
102
|
-
this.lastContentRow = Math.max(this.lastContentRow, row);
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Get the safe row for chat box (below all content)
|
|
106
|
-
*/
|
|
107
|
-
getChatBoxStartRow(terminalRows) {
|
|
108
|
-
// Chat box should start at least 1 row below the last content
|
|
109
|
-
const minStartRow = this.lastContentRow + 1;
|
|
110
|
-
const calculatedStartRow = Math.max(1, terminalRows - this.chatBoxHeight + 1);
|
|
111
|
-
// Use whichever is lower (closer to bottom but still below content)
|
|
112
|
-
return Math.max(minStartRow, calculatedStartRow);
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Clear the queue (useful for interrupts)
|
|
116
|
-
*/
|
|
117
|
-
clear() {
|
|
118
|
-
this.queue = [];
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Get queue length
|
|
122
|
-
*/
|
|
123
|
-
get length() {
|
|
124
|
-
return this.queue.length;
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Check if queue is processing
|
|
128
|
-
*/
|
|
129
|
-
get isProcessing() {
|
|
130
|
-
return this.processing;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Wait for queue to finish processing
|
|
134
|
-
*/
|
|
135
|
-
async waitForCompletion() {
|
|
136
|
-
while (this.processing || this.queue.length > 0) {
|
|
137
|
-
await this.delay(50);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Register default handlers (can be overridden)
|
|
142
|
-
*/
|
|
143
|
-
registerDefaultHandlers() {
|
|
144
|
-
// Default handlers will be registered by Display class
|
|
145
|
-
// This allows for dependency injection of the actual rendering logic
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Utility delay function
|
|
149
|
-
*/
|
|
150
|
-
delay(ms) {
|
|
151
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Global singleton instance
|
|
156
|
-
*/
|
|
157
|
-
let globalQueue = null;
|
|
158
|
-
export function getDisplayEventQueue() {
|
|
159
|
-
if (!globalQueue) {
|
|
160
|
-
globalQueue = new DisplayEventQueue();
|
|
161
|
-
}
|
|
162
|
-
return globalQueue;
|
|
163
|
-
}
|
|
164
|
-
export function resetDisplayEventQueue() {
|
|
165
|
-
globalQueue = null;
|
|
166
|
-
}
|
|
167
|
-
//# sourceMappingURL=DisplayEventQueue.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DisplayEventQueue.js","sourceRoot":"","sources":["../../src/ui/DisplayEventQueue.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SequentialRenderer - Ensures all UI events render sequentially without overlap
|
|
3
|
-
*
|
|
4
|
-
* Key responsibilities:
|
|
5
|
-
* 1. Queue all content writes to prevent overlap
|
|
6
|
-
* 2. Track content position to ensure chat box stays below
|
|
7
|
-
* 3. Coordinate with terminalInput for proper positioning
|
|
8
|
-
* 4. Prevent race conditions between streaming and static content
|
|
9
|
-
*/
|
|
10
|
-
interface ContentBlock {
|
|
11
|
-
content: string;
|
|
12
|
-
type: 'banner' | 'response' | 'tool' | 'status' | 'streaming';
|
|
13
|
-
timestamp: number;
|
|
14
|
-
}
|
|
15
|
-
export declare class SequentialRenderer {
|
|
16
|
-
private writeFunction;
|
|
17
|
-
private updateChatBoxPosition?;
|
|
18
|
-
private contentQueue;
|
|
19
|
-
private isProcessing;
|
|
20
|
-
private lastContentEndRow;
|
|
21
|
-
private terminalRows;
|
|
22
|
-
private chatBoxHeight;
|
|
23
|
-
constructor(writeFunction: (content: string) => void, updateChatBoxPosition?: ((startRow: number) => void) | undefined);
|
|
24
|
-
/**
|
|
25
|
-
* Queue content for sequential rendering
|
|
26
|
-
*/
|
|
27
|
-
queueContent(content: string, type?: ContentBlock['type']): void;
|
|
28
|
-
/**
|
|
29
|
-
* Process the content queue sequentially
|
|
30
|
-
*/
|
|
31
|
-
private processQueue;
|
|
32
|
-
/**
|
|
33
|
-
* Render a single content block
|
|
34
|
-
*/
|
|
35
|
-
private renderBlock;
|
|
36
|
-
/**
|
|
37
|
-
* Count newlines in content
|
|
38
|
-
*/
|
|
39
|
-
private countLines;
|
|
40
|
-
/**
|
|
41
|
-
* Update chat box position to stay below content
|
|
42
|
-
*/
|
|
43
|
-
private updateChatBoxPositionIfNeeded;
|
|
44
|
-
/**
|
|
45
|
-
* Update terminal dimensions
|
|
46
|
-
*/
|
|
47
|
-
updateDimensions(rows: number, chatBoxHeight: number): void;
|
|
48
|
-
/**
|
|
49
|
-
* Reset content position (e.g., after clear screen)
|
|
50
|
-
*/
|
|
51
|
-
resetPosition(): void;
|
|
52
|
-
/**
|
|
53
|
-
* Wait for queue to complete
|
|
54
|
-
*/
|
|
55
|
-
waitForCompletion(): Promise<void>;
|
|
56
|
-
/**
|
|
57
|
-
* Clear the queue
|
|
58
|
-
*/
|
|
59
|
-
clear(): void;
|
|
60
|
-
/**
|
|
61
|
-
* Get current queue length
|
|
62
|
-
*/
|
|
63
|
-
get queueLength(): number;
|
|
64
|
-
private delay;
|
|
65
|
-
}
|
|
66
|
-
export declare function getSequentialRenderer(writeFunction?: (content: string) => void, updateChatBoxPosition?: (startRow: number) => void): SequentialRenderer;
|
|
67
|
-
export declare function resetSequentialRenderer(): void;
|
|
68
|
-
export {};
|
|
69
|
-
//# sourceMappingURL=SequentialRenderer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SequentialRenderer.d.ts","sourceRoot":"","sources":["../../src/ui/SequentialRenderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,CAAC;IAC9D,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,kBAAkB;IAQ3B,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,qBAAqB,CAAC;IARhC,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,aAAa,CAAK;gBAGhB,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,EACxC,qBAAqB,CAAC,GAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,aAAA;IAG5D;;OAEG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,YAAY,CAAC,MAAM,CAAc,GAAG,IAAI;IAY5E;;OAEG;YACW,YAAY;IAuB1B;;OAEG;YACW,WAAW;IAWzB;;OAEG;IACH,OAAO,CAAC,UAAU;IAIlB;;OAEG;IACH,OAAO,CAAC,6BAA6B;IAYrC;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI;IAK3D;;OAEG;IACH,aAAa,IAAI,IAAI;IAIrB;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAMxC;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,OAAO,CAAC,KAAK;CAGd;AAOD,wBAAgB,qBAAqB,CACnC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,EACzC,qBAAqB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GACjD,kBAAkB,CAKpB;AAED,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C"}
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SequentialRenderer - Ensures all UI events render sequentially without overlap
|
|
3
|
-
*
|
|
4
|
-
* Key responsibilities:
|
|
5
|
-
* 1. Queue all content writes to prevent overlap
|
|
6
|
-
* 2. Track content position to ensure chat box stays below
|
|
7
|
-
* 3. Coordinate with terminalInput for proper positioning
|
|
8
|
-
* 4. Prevent race conditions between streaming and static content
|
|
9
|
-
*/
|
|
10
|
-
import { writeLock } from './writeLock.js';
|
|
11
|
-
export class SequentialRenderer {
|
|
12
|
-
writeFunction;
|
|
13
|
-
updateChatBoxPosition;
|
|
14
|
-
contentQueue = [];
|
|
15
|
-
isProcessing = false;
|
|
16
|
-
lastContentEndRow = 1; // Track where content ends
|
|
17
|
-
terminalRows = 24;
|
|
18
|
-
chatBoxHeight = 5;
|
|
19
|
-
constructor(writeFunction, updateChatBoxPosition) {
|
|
20
|
-
this.writeFunction = writeFunction;
|
|
21
|
-
this.updateChatBoxPosition = updateChatBoxPosition;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Queue content for sequential rendering
|
|
25
|
-
*/
|
|
26
|
-
queueContent(content, type = 'response') {
|
|
27
|
-
this.contentQueue.push({
|
|
28
|
-
content,
|
|
29
|
-
type,
|
|
30
|
-
timestamp: Date.now(),
|
|
31
|
-
});
|
|
32
|
-
if (!this.isProcessing) {
|
|
33
|
-
void this.processQueue();
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Process the content queue sequentially
|
|
38
|
-
*/
|
|
39
|
-
async processQueue() {
|
|
40
|
-
if (this.isProcessing)
|
|
41
|
-
return;
|
|
42
|
-
this.isProcessing = true;
|
|
43
|
-
try {
|
|
44
|
-
while (this.contentQueue.length > 0) {
|
|
45
|
-
const block = this.contentQueue.shift();
|
|
46
|
-
if (!block)
|
|
47
|
-
continue;
|
|
48
|
-
await this.renderBlock(block);
|
|
49
|
-
// Small delay to ensure rendering settles
|
|
50
|
-
await this.delay(5);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
finally {
|
|
54
|
-
this.isProcessing = false;
|
|
55
|
-
// Update chat box position after all content is rendered
|
|
56
|
-
this.updateChatBoxPositionIfNeeded();
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Render a single content block
|
|
61
|
-
*/
|
|
62
|
-
async renderBlock(block) {
|
|
63
|
-
await writeLock.withLockAsync(async () => {
|
|
64
|
-
// Write the content
|
|
65
|
-
this.writeFunction(block.content);
|
|
66
|
-
// Update content position tracking
|
|
67
|
-
const linesInBlock = this.countLines(block.content);
|
|
68
|
-
this.lastContentEndRow += linesInBlock;
|
|
69
|
-
}, `render-${block.type}`);
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Count newlines in content
|
|
73
|
-
*/
|
|
74
|
-
countLines(content) {
|
|
75
|
-
return (content.match(/\n/g) || []).length;
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Update chat box position to stay below content
|
|
79
|
-
*/
|
|
80
|
-
updateChatBoxPositionIfNeeded() {
|
|
81
|
-
if (!this.updateChatBoxPosition)
|
|
82
|
-
return;
|
|
83
|
-
// Calculate where chat box should start (below all content)
|
|
84
|
-
const chatBoxStartRow = Math.min(this.lastContentEndRow + 1, this.terminalRows - this.chatBoxHeight + 1);
|
|
85
|
-
this.updateChatBoxPosition(chatBoxStartRow);
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Update terminal dimensions
|
|
89
|
-
*/
|
|
90
|
-
updateDimensions(rows, chatBoxHeight) {
|
|
91
|
-
this.terminalRows = rows;
|
|
92
|
-
this.chatBoxHeight = chatBoxHeight;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Reset content position (e.g., after clear screen)
|
|
96
|
-
*/
|
|
97
|
-
resetPosition() {
|
|
98
|
-
this.lastContentEndRow = 1;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Wait for queue to complete
|
|
102
|
-
*/
|
|
103
|
-
async waitForCompletion() {
|
|
104
|
-
while (this.isProcessing || this.contentQueue.length > 0) {
|
|
105
|
-
await this.delay(10);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Clear the queue
|
|
110
|
-
*/
|
|
111
|
-
clear() {
|
|
112
|
-
this.contentQueue = [];
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Get current queue length
|
|
116
|
-
*/
|
|
117
|
-
get queueLength() {
|
|
118
|
-
return this.contentQueue.length;
|
|
119
|
-
}
|
|
120
|
-
delay(ms) {
|
|
121
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Global singleton instance
|
|
126
|
-
*/
|
|
127
|
-
let globalRenderer = null;
|
|
128
|
-
export function getSequentialRenderer(writeFunction, updateChatBoxPosition) {
|
|
129
|
-
if (!globalRenderer && writeFunction) {
|
|
130
|
-
globalRenderer = new SequentialRenderer(writeFunction, updateChatBoxPosition);
|
|
131
|
-
}
|
|
132
|
-
return globalRenderer;
|
|
133
|
-
}
|
|
134
|
-
export function resetSequentialRenderer() {
|
|
135
|
-
globalRenderer = null;
|
|
136
|
-
}
|
|
137
|
-
//# sourceMappingURL=SequentialRenderer.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SequentialRenderer.js","sourceRoot":"","sources":["../../src/ui/SequentialRenderer.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/writeLock.d.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WriteLock - Shared write lock for coordinating terminal output
|
|
3
|
-
*
|
|
4
|
-
* Prevents race conditions when multiple sources write to stdout:
|
|
5
|
-
* - Display output (messages, tool results)
|
|
6
|
-
* - Terminal input rendering (prompt, status)
|
|
7
|
-
* - Streaming content
|
|
8
|
-
*
|
|
9
|
-
* Uses a simple mutex pattern suitable for Node.js single-threaded event loop.
|
|
10
|
-
*/
|
|
11
|
-
type WriteCallback = () => void;
|
|
12
|
-
declare class WriteLockImpl {
|
|
13
|
-
private locked;
|
|
14
|
-
private readonly pendingWrites;
|
|
15
|
-
private lockHolder;
|
|
16
|
-
/**
|
|
17
|
-
* Check if output is currently locked
|
|
18
|
-
*/
|
|
19
|
-
isLocked(): boolean;
|
|
20
|
-
/**
|
|
21
|
-
* Acquire the lock for exclusive writing
|
|
22
|
-
* @param holder Optional identifier for debugging
|
|
23
|
-
*/
|
|
24
|
-
lock(holder?: string): void;
|
|
25
|
-
/**
|
|
26
|
-
* Release the lock and process any pending writes
|
|
27
|
-
*/
|
|
28
|
-
unlock(): void;
|
|
29
|
-
/**
|
|
30
|
-
* Execute a write callback safely.
|
|
31
|
-
* If locked, the callback is queued until unlock.
|
|
32
|
-
*/
|
|
33
|
-
safeWrite(callback: WriteCallback): void;
|
|
34
|
-
/**
|
|
35
|
-
* Execute a write with the lock held.
|
|
36
|
-
* Ensures exclusive access during the write operation.
|
|
37
|
-
*/
|
|
38
|
-
withLock(callback: WriteCallback, holder?: string): void;
|
|
39
|
-
/**
|
|
40
|
-
* Execute an async operation with the lock held.
|
|
41
|
-
*/
|
|
42
|
-
withLockAsync<T>(callback: () => Promise<T>, holder?: string): Promise<T>;
|
|
43
|
-
/**
|
|
44
|
-
* Process any pending writes that were queued while locked
|
|
45
|
-
*/
|
|
46
|
-
private processPending;
|
|
47
|
-
/**
|
|
48
|
-
* Clear all pending writes (use when resetting state)
|
|
49
|
-
*/
|
|
50
|
-
clearPending(): void;
|
|
51
|
-
/**
|
|
52
|
-
* Get debug info about the lock state
|
|
53
|
-
*/
|
|
54
|
-
getDebugInfo(): {
|
|
55
|
-
locked: boolean;
|
|
56
|
-
holder: string | null;
|
|
57
|
-
pendingCount: number;
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Singleton instance for global use
|
|
62
|
-
*/
|
|
63
|
-
export declare const writeLock: WriteLockImpl;
|
|
64
|
-
export {};
|
|
65
|
-
//# sourceMappingURL=writeLock.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"writeLock.d.ts","sourceRoot":"","sources":["../../src/ui/writeLock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,KAAK,aAAa,GAAG,MAAM,IAAI,CAAC;AAEhC,cAAM,aAAa;IACjB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAuB;IACrD,OAAO,CAAC,UAAU,CAAuB;IAEzC;;OAEG;IACH,QAAQ,IAAI,OAAO;IAInB;;;OAGG;IACH,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAK3B;;OAEG;IACH,MAAM,IAAI,IAAI;IAMd;;;OAGG;IACH,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI;IAQxC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAexD;;OAEG;IACG,aAAa,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAc/E;;OAEG;IACH,OAAO,CAAC,cAAc;IAStB;;OAEG;IACH,YAAY,IAAI,IAAI;IAIpB;;OAEG;IACH,YAAY,IAAI;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE;CAOjF;AAED;;GAEG;AACH,eAAO,MAAM,SAAS,eAAsB,CAAC"}
|
package/dist/ui/writeLock.js
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WriteLock - Shared write lock for coordinating terminal output
|
|
3
|
-
*
|
|
4
|
-
* Prevents race conditions when multiple sources write to stdout:
|
|
5
|
-
* - Display output (messages, tool results)
|
|
6
|
-
* - Terminal input rendering (prompt, status)
|
|
7
|
-
* - Streaming content
|
|
8
|
-
*
|
|
9
|
-
* Uses a simple mutex pattern suitable for Node.js single-threaded event loop.
|
|
10
|
-
*/
|
|
11
|
-
class WriteLockImpl {
|
|
12
|
-
locked = false;
|
|
13
|
-
pendingWrites = [];
|
|
14
|
-
lockHolder = null;
|
|
15
|
-
/**
|
|
16
|
-
* Check if output is currently locked
|
|
17
|
-
*/
|
|
18
|
-
isLocked() {
|
|
19
|
-
return this.locked;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Acquire the lock for exclusive writing
|
|
23
|
-
* @param holder Optional identifier for debugging
|
|
24
|
-
*/
|
|
25
|
-
lock(holder) {
|
|
26
|
-
this.locked = true;
|
|
27
|
-
this.lockHolder = holder ?? null;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Release the lock and process any pending writes
|
|
31
|
-
*/
|
|
32
|
-
unlock() {
|
|
33
|
-
this.locked = false;
|
|
34
|
-
this.lockHolder = null;
|
|
35
|
-
this.processPending();
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Execute a write callback safely.
|
|
39
|
-
* If locked, the callback is queued until unlock.
|
|
40
|
-
*/
|
|
41
|
-
safeWrite(callback) {
|
|
42
|
-
if (this.locked) {
|
|
43
|
-
this.pendingWrites.push(callback);
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
callback();
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Execute a write with the lock held.
|
|
50
|
-
* Ensures exclusive access during the write operation.
|
|
51
|
-
*/
|
|
52
|
-
withLock(callback, holder) {
|
|
53
|
-
if (this.locked) {
|
|
54
|
-
// Queue for later execution
|
|
55
|
-
this.pendingWrites.push(() => this.withLock(callback, holder));
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
this.lock(holder);
|
|
59
|
-
try {
|
|
60
|
-
callback();
|
|
61
|
-
}
|
|
62
|
-
finally {
|
|
63
|
-
this.unlock();
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Execute an async operation with the lock held.
|
|
68
|
-
*/
|
|
69
|
-
async withLockAsync(callback, holder) {
|
|
70
|
-
// Wait for lock to be available
|
|
71
|
-
while (this.locked) {
|
|
72
|
-
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
73
|
-
}
|
|
74
|
-
this.lock(holder);
|
|
75
|
-
try {
|
|
76
|
-
return await callback();
|
|
77
|
-
}
|
|
78
|
-
finally {
|
|
79
|
-
this.unlock();
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Process any pending writes that were queued while locked
|
|
84
|
-
*/
|
|
85
|
-
processPending() {
|
|
86
|
-
while (this.pendingWrites.length > 0 && !this.locked) {
|
|
87
|
-
const callback = this.pendingWrites.shift();
|
|
88
|
-
if (callback) {
|
|
89
|
-
callback();
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Clear all pending writes (use when resetting state)
|
|
95
|
-
*/
|
|
96
|
-
clearPending() {
|
|
97
|
-
this.pendingWrites.length = 0;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Get debug info about the lock state
|
|
101
|
-
*/
|
|
102
|
-
getDebugInfo() {
|
|
103
|
-
return {
|
|
104
|
-
locked: this.locked,
|
|
105
|
-
holder: this.lockHolder,
|
|
106
|
-
pendingCount: this.pendingWrites.length,
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Singleton instance for global use
|
|
112
|
-
*/
|
|
113
|
-
export const writeLock = new WriteLockImpl();
|
|
114
|
-
//# sourceMappingURL=writeLock.js.map
|