@inceptionstack/roundhouse 0.3.11 → 0.3.13

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.
package/README.md CHANGED
@@ -95,7 +95,8 @@ roundhouse install # installs as systemd service, starts automatically
95
95
  roundhouse <command>
96
96
 
97
97
  Commands:
98
- start Start the gateway (foreground)
98
+ start Start the gateway daemon
99
+ run Run the gateway in foreground
99
100
  tui [thread] Open agent TUI on a gateway session
100
101
  install Install as a systemd daemon (requires sudo)
101
102
  uninstall Remove the systemd daemon
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inceptionstack/roundhouse",
3
- "version": "0.3.11",
3
+ "version": "0.3.13",
4
4
  "type": "module",
5
5
  "description": "Multi-platform chat gateway that routes messages through a configured AI agent",
6
6
  "license": "MIT",
package/src/cli/cli.ts CHANGED
@@ -56,6 +56,28 @@ function systemctl(verb: string, message?: string): void {
56
56
  // ── Commands ────────────────────────────────────────
57
57
 
58
58
  async function cmdStart() {
59
+ // If systemd service is installed, start via systemctl
60
+ const serviceInstalled = run(`systemctl list-unit-files ${SERVICE_NAME}.service`, { silent: true }).includes(SERVICE_NAME);
61
+ if (serviceInstalled) {
62
+ const isActive = run(`systemctl is-active ${SERVICE_NAME}`, { silent: true }) === "active";
63
+ if (isActive) {
64
+ console.log("Roundhouse is already running.");
65
+ console.log(" Use: roundhouse restart to restart");
66
+ console.log(" roundhouse status to check status");
67
+ console.log(" roundhouse logs to tail logs");
68
+ return;
69
+ }
70
+ systemctl("start", "Daemon started.");
71
+ return;
72
+ }
73
+
74
+ // No systemd service — fall back to foreground
75
+ console.log("No systemd service found. Running in foreground (use Ctrl+C to stop)...");
76
+ console.log(" Tip: run 'roundhouse install' to set up the systemd daemon.\n");
77
+ await cmdRun();
78
+ }
79
+
80
+ async function cmdRun() {
59
81
  process.env.ROUNDHOUSE_CONFIG = CONFIG_PATH;
60
82
  const indexPath = resolve(__dirname, "..", "index.ts");
61
83
  const jsPath = resolve(__dirname, "..", "dist", "index.js");
@@ -117,15 +139,15 @@ async function cmdInstall() {
117
139
  const binPath = run("which roundhouse", { silent: true });
118
140
  const nodePath = run("which node", { silent: true }) || process.execPath;
119
141
  const tsxPath = resolve(__dirname, "..", "..", "node_modules", ".bin", "tsx");
120
- const srcIndex = resolve(__dirname, "..", "index.ts");
121
142
 
122
143
  let execStart: string;
123
144
  if (binPath) {
124
- execStart = `${nodePath} ${binPath} start`;
145
+ execStart = `${nodePath} ${binPath} run`;
125
146
  } else {
126
- // No global install — use tsx directly
147
+ // No global install — run CLI via tsx with 'run' subcommand
127
148
  const tsxBin = run("which tsx", { silent: true }) || tsxPath;
128
- execStart = `${tsxBin} ${srcIndex}`;
149
+ const cliPath = resolve(__dirname, "cli.ts");
150
+ execStart = `${tsxBin} ${cliPath} run`;
129
151
  }
130
152
 
131
153
  // Compute PATH that includes node's bin dir (for mise/nvm setups)
@@ -417,7 +439,8 @@ Usage:
417
439
  Commands:
418
440
  setup One-command install & configure (also works via npx)
419
441
  pair Pair Telegram account for notifications
420
- start Start the gateway (foreground)
442
+ start Start the gateway daemon
443
+ run Run the gateway in foreground
421
444
  tui [thread] Open agent TUI on a gateway session
422
445
  install Install as a systemd daemon (requires sudo)
423
446
  uninstall Remove the systemd daemon
@@ -600,6 +623,7 @@ const commands: Record<string, () => void | Promise<void>> = {
600
623
  setup: () => cmdSetup(process.argv.slice(3)),
601
624
  pair: () => cmdPair(process.argv.slice(3)),
602
625
  start: cmdStart,
626
+ run: cmdRun,
603
627
  install: cmdInstall,
604
628
  uninstall: cmdUninstall,
605
629
  update: cmdUpdate,
@@ -22,7 +22,7 @@ export const credentialChecks: DoctorCheck[] = [
22
22
  return {
23
23
  id: "telegram-token", category: "credentials", name: "Telegram bot token",
24
24
  status: "fail", summary: "TELEGRAM_BOT_TOKEN not set",
25
- details: ["Set TELEGRAM_BOT_TOKEN in your environment or ~/.roundhouse/env"],
25
+ details: ["Set TELEGRAM_BOT_TOKEN in your environment or ~/.roundhouse/.env"],
26
26
  };
27
27
  }
28
28
  if (!/^\d+:[A-Za-z0-9_-]+$/.test(token)) {
package/src/cli/setup.ts CHANGED
@@ -630,7 +630,7 @@ async function stepConfigure(
630
630
  }
631
631
 
632
632
  await atomicWriteText(ENV_PATH, envLines.join("\n") + "\n");
633
- ok(`~/.roundhouse/env${opts.psst ? " (non-secret config only)" : ""}`);
633
+ ok(`~/.roundhouse/.env${opts.psst ? " (non-secret config only)" : ""}`);
634
634
  }
635
635
 
636
636
  async function stepPair(opts: SetupOptions, botInfo: BotInfo): Promise<PairResult | null> {
@@ -740,12 +740,12 @@ async function stepInstallSystemd(opts: SetupOptions): Promise<void> {
740
740
  }
741
741
  }
742
742
 
743
- // Build ExecStart
743
+ // Build ExecStart — uses `roundhouse run` (foreground mode for systemd)
744
744
  let execStart: string;
745
745
  if (psstBin) {
746
- execStart = `${psstBin} run ${nodeBin} ${roundhouseBin} start`;
746
+ execStart = `${psstBin} run ${nodeBin} ${roundhouseBin} run`;
747
747
  } else {
748
- execStart = `${nodeBin} ${roundhouseBin} start`;
748
+ execStart = `${nodeBin} ${roundhouseBin} run`;
749
749
  }
750
750
 
751
751
  // Always include env file for non-secret config (AWS_PROFILE, etc)
@@ -873,7 +873,7 @@ export async function cmdSetup(argv: string[]): Promise<void> {
873
873
  }
874
874
  log(` Bot: @${botInfo.username}`);
875
875
  log(` Memory: ${opts.extensions.some((e) => e.includes("pi-memory")) ? "agent-managed" : "roundhouse-managed"}`);
876
- log(` Secrets: ${opts.psst ? "psst vault (encrypted)" : "~/.roundhouse/env (plaintext)"}`);
876
+ log(` Secrets: ${opts.psst ? "psst vault (encrypted)" : "~/.roundhouse/.env (plaintext)"}`);
877
877
  log(` Send /status to @${botInfo.username} on Telegram.\n`);
878
878
  } catch (err: any) {
879
879
  log("\n━━━━━━━━━━━━━━━━━━━");
@@ -993,7 +993,7 @@ function printDryRun(opts: SetupOptions): void {
993
993
  log(` Set defaultProvider: ${opts.provider}`);
994
994
  log(` Set defaultModel: ${opts.model}`);
995
995
  log(`Would write: ~/.roundhouse/gateway.config.json`);
996
- log(`Would write: ~/.roundhouse/env${opts.psst ? " (non-secret config only)" : ""}`);
996
+ log(`Would write: ~/.roundhouse/.env${opts.psst ? " (non-secret config only)" : ""}`);
997
997
  log(`Would register ${BOT_COMMANDS.length} bot commands`);
998
998
  if (opts.systemd) log(`Would install systemd service`);
999
999
  log("\nNo changes made.\n");
package/src/config.ts CHANGED
@@ -21,7 +21,10 @@ export const LEGACY_CONFIG_DIR = resolve(homedir(), ".config", "roundhouse");
21
21
  /** Active config directory — use ROUNDHOUSE_DIR */
22
22
  export const CONFIG_DIR = ROUNDHOUSE_DIR;
23
23
  export const CONFIG_PATH = resolve(ROUNDHOUSE_DIR, "gateway.config.json");
24
- export const ENV_FILE_PATH = resolve(ROUNDHOUSE_DIR, "env");
24
+ export const ENV_FILE_PATH = resolve(ROUNDHOUSE_DIR, ".env");
25
+
26
+ /** Legacy env file name (deprecated) */
27
+ export const LEGACY_ENV_FILE_PATH = resolve(ROUNDHOUSE_DIR, "env");
25
28
 
26
29
  /** Cron directories */
27
30
  export const CRON_JOBS_DIR = resolve(ROUNDHOUSE_DIR, "crons");
@@ -109,15 +112,26 @@ export async function resolveConfigPath(): Promise<{ path: string; legacy: boole
109
112
  let envFileWarned = false;
110
113
 
111
114
  export async function resolveEnvFilePath(): Promise<string> {
115
+ // Canonical: ~/.roundhouse/.env
112
116
  if (await fileExists(ENV_FILE_PATH)) return ENV_FILE_PATH;
113
- const legacyEnv = resolve(LEGACY_CONFIG_DIR, "env");
114
- if (await fileExists(legacyEnv)) {
117
+ // Legacy: ~/.roundhouse/env (old name, same directory)
118
+ if (await fileExists(LEGACY_ENV_FILE_PATH)) {
119
+ if (!envFileWarned) {
120
+ envFileWarned = true;
121
+ console.warn(`[roundhouse] \u26a0\ufe0f Env file found at legacy path: ${LEGACY_ENV_FILE_PATH}`);
122
+ console.warn(`[roundhouse] Rename it to ${ENV_FILE_PATH} \u2014 legacy name will be removed in a future version.`);
123
+ }
124
+ return LEGACY_ENV_FILE_PATH;
125
+ }
126
+ // Legacy: ~/.config/roundhouse/env (old directory)
127
+ const legacyDirEnv = resolve(LEGACY_CONFIG_DIR, "env");
128
+ if (await fileExists(legacyDirEnv)) {
115
129
  if (!envFileWarned) {
116
130
  envFileWarned = true;
117
- console.warn(`[roundhouse] \u26a0\ufe0f Env file found at legacy path: ${legacyEnv}`);
131
+ console.warn(`[roundhouse] \u26a0\ufe0f Env file found at legacy path: ${legacyDirEnv}`);
118
132
  console.warn(`[roundhouse] Move it to ${ENV_FILE_PATH} \u2014 legacy path will be removed in a future version.`);
119
133
  }
120
- return legacyEnv;
134
+ return legacyDirEnv;
121
135
  }
122
136
  return ENV_FILE_PATH;
123
137
  }