You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(extensions): an extension's context file is unconditionally resident, with no path gating, budget, or attribution #12030
Part of #12028. Closely related to #11631, which asks for the same thing from the workflow side.
What happens today
Every active extension's context file is concatenated into the system prompt of every request, with no relevance gating of any kind:
packages/core/src/extension/extensionManager.ts:1710-1714 — resolve contextFileName per extension, filtered only by fs.existsSync.
packages/core/src/config/config.ts:8958-8966 — flat-map contextFiles over getActiveExtensions(). The only filter is "extension is active".
packages/core/src/memory/memoryDiscovery.ts:201-204 — added unconditionally to the QWEN.md hierarchy.
memoryDiscovery.ts:385-406 — concatenated verbatim, no size cap.
packages/core/src/core/prompts.ts:698-706 — injected as the contextFiles layer.
There is no path gating, no per-extension budget, no truncation, no attribution, and no way to opt one extension's context out short of deactivating the extension entirely.
Why it matters
In a real session with nine active extensions, their context files totalled 9,989 tokens — 21% of all non-conversation context, present on every request regardless of what the session was doing. Sizes, largest first:
2,164 1,602 1,548 1,487 1,124 1,078 650 172 164
The distribution is the point: two extensions account for a third of the total, and nothing in the system tells their authors that. The remaining context-file budget in the same session was 4,021 tokens of project QWEN.md, 1,180 of auto-memory and 210 of an output-language file — so extensions were the majority of the always-on context layer, at 65% of it.
The same session listed 84 skills for a combined 4,620 tokens — about 55 tokens each, with bodies loaded on demand. Nine context files cost more than twice what eighty-four skills cost.
The same extensions already ship skills. A skill costs 100–200 tokens in the listing and loads its body only when invoked, and SkillConfig.paths (packages/core/src/skills/types.ts:155-157) gates it out of the listing entirely until a tool call touches a matching file (packages/core/src/skills/skill-activation.ts:42-56). So the eager path and the lazy path carry overlapping content, and the eager one is 10–20x more expensive per extension.
Two more asymmetries point the same direction:
.qwen/rules/ supports paths:-conditional context (packages/core/src/config/rulesDiscovery.ts:7-15), but loadRules() scans only <QWEN_HOME>/rules/ and <projectRoot>/.qwen/rules/ (:305-324) — extensions cannot contribute rules.
The newer agent-plugins-v1 format skips contextFileName altogether (extensionManager.ts:1702-1705) and ships skills only. The decision has effectively already been made for plugins; classic extensions never got it.
Suggestions
Any one of these would help; they are not exclusive.
Let an extension's context file carry paths: frontmatter, reusing the rules/skill activation machinery, so it only enters the prompt when relevant.
Let extensions contribute .qwen/rules/-style conditional rules.
Document the migration — "put scenario-specific guidance in a paths:-gated skill, keep only always-true facts in the context file" — and say it in the extension authoring docs, since today nothing signals that a context file is the expensive option.
Part of #12028. Closely related to #11631, which asks for the same thing from the workflow side.
What happens today
Every active extension's context file is concatenated into the system prompt of every request, with no relevance gating of any kind:
packages/core/src/extension/extensionManager.ts:1710-1714— resolvecontextFileNameper extension, filtered only byfs.existsSync.packages/core/src/config/config.ts:8958-8966— flat-mapcontextFilesovergetActiveExtensions(). The only filter is "extension is active".packages/core/src/memory/memoryDiscovery.ts:201-204— added unconditionally to the QWEN.md hierarchy.memoryDiscovery.ts:385-406— concatenated verbatim, no size cap.packages/core/src/core/prompts.ts:698-706— injected as thecontextFileslayer.There is no path gating, no per-extension budget, no truncation, no attribution, and no way to opt one extension's context out short of deactivating the extension entirely.
Why it matters
In a real session with nine active extensions, their context files totalled 9,989 tokens — 21% of all non-conversation context, present on every request regardless of what the session was doing. Sizes, largest first:
The distribution is the point: two extensions account for a third of the total, and nothing in the system tells their authors that. The remaining context-file budget in the same session was 4,021 tokens of project
QWEN.md, 1,180 of auto-memory and 210 of an output-language file — so extensions were the majority of the always-on context layer, at 65% of it.The same session listed 84 skills for a combined 4,620 tokens — about 55 tokens each, with bodies loaded on demand. Nine context files cost more than twice what eighty-four skills cost.
The same extensions already ship skills. A skill costs 100–200 tokens in the listing and loads its body only when invoked, and
SkillConfig.paths(packages/core/src/skills/types.ts:155-157) gates it out of the listing entirely until a tool call touches a matching file (packages/core/src/skills/skill-activation.ts:42-56). So the eager path and the lazy path carry overlapping content, and the eager one is 10–20x more expensive per extension.Two more asymmetries point the same direction:
.qwen/rules/supportspaths:-conditional context (packages/core/src/config/rulesDiscovery.ts:7-15), butloadRules()scans only<QWEN_HOME>/rules/and<projectRoot>/.qwen/rules/(:305-324) — extensions cannot contribute rules.agent-plugins-v1format skipscontextFileNamealtogether (extensionManager.ts:1702-1705) and ships skills only. The decision has effectively already been made for plugins; classic extensions never got it.Suggestions
Any one of these would help; they are not exclusive.
paths:frontmatter, reusing the rules/skill activation machinery, so it only enters the prompt when relevant..qwen/rules/-style conditional rules.paths:-gated skill, keep only always-true facts in the context file" — and say it in the extension authoring docs, since today nothing signals that a context file is the expensive option.config.ts:4702-4727) is a single aggregate line that names no file; with nine extensions it cannot tell an author their extension is the problem. See Percentage-of-context-window budgets scale the wrong way: ToolSearch preload never engages, and the always-on context warning never fires, on large windows #12029 for why the threshold also never fires on large windows.中文说明
属于 #12028。与 #11631 高度相关——那个 issue 从 workflow 的角度提出了同一件事。
现状
每个已启用 extension 的上下文文件都会被拼进每一轮请求的系统提示词,没有任何相关性门控:
packages/core/src/extension/extensionManager.ts:1710-1714—— 按 extension 解析contextFileName,只用fs.existsSync过滤。packages/core/src/config/config.ts:8958-8966—— 对getActiveExtensions()展平contextFiles,唯一的过滤条件是"extension 处于启用状态"。packages/core/src/memory/memoryDiscovery.ts:201-204—— 无条件加入 QWEN.md 层级。memoryDiscovery.ts:385-406—— 原样拼接,无大小上限。packages/core/src/core/prompts.ts:698-706—— 作为contextFiles层注入。没有路径门控、没有单个 extension 的预算、不截断、不归因,除了停用整个 extension 之外也没有办法单独去掉某个 extension 的上下文。
为什么重要
在一个启用了 9 个 extension 的真实会话里,它们的上下文文件合计 9,989 token——占全部非对话上下文的 21%,无论会话在做什么都存在于每一轮请求中。各文件大小,由大到小:
分布本身就是问题所在:两个 extension 占掉了总量的三分之一,而系统没有任何机制告诉它们的作者这件事。同一会话中上下文文件的其余部分是:项目
QWEN.md4,021、auto-memory 1,180、输出语言文件 210——也就是说 extension 占了整个常驻上下文层的 65%。同一会话列出了 84 个 skill,合计 4,620 token,平均每个约 55 token,正文按需加载。9 个上下文文件的开销是 84 个 skill 的两倍多。
而这些 extension 本身已经带了 skill。一个 skill 在清单里只占 100–200 token,正文只在被调用时加载;
SkillConfig.paths(packages/core/src/skills/types.ts:155-157)还能让它在有工具调用碰到匹配文件之前完全不出现在清单里(packages/core/src/skills/skill-activation.ts:42-56)。也就是说急加载和懒加载两条路承载着重叠的内容,而急加载那条每个 extension 贵 10–20 倍。另外两处不对称指向同一个方向:
.qwen/rules/支持paths:条件上下文(packages/core/src/config/rulesDiscovery.ts:7-15),但loadRules()只扫描<QWEN_HOME>/rules/和<projectRoot>/.qwen/rules/(:305-324)——extension 无法提供 rules。agent-plugins-v1格式完全跳过contextFileName(extensionManager.ts:1702-1705),只带 skill。对 plugin 而言这个选择其实已经做了,经典 extension 没跟上。建议
以下任意一条都有帮助,彼此不排斥:
paths:frontmatter,复用 rules / skill 的激活机制,只在相关时进入提示词。.qwen/rules/形式的条件规则。paths:门控的 skill,上下文文件只保留永远成立的事实"。今天没有任何信号告诉作者"上下文文件是贵的那个选项"。config.ts:4702-4727)只有一行聚合信息、不指名文件;有 9 个 extension 时,它无法告诉作者问题出在自己身上。阈值在大窗口下同样不会触发,见 Percentage-of-context-window budgets scale the wrong way: ToolSearch preload never engages, and the always-on context warning never fires, on large windows #12029。