Files
elizaos--eliza/packages/examples/code/src/index.ts
T
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00

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 };