@appkit/llamacpp-cli 1.5.0 → 1.6.0

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 (95) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/MONITORING-ACCURACY-FIX.md +199 -0
  3. package/PER-PROCESS-METRICS.md +190 -0
  4. package/README.md +57 -8
  5. package/dist/cli.js +9 -6
  6. package/dist/cli.js.map +1 -1
  7. package/dist/commands/create.d.ts.map +1 -1
  8. package/dist/commands/create.js +12 -3
  9. package/dist/commands/create.js.map +1 -1
  10. package/dist/commands/monitor.d.ts.map +1 -1
  11. package/dist/commands/monitor.js +51 -1
  12. package/dist/commands/monitor.js.map +1 -1
  13. package/dist/commands/ps.d.ts +3 -1
  14. package/dist/commands/ps.d.ts.map +1 -1
  15. package/dist/commands/ps.js +75 -5
  16. package/dist/commands/ps.js.map +1 -1
  17. package/dist/commands/server-show.d.ts.map +1 -1
  18. package/dist/commands/server-show.js +10 -3
  19. package/dist/commands/server-show.js.map +1 -1
  20. package/dist/commands/start.d.ts.map +1 -1
  21. package/dist/commands/start.js +14 -2
  22. package/dist/commands/start.js.map +1 -1
  23. package/dist/lib/history-manager.d.ts +46 -0
  24. package/dist/lib/history-manager.d.ts.map +1 -0
  25. package/dist/lib/history-manager.js +157 -0
  26. package/dist/lib/history-manager.js.map +1 -0
  27. package/dist/lib/metrics-aggregator.d.ts +2 -1
  28. package/dist/lib/metrics-aggregator.d.ts.map +1 -1
  29. package/dist/lib/metrics-aggregator.js +15 -4
  30. package/dist/lib/metrics-aggregator.js.map +1 -1
  31. package/dist/lib/system-collector.d.ts +9 -4
  32. package/dist/lib/system-collector.d.ts.map +1 -1
  33. package/dist/lib/system-collector.js +29 -28
  34. package/dist/lib/system-collector.js.map +1 -1
  35. package/dist/tui/HistoricalMonitorApp.d.ts +5 -0
  36. package/dist/tui/HistoricalMonitorApp.d.ts.map +1 -0
  37. package/dist/tui/HistoricalMonitorApp.js +490 -0
  38. package/dist/tui/HistoricalMonitorApp.js.map +1 -0
  39. package/dist/tui/MonitorApp.d.ts.map +1 -1
  40. package/dist/tui/MonitorApp.js +84 -62
  41. package/dist/tui/MonitorApp.js.map +1 -1
  42. package/dist/tui/MultiServerMonitorApp.d.ts +1 -1
  43. package/dist/tui/MultiServerMonitorApp.d.ts.map +1 -1
  44. package/dist/tui/MultiServerMonitorApp.js +293 -77
  45. package/dist/tui/MultiServerMonitorApp.js.map +1 -1
  46. package/dist/types/history-types.d.ts +30 -0
  47. package/dist/types/history-types.d.ts.map +1 -0
  48. package/dist/types/history-types.js +11 -0
  49. package/dist/types/history-types.js.map +1 -0
  50. package/dist/types/monitor-types.d.ts +1 -0
  51. package/dist/types/monitor-types.d.ts.map +1 -1
  52. package/dist/types/server-config.d.ts +1 -0
  53. package/dist/types/server-config.d.ts.map +1 -1
  54. package/dist/types/server-config.js.map +1 -1
  55. package/dist/utils/downsample-utils.d.ts +35 -0
  56. package/dist/utils/downsample-utils.d.ts.map +1 -0
  57. package/dist/utils/downsample-utils.js +107 -0
  58. package/dist/utils/downsample-utils.js.map +1 -0
  59. package/dist/utils/file-utils.d.ts +6 -0
  60. package/dist/utils/file-utils.d.ts.map +1 -1
  61. package/dist/utils/file-utils.js +38 -0
  62. package/dist/utils/file-utils.js.map +1 -1
  63. package/dist/utils/process-utils.d.ts +19 -1
  64. package/dist/utils/process-utils.d.ts.map +1 -1
  65. package/dist/utils/process-utils.js +79 -1
  66. package/dist/utils/process-utils.js.map +1 -1
  67. package/docs/images/.gitkeep +1 -0
  68. package/package.json +3 -1
  69. package/src/cli.ts +9 -6
  70. package/src/commands/create.ts +14 -4
  71. package/src/commands/monitor.ts +21 -1
  72. package/src/commands/ps.ts +88 -5
  73. package/src/commands/server-show.ts +10 -3
  74. package/src/commands/start.ts +15 -2
  75. package/src/lib/history-manager.ts +172 -0
  76. package/src/lib/metrics-aggregator.ts +18 -5
  77. package/src/lib/system-collector.ts +31 -28
  78. package/src/tui/HistoricalMonitorApp.ts +548 -0
  79. package/src/tui/MonitorApp.ts +89 -64
  80. package/src/tui/MultiServerMonitorApp.ts +348 -103
  81. package/src/types/history-types.ts +39 -0
  82. package/src/types/monitor-types.ts +1 -0
  83. package/src/types/server-config.ts +1 -0
  84. package/src/utils/downsample-utils.ts +128 -0
  85. package/src/utils/file-utils.ts +40 -0
  86. package/src/utils/process-utils.ts +85 -1
  87. package/test-load.sh +100 -0
  88. package/dist/tui/components/ErrorState.d.ts +0 -8
  89. package/dist/tui/components/ErrorState.d.ts.map +0 -1
  90. package/dist/tui/components/ErrorState.js +0 -22
  91. package/dist/tui/components/ErrorState.js.map +0 -1
  92. package/dist/tui/components/LoadingState.d.ts +0 -8
  93. package/dist/tui/components/LoadingState.d.ts.map +0 -1
  94. package/dist/tui/components/LoadingState.js +0 -21
  95. package/dist/tui/components/LoadingState.js.map +0 -1
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Downsampling utilities for time-series chart data
3
+ * Uses time-aligned buckets to ensure stable charts as new data arrives
4
+ */
5
+
6
+ export interface TimeSeriesPoint {
7
+ timestamp: number;
8
+ value: number;
9
+ }
10
+
11
+ type AggregationMethod = 'max' | 'mean';
12
+
13
+ const ONE_HOUR_MS = 60 * 60 * 1000;
14
+
15
+ /**
16
+ * Core bucketing logic shared by all downsampling functions.
17
+ * Uses ABSOLUTE bucket boundaries that never shift, ensuring chart stability.
18
+ */
19
+ function createTimeBuckets(
20
+ data: TimeSeriesPoint[],
21
+ targetPoints: number,
22
+ startTime: number,
23
+ endTime: number
24
+ ): number[][] {
25
+ const timeRange = endTime - startTime;
26
+ const bucketDuration = Math.ceil(timeRange / targetPoints);
27
+ const alignedStart = Math.floor(startTime / bucketDuration) * bucketDuration;
28
+ const buckets: number[][] = Array.from({ length: targetPoints }, () => []);
29
+
30
+ for (const point of data) {
31
+ if (point.timestamp < startTime || point.timestamp > endTime) continue;
32
+ const bucketIndex = Math.floor((point.timestamp - alignedStart) / bucketDuration);
33
+ if (bucketIndex >= 0 && bucketIndex < targetPoints) {
34
+ buckets[bucketIndex].push(point.value);
35
+ }
36
+ }
37
+
38
+ return buckets;
39
+ }
40
+
41
+ /**
42
+ * Aggregate bucket values using the specified method.
43
+ */
44
+ function aggregateBuckets(buckets: number[][], method: AggregationMethod): number[] {
45
+ return buckets.map(bucket => {
46
+ const validValues = method === 'max'
47
+ ? bucket.filter(v => !isNaN(v) && v > 0)
48
+ : bucket.filter(v => !isNaN(v) && isFinite(v));
49
+
50
+ if (validValues.length === 0) return 0;
51
+
52
+ if (method === 'max') {
53
+ return Math.max(...validValues);
54
+ }
55
+ return validValues.reduce((sum, v) => sum + v, 0) / validValues.length;
56
+ });
57
+ }
58
+
59
+ /**
60
+ * Downsample using time-aligned bucket max - preserves peaks.
61
+ * Best for: GPU/CPU usage, token speeds where peaks matter.
62
+ */
63
+ export function downsampleMaxTime(data: TimeSeriesPoint[], targetPoints: number): number[] {
64
+ if (data.length === 0) return [];
65
+ if (data.length <= targetPoints) return data.map(d => d.value);
66
+
67
+ const buckets = createTimeBuckets(
68
+ data,
69
+ targetPoints,
70
+ data[0].timestamp,
71
+ data[data.length - 1].timestamp
72
+ );
73
+ return aggregateBuckets(buckets, 'max');
74
+ }
75
+
76
+ /**
77
+ * Downsample using time-aligned bucket mean - preserves average trends.
78
+ * Best for: Memory usage where average is meaningful.
79
+ */
80
+ export function downsampleMeanTime(data: TimeSeriesPoint[], targetPoints: number): number[] {
81
+ if (data.length === 0) return [];
82
+ if (data.length <= targetPoints) return data.map(d => d.value);
83
+
84
+ const buckets = createTimeBuckets(
85
+ data,
86
+ targetPoints,
87
+ data[0].timestamp,
88
+ data[data.length - 1].timestamp
89
+ );
90
+ return aggregateBuckets(buckets, 'mean');
91
+ }
92
+
93
+ /**
94
+ * Calculate downsampling ratio as a display string.
95
+ */
96
+ export function getDownsampleRatio(originalCount: number, targetCount: number): string {
97
+ if (originalCount <= targetCount) return '1:1';
98
+ const ratio = Math.round(originalCount / targetCount);
99
+ return `${ratio}:1`;
100
+ }
101
+
102
+ /**
103
+ * Downsample with full hour coverage using max aggregation.
104
+ * Creates buckets for the entire hour (60 minutes), filling gaps with 0.
105
+ * Best for: Hour view where we want to show the full time range.
106
+ */
107
+ export function downsampleMaxTimeWithFullHour(data: TimeSeriesPoint[], targetPoints: number): number[] {
108
+ if (data.length === 0) return Array(targetPoints).fill(0);
109
+
110
+ const now = Date.now();
111
+ const oneHourAgo = now - ONE_HOUR_MS;
112
+ const buckets = createTimeBuckets(data, targetPoints, oneHourAgo, now);
113
+ return aggregateBuckets(buckets, 'max');
114
+ }
115
+
116
+ /**
117
+ * Downsample with full hour coverage using mean aggregation.
118
+ * Creates buckets for the entire hour (60 minutes), filling gaps with 0.
119
+ * Best for: Hour view where we want to show the full time range.
120
+ */
121
+ export function downsampleMeanTimeWithFullHour(data: TimeSeriesPoint[], targetPoints: number): number[] {
122
+ if (data.length === 0) return Array(targetPoints).fill(0);
123
+
124
+ const now = Date.now();
125
+ const oneHourAgo = now - ONE_HOUR_MS;
126
+ const buckets = createTimeBuckets(data, targetPoints, oneHourAgo, now);
127
+ return aggregateBuckets(buckets, 'mean');
128
+ }
@@ -104,3 +104,43 @@ export function expandHome(filePath: string): string {
104
104
  }
105
105
  return filePath;
106
106
  }
107
+
108
+ /**
109
+ * Parse Metal (GPU) memory allocation from llama-server stderr logs
110
+ * Looks for line: "load_tensors: Metal_Mapped model buffer size = 11120.23 MiB"
111
+ * Returns memory in MB, or null if not found
112
+ */
113
+ export async function parseMetalMemoryFromLog(stderrPath: string): Promise<number | null> {
114
+ try {
115
+ // Check if log file exists
116
+ if (!(await fileExists(stderrPath))) {
117
+ return null;
118
+ }
119
+
120
+ // Open file for reading
121
+ const fileHandle = await fs.open(stderrPath, 'r');
122
+
123
+ try {
124
+ // Read first 256KB (Metal allocation happens early during model loading)
125
+ const buffer = Buffer.alloc(256 * 1024);
126
+ const { bytesRead } = await fileHandle.read(buffer, 0, buffer.length, 0);
127
+ const content = buffer.toString('utf-8', 0, bytesRead);
128
+ const lines = content.split('\n');
129
+
130
+ // Look for Metal_Mapped buffer size
131
+ for (const line of lines) {
132
+ const match = line.match(/Metal_Mapped model buffer size\s*=\s*([\d.]+)\s*MiB/);
133
+ if (match) {
134
+ const sizeInMB = parseFloat(match[1]);
135
+ return isNaN(sizeInMB) ? null : sizeInMB;
136
+ }
137
+ }
138
+
139
+ return null;
140
+ } finally {
141
+ await fileHandle.close();
142
+ }
143
+ } catch {
144
+ return null;
145
+ }
146
+ }
@@ -220,13 +220,97 @@ export async function getBatchProcessMemory(pids: number[]): Promise<Map<number,
220
220
 
221
221
  /**
222
222
  * Get memory usage for a single process in bytes
223
- * Uses 'top' on macOS which includes GPU/Metal memory (more accurate for llama-server)
223
+ * Uses 'top' on macOS which reports CPU memory only (NOT GPU/Metal memory)
224
224
  * Returns null if process not found or error occurs
225
225
  * Caches results for 3 seconds to prevent spawning too many top processes
226
226
  *
227
+ * Note: For llama-server processes with GPU offloading, use ServerConfig.metalMemoryMB
228
+ * to get GPU memory allocation (parsed from logs during server startup)
229
+ *
227
230
  * Note: For multiple PIDs, use getBatchProcessMemory() instead - much more efficient
228
231
  */
229
232
  export async function getProcessMemory(pid: number): Promise<number | null> {
230
233
  const result = await getBatchProcessMemory([pid]);
231
234
  return result.get(pid) ?? null;
232
235
  }
236
+
237
+ // Process CPU cache to prevent spawning too many 'ps' processes
238
+ // Cache per PID with 3-second TTL
239
+ const processCpuCache = new Map<number, { value: number | null; timestamp: number }>();
240
+ const PROCESS_CPU_CACHE_TTL = 3000; // 3 seconds
241
+
242
+ /**
243
+ * Batch get CPU usage for multiple processes in one ps call
244
+ * Much more efficient than calling getProcessCpu() multiple times
245
+ * Returns Map<pid, percentage> for all requested PIDs
246
+ */
247
+ export async function getBatchProcessCpu(pids: number[]): Promise<Map<number, number | null>> {
248
+ const result = new Map<number, number | null>();
249
+ const now = Date.now();
250
+
251
+ // Check cache and collect PIDs that need fetching
252
+ const pidsToFetch: number[] = [];
253
+ for (const pid of pids) {
254
+ const cached = processCpuCache.get(pid);
255
+ if (cached && (now - cached.timestamp) < PROCESS_CPU_CACHE_TTL) {
256
+ result.set(pid, cached.value);
257
+ } else {
258
+ pidsToFetch.push(pid);
259
+ }
260
+ }
261
+
262
+ // If all PIDs were cached, return early
263
+ if (pidsToFetch.length === 0) {
264
+ return result;
265
+ }
266
+
267
+ try {
268
+ // Build ps command with all PIDs: ps -p X,Y,Z -o pid=,%cpu=
269
+ const pidList = pidsToFetch.join(',');
270
+ const output = await execCommand(`ps -p ${pidList} -o pid=,%cpu= 2>/dev/null`);
271
+
272
+ // Parse output: each line is "PID %CPU" (e.g., "1438 45.2")
273
+ const lines = output.split('\n');
274
+ for (const line of lines) {
275
+ const match = line.trim().match(/^(\d+)\s+([\d.]+)\s*$/);
276
+ if (!match) continue;
277
+
278
+ const pid = parseInt(match[1], 10);
279
+ const cpuPercent = parseFloat(match[2]);
280
+
281
+ // Cache and store result
282
+ processCpuCache.set(pid, { value: cpuPercent, timestamp: now });
283
+ result.set(pid, cpuPercent);
284
+ }
285
+
286
+ // For any PIDs that weren't in the output, cache null (process not running)
287
+ for (const pid of pidsToFetch) {
288
+ if (!result.has(pid)) {
289
+ processCpuCache.set(pid, { value: null, timestamp: now });
290
+ result.set(pid, null);
291
+ }
292
+ }
293
+
294
+ return result;
295
+ } catch {
296
+ // On error, cache null for all requested PIDs
297
+ for (const pid of pidsToFetch) {
298
+ processCpuCache.set(pid, { value: null, timestamp: now });
299
+ result.set(pid, null);
300
+ }
301
+ return result;
302
+ }
303
+ }
304
+
305
+ /**
306
+ * Get CPU usage for a single process as percentage (0-100+)
307
+ * Uses 'ps -o %cpu' on macOS
308
+ * Returns null if process not found or error occurs
309
+ * Caches results for 3 seconds to prevent spawning too many ps processes
310
+ *
311
+ * Note: For multiple PIDs, use getBatchProcessCpu() instead - much more efficient
312
+ */
313
+ export async function getProcessCpu(pid: number): Promise<number | null> {
314
+ const result = await getBatchProcessCpu([pid]);
315
+ return result.get(pid) ?? null;
316
+ }
package/test-load.sh ADDED
@@ -0,0 +1,100 @@
1
+ #!/bin/bash
2
+
3
+ # Test script for parallel chat requests to multiple llama servers
4
+ # Usage: ./test-load.sh
5
+ # Stop with CTRL-C
6
+
7
+ set -e
8
+
9
+ # Available ports
10
+ PORTS=(9001 9002 9004 9005)
11
+
12
+ # Test prompts with varying complexity
13
+ PROMPTS=(
14
+ "Write a hello world program in Python"
15
+ "Explain quantum computing in simple terms"
16
+ "Write a flappy bird game in Python"
17
+ "What are the benefits of functional programming?"
18
+ "Create a REST API example using FastAPI"
19
+ "Explain the difference between processes and threads"
20
+ "Write a binary search algorithm in JavaScript"
21
+ "What is the difference between HTTP and HTTPS?"
22
+ "Create a simple todo list app in React"
23
+ "Explain Docker containers to a beginner"
24
+ "Write a quicksort implementation in C++"
25
+ "What are the SOLID principles?"
26
+ "Create a SQL query to find duplicate records"
27
+ "Explain async/await in JavaScript"
28
+ "Write a Fibonacci sequence generator in any language"
29
+ )
30
+
31
+ # Colors for output
32
+ RED='\033[0;31m'
33
+ GREEN='\033[0;32m'
34
+ YELLOW='\033[0;33m'
35
+ BLUE='\033[0;34m'
36
+ MAGENTA='\033[0;35m'
37
+ CYAN='\033[0;36m'
38
+ NC='\033[0m' # No Color
39
+
40
+ # Counter for requests
41
+ REQUEST_COUNT=0
42
+
43
+ # Function to run a single chat request
44
+ run_chat() {
45
+ local port=$1
46
+ local prompt=$2
47
+ local request_id=$3
48
+
49
+ echo -e "${CYAN}[Request #${request_id}]${NC} ${YELLOW}Port ${port}:${NC} ${prompt}"
50
+
51
+ # Run the chat request (suppress output except errors)
52
+ if npm run dev -- server run -m "$prompt" "$port" > /dev/null 2>&1; then
53
+ echo -e "${CYAN}[Request #${request_id}]${NC} ${GREEN}✓ Completed${NC} (port ${port})"
54
+ else
55
+ echo -e "${CYAN}[Request #${request_id}]${NC} ${RED}✗ Failed${NC} (port ${port})"
56
+ fi
57
+ }
58
+
59
+ # Trap CTRL-C for clean exit
60
+ trap 'echo -e "\n${YELLOW}Stopping test load script...${NC}"; echo -e "${GREEN}Total requests sent: ${REQUEST_COUNT}${NC}"; exit 0' INT
61
+
62
+ echo -e "${MAGENTA}========================================${NC}"
63
+ echo -e "${MAGENTA} Llama Server Load Test${NC}"
64
+ echo -e "${MAGENTA}========================================${NC}"
65
+ echo -e "${BLUE}Ports: ${PORTS[*]}${NC}"
66
+ echo -e "${BLUE}Parallel requests: 3${NC}"
67
+ echo -e "${BLUE}Press CTRL-C to stop${NC}"
68
+ echo -e "${MAGENTA}========================================${NC}\n"
69
+
70
+ # Function to count running background jobs
71
+ count_running_jobs() {
72
+ jobs -r | wc -l | tr -d ' '
73
+ }
74
+
75
+ # Main loop - maintain exactly 3 concurrent requests at all times
76
+ # Start initial 3 requests
77
+ for i in {1..3}; do
78
+ PORT=${PORTS[$RANDOM % ${#PORTS[@]}]}
79
+ PROMPT=${PROMPTS[$RANDOM % ${#PROMPTS[@]}]}
80
+ ((REQUEST_COUNT++))
81
+ run_chat "$PORT" "$PROMPT" "$REQUEST_COUNT" &
82
+ done
83
+
84
+ # Continuously monitor and start new requests as old ones complete
85
+ while true; do
86
+ # Get count of running background jobs
87
+ RUNNING=$(count_running_jobs)
88
+
89
+ # Start new requests to maintain 3 concurrent
90
+ while [ "$RUNNING" -lt 3 ]; do
91
+ PORT=${PORTS[$RANDOM % ${#PORTS[@]}]}
92
+ PROMPT=${PROMPTS[$RANDOM % ${#PROMPTS[@]}]}
93
+ ((REQUEST_COUNT++))
94
+ run_chat "$PORT" "$PROMPT" "$REQUEST_COUNT" &
95
+ RUNNING=$(count_running_jobs)
96
+ done
97
+
98
+ # Small sleep to avoid busy-waiting
99
+ sleep 0.5
100
+ done
@@ -1,8 +0,0 @@
1
- import React from 'react';
2
- interface ErrorStateProps {
3
- error: string;
4
- onRetry: () => void;
5
- }
6
- export declare function ErrorState({ error, onRetry }: ErrorStateProps): React.JSX.Element;
7
- export {};
8
- //# sourceMappingURL=ErrorState.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ErrorState.d.ts","sourceRoot":"","sources":["../../../src/tui/components/ErrorState.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,eAAe,qBAsB7D"}
@@ -1,22 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ErrorState = ErrorState;
7
- const react_1 = __importDefault(require("react"));
8
- const ink_1 = require("ink");
9
- function ErrorState({ error, onRetry }) {
10
- return (react_1.default.createElement(ink_1.Box, { flexDirection: "column", padding: 2, borderStyle: "round", borderColor: "red" },
11
- react_1.default.createElement(ink_1.Box, null,
12
- react_1.default.createElement(ink_1.Text, { bold: true, color: "red" }, "\u26A0\uFE0F Connection Error")),
13
- react_1.default.createElement(ink_1.Box, { marginTop: 1 },
14
- react_1.default.createElement(ink_1.Text, null, error)),
15
- react_1.default.createElement(ink_1.Box, { marginTop: 2 },
16
- react_1.default.createElement(ink_1.Text, { dimColor: true }, "Press "),
17
- react_1.default.createElement(ink_1.Text, { bold: true }, "[R]"),
18
- react_1.default.createElement(ink_1.Text, { dimColor: true }, " to retry or "),
19
- react_1.default.createElement(ink_1.Text, { bold: true }, "[Q]"),
20
- react_1.default.createElement(ink_1.Text, { dimColor: true }, " to quit"))));
21
- }
22
- //# sourceMappingURL=ErrorState.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ErrorState.js","sourceRoot":"","sources":["../../../src/tui/components/ErrorState.tsx"],"names":[],"mappings":";;;;;AAQA,gCAsBC;AA9BD,kDAA0B;AAC1B,6BAAgC;AAOhC,SAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAmB;IAC5D,OAAO,CACL,8BAAC,SAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,OAAO,EAAE,CAAC,EAAE,WAAW,EAAC,OAAO,EAAC,WAAW,EAAC,KAAK;QAC3E,8BAAC,SAAG;YACF,8BAAC,UAAI,IAAC,IAAI,QAAC,KAAK,EAAC,KAAK,qCAEf,CACH;QAEN,8BAAC,SAAG,IAAC,SAAS,EAAE,CAAC;YACf,8BAAC,UAAI,QAAE,KAAK,CAAQ,CAChB;QAEN,8BAAC,SAAG,IAAC,SAAS,EAAE,CAAC;YACf,8BAAC,UAAI,IAAC,QAAQ,mBAAc;YAC5B,8BAAC,UAAI,IAAC,IAAI,gBAAW;YACrB,8BAAC,UAAI,IAAC,QAAQ,0BAAqB;YACnC,8BAAC,UAAI,IAAC,IAAI,gBAAW;YACrB,8BAAC,UAAI,IAAC,QAAQ,qBAAgB,CAC1B,CACF,CACP,CAAC;AACJ,CAAC"}
@@ -1,8 +0,0 @@
1
- import React from 'react';
2
- interface LoadingStateProps {
3
- message?: string;
4
- progress?: number;
5
- }
6
- export declare function LoadingState({ message, progress }: LoadingStateProps): React.JSX.Element;
7
- export {};
8
- //# sourceMappingURL=LoadingState.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"LoadingState.d.ts","sourceRoot":"","sources":["../../../src/tui/components/LoadingState.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,UAAU,iBAAiB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,YAAY,CAAC,EAAE,OAAsB,EAAE,QAAQ,EAAE,EAAE,iBAAiB,qBAanF"}
@@ -1,21 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.LoadingState = LoadingState;
7
- const react_1 = __importDefault(require("react"));
8
- const ink_1 = require("ink");
9
- function LoadingState({ message = 'Loading...', progress }) {
10
- return (react_1.default.createElement(ink_1.Box, { flexDirection: "column", padding: 2 },
11
- react_1.default.createElement(ink_1.Box, null,
12
- react_1.default.createElement(ink_1.Text, { color: "cyan" },
13
- "\u23F3 ",
14
- message)),
15
- progress !== undefined && (react_1.default.createElement(ink_1.Box, { marginTop: 1 },
16
- react_1.default.createElement(ink_1.Text, { dimColor: true },
17
- "Progress: ",
18
- Math.round(progress),
19
- "%")))));
20
- }
21
- //# sourceMappingURL=LoadingState.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"LoadingState.js","sourceRoot":"","sources":["../../../src/tui/components/LoadingState.tsx"],"names":[],"mappings":";;;;;AAQA,oCAaC;AArBD,kDAA0B;AAC1B,6BAAgC;AAOhC,SAAgB,YAAY,CAAC,EAAE,OAAO,GAAG,YAAY,EAAE,QAAQ,EAAqB;IAClF,OAAO,CACL,8BAAC,SAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,OAAO,EAAE,CAAC;QACpC,8BAAC,SAAG;YACF,8BAAC,UAAI,IAAC,KAAK,EAAC,MAAM;;gBAAI,OAAO,CAAQ,CACjC;QACL,QAAQ,KAAK,SAAS,IAAI,CACzB,8BAAC,SAAG,IAAC,SAAS,EAAE,CAAC;YACf,8BAAC,UAAI,IAAC,QAAQ;;gBAAY,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;oBAAS,CACnD,CACP,CACG,CACP,CAAC;AACJ,CAAC"}