三、配置系统——默认值与解析

本篇讲解 src/config/index.ts。你会了解:这个包有哪些可调参数、默认值是什么、resolveSandboxConfig 怎么把用户传的配置"填满"成运行时配置。

1. 为什么需要配置系统?

不同场景对沙箱的要求不同:

  • CI 环境 :可能想用 autonomous 策略(不问人),因为没人坐在终端前
  • 开发环境 :可能想用 on-request 策略(危险命令要问人),保护安全
  • 演示场景 :可能想用 danger-full-access,图方便

配置系统就是让这些差异变成"改一个参数"的事,而不是"改一堆代码"的事。

2. 默认值常量

config/index.ts 一开头就定义了一堆默认值常量。我们逐个看:

2.1 超时与输出限制

typescript 复制代码
export const DEFAULT_TIMEOUT_MS = 120_000;              // 命令默认超时:2 分钟
export const DEFAULT_MAX_STDOUT_BYTES = 512 * 1024;      // stdout 最大 512KB
export const DEFAULT_MAX_STDERR_BYTES = 512 * 1024;      // stderr 最大 512KB

为什么需要超时? 防止一条命令跑飞了(比如死循环),把整个系统卡住。

为什么需要输出限制? 防止一条命令输出太多(比如 cat /dev/urandom),把磁盘写满。超过限制的内容会被截断,但会有一个 truncated 标志会告诉你是"不完整"的。

2.2 沙箱模式与审批策略

typescript 复制代码
export const DEFAULT_SANDBOX_MODE: SandboxMode = 'workspace-write';
export const DEFAULT_APPROVAL_POLICY: ApprovalPolicy = 'on-request';
export const DEFAULT_EXECUTION_SURFACE: ExecutionSurface = 'direct';
  • 默认模式是 workspace-write(可以在项目里改文件,不能改外面的)
  • 默认审批策略是 on-request(L0/L1 自动过,L2+ 要审批)
  • 默认执行面是 direct(直接在项目根目录执行)

2.3 Git Worktree 相关

typescript 复制代码
export const DEFAULT_WORKTREE_BRANCH_PREFIX = '${元数据目录}-agent';

worktree 分支名的前缀。创建的分支会叫 ${元数据目录}-agent/1704830400000(前缀 + 时间戳)。

2.4 元数据目录

typescript 复制代码
export const SANDBOX_META_DIR = 自定义目录(个人自己决定);

项目内沙箱元数据的目录名。审计日志、worktree 等都放在这个目录下:

c 复制代码
your-project/
└── ${元数据目录}/
    ├── audit/           ← 审计日志
    │   ├── audit.jsonl
    │   └── <runId>/
    │       ├── stdout.txt
    │       ├── stderr.txt
    │       └── metadata.json
    └── worktrees/       ← git worktree 副本

2.5 代理地址

typescript 复制代码
export const DEFAULT_PROXY_URL = 'http://127.0.0.1:8787';

开网时,子进程的 HTTP 流量会走这个本地代理。代理会检查"你要连的域名在不在白名单里"。

2.6 环境变量白名单

typescript 复制代码
export const DEFAULT_ENV_ALLOWLIST = [
  'PATH',         // 可执行文件搜索路径
  'LANG',         // 区域与语言
  'LC_ALL',       // 覆盖全部 locale 类别
  'LC_CTYPE',     // 字符分类与转码
  'TERM',         // 终端类型
  'TERM_PROGRAM', // 终端程序名(如 iTerm、vscode)
  'COLORTERM',    // 是否支持真彩色
  'TMPDIR',       // macOS 临时目录
  'TMP',          // 通用临时目录
  'TEMP',         // Windows 临时目录
  'SYSTEMROOT',   // Windows 系统根目录
  'ComSpec',      // Windows 默认 shell
  'PATHEXT',      // Windows 可执行扩展名列表
] as const;

只有这些环境变量会被传给子进程。像 GITHUB_TOKENSSH_AUTH_SOCK 这些敏感变量会被剥离。

3. DEFAULT_SANDBOX_CONFIG------默认配置快照

typescript 复制代码
export const DEFAULT_SANDBOX_CONFIG = {
  executionSurface: 'direct',
  mode: 'workspace-write',
  approvalPolicy: 'on-request',
  timeoutMs: 120_000,
  maxStdoutBytes: 512 * 1024,
  maxStderrBytes: 512 * 1024,
  network: false,                           // 默认断网
  proxyUrl: 'http://127.0.0.1:8787',
  envAllowlist: [...DEFAULT_ENV_ALLOWLIST],
  extraEnv: {},
  enforceProtectedPaths: true,              // 默认开启路径预检
  protectedHomePaths: [],
  allowDangerousFallback: false,            // 默认不允许回退
  worktreeBranchPrefix: '${元数据目录}-agent',
} as const;

注意 network: false------默认是断网 的!想联网必须显式设置 network: true

4. resolveSandboxConfig------把用户配置"填满"

用户只传了 projectRoot,其他字段怎么办?resolveSandboxConfig 就是来补全的:

typescript 复制代码
export function resolveSandboxConfig(config: SandboxConfig): ... {
  const projectRoot = config.projectRoot;

  return {
    projectRoot,                                             // 必填,原样保留
    executionSurface: config.executionSurface ?? 'direct',
    mode: config.mode ?? 'workspace-write',
    approvalPolicy: config.approvalPolicy ?? 'on-request',
    timeoutMs: config.timeoutMs ?? 120_000,
    maxStdoutBytes: config.maxStdoutBytes ?? 512 * 1024,
    maxStderrBytes: config.maxStderrBytes ?? 512 * 1024,
    network: config.network ?? false,
    proxyUrl: config.proxyUrl ?? 'http://127.0.0.1:8787',
    allowDangerousFallback: config.allowDangerousFallback ?? false,
    auditDir: config.auditDir ?? `${projectRoot}/${元数据目录}/audit`,
    worktreesDir: config.worktreesDir ?? `${projectRoot}/${元数据目录}/worktrees`,
    worktreeBranchPrefix: config.worktreeBranchPrefix ?? '${元数据目录}-agent',
    envAllowlist: config.envAllowlist ?? [...DEFAULT_ENV_ALLOWLIST],
    extraEnv: config.extraEnv ?? {},
    enforceProtectedPaths: config.enforceProtectedPaths ?? true,
    protectedHomePaths: config.protectedHomePaths ?? [],
    profilesDir: config.profilesDir,    // 可选;不传则 runner 自动解析
    onApproval: config.onApproval,      // 可选;不传则除 L0 外默认拒绝
    onOsSandboxUnavailable: config.onOsSandboxUnavailable,
  };
}

模式很简单 :每个字段用 ??(空值合并运算符)来处理------用户传了就用用户的,没传就用默认的。

4.1 自动生成的路径

有两个路径是自动生成的:

typescript 复制代码
auditDir: `${projectRoot}/${元数据目录}/audit`
worktreesDir: `${projectRoot}/${元数据目录}/worktrees`

也就是说,如果你把 projectRoot 设为 /home/user/my-project,审计日志会写到 /home/user/my-project/${元数据目录}/audit/

4.2 两个可选回调

  • onApproval:不传的话,除了 L0 命令,其他一律拒绝。这是一个 fail-closed 的设计------宁可多拦,不可漏放。
  • onOsSandboxUnavailable:不传的话,如果 OS 沙箱不可用(比如不在 macOS 上),直接抛错。也是一个 fail-closed 设计。

5. 手写一遍

现在让我们自己实现一遍 resolveSandboxConfig

typescript 复制代码
import type { SandboxConfig, SandboxMode, ApprovalPolicy, ExecutionSurface } from '../types/index.js';

// 1. 定义默认值常量
const DEFAULT_TIMEOUT_MS = 120_000;
const DEFAULT_MAX_STDOUT_BYTES = 512 * 1024;
const DEFAULT_MAX_STDERR_BYTES = 512 * 1024;
const DEFAULT_SANDBOX_MODE: SandboxMode = 'workspace-write';
const DEFAULT_APPROVAL_POLICY: ApprovalPolicy = 'on-request';
const DEFAULT_EXECUTION_SURFACE: ExecutionSurface = 'direct';

// 2. 实现解析函数
function resolveSandboxConfig(config: SandboxConfig) {
  const projectRoot = config.projectRoot;

  return {
    projectRoot,
    executionSurface: config.executionSurface ?? DEFAULT_EXECUTION_SURFACE,
    mode: config.mode ?? DEFAULT_SANDBOX_MODE,
    approvalPolicy: config.approvalPolicy ?? DEFAULT_APPROVAL_POLICY,
    timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS,
    // ... 其余字段同理
  };
}

就是这么简单------定义默认值 → 用 ?? 补全

6. 配置使用示例

6.1 最简配置

typescript 复制代码
const config = resolveSandboxConfig({
  projectRoot: '/home/user/my-project',
});
// 其他字段全部使用默认值

6.2 自定义配置

typescript 复制代码
const config = resolveSandboxConfig({
  projectRoot: '/home/user/my-project',
  mode: 'read-only',          // 只读模式
  approvalPolicy: 'autonomous', // 不问人
  network: true,               // 允许联网
  timeoutMs: 60_000,           // 超时 1 分钟
  onApproval: async (ctx) => {
    // 自己实现审批逻辑,比如调 API
    console.log(`需要审批: ${ctx.command} (${ctx.riskLevel})`);
    return 'allow_once';
  },
});

7. 小结

概念 要点
默认超时 2 分钟(120,000 ms)
默认输出限制 stdout/stderr 各 512KB
默认模式 workspace-write
默认审批策略 on-request
默认执行面 direct
默认网络 断网false
默认路径预检 开启true
默认危险回退 不允许false
resolveSandboxConfig ?? 把用户配置补全为运行时配置

核心思想:安全的默认值 + 用户可覆盖。不传的参数都会倾向更安全的选项。

相关推荐
拓朗工控3 小时前
视觉检测行业工控机选型指南:核心要素与避坑策略
人工智能·数码相机·视觉检测·工控机·工业电脑
Urbano3 小时前
工装制作全流程科普:从面料到自动化生产
网络·人工智能
武子康3 小时前
调查研究-166 VoxCPM 详解:一个值得重点关注的开源 TTS 项目
人工智能·openai
hhzz3 小时前
详细解读Anthropic报告《当AI构建自己时...》
人工智能
xrgs_shz3 小时前
基于K-Means聚类分析的鸢尾花分类
人工智能·机器学习
Chef_Chen4 小时前
论文解读:GAIA给通用AI助手泼冷水,人类92分GPT-4插件版只到30分
人工智能
Black蜡笔小新4 小时前
自动化AI算法训练服务器DLTM训推一体工作站赋能多行业智能化升级
人工智能·算法·自动化
KaMeidebaby4 小时前
卡梅德生物技术快报|噬菌体文库构建实验优化及偶联体系实验数据分析
大数据·人工智能·架构·spark·新浪微博
NineData4 小时前
SQL 都在等锁时,ChatDBA 先帮 MySQL 找到谁在挡路
数据库·人工智能·sql·mysql·安全·数据复制·数据迁移工具