closer-code 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/.env.example +83 -0
  2. package/API_GUIDE.md +1411 -0
  3. package/AUTO_MKDIR_IMPROVEMENT.md +354 -0
  4. package/CLAUDE.md +55 -0
  5. package/CTRL_C_EXPERIMENT.md +90 -0
  6. package/PROJECT_CLEANUP_SUMMARY.md +121 -0
  7. package/README.md +686 -0
  8. package/cloco.md +51 -0
  9. package/config.example.json +116 -0
  10. package/dist/bash-runner.js +128 -0
  11. package/dist/batch-cli.js +20736 -0
  12. package/dist/closer-cli.js +21190 -0
  13. package/dist/index.js +31228 -0
  14. package/docs/EXPORT_COMMAND.md +152 -0
  15. package/docs/FILE_NAMING_IMPROVEMENT.md +168 -0
  16. package/docs/GLOBAL_CONFIG.md +128 -0
  17. package/docs/LONG_MESSAGE_DISPLAY_FIX.md +202 -0
  18. package/docs/PROJECT_HISTORY_ISOLATION.md +315 -0
  19. package/docs/QUICK_START_HISTORY.md +207 -0
  20. package/docs/TASK_PROGRESS_FEATURE.md +190 -0
  21. package/docs/THINKING_CONTENT_RESEARCH.md +267 -0
  22. package/docs/THINKING_FEATURE.md +187 -0
  23. package/docs/THINKING_IMPROVEMENT_COMPARISON.md +193 -0
  24. package/docs/THINKING_OPTIMIZATION_SUMMARY.md +242 -0
  25. package/docs/UI_IMPROVEMENTS_2025-01-18.md +256 -0
  26. package/docs/WHY_THINKING_SHORT.md +201 -0
  27. package/package.json +49 -0
  28. package/scenarios/README.md +234 -0
  29. package/scenarios/run-all-scenarios.js +342 -0
  30. package/scenarios/scenario1-batch-converter.js +247 -0
  31. package/scenarios/scenario2-code-analyzer.js +375 -0
  32. package/scenarios/scenario3-doc-generator.js +371 -0
  33. package/scenarios/scenario4-log-analyzer.js +496 -0
  34. package/scenarios/scenario5-tdd-helper.js +681 -0
  35. package/src/ai-client-legacy.js +171 -0
  36. package/src/ai-client.js +221 -0
  37. package/src/bash-runner.js +148 -0
  38. package/src/batch-cli.js +327 -0
  39. package/src/cli.jsx +166 -0
  40. package/src/closer-cli.jsx +1103 -0
  41. package/src/closer-cli.jsx.backup +948 -0
  42. package/src/commands/batch.js +62 -0
  43. package/src/commands/chat.js +10 -0
  44. package/src/commands/config.js +154 -0
  45. package/src/commands/help.js +76 -0
  46. package/src/commands/history.js +192 -0
  47. package/src/commands/setup.js +17 -0
  48. package/src/commands/upgrade.js +101 -0
  49. package/src/commands/workflow-tests.js +125 -0
  50. package/src/config.js +343 -0
  51. package/src/conversation.js +962 -0
  52. package/src/git-helper.js +349 -0
  53. package/src/index.js +88 -0
  54. package/src/logger.js +347 -0
  55. package/src/plan.js +193 -0
  56. package/src/planner.js +397 -0
  57. package/src/search.js +195 -0
  58. package/src/setup.js +147 -0
  59. package/src/shortcuts.js +269 -0
  60. package/src/snippets.js +430 -0
  61. package/src/test-modules.js +118 -0
  62. package/src/tools.js +398 -0
  63. package/src/utils/cli.js +124 -0
  64. package/src/utils/validator.js +184 -0
  65. package/src/utils/version.js +33 -0
  66. package/src/utils/workflow-test.js +271 -0
  67. package/src/utils/workflow.js +268 -0
  68. package/test/demo-file-naming.js +92 -0
  69. package/test/demo-thinking.js +124 -0
  70. package/test/final-verification-report.md +303 -0
  71. package/test/research-thinking.js +130 -0
  72. package/test/test-auto-mkdir.js +123 -0
  73. package/test/test-e2e-empty-dir.md +108 -0
  74. package/test/test-export-logic.js +119 -0
  75. package/test/test-global-cloco.js +126 -0
  76. package/test/test-history-isolation.js +291 -0
  77. package/test/test-improved-thinking.js +43 -0
  78. package/test/test-long-message.js +65 -0
  79. package/test/test-plan-functionality.js +95 -0
  80. package/test/test-real-scenario.js +216 -0
  81. package/test/test-thinking-display.js +65 -0
  82. package/test/ui-verification-test.js +203 -0
  83. package/test/verify-history-isolation.sh +71 -0
  84. package/test/verify-thinking.js +339 -0
  85. package/test/workflows/empty-dir-creation.md +51 -0
  86. package/test/workflows/inventor/ascii-teacup.js +199 -0
  87. package/test/workflows/inventor/ascii-teacup.mjs +199 -0
  88. package/test/workflows/inventor/ascii_apple.hs +84 -0
  89. package/test/workflows/inventor/ascii_apple.py +91 -0
  90. package/test/workflows/inventor/cloco.md +3 -0
  91. package/test/workflows/longtalk/cloco.md +19 -0
  92. package/test/workflows/longtalk/emoji_500.txt +63 -0
  93. package/test/workflows/longtalk/emoji_list.txt +20 -0
  94. package/test/workflows/programmer/adder.md +33 -0
  95. package/test/workflows/programmer/expect.md +2 -0
  96. package/test/workflows/programmer/prompt.md +3 -0
  97. package/test/workflows/test-empty-dir-creation.js +113 -0
  98. package/test-ctrl-c.jsx +126 -0
  99. package/test-manual-file-creation.js +151 -0
  100. package/winfix.md +3 -0
package/API_GUIDE.md ADDED
@@ -0,0 +1,1411 @@
1
+ # Closer Code - Anthropic SDK 使用指南
2
+
3
+ > 本指南帮助 Closer Code 项目的工程师更好地使用 `@anthropic-ai/sdk` 简化 AI API 调用,降低封装成本。
4
+
5
+ ---
6
+
7
+ ## 目录
8
+
9
+ 1. [快速入门](#1-快速入门)
10
+ 2. [核心功能对比](#2-核心功能对比)
11
+ 3. [迁移指南](#3-迁移指南)
12
+ 4. [API 使用说明](#4-api-使用说明)
13
+ 5. [扩展思考功能 (Extended Thinking)](#5-扩展思考功能-extended-thinking)
14
+ 6. [最佳实践](#6-最佳实践)
15
+ 7. [常见问题](#7-常见问题)
16
+ 8. [示例代码](#8-示例代码)
17
+
18
+ ---
19
+
20
+ ## 1. 快速入门
21
+
22
+ ### 1.1 安装
23
+
24
+ ```bash
25
+ npm install @anthropic-ai/sdk
26
+ ```
27
+
28
+ ### 1.2 基本使用(5分钟上手)
29
+
30
+ #### 当前方式(closer_code 原生实现)
31
+
32
+ ```javascript
33
+ // 手动实现 fetch、流式处理、错误处理...
34
+ const response = await fetch('https://api.anthropic.com/v1/messages', {
35
+ method: 'POST',
36
+ headers: {
37
+ 'Content-Type': 'application/json',
38
+ 'x-api-key': apiKey,
39
+ 'anthropic-version': '2023-06-01'
40
+ },
41
+ body: JSON.stringify(requestBody)
42
+ });
43
+ // 手动解析响应...
44
+ ```
45
+
46
+ #### 使用 SDK 后(简化版本)
47
+
48
+ ```typescript
49
+ import Anthropic from '@anthropic-ai/sdk';
50
+
51
+ const client = new Anthropic({
52
+ apiKey: process.env.ANTHROPIC_API_KEY
53
+ });
54
+
55
+ const message = await client.messages.create({
56
+ model: 'claude-sonnet-4-5-20250929',
57
+ max_tokens: 8192,
58
+ messages: [{ role: 'user', content: 'Hello, Claude!' }]
59
+ });
60
+
61
+ console.log(message.content);
62
+ ```
63
+
64
+ **优势**:
65
+ - ✅ 无需手动处理 HTTP 请求
66
+ - ✅ 自动类型检查
67
+ - ✅ 内置错误处理和重试
68
+ - ✅ 代码量减少 80%
69
+
70
+ ---
71
+
72
+ ## 2. 核心功能对比
73
+
74
+ ### 2.1 流式响应
75
+
76
+ | 功能 | 原生实现 | SDK 实现 |
77
+ |------|---------|---------|
78
+ | **代码行数** | ~40 行 | ~5 行 |
79
+ | **SSE 解析** | 手动实现 | 自动处理 |
80
+ | **错误处理** | 手动处理 | 内置支持 |
81
+ | **类型安全** | 无 | 完整类型 |
82
+
83
+ #### 原生实现(当前 closer_code)
84
+
85
+ ```javascript
86
+ // ai-client.js: streamFetch 函数
87
+ async function streamFetch(url, options, onChunk) {
88
+ const response = await fetch(url, options);
89
+ if (!response.ok) {
90
+ const error = await response.text();
91
+ throw new Error(`API error: ${response.status} - ${error}`);
92
+ }
93
+
94
+ const reader = response.body.getReader();
95
+ const decoder = new TextDecoder();
96
+ let buffer = '';
97
+
98
+ while (true) {
99
+ const { done, value } = await reader.read();
100
+ if (done) break;
101
+
102
+ buffer += decoder.decode(value, { stream: true });
103
+ const lines = buffer.split('\n');
104
+ buffer = lines.pop() || '';
105
+
106
+ for (const line of lines) {
107
+ if (line.trim().startsWith('data: ')) {
108
+ const data = line.trim().slice(6);
109
+ if (data === '[DONE]') continue;
110
+ try {
111
+ const parsed = JSON.parse(data);
112
+ onChunk(parsed);
113
+ } catch (e) {
114
+ // 忽略解析错误
115
+ }
116
+ }
117
+ }
118
+ }
119
+ }
120
+ ```
121
+
122
+ #### SDK 实现
123
+
124
+ ```typescript
125
+ const stream = await client.messages.create({
126
+ model: 'claude-sonnet-4-5-20250929',
127
+ max_tokens: 8192,
128
+ messages: [{ role: 'user', content: 'Hello!' }],
129
+ stream: true
130
+ });
131
+
132
+ for await (const event of stream) {
133
+ console.log(event.type);
134
+ }
135
+ ```
136
+
137
+ **代码减少:87.5%**
138
+
139
+ ### 2.2 工具执行(Tool Use)
140
+
141
+ | 功能 | 原生实现 | SDK 实现 |
142
+ |------|---------|---------|
143
+ | **工具定义** | 手动构建 schema | 支持多种 schema 格式 |
144
+ | **工具调用循环** | 手动实现 | 自动处理 |
145
+ | **结果传递** | 手动管理 | 自动传递 |
146
+ | **代码量** | ~100 行 | ~20 行 |
147
+
148
+ #### 原生实现(当前 closer_code)
149
+
150
+ ```javascript
151
+ // 手动处理工具调用
152
+ async function executeTools(aiClient, messages, tools) {
153
+ let currentMessages = [...messages];
154
+
155
+ while (true) {
156
+ const response = await aiClient.chat(currentMessages, { tools });
157
+
158
+ const toolResults = [];
159
+ for (const block of response.content) {
160
+ if (block.type === 'tool_use') {
161
+ const result = await executeTool(block.name, block.input);
162
+ toolResults.push({
163
+ role: 'tool',
164
+ toolUseId: block.id,
165
+ content: result
166
+ });
167
+ }
168
+ }
169
+
170
+ if (toolResults.length === 0) {
171
+ return response;
172
+ }
173
+
174
+ currentMessages.push({
175
+ role: 'assistant',
176
+ content: response.content
177
+ });
178
+ currentMessages.push(...toolResults);
179
+ }
180
+ }
181
+ ```
182
+
183
+ #### SDK 实现(使用 toolRunner)
184
+
185
+ ```typescript
186
+ import { z } from 'zod';
187
+ import { betaZodTool } from '@anthropic-ai/sdk/helpers/beta/zod';
188
+
189
+ const weatherTool = betaZodTool({
190
+ name: 'get_weather',
191
+ description: '获取指定地点的天气',
192
+ inputSchema: z.object({
193
+ location: z.string().describe('城市名称')
194
+ }),
195
+ run: async (input) => {
196
+ // 执行工具逻辑
197
+ return `${input.location} 的天气是晴天,温度 20°C`;
198
+ }
199
+ });
200
+
201
+ const finalMessage = await client.beta.messages.toolRunner({
202
+ model: 'claude-sonnet-4-5-20250929',
203
+ max_tokens: 8192,
204
+ messages: [{ role: 'user', content: '北京天气怎么样?' }],
205
+ tools: [weatherTool]
206
+ });
207
+ ```
208
+
209
+ **代码减少:80%**
210
+
211
+ ### 2.3 消息格式化
212
+
213
+ | 功能 | 原生实现 | SDK 实现 |
214
+ |------|---------|---------|
215
+ | **格式转换** | 手动映射 | 类型安全 |
216
+ | **工具结果** | 特殊处理 | 标准格式 |
217
+ | **验证** | 运行时错误 | 编译时检查 |
218
+
219
+ #### 原生实现(当前 closer_code)
220
+
221
+ ```javascript
222
+ // ai-client.js: 格式化消息
223
+ const formattedMessages = messages.map(m => {
224
+ if (m.role === 'tool') {
225
+ return {
226
+ role: 'user',
227
+ content: [{
228
+ type: 'tool_result',
229
+ tool_use_id: m.toolUseId,
230
+ content: m.content
231
+ }]
232
+ };
233
+ }
234
+ return {
235
+ role: m.role,
236
+ content: m.content
237
+ };
238
+ });
239
+ ```
240
+
241
+ #### SDK 实现
242
+
243
+ ```typescript
244
+ import Anthropic from '@anthropic-ai/sdk';
245
+
246
+ // 完全类型安全,IDE 自动补全
247
+ const message: Anthropic.MessageParam = {
248
+ role: 'user',
249
+ content: 'Hello'
250
+ };
251
+
252
+ // 工具结果也是标准格式
253
+ const toolResult: Anthropic.ToolResultBlockParam = {
254
+ type: 'tool_result',
255
+ tool_use_id: 'toolu_xxx',
256
+ content: '执行结果'
257
+ };
258
+ ```
259
+
260
+ ---
261
+
262
+ ## 3. 迁移指南
263
+
264
+ ### 3.1 替换 AnthropicClient 类
265
+
266
+ #### 步骤 1:安装 SDK
267
+
268
+ ```bash
269
+ npm install @anthropic-ai/sdk
270
+ ```
271
+
272
+ #### 步骤 2:创建新的客户端实例
273
+
274
+ **之前(src/ai-client.js)**:
275
+
276
+ ```javascript
277
+ export class AnthropicClient {
278
+ constructor(config) {
279
+ this.apiKey = config.apiKey;
280
+ this.baseURL = config.baseURL || 'https://api.anthropic.com';
281
+ this.model = config.model || 'claude-sonnet-4-5-20250929';
282
+ this.maxTokens = config.maxTokens || 8192;
283
+ }
284
+
285
+ async chat(messages, options = {}) {
286
+ // ... 大量实现代码
287
+ }
288
+ }
289
+ ```
290
+
291
+ **之后(src/ai-client-sdk.js)**:
292
+
293
+ ```typescript
294
+ import Anthropic from '@anthropic-ai/sdk';
295
+
296
+ export class AnthropicClientSDK {
297
+ private client: Anthropic;
298
+ private model: string;
299
+ private maxTokens: number;
300
+
301
+ constructor(config: { apiKey: string; model?: string; maxTokens?: number }) {
302
+ this.client = new Anthropic({
303
+ apiKey: config.apiKey
304
+ });
305
+ this.model = config.model || 'claude-sonnet-4-5-20250929';
306
+ this.maxTokens = config.maxTokens || 8192;
307
+ }
308
+
309
+ async chat(messages: Anthropic.MessageParam[], options?: {
310
+ system?: string;
311
+ tools?: Anthropic.Tool[];
312
+ temperature?: number;
313
+ }) {
314
+ return await this.client.messages.create({
315
+ model: this.model,
316
+ max_tokens: this.maxTokens,
317
+ system: options?.system,
318
+ messages,
319
+ tools: options?.tools,
320
+ temperature: options?.temperature
321
+ });
322
+ }
323
+
324
+ async chatStream(
325
+ messages: Anthropic.MessageParam[],
326
+ options?: { system?: string; tools?: Anthropic.Tool[] },
327
+ onChunk: (event: Anthropic.RawMessageStreamEvent) => void
328
+ ) {
329
+ const stream = await this.client.messages.create({
330
+ model: this.model,
331
+ max_tokens: this.maxTokens,
332
+ system: options?.system,
333
+ messages,
334
+ tools: options?.tools,
335
+ stream: true
336
+ });
337
+
338
+ for await (const event of stream) {
339
+ onChunk(event);
340
+ }
341
+ }
342
+ }
343
+ ```
344
+
345
+ **代码减少:70%**
346
+
347
+ ### 3.2 逐步迁移策略
348
+
349
+ #### 阶段 1:并存期(1-2周)
350
+
351
+ - 保留原有的 `AnthropicClient` 类
352
+ - 新增 `AnthropicClientSDK` 类
353
+ - 新功能使用 SDK,旧功能保持不变
354
+
355
+ #### 阶段 2:适配期(2-4周)
356
+
357
+ - 创建适配器模式,统一接口
358
+ - 逐步将功能迁移到 SDK
359
+ - 充分测试兼容性
360
+
361
+ #### 阶段 3:完全迁移(1-2周)
362
+
363
+ - 移除旧的实现代码
364
+ - 更新所有引用
365
+ - 清理依赖
366
+
367
+ ---
368
+
369
+ ## 4. API 使用说明
370
+
371
+ ### 4.1 初始化客户端
372
+
373
+ ```typescript
374
+ import Anthropic from '@anthropic-ai/sdk';
375
+
376
+ // 基础配置
377
+ const client = new Anthropic({
378
+ apiKey: process.env.ANTHROPIC_API_KEY,
379
+ baseURL: 'https://api.anthropic.com', // 可选
380
+ timeout: 60000 // 可选,默认 10 分钟
381
+ });
382
+
383
+ // 获取模型信息
384
+ const models = await client.models.list();
385
+ console.log(models.data);
386
+ ```
387
+
388
+ ### 4.2 发送消息
389
+
390
+ #### 简单文本消息
391
+
392
+ ```typescript
393
+ const message = await client.messages.create({
394
+ model: 'claude-sonnet-4-5-20250929',
395
+ max_tokens: 1024,
396
+ messages: [{
397
+ role: 'user',
398
+ content: '你好,请介绍一下你自己'
399
+ }]
400
+ });
401
+
402
+ console.log(message.content[0].type); // 'text'
403
+ console.log(message.content[0].text); // 响应内容
404
+ ```
405
+
406
+ #### 多媒体消息(图片/PDF)
407
+
408
+ ```typescript
409
+ const message = await client.messages.create({
410
+ model: 'claude-sonnet-4-5-20250929',
411
+ max_tokens: 1024,
412
+ messages: [{
413
+ role: 'user',
414
+ content: [
415
+ {
416
+ type: 'text',
417
+ text: '请描述这张图片'
418
+ },
419
+ {
420
+ type: 'image',
421
+ source: {
422
+ type: 'base64',
423
+ media_type: 'image/png',
424
+ data: 'iVBORw0KGgoAAAANSUhEUg...' // base64 编码的图片
425
+ }
426
+ }
427
+ ]
428
+ }]
429
+ });
430
+ ```
431
+
432
+ ### 4.3 流式响应
433
+
434
+ #### 基础流式
435
+
436
+ ```typescript
437
+ const stream = await client.messages.create({
438
+ model: 'claude-sonnet-4-5-20250929',
439
+ max_tokens: 1024,
440
+ messages: [{ role: 'user', content: '讲个故事' }],
441
+ stream: true
442
+ });
443
+
444
+ for await (const event of stream) {
445
+ switch (event.type) {
446
+ case 'text_block':
447
+ console.log('收到文本块');
448
+ break;
449
+ case 'content_block_delta':
450
+ console.log('内容增量:', event.delta.text);
451
+ break;
452
+ case 'message_stop':
453
+ console.log('消息结束');
454
+ break;
455
+ }
456
+ }
457
+ ```
458
+
459
+ #### 使用 Stream Helper
460
+
461
+ ```typescript
462
+ const stream = client.messages.stream({
463
+ model: 'claude-sonnet-4-5-20250929',
464
+ max_tokens: 1024,
465
+ messages: [{ role: 'user', content: '写一首诗' }]
466
+ })
467
+ .on('text', (text) => {
468
+ console.log('实时文本:', text);
469
+ })
470
+ .on('error', (error) => {
471
+ console.error('流式错误:', error);
472
+ })
473
+ .on('finalMessage', (message) => {
474
+ console.log('完整消息:', message);
475
+ });
476
+
477
+ await stream.finalMessage();
478
+ ```
479
+
480
+ ### 4.4 工具使用(Tool Use)
481
+
482
+ #### 定义工具
483
+
484
+ ```typescript
485
+ import { z } from 'zod';
486
+ import { betaZodTool } from '@anthropic-ai/sdk/helpers/beta/zod';
487
+
488
+ // 方式 1:使用 Zod(推荐)
489
+ const searchTool = betaZodTool({
490
+ name: 'search_code',
491
+ description: '在代码库中搜索',
492
+ inputSchema: z.object({
493
+ query: z.string().describe('搜索关键词'),
494
+ file_type: z.string().optional().describe('文件类型')
495
+ }),
496
+ run: async (input) => {
497
+ // 执行搜索逻辑
498
+ const results = await searchInCodebase(input.query, input.file_type);
499
+ return JSON.stringify(results);
500
+ }
501
+ });
502
+
503
+ // 方式 2:使用 JSON Schema
504
+ const searchTool2: Anthropic.Tool = {
505
+ name: 'search_code',
506
+ description: '在代码库中搜索',
507
+ input_schema: {
508
+ type: 'object',
509
+ properties: {
510
+ query: {
511
+ type: 'string',
512
+ description: '搜索关键词'
513
+ },
514
+ file_type: {
515
+ type: 'string',
516
+ description: '文件类型'
517
+ }
518
+ },
519
+ required: ['query']
520
+ }
521
+ };
522
+ ```
523
+
524
+ #### 使用工具
525
+
526
+ ```typescript
527
+ // 方式 1:自动工具循环(推荐)
528
+ const finalMessage = await client.beta.messages.toolRunner({
529
+ model: 'claude-sonnet-4-5-20250929',
530
+ max_tokens: 8192,
531
+ messages: [{ role: 'user', content: '搜索所有 TypeScript 文件中的 "API" 关键词' }],
532
+ tools: [searchTool]
533
+ });
534
+
535
+ // 方式 2:手动工具循环
536
+ const response = await client.messages.create({
537
+ model: 'claude-sonnet-4-5-20250929',
538
+ max_tokens: 8192,
539
+ messages: [{ role: 'user', content: '搜索代码' }],
540
+ tools: [searchTool]
541
+ });
542
+
543
+ // 处理工具调用
544
+ let currentMessages = [{ role: 'user', content: '搜索代码' }];
545
+
546
+ for (const block of response.content) {
547
+ if (block.type === 'tool_use') {
548
+ // 执行工具
549
+ const result = await executeTool(block.name, block.input);
550
+
551
+ // 返回结果
552
+ const toolResponse = await client.messages.create({
553
+ model: 'claude-sonnet-4-5-20250929',
554
+ max_tokens: 8192,
555
+ messages: [
556
+ ...currentMessages,
557
+ { role: 'assistant', content: response.content },
558
+ {
559
+ role: 'user',
560
+ content: [{
561
+ type: 'tool_result',
562
+ tool_use_id: block.id,
563
+ content: result
564
+ }]
565
+ }
566
+ ]
567
+ });
568
+ }
569
+ }
570
+ ```
571
+
572
+ ### 4.5 Token 计数
573
+
574
+ ```typescript
575
+ // 在发送消息前计算 token 数量
576
+ const tokenCount = await client.messages.countTokens({
577
+ model: 'claude-sonnet-4-5-20250929',
578
+ messages: [
579
+ { role: 'user', content: '这是一段很长的文本...' }
580
+ ]
581
+ });
582
+
583
+ console.log('输入 tokens:', tokenCount.input_tokens);
584
+
585
+ // 从响应中获取使用信息
586
+ const message = await client.messages.create({...});
587
+ console.log('输入 tokens:', message.usage.input_tokens);
588
+ console.log('输出 tokens:', message.usage.output_tokens);
589
+ ```
590
+
591
+ ### 4.6 扩展思考功能 (Extended Thinking)
592
+
593
+ #### 什么是 Extended Thinking?
594
+
595
+ Extended Thinking 是 Claude 的高级功能,允许模型在生成最终答案之前进行深度思考。当启用此功能时:
596
+
597
+ - 模型会使用指定的 token 预算进行内部推理
598
+ - 响应中会包含 `thinking` 内容块,展示模型的思考过程
599
+ - 适用于复杂问题解决、代码分析、逻辑推理等场景
600
+
601
+ #### 基础用法
602
+
603
+ ```typescript
604
+ const message = await client.messages.create({
605
+ model: 'claude-sonnet-4-5-20250929',
606
+ max_tokens: 3200,
607
+ // 启用扩展思考
608
+ thinking: {
609
+ type: 'enabled',
610
+ budget_tokens: 1600 // 为思考过程分配的 token 数量
611
+ },
612
+ messages: [{
613
+ role: 'user',
614
+ content: '分析这个复杂的算法问题:...'
615
+ }]
616
+ });
617
+
618
+ // 解析响应
619
+ for (const block of message.content) {
620
+ if (block.type === 'thinking') {
621
+ console.log('思考过程:', block.thinking);
622
+ console.log('签名:', block.signature);
623
+ } else if (block.type === 'text') {
624
+ console.log('最终答案:', block.text);
625
+ }
626
+ }
627
+ ```
628
+
629
+ **重要参数说明**:
630
+ - `budget_tokens`: 思考过程的 token 预算
631
+ - 最小值:1024 tokens
632
+ - 必须小于 `max_tokens`
633
+ - 包含在 `max_tokens` 限制内
634
+ - `type`: 设置为 `'enabled'` 启用功能
635
+
636
+ #### 流式响应中使用 Thinking
637
+
638
+ ```typescript
639
+ const stream = client.messages.stream({
640
+ model: 'claude-sonnet-4-5-20250929',
641
+ max_tokens: 3200,
642
+ thinking: {
643
+ type: 'enabled',
644
+ budget_tokens: 1600
645
+ },
646
+ messages: [{
647
+ role: 'user',
648
+ content: '解释量子纠缠的原理'
649
+ }]
650
+ })
651
+ .on('thinking', (thinking) => {
652
+ // 实时接收思考内容
653
+ process.stdout.write(thinking);
654
+ })
655
+ .on('text', (text) => {
656
+ // 接收最终答案
657
+ process.stdout.write(text);
658
+ })
659
+ .on('signature', (signature) => {
660
+ // 接收思考内容的签名
661
+ console.log('\n签名:', signature);
662
+ })
663
+ .on('error', (error) => {
664
+ console.error('错误:', error);
665
+ });
666
+
667
+ const finalMessage = await stream.finalMessage();
668
+ console.log('\n完整消息:', finalMessage);
669
+ ```
670
+
671
+ #### 状态跟踪示例
672
+
673
+ ```typescript
674
+ let thinkingState = 'not-started';
675
+
676
+ const stream = client.messages.stream({
677
+ model: 'claude-sonnet-4-5-20250929',
678
+ max_tokens: 3200,
679
+ thinking: { type: 'enabled', budget_tokens: 1600 },
680
+ messages: [{ role: 'user', content: '你的问题' }]
681
+ })
682
+ .on('thinking', (thinking) => {
683
+ if (thinkingState === 'not-started') {
684
+ console.log('思考过程:\n---------');
685
+ thinkingState = 'started';
686
+ }
687
+ process.stdout.write(thinking);
688
+ })
689
+ .on('text', (text) => {
690
+ if (thinkingState !== 'finished') {
691
+ console.log('\n\n最终答案:\n-----');
692
+ thinkingState = 'finished';
693
+ }
694
+ process.stdout.write(text);
695
+ });
696
+
697
+ await stream.finalMessage();
698
+ ```
699
+
700
+ #### 使用场景建议
701
+
702
+ **适合使用 Extended Thinking 的场景**:
703
+ 1. **复杂问题分析**:需要多步推理的问题
704
+ 2. **代码审查**:深入分析代码逻辑和潜在问题
705
+ 3. **架构设计**:权衡不同技术方案的优劣
706
+ 4. **调试协助**:分析复杂 bug 的根本原因
707
+ 5. **算法优化**:分析和改进算法效率
708
+
709
+ **不推荐使用的场景**:
710
+ 1. 简单问答(会增加成本和延迟)
711
+ 2. 创意写作(思考内容可能对最终输出帮助有限)
712
+ 3. 实时性要求极高的场景
713
+
714
+ #### 成本优化建议
715
+
716
+ ```typescript
717
+ // 根据问题复杂度动态调整 thinking budget
718
+ function calculateThinkingBudget(complexity: 'low' | 'medium' | 'high'): number {
719
+ const budgets = {
720
+ low: 1024, // 简单问题
721
+ medium: 2048, // 中等复杂度
722
+ high: 4096 // 复杂问题
723
+ };
724
+ return budgets[complexity];
725
+ }
726
+
727
+ const message = await client.messages.create({
728
+ model: 'claude-sonnet-4-5-20250929',
729
+ max_tokens: 8192,
730
+ thinking: {
731
+ type: 'enabled',
732
+ budget_tokens: calculateThinkingBudget('high')
733
+ },
734
+ messages: [{ role: 'user', content: complexQuestion }]
735
+ });
736
+ ```
737
+
738
+ #### 禁用 Thinking
739
+
740
+ ```typescript
741
+ // 默认情况下,thinking 是禁用的
742
+ const message = await client.messages.create({
743
+ model: 'claude-sonnet-4-5-20250929',
744
+ max_tokens: 1024,
745
+ messages: [{ role: 'user', content: '简单问题' }]
746
+ });
747
+
748
+ // 或者显式禁用
749
+ const message2 = await client.messages.create({
750
+ model: 'claude-sonnet-4-5-20250929',
751
+ max_tokens: 1024,
752
+ thinking: { type: 'disabled' },
753
+ messages: [{ role: 'user', content: '简单问题' }]
754
+ });
755
+ ```
756
+
757
+ ---
758
+
759
+ ## 6. 最佳实践
760
+
761
+ ### 6.1 错误处理
762
+
763
+ ```typescript
764
+ import {
765
+ APIError,
766
+ APIConnectionError,
767
+ RateLimitError,
768
+ AuthenticationError
769
+ } from '@anthropic-ai/sdk';
770
+
771
+ try {
772
+ const message = await client.messages.create({...});
773
+ } catch (error) {
774
+ if (error instanceof APIConnectionError) {
775
+ console.error('网络连接错误:', error.message);
776
+ } else if (error instanceof RateLimitError) {
777
+ console.error('速率限制,请稍后重试');
778
+ } else if (error instanceof AuthenticationError) {
779
+ console.error('API 密钥无效');
780
+ } else if (error instanceof APIError) {
781
+ console.error('API 错误:', error.message);
782
+ console.error('状态码:', error.status);
783
+ console.error('错误详情:', error.error);
784
+ }
785
+ }
786
+ ```
787
+
788
+ ### 6.2 重试策略
789
+
790
+ SDK 内置自动重试,但可以自定义:
791
+
792
+ ```typescript
793
+ const client = new Anthropic({
794
+ apiKey: process.env.ANTHROPIC_API_KEY,
795
+ maxRetries: 3, // 默认 2
796
+ timeout: 60000
797
+ });
798
+ ```
799
+
800
+ ### 6.3 性能优化
801
+
802
+ #### 1. 使用缓存
803
+
804
+ ```typescript
805
+ const message = await client.messages.create({
806
+ model: 'claude-sonnet-4-5-20250929',
807
+ max_tokens: 8192,
808
+ system: '你是一个编程助手',
809
+ messages: [
810
+ {
811
+ role: 'user',
812
+ content: '分析这段代码'
813
+ }
814
+ ],
815
+ // 启用提示缓存
816
+ cache_control: {
817
+ type: 'ephemeral',
818
+ ttl: '5m'
819
+ }
820
+ });
821
+ ```
822
+
823
+ #### 2. 批量请求
824
+
825
+ ```typescript
826
+ // 使用 Message Batches API
827
+ const batch = await client.messages.batches.create({
828
+ requests: [
829
+ {
830
+ custom_id: 'request-1',
831
+ params: {
832
+ model: 'claude-sonnet-4-5-20250929',
833
+ max_tokens: 1024,
834
+ messages: [{ role: 'user', content: '任务 1' }]
835
+ }
836
+ },
837
+ {
838
+ custom_id: 'request-2',
839
+ params: {
840
+ model: 'claude-sonnet-4-5-20250929',
841
+ max_tokens: 1024,
842
+ messages: [{ role: 'user', content: '任务 2' }]
843
+ }
844
+ }
845
+ ]
846
+ });
847
+
848
+ // 获取结果
849
+ const results = await client.messages.batches.results(batch.id);
850
+ for await (const result of results) {
851
+ console.log(result);
852
+ }
853
+ ```
854
+
855
+ ### 6.4 安全性
856
+
857
+ #### 1. API 密钥管理
858
+
859
+ ```typescript
860
+ // ✅ 好的做法:使用环境变量
861
+ const client = new Anthropic({
862
+ apiKey: process.env.ANTHROPIC_API_KEY
863
+ });
864
+
865
+ // ❌ 不好的做法:硬编码密钥
866
+ const client = new Anthropic({
867
+ apiKey: 'sk-ant-xxx...' // 不要这样做!
868
+ });
869
+ ```
870
+
871
+ #### 2. 输入验证
872
+
873
+ ```typescript
874
+ // 验证用户输入
875
+ function sanitizeUserInput(input: string): string {
876
+ // 移除潜在的恶意内容
877
+ return input
878
+ .replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
879
+ .slice(0, 10000); // 限制长度
880
+ }
881
+
882
+ const message = await client.messages.create({
883
+ model: 'claude-sonnet-4-5-20250929',
884
+ max_tokens: 1024,
885
+ messages: [{
886
+ role: 'user',
887
+ content: sanitizeUserInput(userInput)
888
+ }]
889
+ });
890
+ ```
891
+
892
+ ---
893
+
894
+ ## 7. 常见问题
895
+
896
+ ### 7.1 如何处理超长对话?
897
+
898
+ **问题**:对话历史很长,导致 token 超限。
899
+
900
+ **解决方案**:
901
+
902
+ ```typescript
903
+ // 方案 1:使用 token 计数检查
904
+ async function checkTokenCount(messages: Anthropic.MessageParam[]) {
905
+ const count = await client.messages.countTokens({
906
+ model: 'claude-sonnet-4-5-20250929',
907
+ messages
908
+ });
909
+
910
+ if (count.input_tokens > 100000) {
911
+ // 截断或总结早期消息
912
+ return summarizeMessages(messages);
913
+ }
914
+ return messages;
915
+ }
916
+
917
+ // 方案 2:滑动窗口
918
+ function slidingWindow(messages: Anthropic.MessageParam[], maxMessages = 10) {
919
+ return messages.slice(-maxMessages);
920
+ }
921
+ ```
922
+
923
+ ### 7.2 如何实现多轮对话?
924
+
925
+ ```typescript
926
+ class Conversation {
927
+ private messages: Anthropic.MessageParam[] = [];
928
+ private system: string;
929
+
930
+ constructor(system: string) {
931
+ this.system = system;
932
+ }
933
+
934
+ async say(userMessage: string) {
935
+ this.messages.push({
936
+ role: 'user',
937
+ content: userMessage
938
+ });
939
+
940
+ const response = await client.messages.create({
941
+ model: 'claude-sonnet-4-5-20250929',
942
+ max_tokens: 8192,
943
+ system: this.system,
944
+ messages: this.messages
945
+ });
946
+
947
+ this.messages.push({
948
+ role: 'assistant',
949
+ content: response.content
950
+ });
951
+
952
+ return response;
953
+ }
954
+ }
955
+
956
+ // 使用
957
+ const chat = new Conversation('你是一个编程助手');
958
+ await chat.say('什么是 TypeScript?');
959
+ await chat.say('能给我一个例子吗?');
960
+ ```
961
+
962
+ ### 7.3 如何处理并发请求?
963
+
964
+ ```typescript
965
+ // 使用 Promise.all 并行处理
966
+ const tasks = [
967
+ '分析文件 A',
968
+ '分析文件 B',
969
+ '分析文件 C'
970
+ ];
971
+
972
+ const results = await Promise.all(
973
+ tasks.map(task =>
974
+ client.messages.create({
975
+ model: 'claude-sonnet-4-5-20250929',
976
+ max_tokens: 1024,
977
+ messages: [{ role: 'user', content: task }]
978
+ })
979
+ )
980
+ );
981
+
982
+ // 或者使用 Message Batches API(更适合大量请求)
983
+ ```
984
+
985
+ ### 7.4 如何调试 API 调用?
986
+
987
+ ```typescript
988
+ // 启用详细日志
989
+ const client = new Anthropic({
990
+ apiKey: process.env.ANTHROPIC_API_KEY,
991
+ // 添加日志中间件
992
+ baseURL: 'https://api.anthropic.com'
993
+ });
994
+
995
+ // 检查请求详情
996
+ const message = await client.messages.create({
997
+ model: 'claude-sonnet-4-5-20250929',
998
+ max_tokens: 1024,
999
+ messages: [{ role: 'user', content: '测试' }]
1000
+ }).withResponse();
1001
+
1002
+ console.log('响应头:', message.response.headers);
1003
+ console.log('请求 ID:', message.response.headers.get('request-id'));
1004
+ ```
1005
+
1006
+ ---
1007
+
1008
+ ## 8. 示例代码
1009
+
1010
+ ### 8.1 代码助手(完整示例)
1011
+
1012
+ ```typescript
1013
+ import Anthropic from '@anthropic-ai/sdk';
1014
+ import { betaZodTool } from '@anthropic-ai/sdk/helpers/beta/zod';
1015
+ import { z } from 'zod';
1016
+
1017
+ // 初始化客户端
1018
+ const client = new Anthropic({
1019
+ apiKey: process.env.ANTHROPIC_API_KEY
1020
+ });
1021
+
1022
+ // 定义工具
1023
+ const readFileTool = betaZodTool({
1024
+ name: 'read_file',
1025
+ description: '读取文件内容',
1026
+ inputSchema: z.object({
1027
+ filePath: z.string().describe('文件路径')
1028
+ }),
1029
+ run: async (input) => {
1030
+ const fs = await import('fs/promises');
1031
+ const content = await fs.readFile(input.filePath, 'utf-8');
1032
+ return content;
1033
+ }
1034
+ });
1035
+
1036
+ const writeFileTool = betaZodTool({
1037
+ name: 'write_file',
1038
+ description: '写入文件内容',
1039
+ inputSchema: z.object({
1040
+ filePath: z.string().describe('文件路径'),
1041
+ content: z.string().describe('文件内容')
1042
+ }),
1043
+ run: async (input) => {
1044
+ const fs = await import('fs/promises');
1045
+ await fs.writeFile(input.filePath, input.content, 'utf-8');
1046
+ return '文件已保存';
1047
+ }
1048
+ });
1049
+
1050
+ // 主函数
1051
+ async function codeAssistant(userRequest: string) {
1052
+ const finalMessage = await client.beta.messages.toolRunner({
1053
+ model: 'claude-sonnet-4-5-20250929',
1054
+ max_tokens: 8192,
1055
+ system: '你是一个专业的代码助手,可以帮助用户读写文件和分析代码。',
1056
+ messages: [{ role: 'user', content: userRequest }],
1057
+ tools: [readFileTool, writeFileTool]
1058
+ });
1059
+
1060
+ return finalMessage;
1061
+ }
1062
+
1063
+ // 使用示例
1064
+ const result = await codeAssistant('请读取 src/index.js 文件并分析它的功能');
1065
+ console.log(result.content);
1066
+ ```
1067
+
1068
+ ### 8.2 流式代码助手
1069
+
1070
+ ```typescript
1071
+ async function streamingCodeAssistant(userRequest: string) {
1072
+ const stream = client.messages.stream({
1073
+ model: 'claude-sonnet-4-5-20250929',
1074
+ max_tokens: 8192,
1075
+ system: '你是一个专业的代码助手',
1076
+ messages: [{ role: 'user', content: userRequest }],
1077
+ tools: [readFileTool, writeFileTool]
1078
+ })
1079
+ .on('text', (text) => {
1080
+ process.stdout.write(text);
1081
+ })
1082
+ .on('toolUse', (toolUse) => {
1083
+ console.log('\n[执行工具]', toolUse.name, toolUse.input);
1084
+ })
1085
+ .on('error', (error) => {
1086
+ console.error('\n[错误]', error);
1087
+ });
1088
+
1089
+ const finalMessage = await stream.finalMessage();
1090
+ return finalMessage;
1091
+ }
1092
+ ```
1093
+
1094
+ ### 8.3 交互式对话
1095
+
1096
+ ```typescript
1097
+ import * as readline from 'readline';
1098
+
1099
+ const rl = readline.createInterface({
1100
+ input: process.stdin,
1101
+ output: process.stdout
1102
+ });
1103
+
1104
+ async function askQuestion(query: string): Promise<string> {
1105
+ return new Promise(resolve => {
1106
+ rl.question(query, (answer) => {
1107
+ resolve(answer);
1108
+ });
1109
+ });
1110
+ }
1111
+
1112
+ async function interactiveChat() {
1113
+ const messages: Anthropic.MessageParam[] = [];
1114
+
1115
+ console.log('=== Closer Code 交互式对话 ===');
1116
+ console.log('输入 "quit" 退出\n');
1117
+
1118
+ while (true) {
1119
+ const userInput = await askQuestion('你: ');
1120
+
1121
+ if (userInput.toLowerCase() === 'quit') {
1122
+ break;
1123
+ }
1124
+
1125
+ messages.push({
1126
+ role: 'user',
1127
+ content: userInput
1128
+ });
1129
+
1130
+ const stream = client.messages.stream({
1131
+ model: 'claude-sonnet-4-5-20250929',
1132
+ max_tokens: 8192,
1133
+ messages
1134
+ })
1135
+ .on('text', (text) => {
1136
+ process.stdout.write(text);
1137
+ })
1138
+ .on('finalMessage', (msg) => {
1139
+ messages.push({
1140
+ role: 'assistant',
1141
+ content: msg.content
1142
+ });
1143
+ });
1144
+
1145
+ await stream.finalMessage();
1146
+ console.log('\n');
1147
+ }
1148
+
1149
+ rl.close();
1150
+ }
1151
+
1152
+ interactiveChat();
1153
+ ```
1154
+
1155
+ ### 8.4 智能代码审查助手(使用 Extended Thinking)
1156
+
1157
+ 这是一个展示如何使用 Extended Thinking 功能进行深度代码分析的完整示例:
1158
+
1159
+ ```typescript
1160
+ import Anthropic from '@anthropic-ai/sdk';
1161
+ import { betaZodTool } from '@anthropic-ai/sdk/helpers/beta/zod';
1162
+ import { z } from 'zod';
1163
+
1164
+ const client = new Anthropic({
1165
+ apiKey: process.env.ANTHROPIC_API_KEY
1166
+ });
1167
+
1168
+ // 定义代码分析工具
1169
+ const analyzeFileTool = betaZodTool({
1170
+ name: 'analyze_file',
1171
+ description: '读取并分析代码文件',
1172
+ inputSchema: z.object({
1173
+ filePath: z.string().describe('文件路径'),
1174
+ analysisType: z.enum(['security', 'performance', 'readability', 'all'])
1175
+ .describe('分析类型')
1176
+ }),
1177
+ run: async (input) => {
1178
+ const fs = await import('fs/promises');
1179
+ try {
1180
+ const content = await fs.readFile(input.filePath, 'utf-8');
1181
+ return {
1182
+ success: true,
1183
+ file: input.filePath,
1184
+ content: content.slice(0, 5000), // 限制长度
1185
+ analysisType: input.analysisType
1186
+ };
1187
+ } catch (error) {
1188
+ return {
1189
+ success: false,
1190
+ error: (error as Error).message
1191
+ };
1192
+ }
1193
+ }
1194
+ });
1195
+
1196
+ // 代码审查助手类
1197
+ class CodeReviewAssistant {
1198
+ private client: Anthropic;
1199
+ private model: string;
1200
+
1201
+ constructor() {
1202
+ this.client = new Anthropic({
1203
+ apiKey: process.env.ANTHROPIC_API_KEY
1204
+ });
1205
+ this.model = 'claude-sonnet-4-5-20250929';
1206
+ }
1207
+
1208
+ // 使用 Extended Thinking 进行深度分析
1209
+ async deepAnalysis(userRequest: string, complexity: 'low' | 'medium' | 'high' = 'high') {
1210
+ const thinkingBudgets = {
1211
+ low: 1024,
1212
+ medium: 2048,
1213
+ high: 4096
1214
+ };
1215
+
1216
+ console.log(`\n=== 开始深度分析 (Thinking Budget: ${thinkingBudgets[complexity]} tokens) ===\n`);
1217
+
1218
+ let thinkingState = 'not-started';
1219
+ let thinkingContent = '';
1220
+
1221
+ const stream = this.client.messages.stream({
1222
+ model: this.model,
1223
+ max_tokens: 8192,
1224
+ thinking: {
1225
+ type: 'enabled',
1226
+ budget_tokens: thinkingBudgets[complexity]
1227
+ },
1228
+ system: `你是一个专业的代码审查专家。当分析代码时,你会:
1229
+ 1. 仔细阅读并理解代码逻辑
1230
+ 2. 识别潜在的安全漏洞
1231
+ 3. 分析性能问题
1232
+ 4. 提出改进建议
1233
+ 5. 解释你的推理过程`,
1234
+ messages: [{ role: 'user', content: userRequest }],
1235
+ tools: [analyzeFileTool]
1236
+ })
1237
+ .on('thinking', (thinking) => {
1238
+ if (thinkingState === 'not-started') {
1239
+ console.log('🤔 深度思考中...\n---');
1240
+ thinkingState = 'started';
1241
+ }
1242
+ thinkingContent += thinking;
1243
+ process.stdout.write(thinking);
1244
+ })
1245
+ .on('text', (text) => {
1246
+ if (thinkingState !== 'finished') {
1247
+ console.log('\n\n---\n✅ 分析结果:\n---');
1248
+ thinkingState = 'finished';
1249
+ }
1250
+ process.stdout.write(text);
1251
+ })
1252
+ .on('toolUse', (toolUse) => {
1253
+ console.log('\n\n🔧 使用工具:', toolUse.name);
1254
+ console.log('参数:', JSON.stringify(toolUse.input, null, 2));
1255
+ })
1256
+ .on('error', (error) => {
1257
+ console.error('\n❌ 错误:', error);
1258
+ });
1259
+
1260
+ const finalMessage = await stream.finalMessage();
1261
+
1262
+ console.log('\n\n=== 分析完成 ===');
1263
+ console.log(`思考内容长度: ${thinkingContent.length} 字符`);
1264
+ console.log(`Token 使用: 输入=${finalMessage.usage.input_tokens}, 输出=${finalMessage.usage.output_tokens}`);
1265
+
1266
+ return {
1267
+ finalMessage,
1268
+ thinkingContent
1269
+ };
1270
+ }
1271
+
1272
+ // 快速分析(不使用 Extended Thinking)
1273
+ async quickAnalysis(userRequest: string) {
1274
+ console.log('\n=== 快速分析模式 ===\n');
1275
+
1276
+ const finalMessage = await this.client.beta.messages.toolRunner({
1277
+ model: this.model,
1278
+ max_tokens: 4096,
1279
+ system: '你是一个代码审查助手,快速检查代码问题。',
1280
+ messages: [{ role: 'user', content: userRequest }],
1281
+ tools: [analyzeFileTool]
1282
+ });
1283
+
1284
+ console.log('✅ 快速分析完成');
1285
+ console.log(`Token 使用: 输入=${finalMessage.usage.input_tokens}, 输出=${finalMessage.usage.output_tokens}`);
1286
+
1287
+ return finalMessage;
1288
+ }
1289
+ }
1290
+
1291
+ // 使用示例
1292
+ async function main() {
1293
+ const assistant = new CodeReviewAssistant();
1294
+
1295
+ // 示例 1: 深度分析复杂代码
1296
+ console.log('\n【示例 1: 深度安全分析】');
1297
+ await assistant.deepAnalysis(
1298
+ '请对 src/auth/login.ts 进行全面的安全分析,特别关注SQL注入、XSS和认证漏洞',
1299
+ 'high'
1300
+ );
1301
+
1302
+ // 等待用户输入
1303
+ await new Promise(resolve => setTimeout(resolve, 2000));
1304
+
1305
+ // 示例 2: 快速代码审查
1306
+ console.log('\n\n【示例 2: 快速代码审查】');
1307
+ await assistant.quickAnalysis('检查 src/utils/helpers.ts 中是否有明显的性能问题');
1308
+
1309
+ // 示例 3: 流式深度分析
1310
+ console.log('\n\n【示例 3: 架构设计分析】');
1311
+ const result = await assistant.deepAnalysis(
1312
+ '分析当前项目的架构设计,评估可扩展性和维护性,并提供重构建议',
1313
+ 'high'
1314
+ );
1315
+
1316
+ // 保存分析结果
1317
+ if (result.thinkingContent) {
1318
+ console.log('\n💡 提示: 思考过程已保存到 result.thinkingContent');
1319
+ }
1320
+ }
1321
+
1322
+ // 运行示例
1323
+ if (require.main === module) {
1324
+ main().catch(console.error);
1325
+ }
1326
+
1327
+ export { CodeReviewAssistant };
1328
+ ```
1329
+
1330
+ #### 实际运行效果
1331
+
1332
+ ```bash
1333
+ $ npm run code-review
1334
+
1335
+ === 开始深度分析 (Thinking Budget: 4096 tokens) ===
1336
+
1337
+ 🤔 深度思考中...
1338
+ ---
1339
+ 让我分析这段代码...
1340
+
1341
+ 首先,我需要理解认证流程:
1342
+ 1. 用户提交登录表单
1343
+ 2. 验证用户名和密码
1344
+ 3. 生成会话令牌
1345
+
1346
+ 在安全方面,我注意到:
1347
+ - 密码应该使用哈希存储
1348
+ - 需要防止暴力破解
1349
+ - 应该实现速率限制
1350
+
1351
+ 让我继续分析...
1352
+ ---
1353
+ ✅ 分析结果:
1354
+ ---
1355
+ 基于我的分析,我发现了以下安全问题:
1356
+
1357
+ 1. **SQL 注入风险**: 在第 45 行,查询字符串拼接存在风险...
1358
+ 2. **会话管理**: 建议使用 HTTP-only cookies...
1359
+ 3. **速率限制**: 建议添加登录尝试限制...
1360
+
1361
+ === 分析完成 ===
1362
+ 思考内容长度: 1243 字符
1363
+ Token 使用: 输入=3456, 输出=789
1364
+ ```
1365
+
1366
+ #### 关键特性
1367
+
1368
+ 1. **智能复杂度判断**: 根据问题类型自动调整 thinking budget
1369
+ 2. **实时反馈**: 流式展示思考过程,提升用户体验
1370
+ 3. **工具集成**: 结合文件读取工具进行实际分析
1371
+ 4. **成本优化**: 对简单问题使用快速分析模式
1372
+
1373
+ #### 使用建议
1374
+
1375
+ - **复杂任务**: 使用 `high` 复杂度和较大的 thinking budget (4096+)
1376
+ - **中等任务**: 使用 `medium` 复杂度 (2048 tokens)
1377
+ - **简单任务**: 考虑使用快速分析模式以节省成本
1378
+
1379
+ ---
1380
+
1381
+ 使用 `@anthropic-ai/sdk` 的核心优势:
1382
+
1383
+ 1. **代码量减少 70-80%**
1384
+ 2. **类型安全**:完整的 TypeScript 支持
1385
+ 3. **自动重试**:内置错误处理和重试逻辑
1386
+ 4. **流式响应简化**:无需手动解析 SSE
1387
+ 5. **工具执行自动化**:toolRunner 自动处理工具调用
1388
+ 6. **更好的性能**:优化的网络请求和缓存支持
1389
+ 7. **Extended Thinking 支持**:深度思考功能,解决复杂问题
1390
+ 8. **实时思考过程**:流式展示模型的推理过程
1391
+
1392
+ 开始迁移建议:
1393
+ - ✅ 从新功能开始使用 SDK
1394
+ - ✅ 保留旧代码以确保稳定性
1395
+ - ✅ 逐步迁移核心功能
1396
+ - ✅ 充分测试后完全切换
1397
+
1398
+ ---
1399
+
1400
+ **文档版本**: 1.1.0
1401
+ **最后更新**: 2025-01-18
1402
+ **维护者**: Closer Code 团队
1403
+
1404
+ **更新记录**:
1405
+ - v1.1.0 (2025-01-18): 新增 Extended Thinking 功能完整说明和示例
1406
+ - v1.0.0 (2025-01-17): 初始版本,涵盖基础 API 使用
1407
+
1408
+ **参考资源**:
1409
+ - [Anthropic TypeScript SDK 完整文档](../ref_repo/anthropic-sdk-typescript/api.md)
1410
+ - [Messages API 官方文档](https://docs.anthropic.com/claude/reference/messages-post)
1411
+ - [Closer Code 项目 README](./README.md)