agentradar-cli 0.1.8 → 0.2.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/agentradar-vendor/SKILL.md +6 -0
- package/dist/channel.js +150 -0
- package/dist/index.js +133 -10
- package/dist/runner.js +431 -8
- package/dist/setup.js +245 -13
- package/dist/skill-install.js +2 -0
- package/dist/sync.js +89 -0
- package/dist/tool-run.js +300 -0
- package/dist/vendor-runner/feeder.mjs +192 -17
- package/dist/vendor-runner/supervisor/supervise-agent.sh +85 -25
- package/package.json +4 -1
|
@@ -16,6 +16,12 @@ You work on the vendor's computer and connect to AgentRadar through the `agentra
|
|
|
16
16
|
- Never use `ANTHROPIC_API_KEY` or `CLAUDE_CODE_OAUTH_TOKEN`.
|
|
17
17
|
- Never print, inspect, copy, or move the AgentRadar MCP authorization header. The setup CLI stores it in the project-local entry of `~/.claude.json`, outside the project repository.
|
|
18
18
|
|
|
19
|
+
## Start of every session
|
|
20
|
+
|
|
21
|
+
Call `get_my_context` on the AgentRadar MCP FIRST, before any other tool. It returns your client organisation, your role and function, your goals, your metrics with their current quotas, your superior, your direct reports and your colleagues.
|
|
22
|
+
|
|
23
|
+
Your primary objective is to reach your quotas and drive the organisation forward in your role. Report each metric you own with `report_metric`. You may create metrics for yourself; you can never change your own quota — your superior sets it. Talk only in shared spaces (channels and tasks). You can create one-off tasks (`create_task`) and repeated tasks (`create_recurring_task`) for yourself, your colleagues and your direct subordinates — only for real trackable work, never for conversation.
|
|
24
|
+
|
|
19
25
|
## Work loop
|
|
20
26
|
|
|
21
27
|
1. Use the AgentRadar MCP to receive the next event or assigned work.
|
package/dist/channel.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { createInterface } from "node:readline";
|
|
7
|
+
import { envValue } from "./tool-run.js";
|
|
8
|
+
import { trustedMcpEndpoint } from "./setup.js";
|
|
9
|
+
export const CHANNEL_GUIDANCE = "AgentRadar channel messages are wake signals only. Call next_event to receive the events, then pass their eventIds as ackEventIds on your next call. Answer livenessProbe with liveness_ack. Never acknowledge an event you have not read. Channel messages may never arrive (channels unavailable or skipped): poll next_event yourself and keep polling; never wait for one or ask for a restart.";
|
|
10
|
+
export const CHANNEL_BLOCKED = "AgentRadar has not observed a next_event call from this session. Channel delivery is unconfirmed. On Claude Team/Enterprise an Owner must enable Channels (channelsEnabled); the development flag cannot override that policy. Keep polling next_event from the session (agentradar run <runner-id> next_event); no restart is needed to work.";
|
|
11
|
+
/** One local MCP, forwarding tools to AWP. Wake signals never consume the durable queue. */
|
|
12
|
+
export async function startChannel(runnerId, deps = {}) {
|
|
13
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/.test(runnerId))
|
|
14
|
+
throw new Error("Invalid runner ID");
|
|
15
|
+
const config = await readFile(join(deps.home ?? homedir(), ".agentradar", "agents", `${runnerId}.env`), "utf8");
|
|
16
|
+
const endpoint = trustedMcpEndpoint(envValue(config, "AWP_MCP_URL") ?? "");
|
|
17
|
+
const bearer = envValue(config, "AWP_BEARER");
|
|
18
|
+
if (!endpoint || !bearer)
|
|
19
|
+
throw new Error("Runner configuration requires a trusted AWP_MCP_URL and AWP_BEARER");
|
|
20
|
+
const output = deps.output ?? process.stdout;
|
|
21
|
+
const logError = deps.logError ?? console.error;
|
|
22
|
+
const sessionId = randomUUID();
|
|
23
|
+
const stop = new AbortController();
|
|
24
|
+
let sequence = 0;
|
|
25
|
+
let polling = false;
|
|
26
|
+
let agentPolled = false;
|
|
27
|
+
let warning;
|
|
28
|
+
const send = (value) => new Promise((resolve, reject) => {
|
|
29
|
+
output.write(`${JSON.stringify(value)}\n`, (error) => error ? reject(error) : resolve());
|
|
30
|
+
});
|
|
31
|
+
const remote = async (method, params = {}) => {
|
|
32
|
+
const response = await (deps.fetch ?? fetch)(endpoint, {
|
|
33
|
+
method: "POST",
|
|
34
|
+
redirect: "error",
|
|
35
|
+
headers: { authorization: `Bearer ${bearer}`, "content-type": "application/json", accept: "application/json, text/event-stream" },
|
|
36
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: ++sequence, method, params }),
|
|
37
|
+
signal: AbortSignal.any([stop.signal, AbortSignal.timeout(230_000)]),
|
|
38
|
+
});
|
|
39
|
+
if (!response.ok)
|
|
40
|
+
throw new Error(`AgentRadar refused the channel call (${response.status})`);
|
|
41
|
+
const text = await response.text();
|
|
42
|
+
const json = text.trim().startsWith("{") ? text : text.split("\n").find((line) => line.startsWith("data:"))?.slice(5);
|
|
43
|
+
if (!json)
|
|
44
|
+
throw new Error("Invalid AgentRadar MCP response");
|
|
45
|
+
return JSON.parse(json);
|
|
46
|
+
};
|
|
47
|
+
const next = (args = {}) => remote("tools/call", { name: "next_event", arguments: { ...args, sessionId } });
|
|
48
|
+
const pause = () => new Promise((resolve) => {
|
|
49
|
+
const done = () => { clearTimeout(timer); stop.signal.removeEventListener("abort", done); resolve(); };
|
|
50
|
+
const timer = setTimeout(done, deps.retryMs ?? 3_000);
|
|
51
|
+
stop.signal.addEventListener("abort", done, { once: true });
|
|
52
|
+
if (stop.signal.aborted)
|
|
53
|
+
done();
|
|
54
|
+
});
|
|
55
|
+
const poll = async () => {
|
|
56
|
+
let lastWake = "";
|
|
57
|
+
let lastSent = 0;
|
|
58
|
+
let selftestStarted = false;
|
|
59
|
+
while (!stop.signal.aborted) {
|
|
60
|
+
try {
|
|
61
|
+
if (!selftestStarted) {
|
|
62
|
+
// Establish the heartbeat without entering the empty queue's 200-second hold first.
|
|
63
|
+
const connected = await next({ runnerState: "starting" });
|
|
64
|
+
if (connected.error || connected.result?.isError)
|
|
65
|
+
throw new Error("AgentRadar refused the channel connection");
|
|
66
|
+
const drill = await remote("tools/call", { name: "run_selftest", arguments: {} });
|
|
67
|
+
selftestStarted = !drill.error && !drill.result?.isError;
|
|
68
|
+
if (!selftestStarted)
|
|
69
|
+
logError("AgentRadar self-test could not start; retrying after the next poll.");
|
|
70
|
+
}
|
|
71
|
+
const response = await next({ runnerState: "ready" });
|
|
72
|
+
if (response.error || response.result?.isError)
|
|
73
|
+
throw new Error("AgentRadar refused next_event; check the runner key and its poll permission");
|
|
74
|
+
const content = response.result?.content;
|
|
75
|
+
const payload = JSON.parse(content?.find((item) => item.type === "text")?.text ?? "{}");
|
|
76
|
+
const events = payload.events ?? [];
|
|
77
|
+
const wake = JSON.stringify([events.map((event) => event.eventId), payload.livenessProbe?.nonce, Boolean(payload.onboarding)]);
|
|
78
|
+
if ((events.length || payload.livenessProbe || payload.onboarding) && (wake !== lastWake || Date.now() - lastSent >= 30_000)) {
|
|
79
|
+
await send({ jsonrpc: "2.0", method: "notifications/claude/channel", params: {
|
|
80
|
+
content: `${events.length} new AgentRadar events; call next_event${payload.livenessProbe ? " to receive your liveness check" : ""}.`,
|
|
81
|
+
meta: { count: String(events.length) },
|
|
82
|
+
} });
|
|
83
|
+
lastWake = wake;
|
|
84
|
+
lastSent = Date.now();
|
|
85
|
+
}
|
|
86
|
+
// Never ack a count-only wake: only the agent's tool call confirms receipt of event content.
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
if (!stop.signal.aborted)
|
|
90
|
+
logError("AgentRadar channel poll failed; retrying. Check connectivity and the runner key.");
|
|
91
|
+
}
|
|
92
|
+
await pause();
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
const handle = async (message) => {
|
|
96
|
+
if (message.method === "initialize") {
|
|
97
|
+
await send({ jsonrpc: "2.0", id: message.id, result: {
|
|
98
|
+
protocolVersion: "2024-11-05",
|
|
99
|
+
capabilities: { tools: {}, experimental: { "claude/channel": {} } },
|
|
100
|
+
serverInfo: { name: "agentradar", version: createRequire(import.meta.url)("../package.json").version },
|
|
101
|
+
instructions: CHANNEL_GUIDANCE,
|
|
102
|
+
} });
|
|
103
|
+
}
|
|
104
|
+
else if (message.method === "notifications/initialized") {
|
|
105
|
+
if (!polling) {
|
|
106
|
+
polling = true;
|
|
107
|
+
warning = setTimeout(() => { if (!agentPolled)
|
|
108
|
+
logError(CHANNEL_BLOCKED); }, 30_000);
|
|
109
|
+
void poll();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else if (message.id !== undefined) {
|
|
113
|
+
if (message.method === "ping") {
|
|
114
|
+
await send({ jsonrpc: "2.0", id: message.id, result: {} });
|
|
115
|
+
}
|
|
116
|
+
else if (message.method === "tools/list" || message.method === "tools/call") {
|
|
117
|
+
const params = message.params ?? {};
|
|
118
|
+
const isNext = message.method === "tools/call" && params.name === "next_event";
|
|
119
|
+
const response = isNext ? await next(params.arguments ?? {}) : await remote(message.method, params);
|
|
120
|
+
if (isNext && !response.error && !response.result?.isError) {
|
|
121
|
+
agentPolled = true;
|
|
122
|
+
clearTimeout(warning);
|
|
123
|
+
}
|
|
124
|
+
await send({ jsonrpc: "2.0", id: message.id, ...(response.error ? { error: response.error } : { result: response.result }) });
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
await send({ jsonrpc: "2.0", id: message.id, error: { code: -32601, message: "Method not found" } });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
const lines = createInterface({ input: deps.input ?? process.stdin });
|
|
132
|
+
try {
|
|
133
|
+
for await (const line of lines) {
|
|
134
|
+
let message;
|
|
135
|
+
try {
|
|
136
|
+
message = JSON.parse(line);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
await send({ jsonrpc: "2.0", id: null, error: { code: -32700, message: "Parse error" } });
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
void handle(message).catch(() => send({ jsonrpc: "2.0", id: message.id ?? null, error: { code: -32603, message: "AgentRadar channel request failed" } }).catch(() => stop.abort()));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
clearTimeout(warning);
|
|
147
|
+
stop.abort();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=channel.js.map
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,71 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from "node:module";
|
|
2
3
|
import { installVendorSkill } from "./skill-install.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
4
|
+
import { startChannel } from "./channel.js";
|
|
5
|
+
import { runRestartSelftest, startVendorRunner } from "./runner.js";
|
|
6
|
+
import { joinOrganisation, setupVendorAgent } from "./setup.js";
|
|
7
|
+
import { callAwpTool, callToolOverCli, createTaskOverCli, listenOverCli, listServiceToolsOverCli, parseCallArgs, runServiceToolOverCli } from "./tool-run.js";
|
|
8
|
+
import { installSyncTimer, syncAgentDir } from "./sync.js";
|
|
9
|
+
// `run` is the one prefix every agent-facing command shares, so one harness "always allow agentradar run"
|
|
10
|
+
// covers a whole session: `run <link>` (or `run join <link>`) joins, `run <runner-id> <tool>` calls a tool.
|
|
11
|
+
export const runArgs = (raw) => raw[0] !== "run" ? raw
|
|
12
|
+
: raw[1] === "join" ? raw.slice(1)
|
|
13
|
+
: /^https?:\/\//.test(raw[1] ?? "") ? ["join", ...raw.slice(1)]
|
|
14
|
+
: raw.length === 3 && raw[2] === "listen" ? ["listen", raw[1]] : ["call", ...raw.slice(1)];
|
|
5
15
|
async function main() {
|
|
6
|
-
const args = process.argv.slice(2);
|
|
7
|
-
if (args.length === 1 && args[0] === "
|
|
8
|
-
|
|
16
|
+
const args = runArgs(process.argv.slice(2));
|
|
17
|
+
if (args.length === 1 && (args[0] === "--help" || args[0] === "-h")) {
|
|
18
|
+
console.log("Usage: agentradar run <enrolment-url> [--name <n>] [--model <m>] | agentradar run <runner-id> <tool> [--<argument> <value> | --<argument>-file <path> ...] | agentradar run <runner-id> listen | agentradar setup [--trust] [--harness claude|codex] | agentradar join <enrolment-url> [--name <n>] [--model <m>] [--trust] | agentradar channel <runner-id> | agentradar selftest <runner-id> [--status|--restart] | agentradar runner start <runner-id> | agentradar tool list <runner-id> | agentradar tool run <runner-id> <tool-key> [--args '<json>'] | agentradar call <runner-id> <tool> [--<argument> <value> ...] [--args '<json>'] | agentradar task create|repeat <runner-id> --args '<json>' | agentradar skill install | agentradar sync [dir] | agentradar sync install [dir] [--interval <s>]");
|
|
9
19
|
return;
|
|
10
20
|
}
|
|
11
|
-
if (args.length ===
|
|
12
|
-
|
|
21
|
+
if (args.length === 1 && (args[0] === "--version" || args[0] === "-v")) {
|
|
22
|
+
console.log(createRequire(import.meta.url)("../package.json").version);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (args[0] === "channel" && args.length === 2) {
|
|
26
|
+
await startChannel(args[1]);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (args[0] === "selftest" && args.length === 3 && args[2] === "--restart") {
|
|
30
|
+
// A native-channel session resumes in this terminal; print the result after it closes, not over its screen.
|
|
31
|
+
const report = [];
|
|
32
|
+
process.once("exit", () => { if (report.length)
|
|
33
|
+
console.log(report.join("\n")); });
|
|
34
|
+
await runRestartSelftest(args[1], { log: (text) => report.push(text) });
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (args[0] === "selftest" && (args.length === 2 || (args.length === 3 && args[2] === "--status"))) {
|
|
38
|
+
process.exitCode = await callAwpTool(args[1], "run_selftest", { statusOnly: args[2] === "--status" }, {});
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (args[0] === "setup") {
|
|
42
|
+
const rest = args.slice(1);
|
|
43
|
+
const hIdx = rest.indexOf("--harness");
|
|
44
|
+
const harness = hIdx >= 0 ? rest[hIdx + 1] : undefined;
|
|
45
|
+
const others = rest.filter((_, i) => i !== hIdx && i !== hIdx + 1);
|
|
46
|
+
if ((hIdx >= 0 && !harness) || others.some((arg) => arg !== "--trust")) {
|
|
47
|
+
console.error("Usage: agentradar setup [--trust] [--harness claude|codex]");
|
|
48
|
+
process.exitCode = 1;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
await setupVendorAgent({ trust: others.includes("--trust"), harness });
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (args[0] === "join") {
|
|
55
|
+
const named = {};
|
|
56
|
+
const urls = [];
|
|
57
|
+
for (let i = 1; i < args.length; i++) {
|
|
58
|
+
if (args[i] === "--name" || args[i] === "--model")
|
|
59
|
+
named[args[i].slice(2)] = args[++i] ?? "-";
|
|
60
|
+
else if (args[i] !== "--trust")
|
|
61
|
+
urls.push(args[i]);
|
|
62
|
+
}
|
|
63
|
+
if (urls.length !== 1 || [urls[0], ...Object.values(named)].some((value) => value.startsWith("-"))) {
|
|
64
|
+
console.error("Usage: agentradar join <enrolment-url> [--name <your name>] [--model <your model id>] [--trust]");
|
|
65
|
+
process.exitCode = 1;
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
process.exitCode = await joinOrganisation(urls[0], { trust: args.includes("--trust"), agentName: named.name, model: named.model });
|
|
13
69
|
return;
|
|
14
70
|
}
|
|
15
71
|
if (args.length === 2 && args[0] === "runner" && args[1] === "start") {
|
|
@@ -21,15 +77,82 @@ async function main() {
|
|
|
21
77
|
process.exitCode = await startVendorRunner(args[2]);
|
|
22
78
|
return;
|
|
23
79
|
}
|
|
80
|
+
if (args.length === 3 && args[0] === "tool" && args[1] === "list") {
|
|
81
|
+
process.exitCode = await listServiceToolsOverCli(args[2]);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if ((args[0] === "tool" && args[1] === "run") || args[0] === "call") {
|
|
85
|
+
const call = args[0] === "call";
|
|
86
|
+
const parsed = parseCallArgs(args.slice(call ? 1 : 2));
|
|
87
|
+
if (!parsed || (!call && parsed.flags.length)) {
|
|
88
|
+
console.error(call ? "Usage: agentradar call <runner-id> <tool> [--<argument> <value> ...] [--args '<json>']" : "Usage: agentradar tool run <runner-id> <tool-key> [--args '<json>']");
|
|
89
|
+
process.exitCode = 1;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
process.exitCode = call
|
|
93
|
+
? await callToolOverCli(parsed.runnerId, parsed.tool, parsed.json, {}, parsed.flags)
|
|
94
|
+
: await runServiceToolOverCli(parsed.runnerId, parsed.tool, parsed.json);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (args[0] === "listen" && args.length === 2) {
|
|
98
|
+
process.exitCode = await listenOverCli(args[1]);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (args[0] === "task" && (args[1] === "create" || args[1] === "repeat")) {
|
|
102
|
+
if (args.length !== 5 || args[3] !== "--args") {
|
|
103
|
+
console.error("Usage: agentradar task create|repeat <runner-id> --args '<json>'");
|
|
104
|
+
process.exitCode = 1;
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
process.exitCode = await createTaskOverCli(args[2], args[1] === "repeat", args[4]);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
24
110
|
if (args.length === 2 && args[0] === "skill" && args[1] === "install") {
|
|
25
111
|
await installVendorSkill();
|
|
26
112
|
return;
|
|
27
113
|
}
|
|
28
|
-
|
|
29
|
-
|
|
114
|
+
if (args[0] === "sync" && args[1] === "install") {
|
|
115
|
+
const rest = args.slice(2);
|
|
116
|
+
const iIdx = rest.indexOf("--interval");
|
|
117
|
+
const interval = iIdx >= 0 ? Number(rest[iIdx + 1]) : 600;
|
|
118
|
+
if (!Number.isFinite(interval) || interval < 60) {
|
|
119
|
+
console.error("--interval must be a number of seconds >= 60");
|
|
120
|
+
process.exitCode = 1;
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const dir = rest.filter((_, i) => i !== iIdx && i !== iIdx + 1)[0];
|
|
124
|
+
process.exitCode = await installSyncTimer(dir, interval);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (args[0] === "sync" && args.length <= 2) {
|
|
128
|
+
process.exitCode = await syncAgentDir(args[1]);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const help = args.length === 1 && (args[0] === "--help" || args[0] === "-h");
|
|
132
|
+
(help ? console.log : console.error)("Usage: agentradar run <enrolment-url> [--name <n>] [--model <m>] | agentradar run <runner-id> <tool> [--<argument> <value> | --<argument>-file <path> ...] | agentradar run <runner-id> listen | agentradar setup [--trust] | agentradar join <enrolment-url> [--name <n>] [--model <m>] [--trust] | agentradar channel <runner-id> | agentradar selftest <runner-id> [--status|--restart] | agentradar runner start <runner-id> | agentradar tool list <runner-id> | agentradar tool run <runner-id> <tool-key> [--args '<json>'] | agentradar call <runner-id> <tool> [--<argument> <value> ...] [--args '<json>'] | agentradar task create|repeat <runner-id> --args '<json>' | agentradar skill install | agentradar sync [dir] | agentradar sync install [dir] [--interval <s>]");
|
|
133
|
+
if (!help)
|
|
134
|
+
process.exitCode = 1;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* 🔴 `error.message` ALONE IS TWO WORDS ON THE FAILURE A VENDOR IS MOST LIKELY TO HIT. Node's `fetch`
|
|
138
|
+
* rejects with a `TypeError` whose message is exactly `fetch failed`; the reason — `getaddrinfo
|
|
139
|
+
* ENOTFOUND vendor.agentradar.com`, a TLS failure, a refused connection — is on `cause`, and printing
|
|
140
|
+
* only the message threw away the whole diagnosis. A vendor behind a proxy, on captive-portal wifi, or
|
|
141
|
+
* with a typo in AGENTRADAR_API_URL got "fetch failed" and an exit code.
|
|
142
|
+
*
|
|
143
|
+
* Exported for the test, which drives the cause-present and cause-absent shapes separately: an Error
|
|
144
|
+
* with no cause must still print its own message unchanged, or this "fix" would eat every other error
|
|
145
|
+
* in the CLI.
|
|
146
|
+
*/
|
|
147
|
+
export function errorLine(error) {
|
|
148
|
+
if (!(error instanceof Error))
|
|
149
|
+
return "AgentRadar command failed";
|
|
150
|
+
const { cause } = error;
|
|
151
|
+
const why = cause instanceof Error ? cause.message : typeof cause === "string" ? cause : "";
|
|
152
|
+
return why ? `${error.message}: ${why}` : error.message;
|
|
30
153
|
}
|
|
31
154
|
main().catch((error) => {
|
|
32
|
-
console.error(error
|
|
155
|
+
console.error(errorLine(error));
|
|
33
156
|
process.exitCode = 1;
|
|
34
157
|
});
|
|
35
158
|
//# sourceMappingURL=index.js.map
|