@hatchway/cli 0.50.83 → 0.50.85
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/chunks/{init-Cow6eDTg.js → init-Eo7XainT.js} +3 -2
- package/dist/chunks/{init-Cow6eDTg.js.map → init-Eo7XainT.js.map} +1 -1
- package/dist/chunks/{init-tui-CzevU6HY.js → init-tui-Cgxsmmn-.js} +3 -2
- package/dist/chunks/{init-tui-CzevU6HY.js.map → init-tui-Cgxsmmn-.js.map} +1 -1
- package/dist/chunks/log-buffer-eHyX6VEc.js +279 -0
- package/dist/chunks/log-buffer-eHyX6VEc.js.map +1 -0
- package/dist/chunks/{main-tui-H7JUmYEf.js → main-tui-D580QurF.js} +6 -5
- package/dist/chunks/{main-tui-H7JUmYEf.js.map → main-tui-D580QurF.js.map} +1 -1
- package/dist/chunks/{run-B0hKXBzX.js → run-DbXViD2C.js} +5 -4
- package/dist/chunks/{run-B0hKXBzX.js.map → run-DbXViD2C.js.map} +1 -1
- package/dist/chunks/{runner-logger-instance-Dj_JMznn.js → runner-logger-instance-CaqCFnhr.js} +7 -257
- package/dist/chunks/runner-logger-instance-CaqCFnhr.js.map +1 -0
- package/dist/chunks/{start-B5Vi66EE.js → start-BEIpWjyK.js} +4 -3
- package/dist/chunks/{start-B5Vi66EE.js.map → start-BEIpWjyK.js.map} +1 -1
- package/dist/chunks/{useBuildState-c-9oir2y.js → useBuildState-DjvkDA6v.js} +3 -2
- package/dist/chunks/{useBuildState-c-9oir2y.js.map → useBuildState-DjvkDA6v.js.map} +1 -1
- package/dist/cli/index.js +5 -5
- package/dist/index.js +10 -21
- package/dist/index.js.map +1 -1
- package/package.json +8 -1
- package/dist/chunks/runner-logger-instance-Dj_JMznn.js.map +0 -1
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
// Hatchway CLI - Built with Rollup
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, appendFileSync } from 'node:fs';
|
|
3
|
+
import { resolve, join } from 'node:path';
|
|
4
|
+
import { EventEmitter } from 'node:events';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Get the workspace root directory for the runner.
|
|
8
|
+
* This is where projects will be stored.
|
|
9
|
+
*/
|
|
10
|
+
function getWorkspaceRoot() {
|
|
11
|
+
// Check environment variable first
|
|
12
|
+
const envWorkspace = process.env.WORKSPACE_ROOT;
|
|
13
|
+
if (envWorkspace && existsSync(envWorkspace)) {
|
|
14
|
+
return resolve(envWorkspace);
|
|
15
|
+
}
|
|
16
|
+
// Default to a workspace directory in the user's home
|
|
17
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || '/tmp';
|
|
18
|
+
const defaultWorkspace = resolve(homeDir, 'hatchway-workspace');
|
|
19
|
+
return defaultWorkspace;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* LogBuffer - File-backed circular buffer for log entries
|
|
24
|
+
*
|
|
25
|
+
* Maintains an in-memory buffer of the most recent 100 entries
|
|
26
|
+
* and persists all logs to a file for full history access.
|
|
27
|
+
*/
|
|
28
|
+
const DEFAULT_BUFFER_SIZE = 100;
|
|
29
|
+
// Stable, absolute logs dir beside the built apps (workspace root) — a relative
|
|
30
|
+
// 'logs' resolved against process.cwd(), so writing/reading diverged when the
|
|
31
|
+
// runner was launched from different directories (TUI copy showed 0 lines).
|
|
32
|
+
const LOG_DIR = join(getWorkspaceRoot(), 'logs');
|
|
33
|
+
const LOG_FILE = 'runner-tui.log';
|
|
34
|
+
class LogBuffer extends EventEmitter {
|
|
35
|
+
constructor(options) {
|
|
36
|
+
super();
|
|
37
|
+
this.buffer = [];
|
|
38
|
+
this.maxSize = options?.maxSize ?? DEFAULT_BUFFER_SIZE;
|
|
39
|
+
this.sessionStartTime = Date.now();
|
|
40
|
+
// Set up log file path
|
|
41
|
+
const logDir = options?.logDir ?? LOG_DIR;
|
|
42
|
+
if (!existsSync(logDir)) {
|
|
43
|
+
mkdirSync(logDir, { recursive: true });
|
|
44
|
+
}
|
|
45
|
+
this.logFilePath = join(logDir, LOG_FILE);
|
|
46
|
+
// Write session start marker
|
|
47
|
+
this.writeToFile(`\n${'='.repeat(60)}\n`);
|
|
48
|
+
this.writeToFile(`SESSION START: ${new Date().toISOString()}\n`);
|
|
49
|
+
this.writeToFile(`${'='.repeat(60)}\n\n`);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Add a log entry to the buffer and file
|
|
53
|
+
*/
|
|
54
|
+
add(entry) {
|
|
55
|
+
// Add to in-memory buffer (circular)
|
|
56
|
+
this.buffer.push(entry);
|
|
57
|
+
if (this.buffer.length > this.maxSize) {
|
|
58
|
+
this.buffer.shift();
|
|
59
|
+
}
|
|
60
|
+
// Write to file
|
|
61
|
+
this.writeToFile(this.formatEntryForFile(entry));
|
|
62
|
+
// Emit event for subscribers (TUI components)
|
|
63
|
+
this.emit('log', entry);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get the most recent N entries from memory
|
|
67
|
+
*/
|
|
68
|
+
getRecent(count) {
|
|
69
|
+
const n = count ?? this.maxSize;
|
|
70
|
+
return this.buffer.slice(-n);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get all entries currently in memory
|
|
74
|
+
*/
|
|
75
|
+
getAll() {
|
|
76
|
+
return [...this.buffer];
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Get filtered entries from memory
|
|
80
|
+
*/
|
|
81
|
+
getFiltered(filter) {
|
|
82
|
+
return this.buffer.filter(entry => this.matchesFilter(entry, filter));
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Read entries from the log file (for full history)
|
|
86
|
+
* Returns parsed log entries from the current session
|
|
87
|
+
*/
|
|
88
|
+
readFromFile(maxLines) {
|
|
89
|
+
if (!existsSync(this.logFilePath)) {
|
|
90
|
+
return [];
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
const content = readFileSync(this.logFilePath, 'utf-8');
|
|
94
|
+
const lines = content.split('\n').filter(line => line.trim());
|
|
95
|
+
// Find the last session marker and only read from there
|
|
96
|
+
let sessionStart = 0;
|
|
97
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
98
|
+
if (lines[i].includes('SESSION START:')) {
|
|
99
|
+
sessionStart = i + 1;
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const sessionLines = lines.slice(sessionStart);
|
|
104
|
+
const entries = [];
|
|
105
|
+
for (const line of sessionLines) {
|
|
106
|
+
const parsed = this.parseLogLine(line);
|
|
107
|
+
if (parsed) {
|
|
108
|
+
entries.push(parsed);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (maxLines && entries.length > maxLines) {
|
|
112
|
+
return entries.slice(-maxLines);
|
|
113
|
+
}
|
|
114
|
+
return entries;
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
console.error('Failed to read log file:', error);
|
|
118
|
+
return [];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Get the log file path for external access
|
|
123
|
+
*/
|
|
124
|
+
getLogFilePath() {
|
|
125
|
+
return this.logFilePath;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Convert buffer contents to plain text (for copying)
|
|
129
|
+
*/
|
|
130
|
+
toText(entries) {
|
|
131
|
+
const items = entries ?? this.buffer;
|
|
132
|
+
return items.map(entry => this.formatEntryForDisplay(entry)).join('\n');
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Clear the in-memory buffer (file is preserved)
|
|
136
|
+
*/
|
|
137
|
+
clear() {
|
|
138
|
+
this.buffer = [];
|
|
139
|
+
this.emit('clear');
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Subscribe to new log entries
|
|
143
|
+
*/
|
|
144
|
+
onLog(callback) {
|
|
145
|
+
this.on('log', callback);
|
|
146
|
+
return () => this.off('log', callback);
|
|
147
|
+
}
|
|
148
|
+
// Private methods
|
|
149
|
+
writeToFile(content) {
|
|
150
|
+
try {
|
|
151
|
+
appendFileSync(this.logFilePath, content);
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
// Silently fail - don't break logging if file write fails
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
formatEntryForFile(entry) {
|
|
158
|
+
const timestamp = new Date(entry.timestamp).toISOString();
|
|
159
|
+
const level = entry.level.toUpperCase().padEnd(7);
|
|
160
|
+
const category = entry.category.padEnd(12);
|
|
161
|
+
let line = `[${timestamp}] [${level}] [${category}] ${entry.message}`;
|
|
162
|
+
if (entry.toolName) {
|
|
163
|
+
line += ` | tool=${entry.toolName}`;
|
|
164
|
+
if (entry.toolArgs) {
|
|
165
|
+
line += ` args=${entry.toolArgs}`;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (entry.buildId) {
|
|
169
|
+
line += ` | build=${entry.buildId}`;
|
|
170
|
+
}
|
|
171
|
+
if (entry.data && Object.keys(entry.data).length > 0) {
|
|
172
|
+
line += ` | data=${JSON.stringify(entry.data)}`;
|
|
173
|
+
}
|
|
174
|
+
return line + '\n';
|
|
175
|
+
}
|
|
176
|
+
formatEntryForDisplay(entry) {
|
|
177
|
+
const time = new Date(entry.timestamp).toLocaleTimeString('en-US', {
|
|
178
|
+
hour12: false,
|
|
179
|
+
hour: '2-digit',
|
|
180
|
+
minute: '2-digit',
|
|
181
|
+
second: '2-digit',
|
|
182
|
+
});
|
|
183
|
+
const levelIcon = {
|
|
184
|
+
debug: ' ',
|
|
185
|
+
info: '●',
|
|
186
|
+
success: '✓',
|
|
187
|
+
warn: '⚠',
|
|
188
|
+
error: '✗',
|
|
189
|
+
}[entry.level];
|
|
190
|
+
if (entry.toolName) {
|
|
191
|
+
return `${time} 🔧 ${entry.toolName}${entry.toolArgs ? ` ${entry.toolArgs}` : ''}`;
|
|
192
|
+
}
|
|
193
|
+
return `${time} ${levelIcon} ${entry.message}`;
|
|
194
|
+
}
|
|
195
|
+
parseLogLine(line) {
|
|
196
|
+
// Parse format: [ISO_TIMESTAMP] [LEVEL ] [CATEGORY ] message | key=value...
|
|
197
|
+
const match = line.match(/^\[([^\]]+)\] \[([^\]]+)\] \[([^\]]+)\] (.+)$/);
|
|
198
|
+
if (!match) {
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
const [, timestamp, levelRaw, categoryRaw, rest] = match;
|
|
202
|
+
const level = levelRaw.trim().toLowerCase();
|
|
203
|
+
const category = categoryRaw.trim();
|
|
204
|
+
// Parse message and optional fields
|
|
205
|
+
const parts = rest.split(' | ');
|
|
206
|
+
const message = parts[0];
|
|
207
|
+
const entry = {
|
|
208
|
+
id: `${Date.parse(timestamp)}-${Math.random().toString(36).slice(2, 8)}`,
|
|
209
|
+
timestamp: Date.parse(timestamp),
|
|
210
|
+
level,
|
|
211
|
+
category,
|
|
212
|
+
message,
|
|
213
|
+
};
|
|
214
|
+
// Parse optional key=value pairs
|
|
215
|
+
for (let i = 1; i < parts.length; i++) {
|
|
216
|
+
const [key, ...valueParts] = parts[i].split('=');
|
|
217
|
+
const value = valueParts.join('=');
|
|
218
|
+
switch (key) {
|
|
219
|
+
case 'tool':
|
|
220
|
+
entry.toolName = value;
|
|
221
|
+
break;
|
|
222
|
+
case 'args':
|
|
223
|
+
entry.toolArgs = value;
|
|
224
|
+
break;
|
|
225
|
+
case 'build':
|
|
226
|
+
entry.buildId = value;
|
|
227
|
+
break;
|
|
228
|
+
case 'data':
|
|
229
|
+
try {
|
|
230
|
+
entry.data = JSON.parse(value);
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
// Ignore parse errors
|
|
234
|
+
}
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return entry;
|
|
239
|
+
}
|
|
240
|
+
matchesFilter(entry, filter) {
|
|
241
|
+
if (filter.levels && !filter.levels.includes(entry.level)) {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
if (filter.categories && !filter.categories.includes(entry.category)) {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
if (filter.buildId && entry.buildId !== filter.buildId) {
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
if (filter.verbose === false && entry.verbose) {
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
if (filter.search) {
|
|
254
|
+
const searchLower = filter.search.toLowerCase();
|
|
255
|
+
const messageMatch = entry.message.toLowerCase().includes(searchLower);
|
|
256
|
+
const toolMatch = entry.toolName?.toLowerCase().includes(searchLower);
|
|
257
|
+
const argsMatch = entry.toolArgs?.toLowerCase().includes(searchLower);
|
|
258
|
+
if (!messageMatch && !toolMatch && !argsMatch) {
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
// Singleton instance
|
|
266
|
+
let instance = null;
|
|
267
|
+
function getLogBuffer() {
|
|
268
|
+
if (!instance) {
|
|
269
|
+
instance = new LogBuffer();
|
|
270
|
+
}
|
|
271
|
+
return instance;
|
|
272
|
+
}
|
|
273
|
+
function createLogBuffer(options) {
|
|
274
|
+
instance = new LogBuffer(options);
|
|
275
|
+
return instance;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export { getWorkspaceRoot as a, createLogBuffer as c, getLogBuffer as g };
|
|
279
|
+
//# sourceMappingURL=log-buffer-eHyX6VEc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-buffer-eHyX6VEc.js","sources":["../../src/lib/workspace.ts","../../src/lib/logging/log-buffer.ts"],"sourcesContent":["import { resolve } from 'node:path';\nimport { existsSync } from 'node:fs';\n\n/**\n * Get the workspace root directory for the runner.\n * This is where projects will be stored.\n */\nexport function getWorkspaceRoot(): string {\n // Check environment variable first\n const envWorkspace = process.env.WORKSPACE_ROOT;\n if (envWorkspace && existsSync(envWorkspace)) {\n return resolve(envWorkspace);\n }\n\n // Default to a workspace directory in the user's home\n const homeDir = process.env.HOME || process.env.USERPROFILE || '/tmp';\n const defaultWorkspace = resolve(homeDir, 'hatchway-workspace');\n\n return defaultWorkspace;\n}\n","/**\n * LogBuffer - File-backed circular buffer for log entries\n * \n * Maintains an in-memory buffer of the most recent 100 entries\n * and persists all logs to a file for full history access.\n */\n\nimport { existsSync, mkdirSync, appendFileSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { EventEmitter } from 'node:events';\nimport { getWorkspaceRoot } from '../workspace.js';\nimport type { LogEntry, LogFilter } from './types.js';\n\nconst DEFAULT_BUFFER_SIZE = 100;\n// Stable, absolute logs dir beside the built apps (workspace root) — a relative\n// 'logs' resolved against process.cwd(), so writing/reading diverged when the\n// runner was launched from different directories (TUI copy showed 0 lines).\nconst LOG_DIR = join(getWorkspaceRoot(), 'logs');\nconst LOG_FILE = 'runner-tui.log';\n\nexport class LogBuffer extends EventEmitter {\n private buffer: LogEntry[] = [];\n private maxSize: number;\n private logFilePath: string;\n private sessionStartTime: number;\n\n constructor(options?: { maxSize?: number; logDir?: string }) {\n super();\n this.maxSize = options?.maxSize ?? DEFAULT_BUFFER_SIZE;\n this.sessionStartTime = Date.now();\n \n // Set up log file path\n const logDir = options?.logDir ?? LOG_DIR;\n if (!existsSync(logDir)) {\n mkdirSync(logDir, { recursive: true });\n }\n this.logFilePath = join(logDir, LOG_FILE);\n \n // Write session start marker\n this.writeToFile(`\\n${'='.repeat(60)}\\n`);\n this.writeToFile(`SESSION START: ${new Date().toISOString()}\\n`);\n this.writeToFile(`${'='.repeat(60)}\\n\\n`);\n }\n\n /**\n * Add a log entry to the buffer and file\n */\n add(entry: LogEntry): void {\n // Add to in-memory buffer (circular)\n this.buffer.push(entry);\n if (this.buffer.length > this.maxSize) {\n this.buffer.shift();\n }\n\n // Write to file\n this.writeToFile(this.formatEntryForFile(entry));\n\n // Emit event for subscribers (TUI components)\n this.emit('log', entry);\n }\n\n /**\n * Get the most recent N entries from memory\n */\n getRecent(count?: number): LogEntry[] {\n const n = count ?? this.maxSize;\n return this.buffer.slice(-n);\n }\n\n /**\n * Get all entries currently in memory\n */\n getAll(): LogEntry[] {\n return [...this.buffer];\n }\n\n /**\n * Get filtered entries from memory\n */\n getFiltered(filter: LogFilter): LogEntry[] {\n return this.buffer.filter(entry => this.matchesFilter(entry, filter));\n }\n\n /**\n * Read entries from the log file (for full history)\n * Returns parsed log entries from the current session\n */\n readFromFile(maxLines?: number): LogEntry[] {\n if (!existsSync(this.logFilePath)) {\n return [];\n }\n\n try {\n const content = readFileSync(this.logFilePath, 'utf-8');\n const lines = content.split('\\n').filter(line => line.trim());\n \n // Find the last session marker and only read from there\n let sessionStart = 0;\n for (let i = lines.length - 1; i >= 0; i--) {\n if (lines[i].includes('SESSION START:')) {\n sessionStart = i + 1;\n break;\n }\n }\n\n const sessionLines = lines.slice(sessionStart);\n const entries: LogEntry[] = [];\n\n for (const line of sessionLines) {\n const parsed = this.parseLogLine(line);\n if (parsed) {\n entries.push(parsed);\n }\n }\n\n if (maxLines && entries.length > maxLines) {\n return entries.slice(-maxLines);\n }\n\n return entries;\n } catch (error) {\n console.error('Failed to read log file:', error);\n return [];\n }\n }\n\n /**\n * Get the log file path for external access\n */\n getLogFilePath(): string {\n return this.logFilePath;\n }\n\n /**\n * Convert buffer contents to plain text (for copying)\n */\n toText(entries?: LogEntry[]): string {\n const items = entries ?? this.buffer;\n return items.map(entry => this.formatEntryForDisplay(entry)).join('\\n');\n }\n\n /**\n * Clear the in-memory buffer (file is preserved)\n */\n clear(): void {\n this.buffer = [];\n this.emit('clear');\n }\n\n /**\n * Subscribe to new log entries\n */\n onLog(callback: (entry: LogEntry) => void): () => void {\n this.on('log', callback);\n return () => this.off('log', callback);\n }\n\n // Private methods\n\n private writeToFile(content: string): void {\n try {\n appendFileSync(this.logFilePath, content);\n } catch (error) {\n // Silently fail - don't break logging if file write fails\n }\n }\n\n private formatEntryForFile(entry: LogEntry): string {\n const timestamp = new Date(entry.timestamp).toISOString();\n const level = entry.level.toUpperCase().padEnd(7);\n const category = entry.category.padEnd(12);\n \n let line = `[${timestamp}] [${level}] [${category}] ${entry.message}`;\n \n if (entry.toolName) {\n line += ` | tool=${entry.toolName}`;\n if (entry.toolArgs) {\n line += ` args=${entry.toolArgs}`;\n }\n }\n \n if (entry.buildId) {\n line += ` | build=${entry.buildId}`;\n }\n \n if (entry.data && Object.keys(entry.data).length > 0) {\n line += ` | data=${JSON.stringify(entry.data)}`;\n }\n \n return line + '\\n';\n }\n\n private formatEntryForDisplay(entry: LogEntry): string {\n const time = new Date(entry.timestamp).toLocaleTimeString('en-US', {\n hour12: false,\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n \n const levelIcon = {\n debug: ' ',\n info: '●',\n success: '✓',\n warn: '⚠',\n error: '✗',\n }[entry.level];\n\n if (entry.toolName) {\n return `${time} 🔧 ${entry.toolName}${entry.toolArgs ? ` ${entry.toolArgs}` : ''}`;\n }\n\n return `${time} ${levelIcon} ${entry.message}`;\n }\n\n private parseLogLine(line: string): LogEntry | null {\n // Parse format: [ISO_TIMESTAMP] [LEVEL ] [CATEGORY ] message | key=value...\n const match = line.match(/^\\[([^\\]]+)\\] \\[([^\\]]+)\\] \\[([^\\]]+)\\] (.+)$/);\n if (!match) {\n return null;\n }\n\n const [, timestamp, levelRaw, categoryRaw, rest] = match;\n const level = levelRaw.trim().toLowerCase() as LogEntry['level'];\n const category = categoryRaw.trim() as LogEntry['category'];\n\n // Parse message and optional fields\n const parts = rest.split(' | ');\n const message = parts[0];\n\n const entry: LogEntry = {\n id: `${Date.parse(timestamp)}-${Math.random().toString(36).slice(2, 8)}`,\n timestamp: Date.parse(timestamp),\n level,\n category,\n message,\n };\n\n // Parse optional key=value pairs\n for (let i = 1; i < parts.length; i++) {\n const [key, ...valueParts] = parts[i].split('=');\n const value = valueParts.join('=');\n \n switch (key) {\n case 'tool':\n entry.toolName = value;\n break;\n case 'args':\n entry.toolArgs = value;\n break;\n case 'build':\n entry.buildId = value;\n break;\n case 'data':\n try {\n entry.data = JSON.parse(value);\n } catch {\n // Ignore parse errors\n }\n break;\n }\n }\n\n return entry;\n }\n\n private matchesFilter(entry: LogEntry, filter: LogFilter): boolean {\n if (filter.levels && !filter.levels.includes(entry.level)) {\n return false;\n }\n \n if (filter.categories && !filter.categories.includes(entry.category)) {\n return false;\n }\n \n if (filter.buildId && entry.buildId !== filter.buildId) {\n return false;\n }\n \n if (filter.verbose === false && entry.verbose) {\n return false;\n }\n \n if (filter.search) {\n const searchLower = filter.search.toLowerCase();\n const messageMatch = entry.message.toLowerCase().includes(searchLower);\n const toolMatch = entry.toolName?.toLowerCase().includes(searchLower);\n const argsMatch = entry.toolArgs?.toLowerCase().includes(searchLower);\n \n if (!messageMatch && !toolMatch && !argsMatch) {\n return false;\n }\n }\n \n return true;\n }\n}\n\n// Singleton instance\nlet instance: LogBuffer | null = null;\n\nexport function getLogBuffer(): LogBuffer {\n if (!instance) {\n instance = new LogBuffer();\n }\n return instance;\n}\n\nexport function createLogBuffer(options?: { maxSize?: number; logDir?: string }): LogBuffer {\n instance = new LogBuffer(options);\n return instance;\n}\n"],"names":[],"mappings":";;;;;AAGA;;;AAGG;SACa,gBAAgB,GAAA;;AAE9B,IAAA,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc;AAC/C,IAAA,IAAI,YAAY,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE;AAC5C,QAAA,OAAO,OAAO,CAAC,YAAY,CAAC;IAC9B;;AAGA,IAAA,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,MAAM;IACrE,MAAM,gBAAgB,GAAG,OAAO,CAAC,OAAO,EAAE,oBAAoB,CAAC;AAE/D,IAAA,OAAO,gBAAgB;AACzB;;ACnBA;;;;;AAKG;AAQH,MAAM,mBAAmB,GAAG,GAAG;AAC/B;AACA;AACA;AACA,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,EAAE,EAAE,MAAM,CAAC;AAChD,MAAM,QAAQ,GAAG,gBAAgB;AAE3B,MAAO,SAAU,SAAQ,YAAY,CAAA;AAMzC,IAAA,WAAA,CAAY,OAA+C,EAAA;AACzD,QAAA,KAAK,EAAE;QAND,IAAA,CAAA,MAAM,GAAe,EAAE;QAO7B,IAAI,CAAC,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,mBAAmB;AACtD,QAAA,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,EAAE;;AAGlC,QAAA,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,OAAO;AACzC,QAAA,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE;YACvB,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QACxC;QACA,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC;;AAGzC,QAAA,IAAI,CAAC,WAAW,CAAC,CAAA,EAAA,EAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA,EAAA,CAAI,CAAC;AACzC,QAAA,IAAI,CAAC,WAAW,CAAC,CAAA,eAAA,EAAkB,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA,EAAA,CAAI,CAAC;AAChE,QAAA,IAAI,CAAC,WAAW,CAAC,CAAA,EAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA,IAAA,CAAM,CAAC;IAC3C;AAEA;;AAEG;AACH,IAAA,GAAG,CAAC,KAAe,EAAA;;AAEjB,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;QACvB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE;AACrC,YAAA,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;QACrB;;QAGA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;;AAGhD,QAAA,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC;IACzB;AAEA;;AAEG;AACH,IAAA,SAAS,CAAC,KAAc,EAAA;AACtB,QAAA,MAAM,CAAC,GAAG,KAAK,IAAI,IAAI,CAAC,OAAO;QAC/B,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC9B;AAEA;;AAEG;IACH,MAAM,GAAA;AACJ,QAAA,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;IACzB;AAEA;;AAEG;AACH,IAAA,WAAW,CAAC,MAAiB,EAAA;AAC3B,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACvE;AAEA;;;AAGG;AACH,IAAA,YAAY,CAAC,QAAiB,EAAA;QAC5B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE;AACjC,YAAA,OAAO,EAAE;QACX;AAEA,QAAA,IAAI;YACF,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC;YACvD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;;YAG7D,IAAI,YAAY,GAAG,CAAC;AACpB,YAAA,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE;gBAC1C,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE;AACvC,oBAAA,YAAY,GAAG,CAAC,GAAG,CAAC;oBACpB;gBACF;YACF;YAEA,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC;YAC9C,MAAM,OAAO,GAAe,EAAE;AAE9B,YAAA,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE;gBAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;gBACtC,IAAI,MAAM,EAAE;AACV,oBAAA,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;gBACtB;YACF;YAEA,IAAI,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,QAAQ,EAAE;AACzC,gBAAA,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC;YACjC;AAEA,YAAA,OAAO,OAAO;QAChB;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC;AAChD,YAAA,OAAO,EAAE;QACX;IACF;AAEA;;AAEG;IACH,cAAc,GAAA;QACZ,OAAO,IAAI,CAAC,WAAW;IACzB;AAEA;;AAEG;AACH,IAAA,MAAM,CAAC,OAAoB,EAAA;AACzB,QAAA,MAAM,KAAK,GAAG,OAAO,IAAI,IAAI,CAAC,MAAM;QACpC,OAAO,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;IACzE;AAEA;;AAEG;IACH,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,MAAM,GAAG,EAAE;AAChB,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;IACpB;AAEA;;AAEG;AACH,IAAA,KAAK,CAAC,QAAmC,EAAA;AACvC,QAAA,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC;QACxB,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC;IACxC;;AAIQ,IAAA,WAAW,CAAC,OAAe,EAAA;AACjC,QAAA,IAAI;AACF,YAAA,cAAc,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC;QAC3C;QAAE,OAAO,KAAK,EAAE;;QAEhB;IACF;AAEQ,IAAA,kBAAkB,CAAC,KAAe,EAAA;AACxC,QAAA,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE;AACzD,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;AAE1C,QAAA,IAAI,IAAI,GAAG,CAAA,CAAA,EAAI,SAAS,CAAA,GAAA,EAAM,KAAK,CAAA,GAAA,EAAM,QAAQ,CAAA,EAAA,EAAK,KAAK,CAAC,OAAO,EAAE;AAErE,QAAA,IAAI,KAAK,CAAC,QAAQ,EAAE;AAClB,YAAA,IAAI,IAAI,CAAA,QAAA,EAAW,KAAK,CAAC,QAAQ,EAAE;AACnC,YAAA,IAAI,KAAK,CAAC,QAAQ,EAAE;AAClB,gBAAA,IAAI,IAAI,CAAA,MAAA,EAAS,KAAK,CAAC,QAAQ,EAAE;YACnC;QACF;AAEA,QAAA,IAAI,KAAK,CAAC,OAAO,EAAE;AACjB,YAAA,IAAI,IAAI,CAAA,SAAA,EAAY,KAAK,CAAC,OAAO,EAAE;QACrC;AAEA,QAAA,IAAI,KAAK,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;YACpD,IAAI,IAAI,CAAA,QAAA,EAAW,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA,CAAE;QACjD;QAEA,OAAO,IAAI,GAAG,IAAI;IACpB;AAEQ,IAAA,qBAAqB,CAAC,KAAe,EAAA;AAC3C,QAAA,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,kBAAkB,CAAC,OAAO,EAAE;AACjE,YAAA,MAAM,EAAE,KAAK;AACb,YAAA,IAAI,EAAE,SAAS;AACf,YAAA,MAAM,EAAE,SAAS;AACjB,YAAA,MAAM,EAAE,SAAS;AAClB,SAAA,CAAC;AAEF,QAAA,MAAM,SAAS,GAAG;AAChB,YAAA,KAAK,EAAE,IAAI;AACX,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,OAAO,EAAE,GAAG;AACZ,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA,CAAC,KAAK,CAAC,KAAK,CAAC;AAEd,QAAA,IAAI,KAAK,CAAC,QAAQ,EAAE;YAClB,OAAO,CAAA,EAAG,IAAI,CAAA,MAAA,EAAS,KAAK,CAAC,QAAQ,CAAA,EAAG,KAAK,CAAC,QAAQ,GAAG,CAAA,CAAA,EAAI,KAAK,CAAC,QAAQ,CAAA,CAAE,GAAG,EAAE,CAAA,CAAE;QACtF;QAEA,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,SAAS,IAAI,KAAK,CAAC,OAAO,CAAA,CAAE;IAChD;AAEQ,IAAA,YAAY,CAAC,IAAY,EAAA;;QAE/B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,+CAA+C,CAAC;QACzE,IAAI,CAAC,KAAK,EAAE;AACV,YAAA,OAAO,IAAI;QACb;AAEA,QAAA,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,KAAK;QACxD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,EAAuB;AAChE,QAAA,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,EAA0B;;QAG3D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;AAC/B,QAAA,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC;AAExB,QAAA,MAAM,KAAK,GAAa;YACtB,EAAE,EAAE,CAAA,EAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA,CAAA,EAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA,CAAE;AACxE,YAAA,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;YAChC,KAAK;YACL,QAAQ;YACR,OAAO;SACR;;AAGD,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACrC,YAAA,MAAM,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;YAChD,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC;YAElC,QAAQ,GAAG;AACT,gBAAA,KAAK,MAAM;AACT,oBAAA,KAAK,CAAC,QAAQ,GAAG,KAAK;oBACtB;AACF,gBAAA,KAAK,MAAM;AACT,oBAAA,KAAK,CAAC,QAAQ,GAAG,KAAK;oBACtB;AACF,gBAAA,KAAK,OAAO;AACV,oBAAA,KAAK,CAAC,OAAO,GAAG,KAAK;oBACrB;AACF,gBAAA,KAAK,MAAM;AACT,oBAAA,IAAI;wBACF,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;oBAChC;AAAE,oBAAA,MAAM;;oBAER;oBACA;;QAEN;AAEA,QAAA,OAAO,KAAK;IACd;IAEQ,aAAa,CAAC,KAAe,EAAE,MAAiB,EAAA;AACtD,QAAA,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;AACzD,YAAA,OAAO,KAAK;QACd;AAEA,QAAA,IAAI,MAAM,CAAC,UAAU,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE;AACpE,YAAA,OAAO,KAAK;QACd;AAEA,QAAA,IAAI,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO,EAAE;AACtD,YAAA,OAAO,KAAK;QACd;QAEA,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE;AAC7C,YAAA,OAAO,KAAK;QACd;AAEA,QAAA,IAAI,MAAM,CAAC,MAAM,EAAE;YACjB,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE;AAC/C,YAAA,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;AACtE,YAAA,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;AACrE,YAAA,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;YAErE,IAAI,CAAC,YAAY,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,EAAE;AAC7C,gBAAA,OAAO,KAAK;YACd;QACF;AAEA,QAAA,OAAO,IAAI;IACb;AACD;AAED;AACA,IAAI,QAAQ,GAAqB,IAAI;SAErB,YAAY,GAAA;IAC1B,IAAI,CAAC,QAAQ,EAAE;AACb,QAAA,QAAQ,GAAG,IAAI,SAAS,EAAE;IAC5B;AACA,IAAA,OAAO,QAAQ;AACjB;AAEM,SAAU,eAAe,CAAC,OAA+C,EAAA;AAC7E,IAAA,QAAQ,GAAG,IAAI,SAAS,CAAC,OAAO,CAAC;AACjC,IAAA,OAAO,QAAQ;AACjB;;;;"}
|
|
@@ -4,7 +4,7 @@ import 'chalk';
|
|
|
4
4
|
import { userInfo, homedir } from 'node:os';
|
|
5
5
|
import { join } from 'node:path';
|
|
6
6
|
import { B as Banner } from './Banner-_pJB7dCO.js';
|
|
7
|
-
import '
|
|
7
|
+
import './log-buffer-eHyX6VEc.js';
|
|
8
8
|
import 'node:events';
|
|
9
9
|
import 'node:stream';
|
|
10
10
|
import 'node:process';
|
|
@@ -15,6 +15,7 @@ import 'node:child_process';
|
|
|
15
15
|
import { c as configManager } from './config-manager-DST6RbP8.js';
|
|
16
16
|
import 'assert';
|
|
17
17
|
import 'events';
|
|
18
|
+
import 'node:fs';
|
|
18
19
|
import 'module';
|
|
19
20
|
import 'node:buffer';
|
|
20
21
|
import 'conf';
|
|
@@ -608,7 +609,7 @@ async function startRunner(config) {
|
|
|
608
609
|
console.log('\n Starting Hatchway Runner...\n');
|
|
609
610
|
console.log(` Runner ID: ${config.runnerId}`);
|
|
610
611
|
console.log(' Connecting to remote server...\n');
|
|
611
|
-
const { runCommand } = await import('./run-
|
|
612
|
+
const { runCommand } = await import('./run-DbXViD2C.js');
|
|
612
613
|
await runCommand({
|
|
613
614
|
secret: config.key,
|
|
614
615
|
runnerId: config.runnerId,
|
|
@@ -619,7 +620,7 @@ async function startRunner(config) {
|
|
|
619
620
|
*/
|
|
620
621
|
async function startLocalMode() {
|
|
621
622
|
console.log('\n Starting Hatchway in Local Mode...\n');
|
|
622
|
-
const { startCommand } = await import('./start-
|
|
623
|
+
const { startCommand } = await import('./start-BEIpWjyK.js');
|
|
623
624
|
await startCommand({});
|
|
624
625
|
}
|
|
625
626
|
/**
|
|
@@ -630,7 +631,7 @@ async function runInitialization(config) {
|
|
|
630
631
|
const workspace = config.workspace.startsWith('~')
|
|
631
632
|
? config.workspace.replace('~', homedir())
|
|
632
633
|
: config.workspace;
|
|
633
|
-
const { initTUICommand } = await import('./init-tui-
|
|
634
|
+
const { initTUICommand } = await import('./init-tui-Cgxsmmn-.js');
|
|
634
635
|
// Build options based on form input
|
|
635
636
|
const options = {
|
|
636
637
|
workspace,
|
|
@@ -648,4 +649,4 @@ async function runInitialization(config) {
|
|
|
648
649
|
}
|
|
649
650
|
|
|
650
651
|
export { mainTUICommand };
|
|
651
|
-
//# sourceMappingURL=main-tui-
|
|
652
|
+
//# sourceMappingURL=main-tui-D580QurF.js.map
|