426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
221 lines
6.2 KiB
JavaScript
221 lines
6.2 KiB
JavaScript
#!/usr/bin/env node
|
|
// Suppress elizaOS logs before any imports
|
|
process.env.LOG_LEVEL = "fatal";
|
|
|
|
import type { AgentRuntime } from "@elizaos/core";
|
|
import { main as cliMain } from "./cli.js";
|
|
import { loadEnv } from "./lib/load-env.js";
|
|
|
|
loadEnv();
|
|
|
|
// ============================================================================
|
|
// Environment Detection
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Determine if we should run in interactive (TUI) mode.
|
|
* Interactive mode requires:
|
|
* - stdin and stdout both be TTYs
|
|
* - No message argument provided (unless --interactive flag)
|
|
*/
|
|
function shouldRunInteractive(): boolean {
|
|
const args = process.argv.slice(2);
|
|
|
|
// Explicit interactive flag
|
|
if (args.includes("-i") || args.includes("--interactive")) {
|
|
return true;
|
|
}
|
|
|
|
// Help/version should use CLI mode
|
|
if (
|
|
args.includes("-h") ||
|
|
args.includes("--help") ||
|
|
args.includes("-v") ||
|
|
args.includes("--version")
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
// If there are any arguments (message, file, etc.), use CLI mode
|
|
if (args.length > 0) {
|
|
return false;
|
|
}
|
|
|
|
// Check if TTY is available
|
|
// Bun/watch can sometimes leave `isTTY` undefined even in a real terminal.
|
|
// Only treat it as non-interactive if it is explicitly `false`.
|
|
return process.stdin.isTTY !== false && process.stdout.isTTY !== false;
|
|
}
|
|
|
|
function shouldRunCodingOnly(): boolean {
|
|
const args = process.argv.slice(2);
|
|
const env = process.env.ELIZA_CODE_CODING_ONLY?.trim().toLowerCase();
|
|
return (
|
|
env === "1" ||
|
|
env === "true" ||
|
|
args.includes("--coding-only") ||
|
|
args.includes("--no-orchestrator")
|
|
);
|
|
}
|
|
|
|
// ============================================================================
|
|
// Interactive Mode (TUI)
|
|
// ============================================================================
|
|
|
|
let isShuttingDown = false;
|
|
|
|
// Module-scoped handle to the live TUI app so the fatal handlers below can
|
|
// restore the terminal (raw mode / bracketed paste / cursor) before exiting —
|
|
// that teardown only runs via app.stop(), so a bare process.exit(1) on an
|
|
// unhandled error used to leave the user's shell wedged.
|
|
let activeApp: { stop: () => void } | undefined;
|
|
|
|
/** Best-effort terminal restore before a fatal exit. Never throws. */
|
|
function restoreTerminalBestEffort(): void {
|
|
try {
|
|
activeApp?.stop();
|
|
} catch (error) {
|
|
// error-policy:J6 Terminal restoration continues through every teardown
|
|
// step, while stderr preserves each failed step for diagnosis.
|
|
process.stderr.write(
|
|
`[eliza-code] app teardown failed: ${error instanceof Error ? error.message : String(error)}\n`,
|
|
);
|
|
}
|
|
try {
|
|
if (process.stdout.isTTY) {
|
|
// Disable bracketed paste + Kitty keyboard protocol, show the cursor.
|
|
process.stdout.write("\x1b[?2004l\x1b[<u\x1b[?25h");
|
|
}
|
|
if (process.stdin.isTTY && process.stdin.setRawMode) {
|
|
process.stdin.setRawMode(false);
|
|
}
|
|
} catch (error) {
|
|
// error-policy:J6 This is the last terminal teardown path before exit.
|
|
process.stderr.write(
|
|
`[eliza-code] terminal restore failed: ${error instanceof Error ? error.message : String(error)}\n`,
|
|
);
|
|
}
|
|
}
|
|
|
|
async function cleanup(runtime: AgentRuntime): Promise<void> {
|
|
if (isShuttingDown) return;
|
|
isShuttingDown = true;
|
|
|
|
try {
|
|
const [{ shutdownAgent }, { resetAgentClient }, { useStore }] =
|
|
await Promise.all([
|
|
import("./lib/agent.js"),
|
|
import("./lib/agent-client.js"),
|
|
import("./lib/store.js"),
|
|
]);
|
|
|
|
// Save session before shutdown
|
|
await useStore.getState().saveSessionState();
|
|
|
|
if (runtime) {
|
|
await shutdownAgent(runtime);
|
|
}
|
|
resetAgentClient();
|
|
} catch (error) {
|
|
// error-policy:J6 Process shutdown must reach exit even if persistence or
|
|
// service teardown fails, but the failure remains observable on stderr.
|
|
process.stderr.write(
|
|
`[eliza-code] shutdown failed: ${error instanceof Error ? error.message : String(error)}\n`,
|
|
);
|
|
}
|
|
|
|
process.exit(0);
|
|
}
|
|
|
|
async function runInteractive(): Promise<void> {
|
|
// Validate TTY
|
|
if (process.stdin.isTTY === false || process.stdout.isTTY === false) {
|
|
console.error("❌ Interactive mode requires a terminal.");
|
|
console.error(
|
|
" Use CLI mode for non-interactive usage: eliza-code --help",
|
|
);
|
|
process.exit(1);
|
|
}
|
|
|
|
const [{ App }, { initializeAgent }] = await Promise.all([
|
|
import("./App.js"),
|
|
import("./lib/agent.js"),
|
|
]);
|
|
|
|
let runtime: AgentRuntime | undefined;
|
|
let app: InstanceType<typeof App> | undefined;
|
|
|
|
// Initialize the agent
|
|
runtime = await initializeAgent({ codingOnly: shouldRunCodingOnly() });
|
|
|
|
// Handle SIGINT (Ctrl+C) and SIGTERM
|
|
const handleSignal = () => {
|
|
if (app) {
|
|
app.stop();
|
|
}
|
|
if (runtime) {
|
|
cleanup(runtime);
|
|
}
|
|
};
|
|
|
|
process.on("SIGINT", handleSignal);
|
|
process.on("SIGTERM", handleSignal);
|
|
|
|
// Clear the screen before rendering TUI
|
|
console.clear();
|
|
|
|
// Create and run the app
|
|
app = new App(runtime);
|
|
activeApp = app;
|
|
await app.run();
|
|
activeApp = undefined;
|
|
|
|
// App exited normally (e.g., Ctrl+Q)
|
|
await cleanup(runtime);
|
|
}
|
|
|
|
// ============================================================================
|
|
// Main Entry Point
|
|
// ============================================================================
|
|
|
|
async function main(): Promise<void> {
|
|
if (shouldRunInteractive()) {
|
|
await runInteractive();
|
|
} else {
|
|
const exitCode = await cliMain();
|
|
|
|
// Special code -1 means: force interactive mode
|
|
if (exitCode === -1) {
|
|
await runInteractive();
|
|
} else {
|
|
process.exit(exitCode);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Handle uncaught errors
|
|
process.on("uncaughtException", (error) => {
|
|
restoreTerminalBestEffort();
|
|
console.error("Uncaught exception:", error);
|
|
process.exit(1);
|
|
});
|
|
|
|
process.on("unhandledRejection", (reason) => {
|
|
restoreTerminalBestEffort();
|
|
console.error("Unhandled rejection:", reason);
|
|
process.exit(1);
|
|
});
|
|
|
|
// Run the app
|
|
main().catch((error) => {
|
|
restoreTerminalBestEffort();
|
|
console.error("Fatal error:", error);
|
|
process.exit(1);
|
|
});
|
|
|
|
// ============================================================================
|
|
// Exports for Testing
|
|
// ============================================================================
|
|
|
|
export { runInteractive, shouldRunInteractive };
|