Merge d62b98c5c8 into 4583f88626
This commit is contained in:
commit
3f8c5a0a13
@ -1,4 +1,7 @@
|
|||||||
import { spawn } from "node:child_process";
|
import { spawn } from "node:child_process";
|
||||||
|
import { existsSync, mkdirSync, symlinkSync, lstatSync } from "node:fs";
|
||||||
|
import { homedir } from "node:os";
|
||||||
|
import { join } from "node:path";
|
||||||
import type { RuntimeEnv } from "../runtime.js";
|
import type { RuntimeEnv } from "../runtime.js";
|
||||||
|
|
||||||
export type SignalDaemonOpts = {
|
export type SignalDaemonOpts = {
|
||||||
@ -18,6 +21,84 @@ export type SignalDaemonHandle = {
|
|||||||
stop: () => void;
|
stop: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup Signal data directory for containerized environments.
|
||||||
|
* Auto-detects persistent storage and creates symlink if needed.
|
||||||
|
*
|
||||||
|
* Priority order:
|
||||||
|
* 1. SIGNAL_CLI_DATA_DIR env var (if set)
|
||||||
|
* 2. /data/.local/share/signal-cli (Fly.io convention)
|
||||||
|
* 3. /var/lib/clawdbot/.local/share/signal-cli (alternative persistent location)
|
||||||
|
* 4. Default: ~/.local/share/signal-cli (no symlink needed)
|
||||||
|
*/
|
||||||
|
export function setupSignalDataPersistence(runtime?: RuntimeEnv): void {
|
||||||
|
const log = runtime?.log ?? (() => {});
|
||||||
|
const defaultPath = join(homedir(), ".local", "share", "signal-cli");
|
||||||
|
|
||||||
|
// Check if already a symlink or regular directory exists
|
||||||
|
if (existsSync(defaultPath)) {
|
||||||
|
try {
|
||||||
|
const stats = lstatSync(defaultPath);
|
||||||
|
if (stats.isSymbolicLink()) {
|
||||||
|
log(`signal-cli data already symlinked to persistent storage`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Regular directory exists, don't touch it
|
||||||
|
return;
|
||||||
|
} catch {
|
||||||
|
// Ignore errors, will try to create below
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine persistent storage location
|
||||||
|
let persistentPath: string | null = null;
|
||||||
|
|
||||||
|
// Priority 1: Environment variable
|
||||||
|
if (process.env.SIGNAL_CLI_DATA_DIR) {
|
||||||
|
persistentPath = process.env.SIGNAL_CLI_DATA_DIR;
|
||||||
|
log(`signal-cli: using SIGNAL_CLI_DATA_DIR=${persistentPath}`);
|
||||||
|
}
|
||||||
|
// Priority 2: /data (Fly.io convention)
|
||||||
|
else if (existsSync("/data")) {
|
||||||
|
persistentPath = "/data/.local/share/signal-cli";
|
||||||
|
}
|
||||||
|
// Priority 3: /var/lib/clawdbot
|
||||||
|
else if (existsSync("/var/lib/clawdbot")) {
|
||||||
|
persistentPath = "/var/lib/clawdbot/.local/share/signal-cli";
|
||||||
|
}
|
||||||
|
|
||||||
|
// No persistent storage detected, use default
|
||||||
|
if (!persistentPath) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create persistent directory structure
|
||||||
|
try {
|
||||||
|
mkdirSync(persistentPath, { recursive: true });
|
||||||
|
mkdirSync(join(persistentPath, "data"), { recursive: true });
|
||||||
|
} catch (err) {
|
||||||
|
runtime?.error?.(`signal-cli: failed to create persistent directory: ${String(err)}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create parent directory for symlink
|
||||||
|
try {
|
||||||
|
const parentDir = join(homedir(), ".local", "share");
|
||||||
|
mkdirSync(parentDir, { recursive: true });
|
||||||
|
} catch (err) {
|
||||||
|
runtime?.error?.(`signal-cli: failed to create parent directory: ${String(err)}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create symlink
|
||||||
|
try {
|
||||||
|
symlinkSync(persistentPath, defaultPath);
|
||||||
|
log(`signal-cli: linked ${defaultPath} -> ${persistentPath} for persistence`);
|
||||||
|
} catch (err) {
|
||||||
|
runtime?.error?.(`signal-cli: failed to create symlink: ${String(err)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function classifySignalCliLogLine(line: string): "log" | "error" | null {
|
export function classifySignalCliLogLine(line: string): "log" | "error" | null {
|
||||||
const trimmed = line.trim();
|
const trimmed = line.trim();
|
||||||
if (!trimmed) return null;
|
if (!trimmed) return null;
|
||||||
@ -48,6 +129,9 @@ function buildDaemonArgs(opts: SignalDaemonOpts): string[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function spawnSignalDaemon(opts: SignalDaemonOpts): SignalDaemonHandle {
|
export function spawnSignalDaemon(opts: SignalDaemonOpts): SignalDaemonHandle {
|
||||||
|
// Setup persistent storage for containerized environments
|
||||||
|
setupSignalDataPersistence(opts.runtime);
|
||||||
|
|
||||||
const args = buildDaemonArgs(opts);
|
const args = buildDaemonArgs(opts);
|
||||||
const child = spawn(opts.cliPath, args, {
|
const child = spawn(opts.cliPath, args, {
|
||||||
stdio: ["ignore", "pipe", "pipe"],
|
stdio: ["ignore", "pipe", "pipe"],
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user