Files
Codeman/src/index.ts
T

70 lines
2.2 KiB
JavaScript
Raw Permalink Normal View History

#!/usr/bin/env node
/**
2026-02-26 16:44:34 +01:00
* @fileoverview Codeman CLI entry point
*
2026-02-26 16:44:34 +01:00
* This is the main executable entry point for the Codeman CLI.
* It sets up global error handlers and invokes the CLI parser.
*
* @module index
*/
import { program } from './cli.js';
2026-02-12 14:41:27 +01:00
// Detect if we're running the web server (long-lived process)
// In web mode, we should NOT exit on transient errors — log and continue
const isWebMode = process.argv.includes('web');
// COD-115: Codeman IS a tmux controller; it must never present as a tmux *client*.
// If the web server is launched from inside a tmux pane it inherits TMUX/TMUX_PANE,
// and tmux's nesting guard then kills every new attach-bridge PTY (exit 1 → respawn
// loop, crash-looping any new tmux-backed session). Scrub at the root so every
// downstream `{...process.env}` spread (attach, send-keys, create) is clean regardless
// of launch context. `delete` (not `= undefined`, which node-pty serializes as the
// literal string "undefined" and fails to clear).
if (isWebMode) {
delete process.env.TMUX;
delete process.env.TMUX_PANE;
}
import { MAX_CONSECUTIVE_ERRORS, ERROR_RESET_MS } from './config/server-timing.js';
// Track consecutive unhandled errors in web mode — restart after too many
let consecutiveErrors = 0;
let errorResetTimer: ReturnType<typeof setTimeout> | null = null;
function trackError(): void {
consecutiveErrors++;
if (errorResetTimer) clearTimeout(errorResetTimer);
errorResetTimer = setTimeout(() => {
consecutiveErrors = 0;
}, ERROR_RESET_MS);
if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
console.error(`[FATAL] ${MAX_CONSECUTIVE_ERRORS} consecutive unhandled errors — exiting for systemd restart`);
process.exit(1);
}
}
// Handle uncaught errors
process.on('uncaughtException', (err) => {
console.error('Uncaught exception:', err.message);
2026-02-12 14:41:27 +01:00
if (isWebMode) {
console.error('[RECOVERED] Server continuing after uncaught exception:', err.stack);
trackError();
2026-02-12 14:41:27 +01:00
} else {
process.exit(1);
}
});
process.on('unhandledRejection', (reason) => {
console.error('Unhandled rejection:', reason);
2026-02-12 14:41:27 +01:00
if (isWebMode) {
console.error('[RECOVERED] Server continuing after unhandled rejection');
trackError();
2026-02-12 14:41:27 +01:00
} else {
process.exit(1);
}
});
// Run CLI
program.parse();