| 1 | // Shared config + session storage for the agent sidecar. |
| 2 | // |
| 3 | // The session file holds the agent's device token and its ECDH private key — it |
| 4 | // IS the agent's identity, and (like the ANTHROPIC_API_KEY) it lives only on the |
| 5 | // agent host, never on the lchat server. Keep it secret; back it up. |
| 6 | import { readFileSync, writeFileSync, existsSync } from "node:fs"; |
| 7 | import { fileURLToPath } from "node:url"; |
| 8 | |
| 9 | // The instance base URL, e.g. https://test.example.com. WS base is derived |
| 10 | // (https -> wss, http -> ws). |
| 11 | export const BASE = (process.env.LCHAT_BASE || "").replace(/\/$/, ""); |
| 12 | export const WS_BASE = BASE.replace(/^http/, "ws"); |
| 13 | |
| 14 | // Whether the model brain is available. With no key the sidecar still runs its |
| 15 | // deterministic side (welcomes + slash commands), so a helper "upgrades" from |
| 16 | // BOT to AI exactly when a key is present — the badge follows this (runtime.mjs |
| 17 | // self-declares kind), and non-command messages degrade to a commands hint. |
| 18 | export const AI_ENABLED = !!(process.env.ANTHROPIC_API_KEY || "").trim(); |
| 19 | |
| 20 | export const AGENT_NAME = process.env.LCHAT_AGENT_NAME || "Claude"; |
| 21 | // The app's user-facing name (the product is called Eleven; lchat is the |
| 22 | // project/repo name). Bots refer to the app by this. |
| 23 | export const APP_NAME = process.env.LCHAT_APP_NAME || "Eleven"; |
| 24 | export const MODEL = process.env.LCHAT_MODEL || "claude-sonnet-5"; |
| 25 | // The bare-name "am I being addressed?" gate in runtime.mjs — a tiny yes/no |
| 26 | // call, so it always uses the cheapest model regardless of the bot's MODEL. |
| 27 | export const CLASSIFIER_MODEL = process.env.LCHAT_CLASSIFIER_MODEL || "claude-haiku-4-5"; |
| 28 | |
| 29 | // Session lives next to this module by default so `node agent.mjs` works from |
| 30 | // any cwd; override with LCHAT_SESSION. |
| 31 | export const SESSION_PATH = |
| 32 | process.env.LCHAT_SESSION || fileURLToPath(new URL("./session.json", import.meta.url)); |
| 33 | |
| 34 | export function requireBase() { |
| 35 | if (!BASE) { |
| 36 | console.error("Set LCHAT_BASE to your instance URL, e.g. https://test.example.com"); |
| 37 | process.exit(1); |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | export function loadSession() { |
| 42 | return existsSync(SESSION_PATH) ? JSON.parse(readFileSync(SESSION_PATH, "utf8")) : null; |
| 43 | } |
| 44 | |
| 45 | export function saveSession(s) { |
| 46 | writeFileSync(SESSION_PATH, JSON.stringify(s, null, 2)); |
| 47 | } |
| 48 | |