You've already forked agentic-coding-workflow
bugfix
This commit is contained in:
+322
-20
@@ -29,27 +29,156 @@ func (k MasterKey) LogValue() slog.Value { return slog.StringValue("[REDACTED 32
|
||||
|
||||
// Config 是应用全局配置的根结构。
|
||||
type Config struct {
|
||||
Env string `mapstructure:"env"`
|
||||
DataDir string `mapstructure:"data_dir"`
|
||||
MasterKey MasterKey `mapstructure:"-"` // 解码后的 32 字节,单独从 master_key 解析
|
||||
HTTP HTTPConfig `mapstructure:"http"`
|
||||
DB DBConfig `mapstructure:"db"`
|
||||
Bootstrap BootstrapConfig `mapstructure:"bootstrap"`
|
||||
Workspace Workspace `mapstructure:"workspace"`
|
||||
Git Git `mapstructure:"git"`
|
||||
Chat Chat `mapstructure:"chat"`
|
||||
Storage Storage `mapstructure:"storage"`
|
||||
Jobs JobsConfig `mapstructure:"jobs"`
|
||||
Notify NotifyConfig `mapstructure:"notify"`
|
||||
Acp AcpConfig `mapstructure:"acp"`
|
||||
MCP MCPConfig `mapstructure:"mcp"`
|
||||
Run RunConfig `mapstructure:"run"`
|
||||
Terminal TerminalConfig `mapstructure:"terminal"`
|
||||
Env string `mapstructure:"env"`
|
||||
DataDir string `mapstructure:"data_dir"`
|
||||
MasterKey MasterKey `mapstructure:"-"` // 解码后的 32 字节,单独从 master_key 解析
|
||||
HTTP HTTPConfig `mapstructure:"http"`
|
||||
DB DBConfig `mapstructure:"db"`
|
||||
Bootstrap BootstrapConfig `mapstructure:"bootstrap"`
|
||||
Workspace Workspace `mapstructure:"workspace"`
|
||||
Git Git `mapstructure:"git"`
|
||||
Chat Chat `mapstructure:"chat"`
|
||||
Storage Storage `mapstructure:"storage"`
|
||||
Jobs JobsConfig `mapstructure:"jobs"`
|
||||
Notify NotifyConfig `mapstructure:"notify"`
|
||||
Acp AcpConfig `mapstructure:"acp"`
|
||||
MCP MCPConfig `mapstructure:"mcp"`
|
||||
Run RunConfig `mapstructure:"run"`
|
||||
Terminal TerminalConfig `mapstructure:"terminal"`
|
||||
VCS VCSConfig `mapstructure:"vcs"`
|
||||
Orchestrator OrchestratorConfig `mapstructure:"orchestrator"`
|
||||
Crypto CryptoConfig `mapstructure:"crypto"`
|
||||
User UserConfig `mapstructure:"user"`
|
||||
CodeIndex CodeIndexConfig `mapstructure:"code_index"`
|
||||
Docs DocsConfig `mapstructure:"docs"`
|
||||
Metrics MetricsConfig `mapstructure:"metrics"`
|
||||
}
|
||||
|
||||
// HTTPConfig 描述 HTTP 服务监听参数。
|
||||
// MetricsConfig 控制 Prometheus /metrics 端点。Enabled=false 时不挂载该路由。
|
||||
// AuthToken 非空时要求 Bearer/?token 匹配,避免成本/会话数对未授权方泄露。
|
||||
type MetricsConfig struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
AuthToken string `mapstructure:"auth_token"`
|
||||
}
|
||||
|
||||
// CodeIndexConfig controls the pgvector code index + project memory embeddings.
|
||||
// EmbeddingEndpointID/EmbeddingModel select an OpenAI-compatible or Gemini
|
||||
// endpoint for embeddings (Anthropic has no embeddings API). When the endpoint
|
||||
// is empty, the feature degrades: search_code is disabled and memory_search
|
||||
// falls back to keyword/tag matching.
|
||||
type CodeIndexConfig struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
EmbeddingEndpointID string `mapstructure:"embedding_endpoint_id"` // llm_endpoints.id (UUID); empty disables embeddings
|
||||
EmbeddingModel string `mapstructure:"embedding_model"` // model id producing PlatformEmbeddingDims (1536) vectors
|
||||
ChunkWindowLines int `mapstructure:"chunk_window_lines"`
|
||||
ChunkOverlapLines int `mapstructure:"chunk_overlap_lines"`
|
||||
MaxFileBytes int `mapstructure:"max_file_bytes"`
|
||||
SearchTopKCap int `mapstructure:"search_top_k_cap"`
|
||||
GrepMaxMatches int `mapstructure:"grep_max_matches"`
|
||||
GrepMaxFileBytes int `mapstructure:"grep_max_file_bytes"`
|
||||
}
|
||||
|
||||
// DocsConfig controls auto doc / PR-summary generation on commit.
|
||||
type DocsConfig struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
}
|
||||
|
||||
// CryptoConfig 选择 secret 加密的 key provider(env|vault|kms)。key 版本元数据
|
||||
// 落在 crypto_keys 表;key 材料留在 env/KMS。vault/kms 的客户端尚未接入,选中时
|
||||
// 退回 env provider(见 app.go),以保持启动不破。
|
||||
type CryptoConfig struct {
|
||||
Provider string `mapstructure:"provider"` // env(默认)| vault | kms
|
||||
// Vault/KMS 的连接参数预留位(接入真实客户端时填充)。
|
||||
Vault VaultCfg `mapstructure:"vault"`
|
||||
KMS KMSCfg `mapstructure:"kms"`
|
||||
}
|
||||
|
||||
// VaultCfg 是 HashiCorp Vault transit 的预留配置。
|
||||
type VaultCfg struct {
|
||||
Address string `mapstructure:"address"`
|
||||
Token string `mapstructure:"token"`
|
||||
KeyName string `mapstructure:"key_name"`
|
||||
}
|
||||
|
||||
// KMSCfg 是云 KMS 的预留配置。
|
||||
type KMSCfg struct {
|
||||
KeyID string `mapstructure:"key_id"`
|
||||
Region string `mapstructure:"region"`
|
||||
}
|
||||
|
||||
// UserConfig 控制 user 模块:当前仅登录暴力破解节流。
|
||||
type UserConfig struct {
|
||||
LoginThrottle LoginThrottleCfg `mapstructure:"login_throttle"`
|
||||
}
|
||||
|
||||
// LoginThrottleCfg 控制登录失败计数窗口。Enabled=false 时不节流(开发/测试)。
|
||||
type LoginThrottleCfg struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
MaxFailures int `mapstructure:"max_failures"`
|
||||
Window time.Duration `mapstructure:"window"`
|
||||
}
|
||||
|
||||
// OrchestratorConfig 控制编排器模块:开关、每阶段最大尝试、回合超时、子任务深度与
|
||||
// fan-out 上限。每阶段默认 agent-kind 由 PhaseAgentKinds(agent-kind 名→阶段)映射,
|
||||
// app 层按名解析为 UUID 注入。
|
||||
type OrchestratorConfig struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
MaxAttemptsPerPhase int `mapstructure:"max_attempts_per_phase"`
|
||||
TurnTimeout time.Duration `mapstructure:"turn_timeout"`
|
||||
MaxDepth int `mapstructure:"max_depth"`
|
||||
FanOutLimit int `mapstructure:"fan_out_limit"`
|
||||
// PhaseAgentKinds 把阶段名映射到 agent-kind 名(如 planning→"claude")。app 层在
|
||||
// 装配时按名解析为 agent_kind_id,作为 run.config 未覆盖时的默认值。空 map 表示无
|
||||
// 默认:每个 run 必须在 config.PhaseAgentKinds 显式提供。
|
||||
PhaseAgentKinds map[string]string `mapstructure:"phase_agent_kinds"`
|
||||
// Scheduler 控制任务分解的并行调度器(autonomy roadmap §10)。
|
||||
Scheduler SchedulerConfig `mapstructure:"scheduler"`
|
||||
}
|
||||
|
||||
// SchedulerConfig 控制任务分解并行调度器:拓扑选取就绪子任务、扇出到并行 ACP session。
|
||||
type SchedulerConfig struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
Interval time.Duration `mapstructure:"interval"`
|
||||
// MaxFanoutPerTick 每个 project 每 tick 最多派发的 session 数(<=0 默认 8)。
|
||||
MaxFanoutPerTick int `mapstructure:"max_fanout_per_tick"`
|
||||
// MaxConcurrentPerProject project 内活跃 session 软上限(<=0 不预检,仅靠 acp 层硬上限)。
|
||||
MaxConcurrentPerProject int `mapstructure:"max_concurrent_per_project"`
|
||||
}
|
||||
|
||||
// HTTPConfig 描述 HTTP 服务监听参数及可选的 TLS / CORS / 安全头中间件。
|
||||
type HTTPConfig struct {
|
||||
Addr string `mapstructure:"addr"`
|
||||
Addr string `mapstructure:"addr"`
|
||||
TLS TLSConfig `mapstructure:"tls"`
|
||||
CORS CORSCfg `mapstructure:"cors"`
|
||||
Security SecurityHdrCfg `mapstructure:"security"`
|
||||
}
|
||||
|
||||
// TLSConfig 控制是否以 HTTPS 提供服务。Enabled=true 时 cmd/server 用
|
||||
// ListenAndServeTLS,读取 CertFile/KeyFile。
|
||||
type TLSConfig struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
CertFile string `mapstructure:"cert_file"`
|
||||
KeyFile string `mapstructure:"key_file"`
|
||||
}
|
||||
|
||||
// CORSCfg 控制跨域中间件。默认 off,避免误配破坏 SPA + WS 握手。
|
||||
type CORSCfg struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
AllowedOrigins []string `mapstructure:"allowed_origins"`
|
||||
AllowedMethods []string `mapstructure:"allowed_methods"`
|
||||
AllowedHeaders []string `mapstructure:"allowed_headers"`
|
||||
AllowCredentials bool `mapstructure:"allow_credentials"`
|
||||
MaxAgeSeconds int `mapstructure:"max_age_seconds"`
|
||||
}
|
||||
|
||||
// SecurityHdrCfg 控制安全响应头中间件。HSTS 仅在 TLS 启用时下发(由 app 层
|
||||
// 据 TLS.Enabled 传入)。
|
||||
type SecurityHdrCfg struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
HSTSMaxAgeSeconds int `mapstructure:"hsts_max_age_seconds"`
|
||||
FrameOptions string `mapstructure:"frame_options"`
|
||||
ReferrerPolicy string `mapstructure:"referrer_policy"`
|
||||
ContentSecurityPolicy string `mapstructure:"content_security_policy"`
|
||||
}
|
||||
|
||||
// DBConfig 描述数据库连接参数。
|
||||
@@ -78,6 +207,22 @@ type Git struct {
|
||||
Binary string `mapstructure:"binary"`
|
||||
}
|
||||
|
||||
// VCSConfig 配置 git-host(VCS)REST 客户端与合并网关策略。v1 仅支持 Gitea。
|
||||
// RequireCIPass 默认 false:未接 CI 的仓库不会因 ci_state=unknown 永久卡住合并。
|
||||
type VCSConfig struct {
|
||||
Gitea GiteaConfig `mapstructure:"gitea"`
|
||||
RequireCIPass bool `mapstructure:"require_ci_pass"`
|
||||
}
|
||||
|
||||
// GiteaConfig 是 Gitea provider 的参数。Token 是平台级 PAT(建议组织/管理员
|
||||
// token),BaseURL 默认指向自托管实例 git.jerryyan.net。
|
||||
type GiteaConfig struct {
|
||||
BaseURL string `mapstructure:"base_url"`
|
||||
Token string `mapstructure:"token"`
|
||||
Timeout time.Duration `mapstructure:"timeout"`
|
||||
MergeMethod string `mapstructure:"merge_method"`
|
||||
}
|
||||
|
||||
// Chat 配置 chat 模块的附件、流式、历史与定时清理策略。
|
||||
type Chat struct {
|
||||
Attachment ChatAttachment `mapstructure:"attachment"`
|
||||
@@ -125,6 +270,15 @@ type JobsConfig struct {
|
||||
JobPurge JobPurgeCfg `mapstructure:"job_purge"`
|
||||
AcpEventsPurge AcpEventsPurgeCfg `mapstructure:"acp_events_purge"`
|
||||
MCPTokensPurge MCPTokensPurgeCfg `mapstructure:"mcp_tokens_purge"`
|
||||
AcpSessionReaper AcpSessionReaperCfg `mapstructure:"acp_session_reaper"`
|
||||
AuditRetention AuditRetentionCfg `mapstructure:"audit_retention"`
|
||||
}
|
||||
|
||||
// AuditRetentionCfg 控制审计日志保留期清理:删除早于 Retention 的 audit_logs 行。
|
||||
type AuditRetentionCfg struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
Interval time.Duration `mapstructure:"interval"`
|
||||
Retention time.Duration `mapstructure:"retention"`
|
||||
}
|
||||
|
||||
type RunnerCfg struct {
|
||||
@@ -169,9 +323,21 @@ type MCPTokensPurgeCfg struct {
|
||||
Retention time.Duration `mapstructure:"retention"`
|
||||
}
|
||||
|
||||
// NotifyConfig 是 notify 模块的可选外发通道配置。当前仅 webhook。
|
||||
// AcpSessionReaperCfg 控制 ACP 会话回收器:墙钟超时 + 空闲超时终止。
|
||||
type AcpSessionReaperCfg struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
Interval time.Duration `mapstructure:"interval"`
|
||||
WallClockTimeout time.Duration `mapstructure:"wall_clock_timeout"`
|
||||
IdleTimeout time.Duration `mapstructure:"idle_timeout"`
|
||||
}
|
||||
|
||||
// NotifyConfig 是 notify 模块的可选外发通道配置:webhook(jobs 异步投递)、
|
||||
// email(SMTP)、im(per-user 加密 webhook)。email/im 默认关闭,未配置时
|
||||
// 对应 Notifier 不注册到 Dispatcher,行为与历史一致。
|
||||
type NotifyConfig struct {
|
||||
Webhook WebhookCfg `mapstructure:"webhook"`
|
||||
Email EmailCfg `mapstructure:"email"`
|
||||
IM IMCfg `mapstructure:"im"`
|
||||
}
|
||||
|
||||
// WebhookCfg 是 webhook 通道的配置。enabled=false 时上层 dispatcher 仍会丢弃所有 webhook 消息。
|
||||
@@ -183,6 +349,24 @@ type WebhookCfg struct {
|
||||
Topics []string `mapstructure:"topics"`
|
||||
}
|
||||
|
||||
// EmailCfg 是 SMTP email 通道的配置。Enabled=false(默认)时不注册 EmailNotifier,
|
||||
// 不发任何邮件。Username/Password 为空表示无认证 SMTP(如本地中继)。
|
||||
type EmailCfg struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
SMTPHost string `mapstructure:"smtp_host"`
|
||||
Port int `mapstructure:"port"`
|
||||
From string `mapstructure:"from"`
|
||||
Username string `mapstructure:"username"`
|
||||
Password string `mapstructure:"password"`
|
||||
}
|
||||
|
||||
// IMCfg 是 IM(通用 webhook,如 Slack incoming webhook)通道的配置。
|
||||
// Enabled=false(默认)时不注册 IMNotifier。投递地址是 per-user 的
|
||||
// im_webhook_url(加密落库于 notification_prefs),此处仅做全局开关。
|
||||
type IMCfg struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
}
|
||||
|
||||
// AcpConfig 控制 ACP 模块的并发限流、子进程超时、WS 心跳与事件保留。
|
||||
type AcpConfig struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
@@ -200,6 +384,28 @@ type AcpConfig struct {
|
||||
EventRetentionDays int `mapstructure:"event_retention_days"`
|
||||
ShutdownGrace time.Duration `mapstructure:"shutdown_grace"`
|
||||
PermissionTimeout time.Duration `mapstructure:"permission_timeout"`
|
||||
// BriefTokenBudget 是服务端组装 ACP session 初始 prompt 简报的 token 硬上限。
|
||||
BriefTokenBudget int `mapstructure:"brief_token_budget"`
|
||||
// DefaultProjectBudgetUSD 是 per-project ACP 累计花费的全局软上限(0 = 不限)。
|
||||
// 当 session/agent-kind 均未设置成本上限时作为预算判定基线。
|
||||
DefaultProjectBudgetUSD float64 `mapstructure:"default_project_budget_usd"`
|
||||
// Sandbox 控制 per-session 执行沙箱(none|uid|container)。默认 none:
|
||||
// Windows 开发 / CI / 任何非 Linux 机器都跑 none,行为与历史一致。
|
||||
Sandbox SandboxCfg `mapstructure:"sandbox"`
|
||||
}
|
||||
|
||||
// SandboxCfg 控制 ACP 子进程的 per-session 隔离。mode=none 时全部字段被忽略。
|
||||
type SandboxCfg struct {
|
||||
Mode string `mapstructure:"mode"` // none(默认)| uid | container
|
||||
BaseUID int `mapstructure:"base_uid"` // 低权 UID 基址;per-session uid = base + offset
|
||||
// ProxyURL 注入子进程 env 的 HTTP(S)_PROXY(egress 白名单代理);空 = 不限制。
|
||||
ProxyURL string `mapstructure:"proxy_url"`
|
||||
// 资源上限(OS rlimit / cgroup)。0 = 不设该项。
|
||||
AddressSpaceBytes uint64 `mapstructure:"address_space_bytes"`
|
||||
NProc uint64 `mapstructure:"nproc"`
|
||||
CPUSeconds uint64 `mapstructure:"cpu_seconds"`
|
||||
PIDs uint64 `mapstructure:"pids"`
|
||||
DiskBytes uint64 `mapstructure:"disk_bytes"`
|
||||
}
|
||||
|
||||
// RunConfig 控制 workspace run profiles 模块:进程托管的终止宽限、日志环形缓冲
|
||||
@@ -214,6 +420,20 @@ type RunConfig struct {
|
||||
// EnvWhitelist 是允许从宿主进程透传给被托管命令的环境变量名白名单。
|
||||
// APP_MASTER_KEY、DB DSN、git 凭据等敏感变量绝不应出现在此名单中。
|
||||
EnvWhitelist []string `mapstructure:"env_whitelist"`
|
||||
// Exec 控制一次性 exec 原语(run_command / run_tests MCP 工具)。
|
||||
Exec ExecConfig `mapstructure:"exec"`
|
||||
}
|
||||
|
||||
// ExecConfig 控制 agent 自验证用的一次性 exec(run_command / run_tests):
|
||||
// 默认 / 最大超时、输出捕获上限,以及命令二进制白名单。AllowedCommands 为空表示
|
||||
// 显式不限制命令;默认配置保持非空,生产环境不应放空。
|
||||
type ExecConfig struct {
|
||||
DefaultTimeout time.Duration `mapstructure:"default_timeout"`
|
||||
MaxTimeout time.Duration `mapstructure:"max_timeout"`
|
||||
MaxOutputBytes int `mapstructure:"max_output_bytes"`
|
||||
// AllowedCommands 是允许执行的命令 base name 白名单(如 go / npm / pnpm)。
|
||||
// 为空时不做命令限制(仍受 env 白名单、worktree 路径、超时与树终止约束)。
|
||||
AllowedCommands []string `mapstructure:"allowed_commands"`
|
||||
}
|
||||
|
||||
// TerminalConfig 控制仅限管理员的网页端终端模块:开关、启动的 shell、并发会话上限、
|
||||
@@ -257,6 +477,10 @@ func Load(configFile string) (*Config, error) {
|
||||
v.SetDefault("workspace.push_timeout", "5m")
|
||||
v.SetDefault("workspace.ops_timeout", "60s")
|
||||
v.SetDefault("git.binary", "git")
|
||||
v.SetDefault("vcs.gitea.base_url", "https://git.jerryyan.net")
|
||||
v.SetDefault("vcs.gitea.timeout", "15s")
|
||||
v.SetDefault("vcs.gitea.merge_method", "merge")
|
||||
v.SetDefault("vcs.require_ci_pass", false)
|
||||
v.SetDefault("chat.attachment.max_file_size_mb", 20)
|
||||
v.SetDefault("chat.attachment.max_message_size_mb", 50)
|
||||
v.SetDefault("chat.attachment.mime_whitelist", []string{
|
||||
@@ -281,7 +505,10 @@ func Load(configFile string) (*Config, error) {
|
||||
v.SetDefault("jobs.attachment_cleanup.retention", "720h")
|
||||
v.SetDefault("jobs.job_reaper.enabled", true)
|
||||
v.SetDefault("jobs.job_reaper.interval", "1m")
|
||||
v.SetDefault("jobs.job_reaper.lease_timeout", "5m")
|
||||
// 15m:必须大于 orchestrator.turn_timeout(10m) 才能容纳一次完整的 agent 回合——
|
||||
// jobs handler 超时 = lease_timeout*9/10 = 13.5m > 10m。否则编排器步骤会被中途 reap
|
||||
// 并重复执行(见 app.go 启动期不变量校验)。
|
||||
v.SetDefault("jobs.job_reaper.lease_timeout", "15m")
|
||||
v.SetDefault("jobs.job_purge.enabled", true)
|
||||
v.SetDefault("jobs.job_purge.interval", "24h")
|
||||
v.SetDefault("jobs.job_purge.completed_retention", "168h")
|
||||
@@ -291,8 +518,25 @@ func Load(configFile string) (*Config, error) {
|
||||
v.SetDefault("jobs.mcp_tokens_purge.enabled", true)
|
||||
v.SetDefault("jobs.mcp_tokens_purge.interval", "24h")
|
||||
v.SetDefault("jobs.mcp_tokens_purge.retention", "168h")
|
||||
v.SetDefault("jobs.acp_session_reaper.enabled", true)
|
||||
v.SetDefault("jobs.acp_session_reaper.interval", "1m")
|
||||
v.SetDefault("jobs.acp_session_reaper.wall_clock_timeout", "4h")
|
||||
v.SetDefault("jobs.acp_session_reaper.idle_timeout", "30m")
|
||||
// 审计日志保留期清理:默认 90 天,每日扫描一次。
|
||||
v.SetDefault("jobs.audit_retention.enabled", true)
|
||||
v.SetDefault("jobs.audit_retention.interval", "24h")
|
||||
v.SetDefault("jobs.audit_retention.retention", "2160h")
|
||||
// Prometheus /metrics:默认开启(绑定内网 / 反代鉴权场景留空 token)。
|
||||
v.SetDefault("metrics.enabled", true)
|
||||
v.SetDefault("metrics.auth_token", "")
|
||||
v.SetDefault("notify.webhook.enabled", false)
|
||||
v.SetDefault("notify.webhook.timeout", "10s")
|
||||
// 默认转发的 webhook topic:phase 流转事件供下游自动化(如触发 ACP run)订阅。
|
||||
v.SetDefault("notify.webhook.topics", []string{"requirement.phase_change"})
|
||||
// email / im 通道默认关闭,未显式启用时不注册对应 Notifier。
|
||||
v.SetDefault("notify.email.enabled", false)
|
||||
v.SetDefault("notify.email.port", 587)
|
||||
v.SetDefault("notify.im.enabled", false)
|
||||
v.SetDefault("acp.enabled", true)
|
||||
v.SetDefault("acp.max_active_global", 20)
|
||||
v.SetDefault("acp.max_active_per_user", 3)
|
||||
@@ -308,6 +552,42 @@ func Load(configFile string) (*Config, error) {
|
||||
v.SetDefault("acp.event_retention_days", 7)
|
||||
v.SetDefault("acp.shutdown_grace", "30s")
|
||||
v.SetDefault("acp.permission_timeout", "5m")
|
||||
v.SetDefault("acp.brief_token_budget", 6000)
|
||||
v.SetDefault("acp.default_project_budget_usd", 0)
|
||||
// 沙箱默认 none:Windows 开发 / CI / 非 Linux 机器均不隔离,行为与历史一致。
|
||||
v.SetDefault("acp.sandbox.mode", "none")
|
||||
v.SetDefault("acp.sandbox.base_uid", 0)
|
||||
v.SetDefault("acp.sandbox.proxy_url", "")
|
||||
v.SetDefault("acp.sandbox.address_space_bytes", 0)
|
||||
v.SetDefault("acp.sandbox.nproc", 0)
|
||||
v.SetDefault("acp.sandbox.cpu_seconds", 0)
|
||||
v.SetDefault("acp.sandbox.pids", 0)
|
||||
v.SetDefault("acp.sandbox.disk_bytes", 0)
|
||||
// secret key provider:默认 env(沿用 APP_MASTER_KEY 为 version 1)。
|
||||
v.SetDefault("crypto.provider", "env")
|
||||
// 登录暴力破解节流:默认开启,15 分钟窗口内 10 次失败即 429。
|
||||
v.SetDefault("user.login_throttle.enabled", true)
|
||||
v.SetDefault("user.login_throttle.max_failures", 10)
|
||||
v.SetDefault("user.login_throttle.window", "15m")
|
||||
// HTTP TLS / CORS / 安全头:默认 off(HTTP,无 CORS);安全头默认开启(透传安全)。
|
||||
v.SetDefault("http.tls.enabled", false)
|
||||
v.SetDefault("http.cors.enabled", false)
|
||||
v.SetDefault("http.cors.allow_credentials", true)
|
||||
v.SetDefault("http.cors.max_age_seconds", 600)
|
||||
v.SetDefault("http.security.enabled", true)
|
||||
v.SetDefault("http.security.frame_options", "DENY")
|
||||
v.SetDefault("http.security.referrer_policy", "no-referrer")
|
||||
v.SetDefault("orchestrator.enabled", true)
|
||||
v.SetDefault("orchestrator.max_attempts_per_phase", 3)
|
||||
v.SetDefault("orchestrator.turn_timeout", "10m")
|
||||
v.SetDefault("orchestrator.max_depth", 3)
|
||||
v.SetDefault("orchestrator.fan_out_limit", 3)
|
||||
v.SetDefault("orchestrator.phase_agent_kinds", map[string]string{})
|
||||
// 任务分解并行调度器:默认关闭(须显式开启,配合 jobs 周期 RunnerFn 驱动)。
|
||||
v.SetDefault("orchestrator.scheduler.enabled", false)
|
||||
v.SetDefault("orchestrator.scheduler.interval", "30s")
|
||||
v.SetDefault("orchestrator.scheduler.max_fanout_per_tick", 8)
|
||||
v.SetDefault("orchestrator.scheduler.max_concurrent_per_project", 4)
|
||||
v.SetDefault("mcp.enabled", true)
|
||||
v.SetDefault("mcp.public_url", "http://localhost:8080/mcp")
|
||||
v.SetDefault("mcp.system_token_ttl", "24h")
|
||||
@@ -324,6 +604,15 @@ func Load(configFile string) (*Config, error) {
|
||||
"SystemRoot", "TEMP", "TMP", "USERPROFILE", "APPDATA", "LOCALAPPDATA",
|
||||
"PATHEXT", "ComSpec", "NUMBER_OF_PROCESSORS",
|
||||
})
|
||||
v.SetDefault("run.exec.default_timeout", "60s")
|
||||
v.SetDefault("run.exec.max_timeout", "600s")
|
||||
v.SetDefault("run.exec.max_output_bytes", 1<<20)
|
||||
v.SetDefault("run.exec.allowed_commands", []string{
|
||||
"go", "npm", "pnpm", "yarn", "node",
|
||||
"python", "python3", "pytest", "uv",
|
||||
"cargo", "rustc", "make", "cmake", "ctest",
|
||||
"git",
|
||||
})
|
||||
v.SetDefault("terminal.enabled", true)
|
||||
v.SetDefault("terminal.shell", "/bin/bash") // Windows 开发环境经 APP_TERMINAL_SHELL 覆盖
|
||||
v.SetDefault("terminal.max_sessions", 5)
|
||||
@@ -336,6 +625,18 @@ func Load(configFile string) (*Config, error) {
|
||||
"SystemRoot", "TEMP", "TMP", "USERPROFILE", "APPDATA", "LOCALAPPDATA",
|
||||
"PATHEXT", "ComSpec", "NUMBER_OF_PROCESSORS",
|
||||
})
|
||||
// 代码索引 / 项目记忆:默认开启,但无 embedding endpoint 时自动降级为关键字回退。
|
||||
v.SetDefault("code_index.enabled", true)
|
||||
v.SetDefault("code_index.embedding_endpoint_id", "")
|
||||
v.SetDefault("code_index.embedding_model", "text-embedding-3-small")
|
||||
v.SetDefault("code_index.chunk_window_lines", 60)
|
||||
v.SetDefault("code_index.chunk_overlap_lines", 10)
|
||||
v.SetDefault("code_index.max_file_bytes", 512*1024)
|
||||
v.SetDefault("code_index.search_top_k_cap", 50)
|
||||
v.SetDefault("code_index.grep_max_matches", 200)
|
||||
v.SetDefault("code_index.grep_max_file_bytes", 1<<20)
|
||||
// 自动文档/PR 摘要:默认关闭(避免每次提交都调用 LLM 产生成本)。
|
||||
v.SetDefault("docs.enabled", false)
|
||||
|
||||
if configFile != "" {
|
||||
v.SetConfigFile(configFile)
|
||||
@@ -355,6 +656,7 @@ func Load(configFile string) (*Config, error) {
|
||||
"bootstrap.admin_email",
|
||||
"bootstrap.admin_password",
|
||||
"master_key",
|
||||
"vcs.gitea.token",
|
||||
} {
|
||||
if err := v.BindEnv(key); err != nil {
|
||||
return nil, fmt.Errorf("bind env %s: %w", key, err)
|
||||
|
||||
Reference in New Issue
Block a user