agent-gauntlet 0.10.0 → 0.11.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.
- package/README.md +25 -23
- package/dist/index.js +9226 -0
- package/dist/index.js.map +65 -0
- package/dist/scripts/status.js +280 -0
- package/dist/scripts/status.js.map +10 -0
- package/package.json +22 -8
- package/src/built-in-reviews/code-quality.md +0 -25
- package/src/built-in-reviews/index.ts +0 -28
- package/src/bun-plugins.d.ts +0 -4
- package/src/cli-adapters/claude.ts +0 -327
- package/src/cli-adapters/codex.ts +0 -290
- package/src/cli-adapters/cursor.ts +0 -128
- package/src/cli-adapters/gemini.ts +0 -510
- package/src/cli-adapters/github-copilot.ts +0 -141
- package/src/cli-adapters/index.ts +0 -250
- package/src/cli-adapters/thinking-budget.ts +0 -23
- package/src/commands/check.ts +0 -311
- package/src/commands/ci/index.ts +0 -15
- package/src/commands/ci/init.ts +0 -96
- package/src/commands/ci/list-jobs.ts +0 -90
- package/src/commands/clean.ts +0 -54
- package/src/commands/detect.ts +0 -173
- package/src/commands/health.ts +0 -169
- package/src/commands/help.ts +0 -34
- package/src/commands/index.ts +0 -13
- package/src/commands/init.ts +0 -1878
- package/src/commands/list.ts +0 -33
- package/src/commands/review.ts +0 -311
- package/src/commands/run.ts +0 -29
- package/src/commands/shared.ts +0 -267
- package/src/commands/stop-hook.ts +0 -567
- package/src/commands/validate.ts +0 -20
- package/src/commands/wait-ci.ts +0 -518
- package/src/config/ci-loader.ts +0 -33
- package/src/config/ci-schema.ts +0 -28
- package/src/config/global.ts +0 -87
- package/src/config/loader.ts +0 -301
- package/src/config/schema.ts +0 -165
- package/src/config/stop-hook-config.ts +0 -130
- package/src/config/types.ts +0 -65
- package/src/config/validator.ts +0 -592
- package/src/core/change-detector.ts +0 -137
- package/src/core/diff-stats.ts +0 -442
- package/src/core/entry-point.ts +0 -190
- package/src/core/job.ts +0 -96
- package/src/core/run-executor.ts +0 -621
- package/src/core/runner.ts +0 -290
- package/src/gates/check.ts +0 -118
- package/src/gates/resolve-check-command.ts +0 -21
- package/src/gates/result.ts +0 -54
- package/src/gates/review.ts +0 -1333
- package/src/hooks/adapters/claude-stop-hook.ts +0 -99
- package/src/hooks/adapters/cursor-stop-hook.ts +0 -122
- package/src/hooks/adapters/types.ts +0 -94
- package/src/hooks/stop-hook-handler.ts +0 -748
- package/src/index.ts +0 -47
- package/src/output/app-logger.ts +0 -214
- package/src/output/console-log.ts +0 -168
- package/src/output/console.ts +0 -359
- package/src/output/logger.ts +0 -126
- package/src/output/sinks/console-sink.ts +0 -59
- package/src/output/sinks/file-sink.ts +0 -110
- package/src/scripts/status.ts +0 -433
- package/src/templates/workflow.yml +0 -79
- package/src/types/gauntlet-status.ts +0 -79
- package/src/utils/debug-log.ts +0 -392
- package/src/utils/diff-parser.ts +0 -103
- package/src/utils/execution-state.ts +0 -472
- package/src/utils/log-parser.ts +0 -696
- package/src/utils/sanitizer.ts +0 -3
- package/src/utils/session-ref.ts +0 -91
package/src/index.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
import { Command } from "commander";
|
|
3
|
-
import packageJson from "../package.json" with { type: "json" };
|
|
4
|
-
import {
|
|
5
|
-
registerCheckCommand,
|
|
6
|
-
registerCICommand,
|
|
7
|
-
registerCleanCommand,
|
|
8
|
-
registerDetectCommand,
|
|
9
|
-
registerHealthCommand,
|
|
10
|
-
registerHelpCommand,
|
|
11
|
-
registerInitCommand,
|
|
12
|
-
registerListCommand,
|
|
13
|
-
registerReviewCommand,
|
|
14
|
-
registerRunCommand,
|
|
15
|
-
registerStopHookCommand,
|
|
16
|
-
registerValidateCommand,
|
|
17
|
-
registerWaitCICommand,
|
|
18
|
-
} from "./commands/index.js";
|
|
19
|
-
|
|
20
|
-
const program = new Command();
|
|
21
|
-
|
|
22
|
-
program
|
|
23
|
-
.name("agent-gauntlet")
|
|
24
|
-
.description("AI-assisted quality gates")
|
|
25
|
-
.version(packageJson.version);
|
|
26
|
-
|
|
27
|
-
// Register all commands
|
|
28
|
-
registerRunCommand(program);
|
|
29
|
-
registerCheckCommand(program);
|
|
30
|
-
registerCICommand(program);
|
|
31
|
-
registerCleanCommand(program);
|
|
32
|
-
registerReviewCommand(program);
|
|
33
|
-
registerDetectCommand(program);
|
|
34
|
-
registerListCommand(program);
|
|
35
|
-
registerHealthCommand(program);
|
|
36
|
-
registerInitCommand(program);
|
|
37
|
-
registerValidateCommand(program);
|
|
38
|
-
registerStopHookCommand(program);
|
|
39
|
-
registerWaitCICommand(program);
|
|
40
|
-
registerHelpCommand(program);
|
|
41
|
-
|
|
42
|
-
// Default action: help
|
|
43
|
-
if (process.argv.length < 3) {
|
|
44
|
-
process.argv.push("help");
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
program.parse(process.argv);
|
package/src/output/app-logger.ts
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import fsPromises from "node:fs/promises";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import {
|
|
5
|
-
configure,
|
|
6
|
-
getLogger,
|
|
7
|
-
type LogRecord,
|
|
8
|
-
type Logger as LogTapeLogger,
|
|
9
|
-
} from "@logtape/logtape";
|
|
10
|
-
import { createConsoleSink } from "./sinks/console-sink.js";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Logger modes that determine sink configuration:
|
|
14
|
-
* - "interactive": Console output to stderr (file capture via console-log.ts)
|
|
15
|
-
* - "stop-hook": NO console output (JSON protocol on stdout must be clean)
|
|
16
|
-
* - "ci": Console output to stderr
|
|
17
|
-
*/
|
|
18
|
-
export type LoggerMode = "interactive" | "stop-hook" | "ci";
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Log level options.
|
|
22
|
-
*/
|
|
23
|
-
export type LogLevel = "debug" | "info" | "warning" | "error";
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* App logger configuration options.
|
|
27
|
-
*/
|
|
28
|
-
export interface AppLoggerConfig {
|
|
29
|
-
mode: LoggerMode;
|
|
30
|
-
logDir?: string;
|
|
31
|
-
level?: LogLevel;
|
|
32
|
-
debugLog?: {
|
|
33
|
-
enabled: boolean;
|
|
34
|
-
maxSizeMb?: number;
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Global state for cleanup (file descriptor for debug log, configuration flag)
|
|
39
|
-
let debugLogFd: number | null = null;
|
|
40
|
-
let isConfigured = false;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Safely serialize a value, handling circular references.
|
|
44
|
-
*/
|
|
45
|
-
function safeStringify(value: unknown): string {
|
|
46
|
-
try {
|
|
47
|
-
return JSON.stringify(value);
|
|
48
|
-
} catch {
|
|
49
|
-
return "[Unserializable]";
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Create a debug log sink that writes to .debug.log file.
|
|
55
|
-
* Format matches existing DebugLogger: [ISO_TIMESTAMP] message
|
|
56
|
-
*/
|
|
57
|
-
function createDebugLogSink(logDir: string): (record: LogRecord) => void {
|
|
58
|
-
const debugLogPath = path.join(logDir, ".debug.log");
|
|
59
|
-
|
|
60
|
-
// Open file for append
|
|
61
|
-
debugLogFd = fs.openSync(
|
|
62
|
-
debugLogPath,
|
|
63
|
-
fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_APPEND,
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
return (record: LogRecord) => {
|
|
67
|
-
if (debugLogFd === null) return;
|
|
68
|
-
|
|
69
|
-
const timestamp = new Date(record.timestamp).toISOString();
|
|
70
|
-
const level = record.level.toUpperCase();
|
|
71
|
-
const category = record.category.join(".");
|
|
72
|
-
const message = record.message
|
|
73
|
-
.map((part) => (typeof part === "string" ? part : safeStringify(part)))
|
|
74
|
-
.join("");
|
|
75
|
-
|
|
76
|
-
const line = `[${timestamp}] ${level} [${category}] ${message}\n`;
|
|
77
|
-
|
|
78
|
-
try {
|
|
79
|
-
fs.writeSync(debugLogFd, line);
|
|
80
|
-
} catch {
|
|
81
|
-
// Suppress write errors
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Initialize the application logger with LogTape.
|
|
88
|
-
*
|
|
89
|
-
* IMPORTANT: In stop-hook mode, NO console output is generated.
|
|
90
|
-
* stdout must remain clean for the JSON protocol response.
|
|
91
|
-
* File logging is handled separately by console-log.ts which captures stderr.
|
|
92
|
-
*
|
|
93
|
-
* @param config - Logger configuration
|
|
94
|
-
* @returns Promise that resolves when logger is configured
|
|
95
|
-
*/
|
|
96
|
-
export async function initLogger(config: AppLoggerConfig): Promise<void> {
|
|
97
|
-
// Reset if already configured
|
|
98
|
-
if (isConfigured) {
|
|
99
|
-
await resetLogger();
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const { mode, level = "info", logDir, debugLog } = config;
|
|
103
|
-
|
|
104
|
-
// Ensure log directory exists if we need it for debug log
|
|
105
|
-
if (logDir && debugLog?.enabled) {
|
|
106
|
-
await fsPromises.mkdir(logDir, { recursive: true });
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Build sink configuration
|
|
110
|
-
const sinks: Record<string, (record: LogRecord) => void> = {};
|
|
111
|
-
const activeSinks: string[] = [];
|
|
112
|
-
|
|
113
|
-
// Console sink (only for interactive and ci modes)
|
|
114
|
-
// Outputs to stderr, which gets captured by console-log.ts
|
|
115
|
-
if (mode !== "stop-hook") {
|
|
116
|
-
sinks.console = createConsoleSink();
|
|
117
|
-
activeSinks.push("console");
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Debug log sink (writes directly to .debug.log)
|
|
121
|
-
if (logDir && debugLog?.enabled) {
|
|
122
|
-
sinks.debugLog = createDebugLogSink(logDir);
|
|
123
|
-
activeSinks.push("debugLog");
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Configure LogTape (reset: true needed if LogTape was previously configured)
|
|
127
|
-
// IMPORTANT: Configure the meta logger to suppress its default stdout output.
|
|
128
|
-
// Without this, LogTape writes "LogTape loggers are configured..." to stdout,
|
|
129
|
-
// which breaks the stop-hook JSON protocol.
|
|
130
|
-
try {
|
|
131
|
-
await configure({
|
|
132
|
-
sinks,
|
|
133
|
-
loggers: [
|
|
134
|
-
{
|
|
135
|
-
category: ["gauntlet"],
|
|
136
|
-
lowestLevel: level,
|
|
137
|
-
sinks: activeSinks,
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
// Suppress LogTape's internal meta logger (writes to stdout by default)
|
|
141
|
-
category: ["logtape", "meta"],
|
|
142
|
-
lowestLevel: "fatal",
|
|
143
|
-
sinks: [],
|
|
144
|
-
},
|
|
145
|
-
],
|
|
146
|
-
reset: true,
|
|
147
|
-
});
|
|
148
|
-
isConfigured = true;
|
|
149
|
-
} catch (error) {
|
|
150
|
-
// Close debug log fd if initialization fails to prevent leaks
|
|
151
|
-
if (debugLogFd !== null) {
|
|
152
|
-
try {
|
|
153
|
-
fs.closeSync(debugLogFd);
|
|
154
|
-
} catch {
|
|
155
|
-
// Ignore close errors
|
|
156
|
-
}
|
|
157
|
-
debugLogFd = null;
|
|
158
|
-
}
|
|
159
|
-
throw error;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Reset the logger configuration and close file handles.
|
|
165
|
-
*/
|
|
166
|
-
export async function resetLogger(): Promise<void> {
|
|
167
|
-
if (debugLogFd !== null) {
|
|
168
|
-
try {
|
|
169
|
-
fs.closeSync(debugLogFd);
|
|
170
|
-
} catch {
|
|
171
|
-
// Ignore close errors
|
|
172
|
-
}
|
|
173
|
-
debugLogFd = null;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// Reset LogTape configuration (reset: true required after initial configure)
|
|
177
|
-
// Also suppress meta logger to avoid stdout pollution
|
|
178
|
-
await configure({
|
|
179
|
-
sinks: {},
|
|
180
|
-
loggers: [
|
|
181
|
-
{
|
|
182
|
-
category: ["logtape", "meta"],
|
|
183
|
-
lowestLevel: "fatal",
|
|
184
|
-
sinks: [],
|
|
185
|
-
},
|
|
186
|
-
],
|
|
187
|
-
reset: true,
|
|
188
|
-
});
|
|
189
|
-
isConfigured = false;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Get the root application logger.
|
|
194
|
-
*/
|
|
195
|
-
export function getAppLogger(): LogTapeLogger {
|
|
196
|
-
return getLogger(["gauntlet"]);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Get a child logger for a specific category.
|
|
201
|
-
* Categories are hierarchical, e.g., ["gauntlet", "runner"] or ["gauntlet", "gate", "check"]
|
|
202
|
-
*
|
|
203
|
-
* @param category - The category path (after "gauntlet" prefix)
|
|
204
|
-
*/
|
|
205
|
-
export function getCategoryLogger(...category: string[]): LogTapeLogger {
|
|
206
|
-
return getLogger(["gauntlet", ...category]);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Check if the logger has been configured.
|
|
211
|
-
*/
|
|
212
|
-
export function isLoggerConfigured(): boolean {
|
|
213
|
-
return isConfigured;
|
|
214
|
-
}
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import fsPromises from "node:fs/promises";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { inspect } from "node:util";
|
|
5
|
-
|
|
6
|
-
// biome-ignore lint/suspicious/noControlCharactersInRegex: Required for ANSI escape code stripping
|
|
7
|
-
const ANSI_REGEX = /\x1b\[[0-9;]*m/g;
|
|
8
|
-
|
|
9
|
-
function stripAnsi(text: string): string {
|
|
10
|
-
return text.replace(ANSI_REGEX, "");
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function formatArgs(args: unknown[]): string {
|
|
14
|
-
return args
|
|
15
|
-
.map((a) => (typeof a === "string" ? a : inspect(a, { depth: 4 })))
|
|
16
|
-
.join(" ");
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function openLogFileExclusive(
|
|
20
|
-
logDir: string,
|
|
21
|
-
runNum: number,
|
|
22
|
-
): { fd: number; logPath: string } {
|
|
23
|
-
const logPath = path.join(logDir, `console.${runNum}.log`);
|
|
24
|
-
try {
|
|
25
|
-
const fd = fs.openSync(
|
|
26
|
-
logPath,
|
|
27
|
-
fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL,
|
|
28
|
-
);
|
|
29
|
-
return { fd, logPath };
|
|
30
|
-
} catch (e: unknown) {
|
|
31
|
-
const error = e as { code?: string };
|
|
32
|
-
if (error.code === "EEXIST") {
|
|
33
|
-
// If file exists, something is wrong with our numbering logic
|
|
34
|
-
// Log warning and try incrementing as fallback
|
|
35
|
-
console.error(`Warning: console.${runNum}.log already exists`);
|
|
36
|
-
return openLogFileFallback(logDir, runNum + 1);
|
|
37
|
-
}
|
|
38
|
-
throw e;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function openLogFileFallback(
|
|
43
|
-
logDir: string,
|
|
44
|
-
startNum: number,
|
|
45
|
-
): { fd: number; logPath: string } {
|
|
46
|
-
let runNum = startNum;
|
|
47
|
-
for (let attempts = 0; attempts < 100; attempts++) {
|
|
48
|
-
const logPath = path.join(logDir, `console.${runNum}.log`);
|
|
49
|
-
try {
|
|
50
|
-
const fd = fs.openSync(
|
|
51
|
-
logPath,
|
|
52
|
-
fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL,
|
|
53
|
-
);
|
|
54
|
-
return { fd, logPath };
|
|
55
|
-
} catch (e: unknown) {
|
|
56
|
-
const error = e as { code?: string };
|
|
57
|
-
if (error.code === "EEXIST") {
|
|
58
|
-
runNum++;
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
throw e;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
throw new Error("Failed to create console log file after 100 attempts");
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export interface ConsoleLogHandle {
|
|
68
|
-
/** Restore original console functions */
|
|
69
|
-
restore: () => void;
|
|
70
|
-
/** Write directly to the log file without terminal output */
|
|
71
|
-
writeToLogOnly: (text: string) => void;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Start console logging with unified run numbering.
|
|
76
|
-
* @param logDir The directory to write logs to
|
|
77
|
-
* @param runNumber The run number from Logger (ensures console.N.log matches check.N.log)
|
|
78
|
-
*/
|
|
79
|
-
export async function startConsoleLog(
|
|
80
|
-
logDir: string,
|
|
81
|
-
runNumber: number,
|
|
82
|
-
): Promise<ConsoleLogHandle> {
|
|
83
|
-
await fsPromises.mkdir(logDir, { recursive: true });
|
|
84
|
-
const { fd } = openLogFileExclusive(logDir, runNumber);
|
|
85
|
-
|
|
86
|
-
try {
|
|
87
|
-
const originalLog = console.log;
|
|
88
|
-
const originalError = console.error;
|
|
89
|
-
const originalWarn = console.warn;
|
|
90
|
-
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
91
|
-
const originalStderrWrite = process.stderr.write.bind(process.stderr);
|
|
92
|
-
|
|
93
|
-
let isClosed = false;
|
|
94
|
-
|
|
95
|
-
function writeToLog(text: string): void {
|
|
96
|
-
if (isClosed) return;
|
|
97
|
-
try {
|
|
98
|
-
fs.writeSync(fd, stripAnsi(text));
|
|
99
|
-
} catch {
|
|
100
|
-
// Suppress logging failures to prevent crashing the application
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Only patch console methods in bun (bun's console.log bypasses stdout.write)
|
|
105
|
-
// In Node.js, console.log goes through stdout.write, so patching both would cause double logging
|
|
106
|
-
const isBun = typeof globalThis.Bun !== "undefined";
|
|
107
|
-
if (isBun) {
|
|
108
|
-
console.log = (...args: unknown[]) => {
|
|
109
|
-
writeToLog(`${formatArgs(args)}\n`);
|
|
110
|
-
originalLog(...args);
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
console.error = (...args: unknown[]) => {
|
|
114
|
-
writeToLog(`${formatArgs(args)}\n`);
|
|
115
|
-
originalError(...args);
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
console.warn = (...args: unknown[]) => {
|
|
119
|
-
writeToLog(`${formatArgs(args)}\n`);
|
|
120
|
-
originalWarn(...args);
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
process.stdout.write = ((
|
|
125
|
-
chunk: string | Uint8Array,
|
|
126
|
-
...args: unknown[]
|
|
127
|
-
): boolean => {
|
|
128
|
-
const text =
|
|
129
|
-
typeof chunk === "string" ? chunk : Buffer.from(chunk).toString();
|
|
130
|
-
writeToLog(text);
|
|
131
|
-
return originalStdoutWrite(chunk, ...(args as []));
|
|
132
|
-
}) as typeof process.stdout.write;
|
|
133
|
-
|
|
134
|
-
process.stderr.write = ((
|
|
135
|
-
chunk: string | Uint8Array,
|
|
136
|
-
...args: unknown[]
|
|
137
|
-
): boolean => {
|
|
138
|
-
const text =
|
|
139
|
-
typeof chunk === "string" ? chunk : Buffer.from(chunk).toString();
|
|
140
|
-
writeToLog(text);
|
|
141
|
-
return originalStderrWrite(chunk, ...(args as []));
|
|
142
|
-
}) as typeof process.stderr.write;
|
|
143
|
-
|
|
144
|
-
return {
|
|
145
|
-
restore: () => {
|
|
146
|
-
isClosed = true;
|
|
147
|
-
if (isBun) {
|
|
148
|
-
console.log = originalLog;
|
|
149
|
-
console.error = originalError;
|
|
150
|
-
console.warn = originalWarn;
|
|
151
|
-
}
|
|
152
|
-
process.stdout.write = originalStdoutWrite;
|
|
153
|
-
process.stderr.write = originalStderrWrite;
|
|
154
|
-
try {
|
|
155
|
-
fs.closeSync(fd);
|
|
156
|
-
} catch {
|
|
157
|
-
// Ignore close errors
|
|
158
|
-
}
|
|
159
|
-
},
|
|
160
|
-
writeToLogOnly: (text: string) => {
|
|
161
|
-
writeToLog(text);
|
|
162
|
-
},
|
|
163
|
-
};
|
|
164
|
-
} catch (error) {
|
|
165
|
-
fs.closeSync(fd);
|
|
166
|
-
throw error;
|
|
167
|
-
}
|
|
168
|
-
}
|