SPB Git

Repository Public

config.ts 2.8 KB 71 lines typescript

1import path from 'node:path';2import os from 'node:os';3import { agentProfile, resolveAgentId, type AgentId } from '@cr/shared';45export interface WorkspaceRoot {6  label: string;7  path: string; // absolute; realpath'd at startup by paths.ts8}9export interface RuntimeConfig {10  dataDir: string;11  socketPath: string;12  token: string;13  workspaceRoots: WorkspaceRoot[];14  /** Agent profile of this instance (`CR_AGENT`, default `claude`). */15  agent: AgentId;16  /**17   * Name or absolute path of the instance's agent CLI (historical field name): `CR_AGENT_BIN`,18   * else `CR_CLAUDE_BIN` (claude profile only), else the profile's default binary name.19   */20  claudeBin: string;21  maxSessions: number;22  execHosts: string[];23  termBufferBytes: number;24  tmuxSocketName: string;25  shell: string;26  logLevel: string;27}2829export function parseWorkspaceRoots(raw: string): WorkspaceRoot[] {30  return raw31    .split(',')32    .map((s) => s.trim())33    .filter(Boolean)34    .map((entry) => {35      const eq = entry.indexOf('=');36      const p = path.resolve(eq > 0 ? entry.slice(eq + 1) : entry);37      const label = eq > 0 ? entry.slice(0, eq) : path.basename(p);38      return { label, path: p };39    });40}4142const nonEmpty = (v: string | undefined): string | undefined => (v !== undefined && v.trim() !== '' ? v : undefined);4344/** `CR_INSTALL_AGENT_HOOKS=1`, or its historical alias `CR_INSTALL_CLAUDE_HOOKS=1` for the claude profile. */45export function agentHooksRequested(agent: AgentId, env: NodeJS.ProcessEnv = process.env): boolean {46  return env.CR_INSTALL_AGENT_HOOKS === '1' || (agent === 'claude' && env.CR_INSTALL_CLAUDE_HOOKS === '1');47}4849export function loadConfig(env: NodeJS.ProcessEnv = process.env): RuntimeConfig {50  const profile = agentProfile(resolveAgentId(env.CR_AGENT));51  const dataDir = path.resolve(env.CR_DATA_DIR ?? path.join(os.homedir(), `${profile.slug}-data`));52  const token = env.CR_RUNTIME_TOKEN ?? '';53  if (token.length < 32) throw new Error('CR_RUNTIME_TOKEN must be set (>= 32 chars)');54  const roots = parseWorkspaceRoots(env.CR_WORKSPACE_ROOTS ?? path.join(os.homedir(), 'workspace'));55  if (roots.length === 0) throw new Error('CR_WORKSPACE_ROOTS is empty');56  return {57    dataDir,58    socketPath: env.CR_RUNTIME_SOCKET ?? path.join(dataDir, 'run', 'runtime.sock'),59    token,60    workspaceRoots: roots,61    agent: profile.id,62    claudeBin: nonEmpty(env.CR_AGENT_BIN) ?? (profile.id === 'claude' ? nonEmpty(env.CR_CLAUDE_BIN) : undefined) ?? profile.defaultBinary,63    maxSessions: Number(env.CR_MAX_SESSIONS ?? 12),64    execHosts: (env.CR_EXEC_HOSTS ?? '').split(',').map((s) => s.trim()).filter(Boolean),65    termBufferBytes: Number(env.CR_TERM_BUFFER_BYTES ?? 4 * 1024 * 1024),66    tmuxSocketName: nonEmpty(env.CR_TMUX_SOCKET) ?? profile.slug,67    shell: env.CR_SHELL ?? env.SHELL ?? '/bin/zsh',68    logLevel: env.CR_LOG_LEVEL ?? 'info',69  };70}71
Files main
Menu

Theme