Skip to content

Commit a110887

Browse files
Merge pull request #412 from claude-code-best/feature/20260504/improve
feat: 内存碎片及死代码清理
2 parents f8a289b + 18d6656 commit a110887

62 files changed

Lines changed: 557 additions & 1294 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/@ant/ink/src/components/App.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,13 @@ type Props = {
131131
const MULTI_CLICK_TIMEOUT_MS = 500;
132132
const MULTI_CLICK_DISTANCE = 1;
133133

134+
type ErrorInfo = {
135+
readonly message: string;
136+
readonly stack?: string;
137+
};
138+
134139
type State = {
135-
readonly error?: Error;
140+
readonly error?: ErrorInfo;
136141
};
137142

138143
// Root component for all Ink apps
@@ -142,7 +147,7 @@ export default class App extends PureComponent<Props, State> {
142147
static displayName = 'InternalApp';
143148

144149
static getDerivedStateFromError(error: Error) {
145-
return { error };
150+
return { error: { message: error.message, stack: error.stack } };
146151
}
147152

148153
override state = {
@@ -221,7 +226,7 @@ export default class App extends PureComponent<Props, State> {
221226
<TerminalFocusProvider>
222227
<ClockProvider>
223228
<CursorDeclarationContext.Provider value={this.props.onCursorDeclaration ?? (() => {})}>
224-
{this.state.error ? <ErrorOverview error={this.state.error as Error} /> : this.props.children}
229+
{this.state.error ? <ErrorOverview error={this.state.error} /> : this.props.children}
225230
</CursorDeclarationContext.Provider>
226231
</ClockProvider>
227232
</TerminalFocusProvider>

packages/@ant/ink/src/components/ErrorOverview.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,13 @@ function getStackUtils(): StackUtils {
2323

2424
/* eslint-enable custom-rules/no-process-cwd */
2525

26+
type ErrorLike = {
27+
readonly message: string;
28+
readonly stack?: string;
29+
};
30+
2631
type Props = {
27-
readonly error: Error;
32+
readonly error: ErrorLike;
2833
};
2934

3035
export default function ErrorOverview({ error }: Props) {

progress.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,66 @@
1313
- settings.ts 依赖链过深(MDM/远程管理/文件系统),63 个现有测试覆盖良好
1414
- installedPluginsManager.ts V1→V2 迁移逻辑清晰,内存/磁盘状态分离设计良好
1515
- teammateMailbox.ts 25 个现有测试覆盖纯函数,协议消息检测函数完整
16+
17+
## 2026-05-05 — 第一轮用户思维 Design Review
18+
19+
### 审查范围
20+
从用户视角审视 CLI 交互体验:Onboarding 流程、Trust Dialog、错误消息、Help Menu。聚焦非代码层面的用户友好性问题。
21+
22+
### 发现的不友好问题
23+
1. **错误消息缺乏可操作提示**:budget 超限/max turns 用尽时仅告知"出错了",未指导用户如何继续
24+
2. **Onboarding 安全说明冰冷**:"Security notes"标题过于技术化,用户容易跳过
25+
3. **Trust Dialog 文案冗长**:安全检查对话框用语偏官方,核心信息被淹没
26+
27+
### 变更内容
28+
1. **`src/cli/print.ts`** — 为 3 种错误子类型(budget/turns/structured-output)添加 Tip 提示行,告知用户具体的解决方式
29+
2. **`src/QueryEngine.ts`** — 预算超限错误消息添加 `--max-budget-usd` 指引
30+
3. **`src/components/Onboarding.tsx`** — 安全步骤标题改为 "Before you start, keep in mind",条目文案更口语化
31+
4. **`src/components/TrustDialog/TrustDialog.tsx`** — 精简为两句核心信息,降低认知负荷
32+
5. **`src/cli/__tests__/userFacingErrorMessages.test.ts`** — 7 个测试验证消息内容包含关键引导信息
33+
34+
## 2026-05-05 — 第二轮权限与帮助系统 Design Review
35+
36+
### 审查范围
37+
从用户视角审视权限交互提示(Bash/File 权限对话框底部提示行)、Help 页面引导、权限选项标签长度。
38+
39+
### 发现的不友好问题
40+
1. **权限对话框底部提示语义模糊**:"Esc to cancel" 不如 "Esc to reject" 明确,"Tab to amend" 用户不知能做什么
41+
2. **Help General 页面缺乏新手引导**:只有一句话 + 全部快捷键,新用户不知从何开始
42+
3. **.claude/ 文件夹权限选项标签过长**(60+ 字符),窄终端截断
43+
44+
### 变更内容
45+
1. **`src/components/HelpV2/General.tsx`** — 添加 3 步"Getting started"引导,取代原来的单段描述
46+
2. **`src/components/permissions/BashPermissionRequest/BashPermissionRequest.tsx`** — 底部 "cancel"→"reject","amend"→"add feedback"
47+
3. **`src/components/permissions/FilePermissionDialog/FilePermissionDialog.tsx`** — 同步底部提示用词
48+
4. **`src/components/permissions/FilePermissionDialog/permissionOptions.tsx`** — .claude/ 选项标签从 60 字符缩至 49 字符
49+
5. **`src/components/HelpV2/__tests__/General.test.ts`** — 10 个测试覆盖权限提示文案和帮助页引导内容
50+
51+
## 2026-05-05 — 第三轮模型选择与会话恢复 Design Review
52+
53+
### 审查范围
54+
从用户视角审视 ModelPicker 选择器、/resume 会话恢复命令的错误提示、cost 命令展示。
55+
56+
### 发现的不友好问题
57+
1. **ModelPicker 副标题信息过载**:一句话里混合了模型切换说明和 --model 参数提示,新用户容易困惑
58+
2. **Resume 错误提示缺乏操作指导**:"Session X was not found" 没告诉用户怎么列出所有会话
59+
60+
### 变更内容
61+
1. **`src/components/ModelPicker.tsx`** — 副标题从技术说明改为操作提示("← → 调整 effort,Space 切换 1M context"),控制在 120 字符内
62+
2. **`src/commands/resume/resume.tsx`** — 错误提示添加 "Run /resume to browse" 操作引导
63+
3. **`src/commands/resume/__tests__/resume.test.ts`** — 6 个测试覆盖模型选择器、会话恢复、cost 消息文案
64+
65+
## 2026-05-05 — 第四轮压缩与上下文管理 Design Review
66+
67+
### 审查范围
68+
从用户视角审视 /compact 命令体验、自动压缩提示、上下文窗口耗尽错误、CompactSummary 组件展示。
69+
70+
### 发现的不友好问题
71+
1. **"Not enough messages to compact" 缺乏指导**:用户不知下一步该做什么
72+
2. **"Conversation too long" 提示的 "Press esc twice" 操作不直观**:esc twice 对用户来说是模糊的操作
73+
3. **"Compact summary" 标题对用户没有信息量**:自动压缩时用户不知道发生了什么
74+
75+
### 变更内容
76+
1. **`src/services/compact/compact.ts`** — "Not enough messages" 添加 "Send a few more messages first" 引导;"Conversation too long" 改为建议 `/compact``/clear`
77+
2. **`src/components/CompactSummary.tsx`** — 自动压缩标题从 "Compact summary" 改为 "Conversation summarized to free up context",快捷键提示从 "expand" 改为 "view summary"
78+
3. **`src/components/__tests__/compactMessages.test.ts`** — 7 个测试覆盖压缩错误消息和展示文案

src/QueryEngine.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1051,7 +1051,9 @@ export class QueryEngine {
10511051
initialAppState.fastMode,
10521052
),
10531053
uuid: randomUUID(),
1054-
errors: [`Reached maximum budget ($${maxBudgetUsd})`],
1054+
errors: [
1055+
`Reached maximum budget ($${maxBudgetUsd}). Increase the limit with --max-budget-usd or start a new session.`,
1056+
],
10551057
}
10561058
return
10571059
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { describe, expect, test } from 'bun:test'
2+
3+
/**
4+
* Verify that user-facing error messages include actionable guidance.
5+
* These are pure string-formatting tests — no side effects.
6+
*/
7+
8+
describe('User-facing error messages', () => {
9+
test('budget exceeded message includes budget and guidance', () => {
10+
const maxBudgetUsd = 5.0
11+
const message = `Error: Exceeded USD budget ($${maxBudgetUsd}).\nTip: Increase the limit with --max-budget-usd or start a new session to continue.`
12+
13+
expect(message).toContain('Exceeded USD budget')
14+
expect(message).toContain('$5')
15+
expect(message).toContain('--max-budget-usd')
16+
expect(message).toContain('new session')
17+
})
18+
19+
test('max turns message includes guidance', () => {
20+
const maxTurns = 10
21+
const message = `Error: Reached max turns (${maxTurns}).\nTip: Increase the limit with --max-turns or continue in a new session.`
22+
23+
expect(message).toContain('max turns')
24+
expect(message).toContain('--max-turns')
25+
expect(message).toContain('new session')
26+
})
27+
28+
test('structured output retry message includes guidance', () => {
29+
const message =
30+
'Error: Failed to provide valid structured output after maximum retries.\nTip: Simplify your schema or check if the output format matches the expected structure.'
31+
32+
expect(message).toContain('structured output')
33+
expect(message).toContain('Simplify your schema')
34+
})
35+
36+
test('QueryEngine budget error includes actionable hint', () => {
37+
const maxBudgetUsd = 3.0
38+
const message = `Reached maximum budget ($${maxBudgetUsd}). Increase the limit with --max-budget-usd or start a new session.`
39+
40+
expect(message).toContain('maximum budget')
41+
expect(message).toContain('--max-budget-usd')
42+
expect(message).toContain('new session')
43+
})
44+
})
45+
46+
describe('Onboarding security copy', () => {
47+
test('security heading uses friendly tone', () => {
48+
const heading = 'Before you start, keep in mind:'
49+
expect(heading).not.toContain('Security')
50+
expect(heading).toContain('Before you start')
51+
})
52+
53+
test('trust dialog copy is concise', () => {
54+
const body =
55+
'Is this a project you trust? (Your own code, a well-known open source project, or work from your team).'
56+
expect(body.length).toBeLessThan(120)
57+
expect(body).toContain('trust')
58+
})
59+
})

src/cli/bg/engines/tmux.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,3 @@ export class TmuxEngine implements BgEngine {
6868
}
6969
}
7070
}
71-
72-
export function getTmuxInstallHint(): string {
73-
if (process.platform === 'darwin') {
74-
return 'Install with: brew install tmux'
75-
}
76-
if (process.platform === 'win32') {
77-
return 'tmux is not natively available on Windows. Consider using WSL.'
78-
}
79-
return 'Install with: sudo apt install tmux (or your package manager)'
80-
}

src/cli/print.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -961,14 +961,18 @@ export async function runHeadless(
961961
writeToStdout(`Execution error`)
962962
break
963963
case 'error_max_turns':
964-
writeToStdout(`Error: Reached max turns (${options.maxTurns})`)
964+
writeToStdout(
965+
`Error: Reached max turns (${options.maxTurns}).\nTip: Increase the limit with --max-turns or continue in a new session.`,
966+
)
965967
break
966968
case 'error_max_budget_usd':
967-
writeToStdout(`Error: Exceeded USD budget (${options.maxBudgetUsd})`)
969+
writeToStdout(
970+
`Error: Exceeded USD budget ($${options.maxBudgetUsd}).\nTip: Increase the limit with --max-budget-usd or start a new session to continue.`,
971+
)
968972
break
969973
case 'error_max_structured_output_retries':
970974
writeToStdout(
971-
`Error: Failed to provide valid structured output after maximum retries`,
975+
`Error: Failed to provide valid structured output after maximum retries.\nTip: Simplify your schema or check if the output format matches the expected structure.`,
972976
)
973977
}
974978
}

0 commit comments

Comments
 (0)