@jmylchreest/aide-plugin 0.0.57 → 0.0.58

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Install command — registers aide plugin and MCP server in OpenCode config.
2
+ * Install command — registers aide plugin and MCP server for OpenCode or Codex CLI.
3
3
  *
4
4
  * On reinstall, detects and upgrades stale MCP command configurations
5
5
  * (e.g. old `aide-wrapper` commands) to the current format.
@@ -15,51 +15,37 @@ import {
15
15
  PLUGIN_NAME,
16
16
  MCP_SERVER_NAME,
17
17
  } from "./config.js";
18
+ import { installCodex, isCodexConfigured } from "./codex-config.js";
18
19
 
19
20
  export interface InstallFlags {
20
21
  project?: boolean;
21
22
  noMcp?: boolean;
23
+ platform?: "opencode" | "codex";
22
24
  }
23
25
 
24
- /**
25
- * Check if an existing MCP config has the current expected command format.
26
- * Returns false if the command is missing, empty, or uses an outdated format.
27
- */
28
26
  function isMcpCommandCurrent(config: ReturnType<typeof readConfig>): boolean {
29
27
  const mcpConfig = config.mcp?.[MCP_SERVER_NAME];
30
- if (!mcpConfig?.command || mcpConfig.command.length === 0) {
31
- return false;
32
- }
33
-
28
+ if (!mcpConfig?.command || mcpConfig.command.length === 0) return false;
34
29
  const cmd = mcpConfig.command;
35
-
36
- // Current format: ["bunx", "-y", "@jmylchreest/aide-plugin", "mcp"]
37
- if (
30
+ return (
38
31
  cmd.length === 4 &&
39
32
  cmd[0] === "bunx" &&
40
33
  cmd[1] === "-y" &&
41
34
  cmd[2] === PLUGIN_NAME &&
42
35
  cmd[3] === "mcp"
43
- ) {
44
- return true;
45
- }
46
-
47
- return false;
36
+ );
48
37
  }
49
38
 
50
- export async function install(flags: InstallFlags): Promise<void> {
39
+ async function installOpenCode(flags: InstallFlags): Promise<void> {
51
40
  const configPath = flags.project
52
41
  ? getProjectConfigPath()
53
42
  : getGlobalConfigPath();
54
43
 
55
44
  const scope = flags.project ? "project" : "global";
56
- console.log(`Installing aide plugin (${scope})...\n`);
45
+ console.log(`Installing aide plugin for OpenCode (${scope})...\n`);
57
46
 
58
- // Read existing config
59
47
  const existing = readConfig(configPath);
60
48
  const before = isAideConfigured(existing);
61
-
62
- // Check if MCP command needs updating (stale format from older versions)
63
49
  const mcpNeedsUpdate =
64
50
  !flags.noMcp && before.mcp && !isMcpCommandCurrent(existing);
65
51
 
@@ -71,16 +57,13 @@ export async function install(flags: InstallFlags): Promise<void> {
71
57
  return;
72
58
  }
73
59
 
74
- // If MCP config is stale, remove it so addAideToConfig will write the current version
75
60
  if (mcpNeedsUpdate && existing.mcp) {
76
61
  delete existing.mcp[MCP_SERVER_NAME];
77
62
  }
78
63
 
79
- // Apply changes
80
64
  const updated = addAideToConfig(existing, { noMcp: flags.noMcp });
81
65
  writeConfig(configPath, updated);
82
66
 
83
- // Report what was done
84
67
  const after = isAideConfigured(updated);
85
68
  console.log(`Updated: ${configPath}\n`);
86
69
 
@@ -110,3 +93,47 @@ export async function install(flags: InstallFlags): Promise<void> {
110
93
  );
111
94
  }
112
95
  }
96
+
97
+ async function installForCodex(flags: InstallFlags): Promise<void> {
98
+ const scope = flags.project ? "project" : "user";
99
+ console.log(`Installing aide for Codex CLI (${scope})...\n`);
100
+
101
+ const before = isCodexConfigured(scope);
102
+ if (before.mcp && before.hooks) {
103
+ console.log("aide is already configured for Codex CLI");
104
+ console.log(" mcp: registered in config.toml");
105
+ console.log(" hooks: registered in hooks.json");
106
+ console.log("\nNothing to do.");
107
+ return;
108
+ }
109
+
110
+ const result = installCodex(scope);
111
+
112
+ if (result.configWritten) {
113
+ console.log(" + Added aide MCP server to config.toml");
114
+ } else if (before.mcp) {
115
+ console.log(" = MCP server already registered in config.toml");
116
+ }
117
+
118
+ if (result.hooksWritten) {
119
+ console.log(" + Generated hooks.json with aide hooks");
120
+ } else if (before.hooks) {
121
+ console.log(" = Hooks already registered in hooks.json");
122
+ }
123
+
124
+ console.log("\nInstallation complete. Start Codex CLI to use aide.");
125
+
126
+ if (!flags.project) {
127
+ console.log(
128
+ "\nThe plugin is installed globally and will apply to all Codex CLI sessions.",
129
+ );
130
+ }
131
+ }
132
+
133
+ export async function install(flags: InstallFlags): Promise<void> {
134
+ if (flags.platform === "codex") {
135
+ await installForCodex(flags);
136
+ } else {
137
+ await installOpenCode(flags);
138
+ }
139
+ }
package/src/cli/status.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Status command — shows current aide installation status for OpenCode.
2
+ * Status command — shows current aide installation status for OpenCode or Codex CLI.
3
3
  */
4
4
 
5
5
  import { existsSync } from "fs";
@@ -9,38 +9,71 @@ import {
9
9
  isAideConfigured,
10
10
  readConfig,
11
11
  } from "./config.js";
12
+ import {
13
+ isCodexConfigured,
14
+ getCodexConfigTomlPath,
15
+ getCodexHooksJsonPath,
16
+ } from "./codex-config.js";
17
+
18
+ export interface StatusFlags {
19
+ platform?: "opencode" | "codex";
20
+ }
12
21
 
13
- export async function status(): Promise<void> {
14
- console.log("aide plugin status\n");
22
+ function showOpenCodeStatus(): void {
23
+ console.log("aide plugin status (OpenCode)\n");
15
24
 
16
25
  const globalPath = getGlobalConfigPath();
17
26
  const projectPath = getProjectConfigPath();
18
27
 
19
- // Global config
20
28
  console.log(`Global config: ${globalPath}`);
21
29
  if (existsSync(globalPath)) {
22
- const globalConfig = readConfig(globalPath);
23
- const globalStatus = isAideConfigured(globalConfig);
24
- console.log(
25
- ` plugin: ${globalStatus.plugin ? "registered" : "not found"}`,
26
- );
27
- console.log(` mcp: ${globalStatus.mcp ? "registered" : "not found"}`);
30
+ const s = isAideConfigured(readConfig(globalPath));
31
+ console.log(` plugin: ${s.plugin ? "registered" : "not found"}`);
32
+ console.log(` mcp: ${s.mcp ? "registered" : "not found"}`);
28
33
  } else {
29
34
  console.log(" (file does not exist)");
30
35
  }
31
36
 
32
37
  console.log();
33
38
 
34
- // Project config
35
39
  console.log(`Project config: ${projectPath}`);
36
40
  if (existsSync(projectPath)) {
37
- const projectConfig = readConfig(projectPath);
38
- const projectStatus = isAideConfigured(projectConfig);
39
- console.log(
40
- ` plugin: ${projectStatus.plugin ? "registered" : "not found"}`,
41
- );
42
- console.log(` mcp: ${projectStatus.mcp ? "registered" : "not found"}`);
41
+ const s = isAideConfigured(readConfig(projectPath));
42
+ console.log(` plugin: ${s.plugin ? "registered" : "not found"}`);
43
+ console.log(` mcp: ${s.mcp ? "registered" : "not found"}`);
43
44
  } else {
44
45
  console.log(" (file does not exist)");
45
46
  }
46
47
  }
48
+
49
+ function showCodexStatus(): void {
50
+ console.log("aide plugin status (Codex CLI)\n");
51
+
52
+ const userConfig = getCodexConfigTomlPath("user");
53
+ const userHooks = getCodexHooksJsonPath("user");
54
+ const userStatus = isCodexConfigured("user");
55
+
56
+ console.log(`User config: ${userConfig}`);
57
+ console.log(`User hooks: ${userHooks}`);
58
+ console.log(` mcp: ${userStatus.mcp ? "registered" : "not found"}`);
59
+ console.log(` hooks: ${userStatus.hooks ? "registered" : "not found"}`);
60
+
61
+ console.log();
62
+
63
+ const projectConfig = getCodexConfigTomlPath("project");
64
+ const projectHooks = getCodexHooksJsonPath("project");
65
+ const projectStatus = isCodexConfigured("project");
66
+
67
+ console.log(`Project config: ${projectConfig}`);
68
+ console.log(`Project hooks: ${projectHooks}`);
69
+ console.log(` mcp: ${projectStatus.mcp ? "registered" : "not found"}`);
70
+ console.log(` hooks: ${projectStatus.hooks ? "registered" : "not found"}`);
71
+ }
72
+
73
+ export async function status(flags?: StatusFlags): Promise<void> {
74
+ if (flags?.platform === "codex") {
75
+ showCodexStatus();
76
+ } else {
77
+ showOpenCodeStatus();
78
+ }
79
+ }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Uninstall command — removes aide plugin and MCP server from OpenCode config.
2
+ * Uninstall command — removes aide plugin and MCP server from OpenCode or Codex CLI config.
3
3
  */
4
4
 
5
5
  import {
@@ -10,18 +10,20 @@ import {
10
10
  removeAideFromConfig,
11
11
  writeConfig,
12
12
  } from "./config.js";
13
+ import { uninstallCodex, isCodexConfigured } from "./codex-config.js";
13
14
 
14
15
  export interface UninstallFlags {
15
16
  project?: boolean;
17
+ platform?: "opencode" | "codex";
16
18
  }
17
19
 
18
- export async function uninstall(flags: UninstallFlags): Promise<void> {
20
+ async function uninstallOpenCode(flags: UninstallFlags): Promise<void> {
19
21
  const configPath = flags.project
20
22
  ? getProjectConfigPath()
21
23
  : getGlobalConfigPath();
22
24
 
23
25
  const scope = flags.project ? "project" : "global";
24
- console.log(`Uninstalling aide plugin (${scope})...\n`);
26
+ console.log(`Uninstalling aide plugin from OpenCode (${scope})...\n`);
25
27
 
26
28
  const existing = readConfig(configPath);
27
29
  const before = isAideConfigured(existing);
@@ -36,13 +38,32 @@ export async function uninstall(flags: UninstallFlags): Promise<void> {
36
38
  writeConfig(configPath, updated);
37
39
 
38
40
  console.log(`Updated: ${configPath}\n`);
41
+ if (before.plugin) console.log(` - Removed aide plugin from plugin array`);
42
+ if (before.mcp) console.log(` - Removed aide MCP server`);
43
+ console.log("\nUninstallation complete.");
44
+ }
39
45
 
40
- if (before.plugin) {
41
- console.log(` - Removed aide plugin from plugin array`);
42
- }
43
- if (before.mcp) {
44
- console.log(` - Removed aide MCP server`);
46
+ async function uninstallFromCodex(flags: UninstallFlags): Promise<void> {
47
+ const scope = flags.project ? "project" : "user";
48
+ console.log(`Uninstalling aide from Codex CLI (${scope})...\n`);
49
+
50
+ const before = isCodexConfigured(scope);
51
+ if (!before.mcp && !before.hooks) {
52
+ console.log("aide is not configured for Codex CLI.");
53
+ console.log("\nNothing to do.");
54
+ return;
45
55
  }
46
56
 
57
+ const result = uninstallCodex(scope);
58
+ if (result.configRemoved) console.log(" - Removed aide MCP server from config.toml");
59
+ if (result.hooksRemoved) console.log(" - Removed aide hooks from hooks.json");
47
60
  console.log("\nUninstallation complete.");
48
61
  }
62
+
63
+ export async function uninstall(flags: UninstallFlags): Promise<void> {
64
+ if (flags.platform === "codex") {
65
+ await uninstallFromCodex(flags);
66
+ } else {
67
+ await uninstallOpenCode(flags);
68
+ }
69
+ }
@@ -8,6 +8,7 @@
8
8
  * Supports:
9
9
  * - Claude Code: ~/.claude.json (user), .mcp.json (project) (reads legacy ~/.mcp.json)
10
10
  * - OpenCode: ~/.config/opencode/opencode.json (user), ./opencode.json (project)
11
+ * - Codex CLI: ~/.codex/config.toml (user), .codex/config.toml (project)
11
12
  * - Aide canonical: ~/.aide/config/mcp.json (user), .aide/config/mcp.json (project)
12
13
  *
13
14
  * Uses a journal to detect intentional deletions from the aide canonical file,
@@ -21,17 +22,17 @@ import {
21
22
  writeFileSync,
22
23
  mkdirSync,
23
24
  statSync,
24
- unlinkSync,
25
25
  } from "fs";
26
26
  import { join, dirname } from "path";
27
27
  import { homedir } from "os";
28
+ import * as TOML from "smol-toml";
28
29
 
29
30
  // =============================================================================
30
31
  // Types
31
32
  // =============================================================================
32
33
 
33
34
  /** Platform identifier for the current assistant. */
34
- export type McpPlatform = "claude-code" | "opencode";
35
+ export type McpPlatform = "claude-code" | "opencode" | "codex";
35
36
 
36
37
  /**
37
38
  * Discover MCP server names managed by installed Claude Code plugins.
@@ -204,6 +205,11 @@ function getAssistantReadPaths(
204
205
  ? [join(homedir(), ".config", "opencode", "opencode.json")]
205
206
  : [join(cwd, "opencode.json")];
206
207
  }
208
+ if (platform === "codex") {
209
+ return scope === "user"
210
+ ? [join(homedir(), ".codex", "config.toml")]
211
+ : [join(cwd, ".codex", "config.toml")];
212
+ }
207
213
  return [];
208
214
  }
209
215
 
@@ -222,6 +228,11 @@ function getAssistantWritePaths(
222
228
  ? [join(homedir(), ".config", "opencode", "opencode.json")]
223
229
  : [join(cwd, "opencode.json")];
224
230
  }
231
+ if (platform === "codex") {
232
+ return scope === "user"
233
+ ? [join(homedir(), ".codex", "config.toml")]
234
+ : [join(cwd, ".codex", "config.toml")];
235
+ }
225
236
  return [];
226
237
  }
227
238
 
@@ -369,6 +380,59 @@ function readOpenCodeConfig(path: string): Record<string, CanonicalMcpServer> {
369
380
  }
370
381
  }
371
382
 
383
+ /**
384
+ * Read Codex CLI MCP config from config.toml.
385
+ *
386
+ * Format:
387
+ * ```toml
388
+ * [mcp_servers.name]
389
+ * command = "npx"
390
+ * args = ["package-name"]
391
+ *
392
+ * [mcp_servers.name.env]
393
+ * KEY = "value"
394
+ * ```
395
+ */
396
+ function readCodexConfig(path: string): Record<string, CanonicalMcpServer> {
397
+ if (!existsSync(path)) return {};
398
+
399
+ try {
400
+ const raw = TOML.parse(readFileSync(path, "utf-8"));
401
+ const servers: Record<string, CanonicalMcpServer> = {};
402
+
403
+ const mcpServers = raw.mcp_servers as
404
+ | Record<string, Record<string, unknown>>
405
+ | undefined;
406
+ if (
407
+ typeof mcpServers !== "object" ||
408
+ mcpServers === null ||
409
+ Array.isArray(mcpServers)
410
+ )
411
+ return {};
412
+
413
+ for (const [name, def] of Object.entries(mcpServers)) {
414
+ const hasUrl = typeof def.url === "string";
415
+ const isRemote = hasUrl;
416
+
417
+ servers[name] = {
418
+ name,
419
+ type: isRemote ? "remote" : "local",
420
+ transport: isRemote ? "http" : undefined,
421
+ command: def.command as string | undefined,
422
+ args: def.args as string[] | undefined,
423
+ url: def.url as string | undefined,
424
+ env: (def.env as Record<string, string>) || undefined,
425
+ headers: def.headers as Record<string, string> | undefined,
426
+ enabled: true,
427
+ };
428
+ }
429
+
430
+ return servers;
431
+ } catch {
432
+ return {};
433
+ }
434
+ }
435
+
372
436
  /**
373
437
  * Read MCP servers from a specific assistant's config file.
374
438
  */
@@ -378,6 +442,7 @@ function readAssistantConfig(
378
442
  ): Record<string, CanonicalMcpServer> {
379
443
  if (platform === "claude-code") return readClaudeConfig(path);
380
444
  if (platform === "opencode") return readOpenCodeConfig(path);
445
+ if (platform === "codex") return readCodexConfig(path);
381
446
  return {};
382
447
  }
383
448
 
@@ -511,6 +576,59 @@ function writeOpenCodeConfig(
511
576
  writeFileSync(path, JSON.stringify(existing, null, 2) + "\n");
512
577
  }
513
578
 
579
+ /**
580
+ * Write canonical servers to a Codex CLI config.toml file.
581
+ *
582
+ * Preserves all non-mcp_servers content in the file.
583
+ */
584
+ function writeCodexConfig(
585
+ path: string,
586
+ servers: Record<string, CanonicalMcpServer>,
587
+ ): void {
588
+ const dir = dirname(path);
589
+ if (!existsSync(dir)) {
590
+ mkdirSync(dir, { recursive: true });
591
+ }
592
+
593
+ // Read existing file to preserve non-mcp_servers keys
594
+ let existing: Record<string, unknown> = {};
595
+ if (existsSync(path)) {
596
+ try {
597
+ existing = TOML.parse(readFileSync(path, "utf-8")) as Record<
598
+ string,
599
+ unknown
600
+ >;
601
+ } catch {
602
+ // Start fresh
603
+ }
604
+ }
605
+
606
+ const mcpServers: Record<string, Record<string, unknown>> = {};
607
+ for (const [name, server] of Object.entries(servers)) {
608
+ const entry: Record<string, unknown> = {};
609
+
610
+ if (server.type === "remote") {
611
+ if (server.url) entry.url = server.url;
612
+ if (server.headers) entry.headers = server.headers;
613
+ } else {
614
+ if (server.command) entry.command = server.command;
615
+ if (server.args) entry.args = server.args;
616
+ }
617
+
618
+ if (server.env && Object.keys(server.env).length > 0) {
619
+ entry.env = server.env;
620
+ }
621
+
622
+ mcpServers[name] = entry;
623
+ }
624
+
625
+ existing.mcp_servers = mcpServers;
626
+ writeFileSync(
627
+ path,
628
+ TOML.stringify(existing as Record<string, unknown>) + "\n",
629
+ );
630
+ }
631
+
514
632
  /**
515
633
  * Write canonical servers to the current assistant's config file.
516
634
  */
@@ -521,6 +639,7 @@ function writeAssistantConfig(
521
639
  ): void {
522
640
  if (platform === "claude-code") writeClaudeConfig(path, servers);
523
641
  else if (platform === "opencode") writeOpenCodeConfig(path, servers);
642
+ else if (platform === "codex") writeCodexConfig(path, servers);
524
643
  }
525
644
 
526
645
  // =============================================================================
@@ -644,7 +763,7 @@ interface McpSource {
644
763
  * Gather all MCP config source files for a given scope.
645
764
  */
646
765
  function gatherSources(scope: McpScope, cwd: string): McpSource[] {
647
- const platforms: McpPlatform[] = ["claude-code", "opencode"];
766
+ const platforms: McpPlatform[] = ["claude-code", "opencode", "codex"];
648
767
  const sources: McpSource[] = [];
649
768
 
650
769
  const aidePath =
@@ -882,13 +1001,7 @@ function syncScope(
882
1001
  sortedStringify(existingAssistant) !== sortedStringify(assistantServers);
883
1002
 
884
1003
  if (assistantChanged) {
885
- if (Object.keys(assistantServers).length === 0 && existsSync(p)) {
886
- // No servers to write — remove the file rather than leaving
887
- // an empty mcpServers block that the assistant still loads.
888
- try { unlinkSync(p); } catch { /* ignore */ }
889
- } else if (Object.keys(assistantServers).length > 0) {
890
- writeAssistantConfig(platform, p, assistantServers);
891
- }
1004
+ writeAssistantConfig(platform, p, assistantServers);
892
1005
  result.modified = true;
893
1006
  }
894
1007
  }
@@ -911,7 +1024,7 @@ function syncScope(
911
1024
  * handles intentional deletions via a journal, and writes the result to
912
1025
  * both the aide canonical config and the current assistant's config files.
913
1026
  *
914
- * @param platform - The current assistant platform ("claude-code" or "opencode")
1027
+ * @param platform - The current assistant platform ("claude-code", "opencode", or "codex")
915
1028
  * @param cwd - The project working directory
916
1029
  * @returns Combined sync results for both user and project scopes
917
1030
  */
package/src/core/types.ts CHANGED
@@ -111,7 +111,7 @@ export interface Skill {
111
111
  path: string;
112
112
  triggers: string[];
113
113
  description?: string;
114
- /** Optional platform restriction. If set, only matched on listed platforms ("opencode", "claude-code"). */
114
+ /** Optional platform restriction. If set, only matched on listed platforms ("opencode", "claude-code", "codex"). */
115
115
  platforms?: string[];
116
116
  /** Optional binary requirement. If set, skill is only matched when all listed binaries exist on PATH. */
117
117
  requires_binary?: string[];
@@ -156,7 +156,7 @@ export const MAX_PERSISTENCE_ITERATIONS = 20;
156
156
  * Identifies which host platform aide is running in.
157
157
  * Used for platform-specific behavior like binary discovery or context injection.
158
158
  */
159
- export type AidePlatform = "claude-code" | "opencode" | "unknown";
159
+ export type AidePlatform = "claude-code" | "opencode" | "codex" | "unknown";
160
160
 
161
161
  /**
162
162
  * Options for finding the aide binary.
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Agent Cleanup Hook (Stop)
4
+ *
5
+ * Cleans up agent-specific state when an agent stops.
6
+ * This prevents stale state from polluting future agents with the same ID.
7
+ *
8
+ * Runs after persistence hook to clean up when agent is allowed to stop.
9
+ */
10
+
11
+ import { existsSync, appendFileSync } from "fs";
12
+ import { join } from "path";
13
+ import { readStdin } from "../lib/hook-utils.js";
14
+ import { findAideBinary } from "../core/aide-client.js";
15
+ import { cleanupAgent } from "../core/cleanup.js";
16
+ import { debug } from "../lib/logger.js";
17
+
18
+ const SOURCE = "agent-cleanup";
19
+
20
+ interface HookInput {
21
+ hook_event_name: string;
22
+ session_id: string;
23
+ cwd: string;
24
+ agent_id?: string;
25
+ transcript_path?: string;
26
+ permission_mode?: string;
27
+ }
28
+
29
+ async function main(): Promise<void> {
30
+ try {
31
+ const input = await readStdin();
32
+ if (!input.trim()) {
33
+ console.log(JSON.stringify({ continue: true }));
34
+ return;
35
+ }
36
+
37
+ const data: HookInput = JSON.parse(input);
38
+ const cwd = data.cwd || process.cwd();
39
+ const agentId = data.agent_id || data.session_id;
40
+
41
+ // Clean up agent-specific state — delegates to core
42
+ if (agentId) {
43
+ const binary = findAideBinary({
44
+ cwd,
45
+ pluginRoot:
46
+ process.env.AIDE_PLUGIN_ROOT || process.env.CLAUDE_PLUGIN_ROOT,
47
+ });
48
+ if (binary) {
49
+ const cleared = cleanupAgent(binary, cwd, agentId);
50
+ if (cleared) {
51
+ const logDir = join(cwd, ".aide", "_logs");
52
+ if (existsSync(logDir)) {
53
+ const logPath = join(logDir, "agent-cleanup.log");
54
+ const timestamp = new Date().toISOString();
55
+ appendFileSync(
56
+ logPath,
57
+ `${timestamp} Cleaned up state for agent: ${agentId}\n`,
58
+ );
59
+ }
60
+ }
61
+ }
62
+ }
63
+
64
+ // Always continue - cleanup is best-effort
65
+ console.log(JSON.stringify({ continue: true }));
66
+ } catch (error) {
67
+ debug(SOURCE, `Hook error: ${error}`);
68
+ console.log(JSON.stringify({ continue: true }));
69
+ }
70
+ }
71
+
72
+ process.on("uncaughtException", (err) => {
73
+ debug(SOURCE, `UNCAUGHT EXCEPTION: ${err}`);
74
+ try {
75
+ console.log(JSON.stringify({ continue: true }));
76
+ } catch {
77
+ console.log('{"continue":true}');
78
+ }
79
+ process.exit(0);
80
+ });
81
+ process.on("unhandledRejection", (reason) => {
82
+ debug(SOURCE, `UNHANDLED REJECTION: ${reason}`);
83
+ try {
84
+ console.log(JSON.stringify({ continue: true }));
85
+ } catch {
86
+ console.log('{"continue":true}');
87
+ }
88
+ process.exit(0);
89
+ });
90
+
91
+ main();