主要变更: - Skill Learning 闭环系统 (9/9 AC) - Opus 4.7 模型层接入 + adaptive thinking - Prompt 工程优化 (64 审计测试) - Agent Teams 简化门控 (默认启用) - Windows Terminal 后端修复 (EncodedCommand/WT_SESSION) - TF-IDF 技能搜索精准化 (字段加权/CJK 优化) - Autonomy 系统 (/autonomy 命令) - ACP 协议完整实现 - mock.module 泄漏修复 (CI 全绿) - 152+ lint/type 修复
11 KiB
BuiltinStatusLine 断连分析报告
概述
内置额度状态行组件 BuiltinStatusLine 在当前分支 chore/lint-cleanup 上不显示。该组件能够直接在终端底部渲染模型名称、Context 用量百分比、速率限制 bucket 进度条、余额(Balance)和累计花费(Cost),无需任何外部脚本配置。
当前状态:组件已升级到新的 providerUsage 类型系统,但未被接入渲染树,处于孤岛状态。
时间线
1. PR #89 (commit 913702d9) — 功能正常
- 创建
BuiltinStatusLine.tsx组件 StatusLine.tsx中import { BuiltinStatusLine }并在StatusLineInner中直接渲染<BuiltinStatusLine />statusLineShouldDisplay()返回return true(无条件显示)- 文件数:仅修改
BuiltinStatusLine.tsx+StatusLine.tsx
2. commit 5b1a52b8("更新大量 tsx 原始文件")— 上游覆盖
- 合入上游 Anthropic 官方代码,
StatusLine.tsx被完整替换为外部命令版本 import { BuiltinStatusLine }被移除statusLineShouldDisplay()变为return settings?.statusLine !== undefinedStatusLineInner变为调用executeStatusLineCommand()的外部脚本执行逻辑BuiltinStatusLine.tsx文件保留,但无人引用
3. commit 7b9287b1(当前分支 chore/lint-cleanup)— 升级组件但未恢复接线
- 升级
BuiltinStatusLine.tsx的 props 接口:rateLimits: { five_hour?, seven_day? }→buckets: ProviderUsageBucket[]+balance?: ProviderBalance - 新建完整的
providerUsage服务层(11 个文件,+704 行) - 未修改
StatusLine.tsx(git diff main...HEAD 为空) - 结果:组件升级完成,数据源就绪,但渲染入口仍然缺失
当前状态对比
StatusLine.tsx(当前 — 外部命令版本)
文件: src/components/StatusLine.tsx
statusLineShouldDisplay (行 59-64):
export function statusLineShouldDisplay(settings: ReadonlySettings): boolean {
if (feature('KAIROS') && getKairosActive()) return false
return settings?.statusLine !== undefined // ← 需要 settings 配置
}
StatusLineInner 渲染逻辑 (行 273-278):
const text = await executeStatusLineCommand( // ← 调用外部 shell 命令
statusInput,
controller.signal,
undefined,
logResult,
)
渲染输出 (行 397-407):
<Box paddingX={paddingX} gap={2}>
{statusLineText ? (
<Text dimColor wrap="truncate">
<Ansi>{statusLineText}</Ansi> // ← 渲染外部命令的 stdout
</Text>
) : isFullscreenEnvEnabled() ? (
<Text> </Text>
) : null}
</Box>
关键依赖: 需要 ~/.claude/settings.json 中配置 statusLine: { type: "command", command: "..." }
StatusLine.tsx(PR #89 — 内置版本,能正常工作)
statusLineShouldDisplay (行 17-20):
export function statusLineShouldDisplay(settings: ReadonlySettings): boolean {
if (feature('KAIROS') && getKairosActive()) return false;
return true; // ← 无条件显示
}
import (行 15):
import { BuiltinStatusLine } from './BuiltinStatusLine.js';
StatusLineInner 渲染 (行 50-58):
return (
<BuiltinStatusLine
modelName={modelDisplay}
contextUsedPct={contextPercentages.used}
usedTokens={usedTokens}
contextWindowSize={contextWindowSize}
totalCostUsd={totalCost}
rateLimits={rawUtil}
/>
);
BuiltinStatusLine.tsx(当前 — 已升级但未接入)
文件: src/components/BuiltinStatusLine.tsx
Props 接口 (行 8-16):
type BuiltinStatusLineProps = {
modelName: string;
contextUsedPct: number;
usedTokens: number;
contextWindowSize: number;
totalCostUsd: number;
buckets: ProviderUsageBucket[]; // ← 新接口(原为 rateLimits)
balance?: ProviderBalance; // ← 新增
};
渲染内容 (行 80-131):
- 行 82: 模型名称
- 行 84-87: Context 用量百分比 + token 计数
- 行 89-112: buckets 循环渲染(进度条 + 百分比 + 重置倒计时)
- 行 114-120: Balance 余额显示
- 行 124-129: Cost 花费显示
导出 (行 134):
export const BuiltinStatusLine = React.memo(BuiltinStatusLineInner);
被引用情况: 无任何文件 import 此组件(grep import.*BuiltinStatusLine 返回 0 结果)
断连的精确位置
断点 1: statusLineShouldDisplay 条件变化
| 版本 | 代码 | 行为 |
|---|---|---|
PR #89 (913702d9) |
return true |
无条件显示 |
当前 (StatusLine.tsx:63) |
return settings?.statusLine !== undefined |
需要 settings.json 中配置 statusLine 字段 |
文件: src/components/StatusLine.tsx 行 63
断点 2: BuiltinStatusLine import 被移除
| 版本 | 代码 |
|---|---|
| PR #89 行 15 | import { BuiltinStatusLine } from './BuiltinStatusLine.js'; |
| 当前 | 无此 import(StatusLine.tsx 全文不含 BuiltinStatusLine) |
文件: src/components/StatusLine.tsx(缺失 import)
断点 3: 渲染逻辑被替换
| 版本 | 渲染方式 |
|---|---|
| PR #89 行 50-58 | <BuiltinStatusLine modelName={...} contextUsedPct={...} ... /> |
| 当前行 273-278 | executeStatusLineCommand(statusInput, controller.signal, ...) |
文件: src/components/StatusLine.tsx 行 273(当前)vs PR #89 行 50
调用链(当前)
PromptInputFooter.tsx:165
└─ statusLineShouldDisplay(settings) → settings?.statusLine !== undefined → false(无配置)
└─ <StatusLine /> 不渲染
└─ BuiltinStatusLine 永远不可见
调用链(PR #89,正常工作)
PromptInputFooter.tsx:165
└─ statusLineShouldDisplay(settings) → true
└─ <StatusLine />
└─ <BuiltinStatusLine modelName={...} buckets={...} balance={...} />
└─ 直接渲染额度信息
数据源状态(已就绪)
当前分支在 commit 7b9287b1 中新建了完整的 providerUsage 服务层,作为 BuiltinStatusLine 的数据源:
| 文件 | 行数 | 功能 |
|---|---|---|
src/services/providerUsage/types.ts (行 1-41) |
41 | ProviderUsageBucket、ProviderBalance、ProviderUsage 类型定义 |
src/services/providerUsage/store.ts (行 1-69) |
69 | 单例 store:getProviderUsage()、updateProviderBuckets()、setProviderBalance()、subscribeProviderUsage() |
src/services/providerUsage/adapters/anthropic.ts |
40 | Anthropic 响应头解析 → buckets |
src/services/providerUsage/adapters/openai.ts |
97 | OpenAI 响应头解析 → buckets |
src/services/providerUsage/adapters/bedrock.ts |
38 | AWS Bedrock 适配器 |
src/services/providerUsage/balance/generic.ts |
118 | 通用余额轮询器 |
src/services/providerUsage/balance/deepseek.ts |
85 | DeepSeek 余额轮询 |
src/services/providerUsage/balance/poller.ts |
78 | 余额轮询框架 |
src/services/providerUsage/balance/types.ts |
9 | 余额轮询类型 |
src/services/providerUsage/__tests__/providerUsage.test.ts |
120 | 单元测试 |
src/services/claudeAiLimits.ts (行 15-16) |
+12 | 新增 anthropicAdapter import + updateProviderBuckets 调用 |
总计: 11 文件,+704 行。数据从 API 响应头 → adapter 解析 → store 存储 → 可供 UI 消费的完整管道已就绪。
旧数据源 getRawUtilization()(claudeAiLimits.ts:162)仍然存在,返回 { five_hour?, seven_day? } 格式,当前 StatusLine.tsx:96 仍在使用它构建 buildStatusLineCommandInput 的 rate_limits 字段。
修复方案
需要修改 1 个文件: src/components/StatusLine.tsx
修改 1: 恢复 statusLineShouldDisplay 为无条件显示(或 fallback 到内置)
当前 (StatusLine.tsx:59-64):
export function statusLineShouldDisplay(settings: ReadonlySettings): boolean {
if (feature('KAIROS') && getKairosActive()) return false
return settings?.statusLine !== undefined
}
修复为:
export function statusLineShouldDisplay(settings: ReadonlySettings): boolean {
if (feature('KAIROS') && getKairosActive()) return false
return true // 内置 StatusLine 始终可用,不需要 settings 配置
}
修改 2: 恢复 BuiltinStatusLine import
在 StatusLine.tsx 顶部添加:
import { BuiltinStatusLine } from './BuiltinStatusLine.js'
修改 3: 添加 providerUsage store 的数据连接
添加 import:
import { getProviderUsage } from '../services/providerUsage/store.js'
修改 4: StatusLineInner 渲染逻辑 — 无外部命令时 fallback 到内置
在 StatusLineInner 中(约行 185-408),当 settings?.statusLine 未配置时,直接渲染 <BuiltinStatusLine />,否则保留外部命令逻辑。
推荐方案: 将 StatusLineInner 改为双模式:
function StatusLineInner({ messagesRef, lastAssistantMessageId, vimMode }: Props): React.ReactNode {
const settings = useSettings()
// 如果配置了外部命令,走外部命令渲染路径(保留现有逻辑)
if (settings?.statusLine) {
return <ExternalStatusLine messagesRef={messagesRef} lastAssistantMessageId={lastAssistantMessageId} vimMode={vimMode} />
}
// 否则使用内置 BuiltinStatusLine
return <BuiltinStatusLineWrapper messagesRef={messagesRef} lastAssistantMessageId={lastAssistantMessageId} />
}
其中 BuiltinStatusLineWrapper 需要:
- 从
useMainLoopModel()获取模型名 - 从
getCurrentUsage()+getContextWindowForModel()计算 context 百分比 - 从
getProviderUsage()获取buckets和balance - 从
getTotalCost()获取花费 - 传入
<BuiltinStatusLine />的 props
相关文件索引
| 文件路径 | 角色 |
|---|---|
src/components/BuiltinStatusLine.tsx |
内置状态行组件(已升级,未接入) |
src/components/StatusLine.tsx |
状态行入口(当前为外部命令版本,需修改) |
src/components/PromptInput/PromptInputFooter.tsx:28-30,165 |
渲染入口(import StatusLine + 条件渲染) |
src/services/providerUsage/types.ts |
ProviderUsageBucket、ProviderBalance 类型定义 |
src/services/providerUsage/store.ts |
getProviderUsage() 数据存储 |
src/services/providerUsage/adapters/anthropic.ts |
Anthropic 响应头 → buckets 适配器 |
src/services/providerUsage/adapters/openai.ts |
OpenAI 响应头 → buckets 适配器 |
src/services/providerUsage/adapters/bedrock.ts |
Bedrock 适配器 |
src/services/providerUsage/balance/generic.ts |
通用余额轮询 |
src/services/providerUsage/balance/deepseek.ts |
DeepSeek 余额轮询 |
src/services/providerUsage/balance/poller.ts |
轮询框架 |
src/services/claudeAiLimits.ts:15-16,162-164 |
getRawUtilization()(旧数据源)+ updateProviderBuckets(新数据管道) |