package config // 本文件承载「上下文预算」的配置语义(design/04 §1.3 上下文溢出压缩 + // 附录 A.3 的主人裁决)。推导本身在 context_budget.go。 // // CONTEXT_MAX_TOKENS 是**三态**取值: // // - 未设置(默认) = 按模型窗口推导(DeriveContextBudget); // - > 0 = 显式覆盖(原样使用); // - 0 / 负数 = 关闭压缩(行为与引入推导之前逐字节一致)。 // // 「未设置」不能用 0 表达:0 已经被「关闭压缩」占用。因此「有没有配过这个键」 // 必须单独记录(ContextConfig.MaxTokensSet,由 Load 在解码阶段填), // 这正是 design/04 附录 A.3 第 2 条要求的「用 os.LookupEnv 判未设置,不要靠 0」。 // // 旧口径(「默认模型 gpt-4o 窗口 128K ÷ 4 ⇒ 32K」)随本切片作废:默认模型的 // 真实窗口已达 1M token(DevDocs/reference/deepseek/facts-for-cyrene.md), // 固定 32K 会既丢上下文、又因反复压缩作废 KV 缓存前缀而反复烧钱(附录 A.2)。 // ContextMaxTokensEnv 是上下文预算的配置键名。它必须与 ContextConfig.MaxTokens // 的 env 标签**逐字一致**(Load 用它判定「未设置」),一致性由 // context_budget_test.go 的 TestContextMaxTokensEnvMatchesTag 钉住。 const ContextMaxTokensEnv = "CONTEXT_MAX_TOKENS" // ContextConfig 承载运行时循环的上下文预算(design/04 §1.3)。 // 它与 MCP / Capacity 一样是运行时调优量,由组合根消费。 type ContextConfig struct { // MaxTokens 是触发溢出压缩的上下文预算,单位是循环离线估算的 token 数 // (CONTEXT_MAX_TOKENS)。三态语义见本文件顶部说明。 // // **它刻意没有 default 标签**:未配置时值为 0,而「0 且未配置」与 // 「显式 0」由 MaxTokensSet 区分 —— 前者按窗口推导,后者关闭压缩。 MaxTokens int `env:"CONTEXT_MAX_TOKENS"` // MaxTokensSet 报告 CONTEXT_MAX_TOKENS 是否由进程环境或 .env 文件给出。 // 它由 Load 填写,不参与反射解码(没有 env 标签)。 // // 判定规则(DeriveContextBudget 是唯一判据):MaxTokens > 0 一律按显式覆盖、 // < 0 一律按关闭;只有 MaxTokens == 0 需要本标志区分「显式 0 = 关闭」与 // 「未设置 = 推导」。因此手工构造 Config 的调用方给出非零值时不必同步本标志, // 但**要表达「显式 0 = 关闭」就必须置真**。 MaxTokensSet bool // DocumentMaxInjectChars 是**单份附件正文注入模型可见上下文**的字符上限 // (DOCUMENT_MAX_INJECT_CHARS)。0(默认)= 按推导出的上下文预算算 // (loop.DocumentInjectCharsFor);> 0 = 显式覆盖。 // // 它与「sidecar 存多少」是两个数(design/24 §9.6 连带项、切片 T1 §7.2): // sidecar 存抽取得到的全文,只受安全上限 documents.MaxSidecarBytes 约束; // 本项只决定每回合往上下文里注入多少,截断因此发生在**装配期**, // 于是清单行的续读游标才真是「继续读的起点」。 DocumentMaxInjectChars int `env:"DOCUMENT_MAX_INJECT_CHARS"` }