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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "erosolar-cli",
3
- "version": "2.1.33",
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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"}
@@ -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"}
@@ -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