Skip to content

Commit d7a729c

Browse files
feat: 完成第二版类型清理
1 parent 4c0a655 commit d7a729c

604 files changed

Lines changed: 595 additions & 953 deletions

File tree

Some content is hidden

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

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ echo "say hello" | bun run src/entrypoints/cli.tsx -p
5454
bun run build
5555
```
5656

57-
构建产物输出到 `dist/cli.js`~25 MB,5300+ 模块)。
57+
构建产物输出到 `dist/cli.js`~25.75 MB,5326 模块)。
5858

5959
## 项目结构
6060

@@ -95,7 +95,7 @@ claude-code/
9595

9696
### 类型状态
9797

98-
仍有 ~1341 个 tsc 错误,均为反编译产生的源码级类型问题(`unknown` / `never` / `{}`),**不影响 Bun 运行时**
98+
经过系统性修复,tsc 错误从 ~1341 降至 **~289**(减少 78%)。剩余错误分散在小文件中,均为反编译产生的源码级类型问题,**不影响 Bun 运行时**。详见 [RECORD.md](./RECORD.md) 第六节
9999

100100
### Monorepo
101101

RECORD.md

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ bun run build
5757

5858
### TS 类型错误说明
5959

60-
仍有 ~1341 个 tsc 错误,绝大多数是反编译产生的源码级类型问题(unknown/never/{}),**不影响 Bun 运行时**。不再逐个修复
60+
~~仍有 ~1341 个 tsc 错误~~ → 经过系统性类型修复,已降至 **~294 个**(减少 78%)。剩余错误分散在小文件中,均为反编译产生的源码级类型问题(`unknown`/`never`/`{}`),**不影响 Bun 运行时**
6161

6262
---
6363

@@ -157,3 +157,62 @@ $ bun run build
157157
Bundled 5326 modules in 491ms
158158
cli.js 25.74 MB (entry point)
159159
```
160+
161+
---
162+
163+
## 六、系统性类型修复(2026-03-31)
164+
165+
### 6.1 背景
166+
167+
反编译产生的源码存在 ~1341 个 tsc 类型错误,主要成因:
168+
- `unknown` 类型上的属性访问(714 个,占 54%)
169+
- 类型赋值不兼容(212 个)
170+
- 参数类型不匹配(140 个)
171+
- 不可能的字面量比较(106 个,如 `"external" === 'ant'`
172+
173+
### 6.2 修复策略
174+
175+
通过 4 轮并行 agent(每轮 7 个)系统性修复,**从 1341 降至 ~294**(减少 78%)。
176+
177+
#### 根因修复(影响面最大)
178+
179+
| 修复 | 影响 |
180+
|------|------|
181+
| `useAppState<R>` 添加泛型签名 (`AppState.tsx`) | 消除全局大量 `unknown` 返回值 |
182+
| `Message` 类型重构 (`message.ts`) | content 改为 `string \| ContentBlockParam[] \| ContentBlock[]`;添加 `MessageType` 扩展联合;`GroupedToolUseMessage`/`CollapsedReadSearchGroup` 结构化 |
183+
| `SDKAssistantMessageError` 命名冲突修复 (`coreTypes.generated.ts`) | 解决 37 个 errors.ts 类型错误 |
184+
| SDK 消息类型增强 (`coreTypes.generated.ts`) | `SDKAssistantMessage`/`SDKUserMessage` 等添加具体字段声明 |
185+
| `NonNullableUsage` 扩展 (`sdkUtilityTypes.ts`) | 添加 snake_case 属性声明 |
186+
187+
#### 批量模式修复
188+
189+
| 模式 | 修复方式 | 数量 |
190+
|------|----------|------|
191+
| `"external" === 'ant'` 编译常量比较 | `("external" as string) === 'ant'` | ~60 处 |
192+
| `unknown` 属性访问 | 精确类型断言(`as SomeType`| ~400 处 |
193+
| `message.content` union 无法调用数组方法 | `Array.isArray()` 守卫 | ~80 处 |
194+
| stub 包缺失方法/类型 | 补全 stub 类型声明 | ~15 个包 |
195+
196+
#### Stub 包类型补全
197+
198+
|| 补全内容 |
199+
|----|----------|
200+
| `@ant/computer-use-swift` | `ComputerUseAPI` 完整接口(apps/display/screenshot) |
201+
| `@ant/computer-use-input` | `ComputerUseInputAPI` 完整接口 |
202+
| `audio-capture-napi` | 4 个函数签名 |
203+
204+
### 6.3 修复的关键文件
205+
206+
| 文件 | 修复错误数 |
207+
|------|-----------|
208+
| `src/screens/REPL.tsx` | ~100 |
209+
| `src/utils/hooks.ts` | ~81 |
210+
| `src/utils/sessionStorage.ts` | ~58 |
211+
| `src/components/PromptInput/` | ~45 |
212+
| `src/services/api/errors.ts` | ~37 |
213+
| `src/utils/computerUse/executor.ts` | ~36 |
214+
| `src/utils/messages.ts` | ~83 |
215+
| `src/QueryEngine.ts` | ~39 |
216+
| `src/services/api/claude.ts` | ~35 |
217+
| `src/cli/print.ts` + `structuredIO.ts` | ~46 |
218+
| 其他 ~50 个文件 | ~487 |

bun.lock

Lines changed: 78 additions & 78 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,14 @@
1-
const stub: any = {}
2-
export default stub
1+
// Auto-generated stub — replace with real implementation
2+
export function isNativeAudioAvailable(): boolean {
3+
return false
4+
}
5+
export function isNativeRecordingActive(): boolean {
6+
return false
7+
}
8+
export function stopNativeRecording(): void {}
9+
export function startNativeRecording(
10+
_onData: (data: Buffer) => void,
11+
_onEnd: () => void,
12+
): boolean {
13+
return false
14+
}

scripts/remove-sourcemaps.mjs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/env node
2+
/**
3+
* 清除 src/ 下所有 .ts/.tsx 文件中的 //# sourceMappingURL= 行
4+
* 用法: node scripts/remove-sourcemaps.mjs [--dry-run]
5+
*/
6+
import { readdir, readFile, writeFile } from "fs/promises";
7+
import { join, extname } from "path";
8+
9+
const SRC_DIR = new URL("../src", import.meta.url).pathname;
10+
const DRY_RUN = process.argv.includes("--dry-run");
11+
const EXTENSIONS = new Set([".ts", ".tsx"]);
12+
const PATTERN = /^\s*\/\/# sourceMappingURL=.*$/gm;
13+
14+
async function* walk(dir) {
15+
for (const entry of await readdir(dir, { withFileTypes: true })) {
16+
const full = join(dir, entry.name);
17+
if (entry.isDirectory()) {
18+
yield* walk(full);
19+
} else if (EXTENSIONS.has(extname(entry.name))) {
20+
yield full;
21+
}
22+
}
23+
}
24+
25+
let total = 0;
26+
for await (const file of walk(SRC_DIR)) {
27+
const content = await readFile(file, "utf8");
28+
if (!PATTERN.test(content)) continue;
29+
// reset lastIndex after test
30+
PATTERN.lastIndex = 0;
31+
const cleaned = content.replace(PATTERN, "").replace(/\n{3,}/g, "\n\n");
32+
if (DRY_RUN) {
33+
console.log(`[dry-run] ${file}`);
34+
} else {
35+
await writeFile(file, cleaned, "utf8");
36+
}
37+
total++;
38+
}
39+
40+
console.log(`\n${DRY_RUN ? "[dry-run] " : ""}Processed ${total} files.`);

src/Tool.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ export function filterToolProgressMessages(
314314
): ProgressMessage<ToolProgressData>[] {
315315
return progressMessagesForMessage.filter(
316316
(msg): msg is ProgressMessage<ToolProgressData> =>
317-
msg.data?.type !== 'hook_progress',
317+
(msg.data as { type?: string })?.type !== 'hook_progress',
318318
)
319319
}
320320

src/bridge/inboundMessages.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export function extractInboundMessageFields(
2424
| { content: string | Array<ContentBlockParam>; uuid: UUID | undefined }
2525
| undefined {
2626
if (msg.type !== 'user') return undefined
27-
const content = msg.message?.content
27+
const content = (msg.message as { content?: string | Array<ContentBlockParam> } | undefined)?.content
2828
if (!content) return undefined
2929
if (Array.isArray(content) && content.length === 0) return undefined
3030

src/bridge/initReplBridge.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ export async function initReplBridge(
284284
msg.isMeta ||
285285
msg.toolUseResult ||
286286
msg.isCompactSummary ||
287-
(msg.origin && msg.origin.kind !== 'human') ||
287+
(msg.origin && (msg.origin as { kind?: string }).kind !== 'human') ||
288288
isSyntheticMessage(msg)
289289
)
290290
continue

src/bridge/remoteBridgeCore.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -812,11 +812,11 @@ export async function initEnvLessBridgeCore(
812812
},
813813
writeSdkMessages(messages: SDKMessage[]) {
814814
const filtered = messages.filter(
815-
m => !m.uuid || !recentPostedUUIDs.has(m.uuid),
815+
m => !m.uuid || !recentPostedUUIDs.has(m.uuid as string),
816816
)
817817
if (filtered.length === 0) return
818818
for (const msg of filtered) {
819-
if (msg.uuid) recentPostedUUIDs.add(msg.uuid)
819+
if (msg.uuid) recentPostedUUIDs.add(msg.uuid as string)
820820
}
821821
const events = filtered.map(m => ({ ...m, session_id: sessionId }))
822822
void transport.writeBatch(events)
@@ -829,7 +829,7 @@ export async function initEnvLessBridgeCore(
829829
return
830830
}
831831
const event = { ...request, session_id: sessionId }
832-
if (request.request.subtype === 'can_use_tool') {
832+
if ((request as { request?: { subtype?: string } }).request?.subtype === 'can_use_tool') {
833833
transport.reportState('requires_action')
834834
}
835835
void transport.write(event)

0 commit comments

Comments
 (0)