Repository navigation
[Bug] memos-local-plugin: config validator reports schema-declared 'reasoning' keys as unknown on every boot (same class as #2247) #2474
Description
Activity
- addedai:taskDispatched to AI coding agent | 已派发给 AI 编码任务Dispatched to AI coding agent | 已派发给 AI 编码任务area:pluginOpenClaw & HermesOpenClaw & Hermesstatus:in-progressSomeone or AI is working on it | 人工或 AI 正在处理Someone or AI is working on it | 人工或 AI 正在处理types:bugSomething isn't working | 功能异常Something isn't working | 功能异常
on Oct 8, 2026 🤖 AutoDev has picked up this issue and started working on it.
Task ID:
85e5733f87f42cdc
Working branch:bugfix/autodev-2474-20261008202913915
Target branch:latest dev* branch
Workflow: opsp (analysis → coding → testing → PR)I will post the PR link here once done. If I need more information, I will ask in the comments.
- added a commit that references this issue
on Oct 8, 2026 ✅ AutoDev task
85e5733f87f42cdccompleted.Summary: Fixes #2474 — the
memos-local-pluginconfig validator falsely reported schema-declaredreasoningfields (llm.reasoning,skillEvolver.reasoning,l3Llm.reasoning) as unknown config keys on every boot. The root cause waspruneUnknowninapps/memos-local-plugin/core/config/index.tsusingDEFAULT_CONFIGas the "known keys" oracle, which misses anyType.Optional(...)field without a concrete default — the same defect class as #2247/#2248.The fix rewrites
pruneUnknownto walk the TypeBoxConfigSchemadirectly: it uses thepropertiesmap oftype: "object"nodes to decide what is known, and treatspatternProperties(TypeBoxType.Record) as a free-form map sollm.headers,logging.channels, and similar free-form sections continue to accept arbitrary child keys. The existingFREE_FORM_CONFIG_PATHSallowlist is preserved for backward compatibility. The warning text, pass-through semantics, and the downstream pipeline (deepMerge → Value.Default → Value.Errors) are all unchanged.Verification: a new
tests/unit/config/schema-driven-unknown-keys.test.tsadds 9 regression cases (reasoning no-warning across all three LLM slots, typos still warn, Record-based free-form maps unchanged, nested unknowns inside a known Optional block still warn, resolved config retains the reasoning block byte-for-byte). Full plugin unit suite 1599 pass + 1 skipped, integration suite 6/6,tsc -p tsconfig.json --noEmitclean.Base branch:
main
Branch:bugfix/autodev-2474-20261008202913915
Commit:42427d5
PR: #2475
Assigned to: @syzsunshine219
Reviewers: @whipser030, @hijzy- addedai:testingAI agent is running tests | AI 正在运行测试AI agent is running tests | AI 正在运行测试ai:failedAI task failed | AI 任务失败AI task failed | AI 任务失败and removedai:codingAI agent is coding | AI 正在编码AI agent is coding | AI 正在编码ai:testingAI agent is running tests | AI 正在运行测试AI agent is running tests | AI 正在运行测试ai:taskDispatched to AI coding agent | 已派发给 AI 编码任务Dispatched to AI coding agent | 已派发给 AI 编码任务
on Oct 8, 2026
Summary
Every boot logs a false
unknown config keywarning for each LLM slot that setsreasoning:reasoningis a declared field (reasoning: Type.Optional(ReasoningSchema)inLlmSchemaandSkillEvolverSchema,core/config/schema.ts), and it is applied: the value passes through to the request body. Only the warning is wrong.This is the same class as #2247 (
llm.maxTokens/llm.headers). #2248 fixed that one by adding those keys toDEFAULT_CONFIG, butreasoningwas not covered, andcore/config/defaults.tsonmainstill has noreasoningentry.Cause
pruneUnknown(raw, DEFAULT_CONFIG, …)(core/config/index.ts) decides "unknown" by membership in the defaults object, not the schema. AnyType.Optional(...)field without a default is reported as unknown, so this will recur for every future optional key.Why it matters
A warning that fires on every boot trains operators to ignore
config.warning, and a real typo (reasonning, or a key removed from the schema) then gets lost in it.Suggested fix
Prefer deriving the known keys from the TypeBox schema: walk
Type.Objectproperties, recursing into nested objects, and keepFREE_FORM_CONFIG_PATHSas it is. That fixesreasoningand every future optional field at once. The lighter option, following #2248, is to add areasoningdefault, but the request body must still omit it when it isn't configured.Test idea
llm.reasoning: { enabled: false }produces no warning;llm.reasonning: {}still warns; the resolved config keepsreasoningunchanged.