@parall/claude-agent 1.28.1 → 1.29.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/dist/dispatch.d.ts.map +1 -1
- package/dist/dispatch.js +29 -11
- package/dist/index.js +3 -10
- package/package.json +4 -4
- package/src/dispatch.ts +30 -11
- package/src/index.ts +3 -10
package/dist/dispatch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,YAAY,EACZ,QAAQ,EAER,YAAY,EACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,EACL,oBAAoB,EAErB,MAAM,sBAAsB,CAAC;AAE9B,KAAK,wBAAwB,GAAG,IAAI,CAClC,iBAAiB,EACf,gBAAgB,GAChB,aAAa,GACb,cAAc,GACd,oBAAoB,GACpB,WAAW,GACX,YAAY,GACZ,iBAAiB,GACjB,OAAO,GACP,gBAAgB,GAChB,cAAc,CACjB,GAAG;IACF,cAAc,EAAE,oBAAoB,CAAC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,yBAAyB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3D,iDAAiD;IACjD,wBAAwB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC;CAC3D,CAAC;
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,YAAY,EACZ,QAAQ,EAER,YAAY,EACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,EACL,oBAAoB,EAErB,MAAM,sBAAsB,CAAC;AAE9B,KAAK,wBAAwB,GAAG,IAAI,CAClC,iBAAiB,EACf,gBAAgB,GAChB,aAAa,GACb,cAAc,GACd,oBAAoB,GACpB,WAAW,GACX,YAAY,GACZ,iBAAiB,GACjB,OAAO,GACP,gBAAgB,GAChB,cAAc,CACjB,GAAG;IACF,cAAc,EAAE,oBAAoB,CAAC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,yBAAyB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3D,iDAAiD;IACjD,wBAAwB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC;CAC3D,CAAC;AAgBF,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,CAAC,UAAU,EAC5B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,YAAY,CAAC,SAAS,CAAC,EAChC,IAAI,EAAE;IAAE,WAAW,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACnD,MAAM,CAAC,UAAU,CAuBnB;AAiBD,qBAAa,iBAAkB,YAAW,eAAe;IAO3C,OAAO,CAAC,QAAQ,CAAC,IAAI;IANjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmC;IAC7D,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA6B;IAC/D,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,YAAY,CAAqB;gBAEZ,IAAI,EAAE,wBAAwB;IAI3D,IAAI,YAAY,IAAI,MAAM,GAAG,SAAS,CAAwB;IAC9D,IAAI,aAAa,IAAI,MAAM,GAAG,SAAS,CAA8B;IAErE,YAAY,CAAC,MAAM,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI;IAY7E,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAchE,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAI1C,QAAQ,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,YAAY,GAAG,aAAa,CAAC,YAAY,CAAC;IAiCxG,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIvD,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAQ7D,WAAW,CAAC,EAAE,UAAU,EAAE,EAAE,QAAQ;IAIpC,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,eAAe;IAQ/B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAS/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAAU;IAEvD;;;;;;;;;OASG;YACY,gBAAgB;YAsDhB,OAAO;IA2GtB,OAAO,CAAC,aAAa;IAyBrB,OAAO,CAAC,YAAY;IA+CpB,OAAO,CAAC,WAAW;IAkBnB,OAAO,CAAC,gBAAgB;IAWxB,OAAO,CAAC,SAAS;IAwCjB,OAAO,CAAC,uBAAuB;CAkBhC"}
|
package/dist/dispatch.js
CHANGED
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
|
-
import { spawn } from "node:child_process";
|
|
4
|
+
import { execSync, spawn } from "node:child_process";
|
|
5
5
|
import { appendPreparedLocalAttachmentRefs, pinLocalAttachmentPaths, } from "@parall/agent-core/internal/attachment-input";
|
|
6
6
|
import { parseClaudeStreamJson } from "./output-parser.js";
|
|
7
|
+
const IS_WIN32 = process.platform === "win32";
|
|
8
|
+
function quoteWin32Arg(arg) {
|
|
9
|
+
if (!/[\s"&|^<>()]/.test(arg))
|
|
10
|
+
return arg;
|
|
11
|
+
return `"${arg.replace(/"/g, '""')}"`;
|
|
12
|
+
}
|
|
13
|
+
function killWin32Tree(pid) {
|
|
14
|
+
try {
|
|
15
|
+
execSync(`taskkill /T /F /PID ${pid}`, { windowsHide: true, stdio: "ignore" });
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
7
22
|
export function buildSpawnEnv(parentEnv, claudeHome, context, opts) {
|
|
8
23
|
const env = { ...parentEnv };
|
|
9
24
|
if (!opts.allowApiKey) {
|
|
@@ -245,9 +260,12 @@ export class ClaudeCodeAdapter {
|
|
|
245
260
|
if (next.done) {
|
|
246
261
|
state.done = true;
|
|
247
262
|
this.processes.delete(sessionKey);
|
|
263
|
+
const detail = state.handle.stderrChunks.join("").trim();
|
|
264
|
+
const exit = await state.handle.exitPromise.catch(() => ({ code: null, signal: null }));
|
|
265
|
+
if (detail) {
|
|
266
|
+
log?.warn?.(`claude-agent: subprocess stderr: ${detail}`);
|
|
267
|
+
}
|
|
248
268
|
if (!sawError) {
|
|
249
|
-
const detail = state.handle.stderrChunks.join("").trim();
|
|
250
|
-
const exit = await state.handle.exitPromise.catch(() => ({ code: null, signal: null }));
|
|
251
269
|
yield {
|
|
252
270
|
type: "error",
|
|
253
271
|
message: detail
|
|
@@ -316,10 +334,11 @@ export class ClaudeCodeAdapter {
|
|
|
316
334
|
const args = this.buildArgs(sessionKey);
|
|
317
335
|
const env = buildSpawnEnv(process.env, this.opts.claudeHome, this.buildPlaceholderContext(sessionKey), { allowApiKey: this.opts.allowApiKey, effortLevel: this._effortLevel });
|
|
318
336
|
log?.info(`claude-agent: spawn long-lived ${this.opts.claudeBin} (session ${sessionKey}, model=${this._model || "default"}, effort=${this._effortLevel || "default"}, mode=${this.opts.permissionMode})`);
|
|
319
|
-
const proc = spawn(this.opts.claudeBin, args, {
|
|
337
|
+
const proc = spawn(IS_WIN32 ? quoteWin32Arg(this.opts.claudeBin) : this.opts.claudeBin, IS_WIN32 ? args.map(quoteWin32Arg) : args, {
|
|
320
338
|
cwd: this.opts.workspaceDir,
|
|
321
339
|
env,
|
|
322
340
|
stdio: ["pipe", "pipe", "pipe"],
|
|
341
|
+
shell: IS_WIN32,
|
|
323
342
|
});
|
|
324
343
|
if (!proc.stdout || !proc.stderr || !proc.stdin) {
|
|
325
344
|
throw new Error("Claude subprocess did not provide stdio pipes");
|
|
@@ -329,13 +348,11 @@ export class ClaudeCodeAdapter {
|
|
|
329
348
|
stderrChunks.push(chunk.toString());
|
|
330
349
|
});
|
|
331
350
|
proc.stdin.on("error", () => {
|
|
332
|
-
// stdin pipe broken: kill the process so parser.next() sees EOF
|
|
333
|
-
// instead of hanging forever on a process that's alive but can't
|
|
334
|
-
// accept input. If the process was already exiting (the common
|
|
335
|
-
// EPIPE-on-close race), kill is a harmless no-op.
|
|
336
351
|
proc.stdin.destroy();
|
|
337
352
|
if (proc.exitCode === null && proc.signalCode === null) {
|
|
338
|
-
proc.
|
|
353
|
+
if (!IS_WIN32 || !proc.pid || !killWin32Tree(proc.pid)) {
|
|
354
|
+
proc.kill("SIGTERM");
|
|
355
|
+
}
|
|
339
356
|
}
|
|
340
357
|
});
|
|
341
358
|
const exitPromise = new Promise((resolve) => {
|
|
@@ -356,7 +373,9 @@ export class ClaudeCodeAdapter {
|
|
|
356
373
|
catch { /* best-effort */ }
|
|
357
374
|
if (state.handle.proc.exitCode === null && state.handle.proc.signalCode === null) {
|
|
358
375
|
try {
|
|
359
|
-
state.handle.proc.
|
|
376
|
+
if (!IS_WIN32 || !state.handle.proc.pid || !killWin32Tree(state.handle.proc.pid)) {
|
|
377
|
+
state.handle.proc.kill("SIGTERM");
|
|
378
|
+
}
|
|
360
379
|
}
|
|
361
380
|
catch { /* best-effort */ }
|
|
362
381
|
}
|
|
@@ -373,7 +392,6 @@ export class ClaudeCodeAdapter {
|
|
|
373
392
|
}
|
|
374
393
|
buildArgs(sessionKey) {
|
|
375
394
|
const args = [
|
|
376
|
-
"-p",
|
|
377
395
|
"--verbose",
|
|
378
396
|
"--input-format",
|
|
379
397
|
"stream-json",
|
package/dist/index.js
CHANGED
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import * as os from "node:os";
|
|
3
|
-
import { ParallAgentGateway, createPlatformConfigManager, isPlatformManagedProfile, parseShutdownDeadlineMs } from "@parall/agent-core";
|
|
3
|
+
import { ParallAgentGateway, createPlatformConfigManager, createLogger, isPlatformManagedProfile, parseShutdownDeadlineMs } from "@parall/agent-core";
|
|
4
4
|
import { ApiError, ParallClient, ParallWs } from "@parall/sdk";
|
|
5
5
|
import { buildClaudeRuntimeKey, contextFilePathForSession, resolveClaudeAgentConfig, resolveWsUrl, sessionStateFilePathForRuntime, stepIdFilePathForSession, } from "./config.js";
|
|
6
6
|
import { ClaudeCodeAdapter } from "./dispatch.js";
|
|
7
7
|
import { ClaudeSessionManager } from "./session-manager.js";
|
|
8
8
|
import { ensureClaudeWorkspace } from "./workspace.js";
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
info: (msg) => console.log(`[${prefix}] ${msg}`),
|
|
12
|
-
warn: (msg) => console.warn(`[${prefix}] ${msg}`),
|
|
13
|
-
error: (msg) => console.error(`[${prefix}] ${msg}`),
|
|
14
|
-
};
|
|
15
|
-
}
|
|
9
|
+
const log = createLogger("claude-agent");
|
|
16
10
|
async function getAgentMeWithLegacyFallback(client, orgId) {
|
|
17
11
|
try {
|
|
18
12
|
return await client.getAgentMe(orgId);
|
|
@@ -27,7 +21,6 @@ async function getAgentMeWithLegacyFallback(client, orgId) {
|
|
|
27
21
|
}
|
|
28
22
|
async function main() {
|
|
29
23
|
const config = resolveClaudeAgentConfig(process.env);
|
|
30
|
-
const log = createLogger("claude-agent");
|
|
31
24
|
if (config.allowApiKey &&
|
|
32
25
|
(process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN)) {
|
|
33
26
|
// Surface the billing path: default is OAuth (Claude.ai subscription); this
|
|
@@ -154,6 +147,6 @@ async function main() {
|
|
|
154
147
|
}
|
|
155
148
|
}
|
|
156
149
|
main().catch((err) => {
|
|
157
|
-
|
|
150
|
+
log.error(`fatal: ${String(err)}`);
|
|
158
151
|
process.exitCode = 1;
|
|
159
152
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parall/claude-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.29.0",
|
|
4
4
|
"description": "Claude Code bridge runtime for self-hosted Parall agents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"src"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@parall/agent-core": "1.
|
|
29
|
-
"@parall/
|
|
30
|
-
"@parall/
|
|
28
|
+
"@parall/agent-core": "1.29.0",
|
|
29
|
+
"@parall/cli": "1.29.0",
|
|
30
|
+
"@parall/sdk": "1.29.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@types/node": "^22.0.0",
|
package/src/dispatch.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
|
-
import { spawn } from "node:child_process";
|
|
4
|
+
import { execSync, spawn } from "node:child_process";
|
|
5
5
|
import {
|
|
6
6
|
appendPreparedLocalAttachmentRefs,
|
|
7
7
|
pinLocalAttachmentPaths,
|
|
@@ -43,6 +43,20 @@ type ClaudeCodeAdapterOptions = Pick<
|
|
|
43
43
|
stepIdFilePathForSession?: (sessionKey: string) => string;
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
+
const IS_WIN32 = process.platform === "win32";
|
|
47
|
+
|
|
48
|
+
function quoteWin32Arg(arg: string): string {
|
|
49
|
+
if (!/[\s"&|^<>()]/.test(arg)) return arg;
|
|
50
|
+
return `"${arg.replace(/"/g, '""')}"`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function killWin32Tree(pid: number): boolean {
|
|
54
|
+
try {
|
|
55
|
+
execSync(`taskkill /T /F /PID ${pid}`, { windowsHide: true, stdio: "ignore" });
|
|
56
|
+
return true;
|
|
57
|
+
} catch { return false; }
|
|
58
|
+
}
|
|
59
|
+
|
|
46
60
|
export function buildSpawnEnv(
|
|
47
61
|
parentEnv: NodeJS.ProcessEnv,
|
|
48
62
|
claudeHome: string,
|
|
@@ -317,9 +331,12 @@ export class ClaudeCodeAdapter implements DispatchAdapter {
|
|
|
317
331
|
if (next.done) {
|
|
318
332
|
state.done = true;
|
|
319
333
|
this.processes.delete(sessionKey);
|
|
334
|
+
const detail = state.handle.stderrChunks.join("").trim();
|
|
335
|
+
const exit = await state.handle.exitPromise.catch(() => ({ code: null, signal: null } as const));
|
|
336
|
+
if (detail) {
|
|
337
|
+
log?.warn?.(`claude-agent: subprocess stderr: ${detail}`);
|
|
338
|
+
}
|
|
320
339
|
if (!sawError) {
|
|
321
|
-
const detail = state.handle.stderrChunks.join("").trim();
|
|
322
|
-
const exit = await state.handle.exitPromise.catch(() => ({ code: null, signal: null } as const));
|
|
323
340
|
yield {
|
|
324
341
|
type: "error",
|
|
325
342
|
message: detail
|
|
@@ -406,10 +423,13 @@ export class ClaudeCodeAdapter implements DispatchAdapter {
|
|
|
406
423
|
`claude-agent: spawn long-lived ${this.opts.claudeBin} (session ${sessionKey}, model=${this._model || "default"}, effort=${this._effortLevel || "default"}, mode=${this.opts.permissionMode})`,
|
|
407
424
|
);
|
|
408
425
|
|
|
409
|
-
const proc = spawn(
|
|
426
|
+
const proc = spawn(
|
|
427
|
+
IS_WIN32 ? quoteWin32Arg(this.opts.claudeBin) : this.opts.claudeBin,
|
|
428
|
+
IS_WIN32 ? args.map(quoteWin32Arg) : args, {
|
|
410
429
|
cwd: this.opts.workspaceDir,
|
|
411
430
|
env,
|
|
412
431
|
stdio: ["pipe", "pipe", "pipe"],
|
|
432
|
+
shell: IS_WIN32,
|
|
413
433
|
});
|
|
414
434
|
|
|
415
435
|
if (!proc.stdout || !proc.stderr || !proc.stdin) {
|
|
@@ -421,13 +441,11 @@ export class ClaudeCodeAdapter implements DispatchAdapter {
|
|
|
421
441
|
stderrChunks.push(chunk.toString());
|
|
422
442
|
});
|
|
423
443
|
proc.stdin.on("error", () => {
|
|
424
|
-
// stdin pipe broken: kill the process so parser.next() sees EOF
|
|
425
|
-
// instead of hanging forever on a process that's alive but can't
|
|
426
|
-
// accept input. If the process was already exiting (the common
|
|
427
|
-
// EPIPE-on-close race), kill is a harmless no-op.
|
|
428
444
|
proc.stdin.destroy();
|
|
429
445
|
if (proc.exitCode === null && proc.signalCode === null) {
|
|
430
|
-
proc.
|
|
446
|
+
if (!IS_WIN32 || !proc.pid || !killWin32Tree(proc.pid)) {
|
|
447
|
+
proc.kill("SIGTERM");
|
|
448
|
+
}
|
|
431
449
|
}
|
|
432
450
|
});
|
|
433
451
|
|
|
@@ -450,7 +468,9 @@ export class ClaudeCodeAdapter implements DispatchAdapter {
|
|
|
450
468
|
} catch { /* best-effort */ }
|
|
451
469
|
if (state.handle.proc.exitCode === null && state.handle.proc.signalCode === null) {
|
|
452
470
|
try {
|
|
453
|
-
state.handle.proc.
|
|
471
|
+
if (!IS_WIN32 || !state.handle.proc.pid || !killWin32Tree(state.handle.proc.pid)) {
|
|
472
|
+
state.handle.proc.kill("SIGTERM");
|
|
473
|
+
}
|
|
454
474
|
} catch { /* best-effort */ }
|
|
455
475
|
}
|
|
456
476
|
}
|
|
@@ -468,7 +488,6 @@ export class ClaudeCodeAdapter implements DispatchAdapter {
|
|
|
468
488
|
|
|
469
489
|
private buildArgs(sessionKey: string): string[] {
|
|
470
490
|
const args = [
|
|
471
|
-
"-p",
|
|
472
491
|
"--verbose",
|
|
473
492
|
"--input-format",
|
|
474
493
|
"stream-json",
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import * as os from "node:os";
|
|
4
|
-
import { ParallAgentGateway, createPlatformConfigManager, isPlatformManagedProfile, parseShutdownDeadlineMs } from "@parall/agent-core";
|
|
4
|
+
import { ParallAgentGateway, createPlatformConfigManager, createLogger, isPlatformManagedProfile, parseShutdownDeadlineMs } from "@parall/agent-core";
|
|
5
5
|
import { ApiError, ParallClient, ParallWs } from "@parall/sdk";
|
|
6
6
|
import {
|
|
7
7
|
buildClaudeRuntimeKey,
|
|
@@ -15,13 +15,7 @@ import { ClaudeCodeAdapter } from "./dispatch.js";
|
|
|
15
15
|
import { ClaudeSessionManager } from "./session-manager.js";
|
|
16
16
|
import { ensureClaudeWorkspace } from "./workspace.js";
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
return {
|
|
20
|
-
info: (msg: string) => console.log(`[${prefix}] ${msg}`),
|
|
21
|
-
warn: (msg: string) => console.warn(`[${prefix}] ${msg}`),
|
|
22
|
-
error: (msg: string) => console.error(`[${prefix}] ${msg}`),
|
|
23
|
-
};
|
|
24
|
-
}
|
|
18
|
+
const log = createLogger("claude-agent");
|
|
25
19
|
|
|
26
20
|
async function getAgentMeWithLegacyFallback(client: ParallClient, orgId: string) {
|
|
27
21
|
try {
|
|
@@ -37,7 +31,6 @@ async function getAgentMeWithLegacyFallback(client: ParallClient, orgId: string)
|
|
|
37
31
|
|
|
38
32
|
async function main() {
|
|
39
33
|
const config = resolveClaudeAgentConfig(process.env);
|
|
40
|
-
const log = createLogger("claude-agent");
|
|
41
34
|
|
|
42
35
|
if (
|
|
43
36
|
config.allowApiKey &&
|
|
@@ -179,6 +172,6 @@ async function main() {
|
|
|
179
172
|
}
|
|
180
173
|
|
|
181
174
|
main().catch((err) => {
|
|
182
|
-
|
|
175
|
+
log.error(`fatal: ${String(err)}`);
|
|
183
176
|
process.exitCode = 1;
|
|
184
177
|
});
|