// 启动必需配置(ADR-0011):其余运行配置都在后台 settings 中管理 import os from 'node:os' import path from 'node:path' import { fileURLToPath } from 'node:url' const env = process.env const isDev = env.NODE_ENV !== 'production' /** 仓库根目录(仅开发时使用) */ const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../..') export const config = { host: env.AGENT_SERVER_HOST ?? '127.0.0.1', port: Number(env.AGENT_SERVER_PORT ?? 8787), /** 服务数据目录:生产为 /srv/agent-server(属主 agentsvc);开发时默认放在仓库的 .dev-data,避免与生产服务冲突 */ dataDir: path.resolve(env.AGENT_SERVER_DATA_DIR ?? (isDev ? path.join(repoRoot, '.dev-data') : '/srv/agent-server')), /** 共享只读资源(Python 运行环境、技能目录)所在目录,开发与生产共用 */ sharedDir: path.resolve(env.AGENT_SERVER_SHARED_DIR ?? '/srv/agent-server'), /** 首次启动时的后台密码;未设置则随机生成并打印到日志 */ adminPassword: env.AGENT_SERVER_ADMIN_PASSWORD, /** 后台静态资源目录(生产部署时由服务托管) */ adminDist: env.AGENT_SERVER_ADMIN_DIST, /** 业务平台 SDK 包目录(默认为后台静态资源旁边的 sdk 目录) */ sdkDist: env.AGENT_SERVER_SDK_DIST, /** * 信任哪些反向代理的 X-Forwarded-* 头:未设置或 false 为不信任;true 为信任所有来源(仅在服务只能经由代理访问时使用); * 也可以是逗号分隔的代理 IP / CIDR(推荐),只信任来自这些地址的转发信息,直接访问的客户端无法伪造 */ trustProxy: parseTrustProxy(env.AGENT_SERVER_TRUST_PROXY), home: os.homedir(), isDev, logLevel: env.LOG_LEVEL ?? 'info', } /** 引擎访问 MCP Gateway 的地址(引擎与服务在同一台机器上) */ export const gatewayUrl = () => `http://127.0.0.1:${config.port}/mcp` /** 服务版本(概览页与 API 协议文档中显示) */ export const APP_VERSION = '0.1.0' export const dbPath = () => path.join(config.dataDir, 'data', 'agent.db') /** * 服务管理的技能生效目录:服务可写、Agent 只读(ADR-0022)。单独放在顶层,不与数据库等放在 data 下; * 这里只放生效的技能,文件库、上传暂存与目录缓存仍在 data 下(Agent 不可见) */ export const managedSkillsDir = () => path.join(config.dataDir, 'managed-skills') /** 第三方技能目录(Claude 插件格式,两个引擎共用,ADR-0017) */ export const communitySkillsDir = () => path.join(managedSkillsDir(), 'community') /** 自定义技能:生效目录(Claude 插件格式,两个引擎共用)、按内容寻址的文件库、上传的 zip 解压目录(docs/design/12-custom-skills.md) */ export const customSkillsDir = () => path.join(managedSkillsDir(), 'custom') export const customSkillStoreDir = () => path.join(config.dataDir, 'data', 'custom-skill-store') export const skillUploadsDir = () => path.join(config.dataDir, 'data', 'skill-uploads') function parseTrustProxy(v: string | undefined): boolean | string[] { if (!v || v === 'false') return false if (v === 'true') return true return v.split(',').map(s => s.trim()).filter(Boolean) }