@pokit/tabs-core 0.0.1

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.
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Shared Tab State Management Hook
3
+ *
4
+ * Framework-agnostic state management for tabbed terminal interfaces.
5
+ * Handles tab selection, scroll offsets, auto-scroll behavior, and help hint visibility.
6
+ */
7
+ import { useState, useEffect, useCallback } from 'react';
8
+ import { HELP_HINT_DURATION_MS } from '../constants/keyboard.js';
9
+ /**
10
+ * Hook for managing tabbed interface state.
11
+ *
12
+ * Provides:
13
+ * - Per-tab scroll offsets with auto-scroll behavior
14
+ * - Tab navigation helpers
15
+ * - Help hint auto-dismiss timer
16
+ */
17
+ export function useTabsState({ tabs, activeIndex, onActiveIndexChange, viewHeight, }) {
18
+ // Show help hint for first N seconds
19
+ const [showHelpHint, setShowHelpHint] = useState(true);
20
+ useEffect(() => {
21
+ const timer = setTimeout(() => setShowHelpHint(false), HELP_HINT_DURATION_MS);
22
+ return () => clearTimeout(timer);
23
+ }, []);
24
+ // Per-tab scroll offsets
25
+ const [scrollOffsets, setScrollOffsets] = useState(() => new Map());
26
+ // Per-tab auto-scroll state
27
+ const [autoScroll, setAutoScroll] = useState(() => new Map(tabs.map((t) => [t.id, true])));
28
+ const activeTab = tabs[activeIndex];
29
+ const activeScrollOffset = scrollOffsets.get(activeTab?.id ?? '') ?? 0;
30
+ // Calculate scroll state
31
+ const totalLines = activeTab?.output.length ?? 0;
32
+ const maxScroll = Math.max(0, totalLines - viewHeight);
33
+ const canScrollUp = activeScrollOffset > 0;
34
+ const canScrollDown = activeScrollOffset < maxScroll;
35
+ // Auto-scroll when new output arrives (if auto-scroll enabled for this tab)
36
+ useEffect(() => {
37
+ if (!activeTab)
38
+ return;
39
+ const shouldAutoScroll = autoScroll.get(activeTab.id) ?? true;
40
+ if (shouldAutoScroll) {
41
+ const maxScroll = Math.max(0, activeTab.output.length - viewHeight);
42
+ setScrollOffsets((prev) => {
43
+ const next = new Map(prev);
44
+ next.set(activeTab.id, maxScroll);
45
+ return next;
46
+ });
47
+ }
48
+ }, [activeTab, viewHeight, autoScroll]);
49
+ const scrollBy = useCallback((delta) => {
50
+ if (!activeTab)
51
+ return;
52
+ const maxScroll = Math.max(0, activeTab.output.length - viewHeight);
53
+ setScrollOffsets((prev) => {
54
+ const next = new Map(prev);
55
+ const current = prev.get(activeTab.id) ?? 0;
56
+ const newOffset = Math.max(0, Math.min(maxScroll, current + delta));
57
+ next.set(activeTab.id, newOffset);
58
+ // If scrolled away from bottom, disable auto-scroll
59
+ // If scrolled to bottom, re-enable auto-scroll
60
+ const atBottom = newOffset >= maxScroll;
61
+ setAutoScroll((as) => {
62
+ const asNext = new Map(as);
63
+ asNext.set(activeTab.id, atBottom);
64
+ return asNext;
65
+ });
66
+ return next;
67
+ });
68
+ }, [activeTab, viewHeight]);
69
+ const switchTab = useCallback((newIndex) => {
70
+ if (newIndex >= 0 && newIndex < tabs.length) {
71
+ onActiveIndexChange(newIndex);
72
+ }
73
+ }, [tabs.length, onActiveIndexChange]);
74
+ const nextTab = useCallback(() => {
75
+ switchTab((activeIndex + 1) % tabs.length);
76
+ }, [activeIndex, tabs.length, switchTab]);
77
+ const prevTab = useCallback(() => {
78
+ switchTab((activeIndex - 1 + tabs.length) % tabs.length);
79
+ }, [activeIndex, tabs.length, switchTab]);
80
+ return {
81
+ // State
82
+ showHelpHint,
83
+ activeScrollOffset,
84
+ canScrollUp,
85
+ canScrollDown,
86
+ // Actions
87
+ scrollBy,
88
+ switchTab,
89
+ nextTab,
90
+ prevTab,
91
+ };
92
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @pokit/tabs-core
3
+ *
4
+ * Shared logic for CLI tabs adapters (Ink, OpenTUI).
5
+ * Framework-agnostic types, state management, and process handling.
6
+ */
7
+ export type { TabStatus, TabProcess, StatusIndicator, ActivityNode, GroupNode, EventDrivenState, } from './types.js';
8
+ export { MAX_OUTPUT_LINES, MAX_LINE_LENGTH, BUFFER_WARNING_THRESHOLD, STATUS_INDICATORS, getStatusIndicator, } from './types.js';
9
+ export type { RingBufferOptions, OutputBufferOptions } from './ring-buffer.js';
10
+ export { RingBuffer, OutputBuffer } from './ring-buffer.js';
11
+ export { createInitialState, reducer, getTabsGroupActivities, findTabsGroup, } from './state-reducer.js';
12
+ export type { TabSpec, ProcessManagerCallbacks, ProcessManagerOptions } from './process-manager.js';
13
+ export { ProcessManager, OUTPUT_BATCH_MS } from './process-manager.js';
14
+ export type { Shortcut, ShortcutGroup } from './constants/index.js';
15
+ export { HELP_CONTENT, KEY_SEQUENCES, ctrlKeyToSequence, HELP_HINT_DURATION_MS, } from './constants/index.js';
16
+ export type { UseTabsStateOptions, TabsState, TabsActions, KeyboardCallbacks, KeyboardState, NormalizedKeyEvent, KeyboardAction, } from './hooks/index.js';
17
+ export { useTabsState, processKeyEvent, useKeyboardCallbackRefs, executeKeyboardAction, } from './hooks/index.js';
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,YAAY,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,YAAY,EACZ,SAAS,EACT,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,wBAAwB,EACxB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAMpB,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE/E,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAM5D,OAAO,EACL,kBAAkB,EAClB,OAAO,EACP,sBAAsB,EACtB,aAAa,GACd,MAAM,oBAAoB,CAAC;AAM5B,YAAY,EAAE,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAEpG,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAMvE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EACL,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAM9B,YAAY,EACV,mBAAmB,EACnB,SAAS,EACT,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,kBAAkB,EAClB,cAAc,GACf,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,YAAY,EACZ,eAAe,EACf,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @pokit/tabs-core
3
+ *
4
+ * Shared logic for CLI tabs adapters (Ink, OpenTUI).
5
+ * Framework-agnostic types, state management, and process handling.
6
+ */
7
+ export { MAX_OUTPUT_LINES, MAX_LINE_LENGTH, BUFFER_WARNING_THRESHOLD, STATUS_INDICATORS, getStatusIndicator, } from './types.js';
8
+ export { RingBuffer, OutputBuffer } from './ring-buffer.js';
9
+ // =============================================================================
10
+ // State Reducer
11
+ // =============================================================================
12
+ export { createInitialState, reducer, getTabsGroupActivities, findTabsGroup, } from './state-reducer.js';
13
+ export { ProcessManager, OUTPUT_BATCH_MS } from './process-manager.js';
14
+ export { HELP_CONTENT, KEY_SEQUENCES, ctrlKeyToSequence, HELP_HINT_DURATION_MS, } from './constants/index.js';
15
+ export { useTabsState, processKeyEvent, useKeyboardCallbackRefs, executeKeyboardAction, } from './hooks/index.js';
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Process Manager for CLI Tabs
3
+ *
4
+ * Manages spawning, output buffering, and lifecycle of child processes.
5
+ * Framework-agnostic - provides callbacks for UI frameworks to consume.
6
+ */
7
+ import type { TabStatus, TabProcess } from './types.js';
8
+ export declare const OUTPUT_BATCH_MS = 16;
9
+ /**
10
+ * A tab specification for the tabbed terminal UI.
11
+ * This is the internal format used by adapters after task resolution.
12
+ */
13
+ export type TabSpec = {
14
+ label: string;
15
+ exec: string;
16
+ };
17
+ export type ProcessManagerCallbacks = {
18
+ /** Called when new output lines are available for a tab */
19
+ onOutputUpdate: (index: number, lines: string[]) => void;
20
+ /** Called when a process status changes */
21
+ onStatusChange: (index: number, status: TabStatus, exitCode?: number) => void;
22
+ /** Called when a process encounters an error */
23
+ onError: (index: number, error: string) => void;
24
+ };
25
+ export type ProcessManagerOptions = {
26
+ /** Working directory for commands */
27
+ cwd: string;
28
+ /** Environment variables for commands */
29
+ env: Record<string, string | undefined>;
30
+ /** Callbacks for state updates */
31
+ callbacks: ProcessManagerCallbacks;
32
+ };
33
+ /**
34
+ * Manages child processes for tabbed terminal UI.
35
+ *
36
+ * Features:
37
+ * - Batched output updates (16ms) to reduce render frequency
38
+ * - Process lifecycle management (start, restart, kill)
39
+ * - Automatic cleanup on destroy
40
+ */
41
+ export declare class ProcessManager {
42
+ private items;
43
+ private options;
44
+ private processes;
45
+ private outputBuffers;
46
+ private flushScheduled;
47
+ private destroyed;
48
+ constructor(items: TabSpec[], options: ProcessManagerOptions);
49
+ /**
50
+ * Get initial tab process states
51
+ */
52
+ getInitialTabs(): TabProcess[];
53
+ /**
54
+ * Start all processes
55
+ */
56
+ start(): void;
57
+ /**
58
+ * Restart a specific process
59
+ */
60
+ restart(index: number): void;
61
+ /**
62
+ * Kill a specific process
63
+ */
64
+ kill(index: number): void;
65
+ /**
66
+ * Kill all processes
67
+ */
68
+ killAll(): void;
69
+ /**
70
+ * Destroy the manager and cleanup all resources
71
+ */
72
+ destroy(): void;
73
+ private spawnProcess;
74
+ private appendOutput;
75
+ private scheduleFlush;
76
+ private flushOutput;
77
+ }
78
+ //# sourceMappingURL=process-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-manager.d.ts","sourceRoot":"","sources":["../src/process-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExD,eAAO,MAAM,eAAe,KAAK,CAAC;AAMlC;;;GAGG;AACH,MAAM,MAAM,OAAO,GAAG;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,2DAA2D;IAC3D,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACzD,2CAA2C;IAC3C,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9E,gDAAgD;IAChD,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACxC,kCAAkC;IAClC,SAAS,EAAE,uBAAuB,CAAC;CACpC,CAAC;AAUF;;;;;;;GAOG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,aAAa,CAAwC;IAC7D,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,SAAS,CAAS;gBAEd,KAAK,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,qBAAqB;IAM5D;;OAEG;IACH,cAAc,IAAI,UAAU,EAAE;IAU9B;;OAEG;IACH,KAAK,IAAI,IAAI;IAQb;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IA2B5B;;OAEG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAUzB;;OAEG;IACH,OAAO,IAAI,IAAI;IAQf;;OAEG;IACH,OAAO,IAAI,IAAI;IAUf,OAAO,CAAC,YAAY;IAgCpB,OAAO,CAAC,YAAY;IAkBpB,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,WAAW;CAcpB"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Process Manager for CLI Tabs
3
+ *
4
+ * Manages spawning, output buffering, and lifecycle of child processes.
5
+ * Framework-agnostic - provides callbacks for UI frameworks to consume.
6
+ */
7
+ import { spawn } from 'node:child_process';
8
+ export const OUTPUT_BATCH_MS = 16;
9
+ // =============================================================================
10
+ // ProcessManager Class
11
+ // =============================================================================
12
+ /**
13
+ * Manages child processes for tabbed terminal UI.
14
+ *
15
+ * Features:
16
+ * - Batched output updates (16ms) to reduce render frequency
17
+ * - Process lifecycle management (start, restart, kill)
18
+ * - Automatic cleanup on destroy
19
+ */
20
+ export class ProcessManager {
21
+ items;
22
+ options;
23
+ processes = [];
24
+ outputBuffers = new Map();
25
+ flushScheduled = false;
26
+ destroyed = false;
27
+ constructor(items, options) {
28
+ this.items = items;
29
+ this.options = options;
30
+ this.processes = new Array(items.length).fill(null);
31
+ }
32
+ /**
33
+ * Get initial tab process states
34
+ */
35
+ getInitialTabs() {
36
+ return this.items.map((item, i) => ({
37
+ id: `tab-${i}`,
38
+ label: item.label,
39
+ exec: item.exec,
40
+ output: [],
41
+ status: 'running',
42
+ }));
43
+ }
44
+ /**
45
+ * Start all processes
46
+ */
47
+ start() {
48
+ if (this.destroyed)
49
+ return;
50
+ for (let i = 0; i < this.items.length; i++) {
51
+ this.spawnProcess(i);
52
+ }
53
+ }
54
+ /**
55
+ * Restart a specific process
56
+ */
57
+ restart(index) {
58
+ if (this.destroyed)
59
+ return;
60
+ const item = this.items[index];
61
+ if (!item)
62
+ return;
63
+ // Kill existing process
64
+ const existingProc = this.processes[index];
65
+ if (existingProc && !existingProc.killed) {
66
+ existingProc.kill('SIGTERM');
67
+ }
68
+ // Clear output buffer
69
+ this.outputBuffers.delete(index);
70
+ // Notify UI to show "Restarting..."
71
+ this.options.callbacks.onOutputUpdate(index, ['Restarting...', '']);
72
+ this.options.callbacks.onStatusChange(index, 'running');
73
+ // Spawn new process after short delay
74
+ setTimeout(() => {
75
+ if (!this.destroyed) {
76
+ this.spawnProcess(index);
77
+ }
78
+ }, 100);
79
+ }
80
+ /**
81
+ * Kill a specific process
82
+ */
83
+ kill(index) {
84
+ const proc = this.processes[index];
85
+ if (proc && !proc.killed) {
86
+ proc.kill('SIGTERM');
87
+ }
88
+ this.options.callbacks.onOutputUpdate(index, ['', 'Stopped']);
89
+ this.options.callbacks.onStatusChange(index, 'stopped');
90
+ }
91
+ /**
92
+ * Kill all processes
93
+ */
94
+ killAll() {
95
+ for (const proc of this.processes) {
96
+ if (proc && !proc.killed) {
97
+ proc.kill('SIGTERM');
98
+ }
99
+ }
100
+ }
101
+ /**
102
+ * Destroy the manager and cleanup all resources
103
+ */
104
+ destroy() {
105
+ this.destroyed = true;
106
+ this.killAll();
107
+ this.outputBuffers.clear();
108
+ }
109
+ // ===========================================================================
110
+ // Private Methods
111
+ // ===========================================================================
112
+ spawnProcess(index) {
113
+ const item = this.items[index];
114
+ if (!item)
115
+ return;
116
+ const proc = spawn('sh', ['-c', item.exec], {
117
+ cwd: this.options.cwd,
118
+ env: {
119
+ ...this.options.env,
120
+ FORCE_COLOR: '1',
121
+ },
122
+ stdio: ['inherit', 'pipe', 'pipe'],
123
+ });
124
+ this.processes[index] = proc;
125
+ const handleData = (data) => this.appendOutput(index, data);
126
+ proc.stdout?.on('data', handleData);
127
+ proc.stderr?.on('data', handleData);
128
+ proc.on('close', (code) => {
129
+ this.flushOutput();
130
+ const status = code === 0 ? 'done' : 'error';
131
+ this.options.callbacks.onStatusChange(index, status, code ?? undefined);
132
+ });
133
+ proc.on('error', (err) => {
134
+ this.options.callbacks.onError(index, err.message);
135
+ this.options.callbacks.onStatusChange(index, 'error');
136
+ });
137
+ }
138
+ appendOutput(index, data) {
139
+ const text = data.toString('utf-8');
140
+ const lines = text.split(/\r?\n/).filter((line, idx, arr) => {
141
+ return line || idx < arr.length - 1;
142
+ });
143
+ if (lines.length === 0)
144
+ return;
145
+ let buffer = this.outputBuffers.get(index);
146
+ if (!buffer) {
147
+ buffer = { lines: [] };
148
+ this.outputBuffers.set(index, buffer);
149
+ }
150
+ buffer.lines.push(...lines);
151
+ this.scheduleFlush();
152
+ }
153
+ scheduleFlush() {
154
+ if (this.flushScheduled)
155
+ return;
156
+ this.flushScheduled = true;
157
+ setTimeout(() => this.flushOutput(), OUTPUT_BATCH_MS);
158
+ }
159
+ flushOutput() {
160
+ this.flushScheduled = false;
161
+ const buffersSnapshot = this.outputBuffers;
162
+ this.outputBuffers = new Map();
163
+ if (buffersSnapshot.size === 0)
164
+ return;
165
+ for (const [index, buffer] of buffersSnapshot.entries()) {
166
+ if (buffer.lines.length > 0) {
167
+ this.options.callbacks.onOutputUpdate(index, buffer.lines);
168
+ }
169
+ }
170
+ }
171
+ }
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Ring Buffer Implementation
3
+ *
4
+ * A fixed-capacity circular buffer with O(1) push operations.
5
+ * When full, oldest elements are automatically overwritten.
6
+ *
7
+ * Key features:
8
+ * - O(1) push operations (no array shifting)
9
+ * - Configurable capacity with buffer pressure warnings
10
+ * - Track number of dropped items
11
+ * - Dropped line indicator support
12
+ */
13
+ export type RingBufferOptions = {
14
+ /** Maximum number of items to store */
15
+ capacity: number;
16
+ /** Maximum length of each line (truncate longer lines) */
17
+ maxLineLength?: number;
18
+ /** Percentage (0-100) at which to trigger pressure warning */
19
+ warnAtPercentage?: number;
20
+ /** Callback when buffer pressure threshold is reached */
21
+ onPressure?: (usage: number) => void;
22
+ };
23
+ /**
24
+ * A circular buffer that overwrites oldest items when full.
25
+ * All operations are O(1) except toArray() which is O(n).
26
+ */
27
+ export declare class RingBuffer<T> {
28
+ private buffer;
29
+ private head;
30
+ private _length;
31
+ private readonly capacity;
32
+ private readonly maxLineLength?;
33
+ private readonly warnAtPercentage;
34
+ private readonly onPressure?;
35
+ private _droppedCount;
36
+ private warningEmitted;
37
+ constructor(options: RingBufferOptions);
38
+ /**
39
+ * Number of items currently in the buffer
40
+ */
41
+ get length(): number;
42
+ /**
43
+ * Number of items that have been dropped due to capacity limits
44
+ */
45
+ get droppedCount(): number;
46
+ /**
47
+ * Current buffer usage as a percentage (0-100)
48
+ */
49
+ get usagePercentage(): number;
50
+ /**
51
+ * Whether the buffer is at capacity
52
+ */
53
+ get isFull(): boolean;
54
+ /**
55
+ * Push an item into the buffer.
56
+ * If full, the oldest item is overwritten and droppedCount is incremented.
57
+ *
58
+ * @param item - The item to add
59
+ * @returns true if an item was dropped, false otherwise
60
+ */
61
+ push(item: T): boolean;
62
+ /**
63
+ * Push multiple items into the buffer.
64
+ *
65
+ * @param items - Array of items to add
66
+ * @returns Number of items that were dropped
67
+ */
68
+ pushMany(items: T[]): number;
69
+ /**
70
+ * Clear all items from the buffer and reset dropped count.
71
+ */
72
+ clear(): void;
73
+ /**
74
+ * Convert buffer contents to an array in correct order (oldest to newest).
75
+ * This is O(n) where n is the number of items in the buffer.
76
+ */
77
+ toArray(): T[];
78
+ /**
79
+ * Get the item at the specified index (0 = oldest).
80
+ */
81
+ get(index: number): T | undefined;
82
+ /**
83
+ * Get a slice of items from the buffer.
84
+ *
85
+ * @param start - Start index (inclusive)
86
+ * @param end - End index (exclusive), defaults to length
87
+ */
88
+ slice(start: number, end?: number): T[];
89
+ /**
90
+ * Reset the warning flag so it can be emitted again.
91
+ * Useful after displaying a warning to the user.
92
+ */
93
+ resetWarning(): void;
94
+ private checkPressure;
95
+ }
96
+ export type OutputBufferOptions = {
97
+ /** Maximum number of lines to store */
98
+ maxLines?: number;
99
+ /** Maximum length of each line */
100
+ maxLineLength?: number;
101
+ /** Warning threshold percentage */
102
+ warnAtPercentage?: number;
103
+ /** Callback when pressure threshold is reached */
104
+ onPressure?: (tabId: string, usage: number) => void;
105
+ /** Tab identifier for pressure callback */
106
+ tabId?: string;
107
+ };
108
+ /**
109
+ * Specialized output buffer for tab process output.
110
+ * Wraps RingBuffer with dropped line indicator support.
111
+ */
112
+ export declare class OutputBuffer {
113
+ private buffer;
114
+ private readonly tabId;
115
+ private lastReportedDropped;
116
+ constructor(options?: OutputBufferOptions);
117
+ get length(): number;
118
+ get droppedCount(): number;
119
+ get usagePercentage(): number;
120
+ get isFull(): boolean;
121
+ /**
122
+ * Push lines into the buffer.
123
+ */
124
+ push(...lines: string[]): void;
125
+ /**
126
+ * Clear the buffer.
127
+ */
128
+ clear(): void;
129
+ /**
130
+ * Get all lines as an array with dropped line indicator if applicable.
131
+ * The dropped indicator is inserted at the beginning if lines were dropped.
132
+ */
133
+ toArray(): string[];
134
+ /**
135
+ * Get lines without the dropped indicator.
136
+ */
137
+ toArrayRaw(): string[];
138
+ /**
139
+ * Reset the warning flag.
140
+ */
141
+ resetWarning(): void;
142
+ }
143
+ //# sourceMappingURL=ring-buffer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ring-buffer.d.ts","sourceRoot":"","sources":["../src/ring-buffer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,uCAAuC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yDAAyD;IACzD,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC,CAAC;AAMF;;;GAGG;AACH,qBAAa,UAAU,CAAC,CAAC;IACvB,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAA0B;IACtD,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,cAAc,CAAS;gBAEnB,OAAO,EAAE,iBAAiB;IAQtC;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;OAEG;IACH,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED;;OAEG;IACH,IAAI,eAAe,IAAI,MAAM,CAE5B;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED;;;;;;OAMG;IACH,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO;IA8BtB;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,MAAM;IAU5B;;OAEG;IACH,KAAK,IAAI,IAAI;IAQb;;;OAGG;IACH,OAAO,IAAI,CAAC,EAAE;IAqBd;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAWjC;;;;;OAKG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,EAAE;IAiBvC;;;OAGG;IACH,YAAY,IAAI,IAAI;IAQpB,OAAO,CAAC,aAAa;CAStB;AAMD,MAAM,MAAM,mBAAmB,GAAG;IAChC,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kDAAkD;IAClD,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAMF;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,mBAAmB,CAAK;gBAEpB,OAAO,GAAE,mBAAwB;IAY7C,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,IAAI,eAAe,IAAI,MAAM,CAE5B;IAED,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED;;OAEG;IACH,IAAI,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAI9B;;OAEG;IACH,KAAK,IAAI,IAAI;IAKb;;;OAGG;IACH,OAAO,IAAI,MAAM,EAAE;IAenB;;OAEG;IACH,UAAU,IAAI,MAAM,EAAE;IAItB;;OAEG;IACH,YAAY,IAAI,IAAI;CAGrB"}