closer-code 1.0.0 → 1.0.1

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 (99) hide show
  1. package/.closer-code.example.json +32 -0
  2. package/DUAL_OPTIMIZATION_COMPLETE.md +293 -0
  3. package/README.md +167 -557
  4. package/README_OPENAI.md +163 -0
  5. package/THINKING_THROTTLING_OPTIMIZATION.md +244 -0
  6. package/THROTTLING_1_5S_OPTIMIZATION.md +401 -0
  7. package/TOOLS_IMPROVEMENTS_SUMMARY.md +273 -0
  8. package/cloco.md +5 -1
  9. package/config.example.json +15 -94
  10. package/config.mcp.example.json +81 -0
  11. package/dist/bash-runner.js +5 -126
  12. package/dist/batch-cli.js +286 -20658
  13. package/dist/closer-cli.js +329 -21135
  14. package/dist/index.js +308 -31036
  15. package/docs/ANTHROPIC_TOOL_ERROR_HANDLING.md +220 -0
  16. package/docs/BUILD_COMMANDS.md +79 -0
  17. package/docs/CTRL_Z_SUPPORT.md +189 -0
  18. package/docs/DEEPSEEK_R1_INTEGRATION.md +427 -0
  19. package/docs/FIX_OPENAI_TOOL_ERROR_HANDLING.md +375 -0
  20. package/docs/FIX_OPENAI_TOOL_RESULT.md +198 -0
  21. package/docs/INPUT_ENHANCEMENTS.md +192 -0
  22. package/docs/MCP_IMPLEMENTATION_SUMMARY.md +428 -0
  23. package/docs/MCP_INTEGRATION.md +418 -0
  24. package/docs/MCP_QUICKSTART.md +299 -0
  25. package/docs/MCP_README.md +166 -0
  26. package/docs/MINIFY_BUILD.md +180 -0
  27. package/docs/MULTILINE_INPUT_FEATURE.md +119 -0
  28. package/docs/OPENAI_CLIENT.md +258 -0
  29. package/docs/PROJECT_LOCAL_CONFIG.md +471 -0
  30. package/docs/PROJECT_LOCAL_CONFIG_SUMMARY.md +407 -0
  31. package/docs/REFACTOR_CONVERSATION.md +306 -0
  32. package/docs/REGION_EDIT_DESIGN.md +475 -0
  33. package/docs/SIGNAL_HANDLING.md +171 -0
  34. package/docs/STREAM_UPDATE_THROTTLE.md +273 -0
  35. package/docs/TOOLS_REFACTOR_PLAN.md +520 -0
  36. package/ds_r1.md +249 -0
  37. package/examples/abort-fence-example.js +294 -0
  38. package/package.json +18 -4
  39. package/src/ai-client-legacy.js +6 -1
  40. package/src/ai-client-openai.js +672 -0
  41. package/src/ai-client.js +30 -13
  42. package/src/closer-cli.jsx +450 -162
  43. package/src/components/fullscreen-conversation.jsx +157 -0
  44. package/src/components/ink-text-input/index.jsx +324 -0
  45. package/src/components/multiline-text-input.jsx +614 -0
  46. package/src/components/progress-bar.jsx +135 -0
  47. package/src/components/tool-detail-view.jsx +82 -0
  48. package/src/components/tool-renderers/bash-renderer.jsx +197 -0
  49. package/src/components/tool-renderers/file-edit-renderer.jsx +247 -0
  50. package/src/components/tool-renderers/file-read-renderer.jsx +261 -0
  51. package/src/components/tool-renderers/file-write-renderer.jsx +222 -0
  52. package/src/components/tool-renderers/index.jsx +178 -0
  53. package/src/components/tool-renderers/list-renderer.jsx +274 -0
  54. package/src/components/tool-renderers/search-renderer.jsx +248 -0
  55. package/src/config.js +182 -20
  56. package/src/conversation/abort-fence.js +158 -0
  57. package/src/conversation/core.js +377 -0
  58. package/src/conversation/index.js +33 -0
  59. package/src/conversation/mcp-integration.js +96 -0
  60. package/src/conversation/plan-manager.js +295 -0
  61. package/src/conversation/stream-handler.js +154 -0
  62. package/src/conversation/tool-executor.js +264 -0
  63. package/src/conversation.js +23 -958
  64. package/src/hooks/use-throttled-state.js +158 -0
  65. package/src/input/enhanced-input.jsx +268 -0
  66. package/src/input/history.js +342 -0
  67. package/src/logger.js +20 -0
  68. package/src/mcp/client.js +275 -0
  69. package/src/mcp/tools-adapter.js +149 -0
  70. package/src/planner.js +18 -5
  71. package/src/prompt-builder.js +159 -0
  72. package/src/tools.js +457 -25
  73. package/src/utils/json-parser.js +231 -0
  74. package/src/utils/json-repair.js +146 -0
  75. package/src/utils/platform.js +259 -0
  76. package/test/test-ctrl-bf.js +121 -0
  77. package/test/test-deepseek-reasoning.js +118 -0
  78. package/test/test-history-navigation.js +80 -0
  79. package/test/test-input-fix.js +105 -0
  80. package/test/test-input-history.js +98 -0
  81. package/test/test-mcp.js +115 -0
  82. package/test/test-openai-client.js +152 -0
  83. package/test/test-openai-tool-result.js +199 -0
  84. package/test/test-project-config.js +106 -0
  85. package/test/test-shortcuts.js +79 -0
  86. package/test/test-stream-throttle.js +124 -0
  87. package/test/test-tool-error-handling.js +95 -0
  88. package/test/verify-input-fix.sh +35 -0
  89. package/test-abort-fence.js +263 -0
  90. package/test-abort-fix.js +54 -0
  91. package/test-abort-new-conversation.js +75 -0
  92. package/test-ctrl-z.js +54 -0
  93. package/test-file-read.js +105 -0
  94. package/test-tool-display.js +127 -0
  95. package/src/closer-cli.jsx.backup +0 -948
  96. package/test/workflows/longtalk/cloco.md +0 -19
  97. package/test/workflows/longtalk/emoji_500.txt +0 -63
  98. package/test/workflows/longtalk/emoji_list.txt +0 -20
  99. package/test-ctrl-c.jsx +0 -126
@@ -0,0 +1,163 @@
1
+ # OpenAI 客户端快速开始指南
2
+
3
+ ## 安装
4
+
5
+ ```bash
6
+ npm install
7
+ ```
8
+
9
+ **注意**: 由于 `@openai/agents` 与 `zod@3.25.68+` 的兼容性问题,安装时使用了 `--legacy-peer-deps` 选项。
10
+
11
+ ## 配置
12
+
13
+ ### 方式 1: 环境变量
14
+
15
+ ```bash
16
+ export OPENAI_API_KEY=sk-your_api_key_here
17
+ ```
18
+
19
+ ### 方式 2: 配置文件
20
+
21
+ 创建或编辑 `~/.closer-code/config.json`:
22
+
23
+ ```json
24
+ {
25
+ "ai": {
26
+ "provider": "openai",
27
+ "openai": {
28
+ "apiKey": "sk-your_api_key_here",
29
+ "baseURL": "https://api.openai.com/v1",
30
+ "model": "gpt-4o",
31
+ "maxTokens": 8192
32
+ }
33
+ }
34
+ }
35
+ ```
36
+
37
+ ## 使用
38
+
39
+ ### 基础对话
40
+
41
+ ```bash
42
+ # 启动 CLI
43
+ closer
44
+
45
+ # 或者
46
+ node dist/index.js
47
+ ```
48
+
49
+ ### 代码示例
50
+
51
+ ```javascript
52
+ import { createAIClient } from './src/ai-client.js';
53
+
54
+ const config = {
55
+ ai: {
56
+ provider: 'openai',
57
+ openai: {
58
+ apiKey: 'sk-your_api_key_here',
59
+ model: 'gpt-4o',
60
+ maxTokens: 8192
61
+ }
62
+ }
63
+ };
64
+
65
+ const client = createAIClient(config);
66
+
67
+ // 简单对话
68
+ const response = await client.chat(
69
+ [{ role: 'user', content: 'Hello, OpenAI!' }],
70
+ { temperature: 0.7 }
71
+ );
72
+
73
+ console.log(response.content);
74
+ ```
75
+
76
+ ### 使用工具
77
+
78
+ ```javascript
79
+ import { bashTool, readFileTool } from './src/tools.js';
80
+
81
+ const result = await client.chatWithTools(
82
+ [{ role: 'user', content: 'List files in current directory' }],
83
+ [bashTool, readFileTool],
84
+ { temperature: 0.7 }
85
+ );
86
+ ```
87
+
88
+ ### 流式响应
89
+
90
+ ```javascript
91
+ await client.chatStream(
92
+ [{ role: 'user', content: 'Tell me a story' }],
93
+ {},
94
+ (chunk) => {
95
+ if (chunk.type === 'text') {
96
+ process.stdout.write(chunk.delta);
97
+ }
98
+ }
99
+ );
100
+ ```
101
+
102
+ ## 测试
103
+
104
+ ```bash
105
+ # 运行测试
106
+ export OPENAI_API_KEY=your_key
107
+ node test/test-openai-client.js
108
+ ```
109
+
110
+ ## 切换 Provider
111
+
112
+ 在配置文件中更改 `provider` 字段即可在 Anthropic 和 OpenAI 之间切换:
113
+
114
+ ```json
115
+ {
116
+ "ai": {
117
+ "provider": "anthropic", // 或 "openai"
118
+ "anthropic": {
119
+ "apiKey": "sk-ant-..."
120
+ },
121
+ "openai": {
122
+ "apiKey": "sk-..."
123
+ }
124
+ }
125
+ }
126
+ ```
127
+
128
+ ## 支持的模型
129
+
130
+ ### OpenAI
131
+ - `gpt-4o` (推荐)
132
+ - `gpt-4o-mini`
133
+ - `gpt-4-turbo`
134
+ - `gpt-3.5-turbo`
135
+
136
+ ### Anthropic
137
+ - `claude-sonnet-4-5-20250929` (推荐)
138
+ - `claude-opus-4-5-20251101`
139
+ - `claude-haiku-4-5-20251101`
140
+
141
+ ## 常见问题
142
+
143
+ ### 1. 安装失败
144
+
145
+ 如果遇到 zod 版本冲突,使用:
146
+
147
+ ```bash
148
+ npm install --legacy-peer-deps
149
+ ```
150
+
151
+ ### 2. API 密钥错误
152
+
153
+ 确保设置了正确的环境变量或配置文件中的 API 密钥。
154
+
155
+ ### 3. 模型不存在
156
+
157
+ 检查配置文件中的 `model` 字段是否为您有权限访问的模型。
158
+
159
+ ## 更多信息
160
+
161
+ - [详细实现文档](./docs/OPENAI_CLIENT.md)
162
+ - [实现总结](./IMPLEMENTATION_SUMMARY.md)
163
+ - [OpenAI Agents SDK 文档](https://www.npmjs.com/package/@openai/agents)
@@ -0,0 +1,244 @@
1
+ # Thinking 区域更新优化方案
2
+
3
+ ## 📊 问题分析
4
+
5
+ ### 当前问题
6
+
7
+ Thinking 区域的更新频率远高于 Conversation 区域,导致性能问题:
8
+
9
+ | 区域 | 触发频率 | 更新内容 | 性能影响 |
10
+ |------|----------|----------|----------|
11
+ | **Conversation** | 低频(token 生成) | 完整的 token 内容 | 较小 |
12
+ | **Thinking** | **高频**(thinking delta) | **逐字符/逐词增量** | **较大** |
13
+
14
+ ### 性能影响
15
+
16
+ 每次 Thinking 更新都会触发:
17
+ 1. **重新格式化**:`formatThinkingAsLines()` 处理所有 thinking 行
18
+ 2. **重新计算滚动**:计算滚动位置和可见范围
19
+ 3. **重新渲染**:React 重新渲染整个区域
20
+
21
+ ### 数据对比
22
+
23
+ 假设 AI 生成一个 1000 字符的 thinking 内容:
24
+
25
+ - **Conversation**:约 250 次 token 更新(假设平均 4 字符/token)
26
+ - **Thinking**:约 1000 次 delta 更新(逐字符)
27
+
28
+ **Thinking 的更新频率是 Conversation 的 4 倍!**
29
+
30
+ ## ✅ 解决方案
31
+
32
+ ### 方案 1:使用 Throttling Hook(推荐)
33
+
34
+ 使用 `useSmartThrottledState` Hook 来优化 Thinking 区域的更新。
35
+
36
+ #### 实施步骤
37
+
38
+ 1. **导入 Hook**
39
+ ```javascript
40
+ import { useSmartThrottledState } from './hooks/use-throttled-state.js';
41
+ ```
42
+
43
+ 2. **创建带节流的更新函数**
44
+ ```javascript
45
+ const [thinking, setThinking] = useState([]);
46
+ const { updateSmart } = useSmartThrottledState(setThinking, {
47
+ throttleDelay: 50, // 节流延迟 50ms
48
+ immediateTypes: ['tool_start', 'tool_complete', 'thinking_signature', 'thinking_redacted']
49
+ });
50
+ ```
51
+
52
+ 3. **在 progress 回调中使用**
53
+ ```javascript
54
+ // 原代码
55
+ if (progress.type === 'thinking') {
56
+ setThinking(prev => [...prev, ...]);
57
+ }
58
+
59
+ // 优化后
60
+ if (progress.type === 'thinking') {
61
+ updateSmart(newThinking, 'thinking');
62
+ } else if (progress.type === 'tool_start') {
63
+ updateSmart(newThinking, 'tool_start');
64
+ }
65
+ ```
66
+
67
+ #### 优化效果
68
+
69
+ - **减少渲染次数**:从 1000 次降低到约 20 次(50ms 节流)
70
+ - **保持响应性**:重要事件(如工具调用)仍然立即更新
71
+ - **用户体验**:几乎无感知,因为 50ms 的延迟人眼无法察觉
72
+
73
+ ### 方案 2:增加 Delta 阈值
74
+
75
+ 只有当累积的 delta 达到一定长度时才更新。
76
+
77
+ #### 实施步骤
78
+
79
+ 1. **添加累积缓冲区**
80
+ ```javascript
81
+ const thinkingBufferRef = useRef('');
82
+ const lastThinkingUpdateRef = useRef(0);
83
+
84
+ if (progress.type === 'thinking') {
85
+ const delta = progress.delta || '';
86
+ thinkingBufferRef.current += delta;
87
+
88
+ // 只有当累积超过 20 个字符或超过 100ms 时才更新
89
+ const now = Date.now();
90
+ if (thinkingBufferRef.current.length > 20 ||
91
+ now - lastThinkingUpdateRef.current > 100) {
92
+ setThinking(prev => {
93
+ // 使用累积的 delta
94
+ const newThinking = [...prev];
95
+ // ... 更新逻辑
96
+ return newThinking;
97
+ });
98
+
99
+ thinkingBufferRef.current = '';
100
+ lastThinkingUpdateRef.current = now;
101
+ }
102
+ }
103
+ ```
104
+
105
+ #### 优化效果
106
+
107
+ - **减少更新次数**:从 1000 次降低到约 50 次(20 字符阈值)
108
+ - **保持完整性**:最终内容完全一致
109
+ - **实现简单**:不需要额外的 Hook
110
+
111
+ ### 方案 3:使用 requestAnimationFrame
112
+
113
+ 利用浏览器的 `requestAnimationFrame` 来优化更新时机。
114
+
115
+ #### 实施步骤
116
+
117
+ ```javascript
118
+ const rafRef = useRef(null);
119
+ const pendingThinkingRef = useRef(null);
120
+
121
+ if (progress.type === 'thinking') {
122
+ pendingThinkingRef.current = newThinking;
123
+
124
+ if (!rafRef.current) {
125
+ rafRef.current = requestAnimationFrame(() => {
126
+ if (pendingThinkingRef.current) {
127
+ setThinking(pendingThinkingRef.current);
128
+ pendingThinkingRef.current = null;
129
+ }
130
+ rafRef.current = null;
131
+ });
132
+ }
133
+ }
134
+ ```
135
+
136
+ #### 优化效果
137
+
138
+ - **与屏幕刷新率同步**:通常 60fps,即 16.67ms 更新一次
139
+ - **平滑更新**:避免卡顿
140
+ - **浏览器优化**:浏览器会自动优化渲染时机
141
+
142
+ ## 📊 方案对比
143
+
144
+ | 方案 | 优点 | 缺点 | 推荐度 |
145
+ |------|------|------|--------|
146
+ | **Throttling Hook** | 灵活、可控、易用 | 需要额外代码 | ⭐⭐⭐⭐⭐ |
147
+ | **Delta 阈值** | 简单、无需 Hook | 可能丢失部分中间状态 | ⭐⭐⭐⭐ |
148
+ | **requestAnimationFrame** | 与屏幕同步 | Node.js 环境不适用 | ⭐⭐⭐ |
149
+
150
+ ## 🚀 推荐实施方案
151
+
152
+ ### 组合方案:Throttling + Delta 阈值
153
+
154
+ 结合两种方案,获得最佳性能:
155
+
156
+ ```javascript
157
+ const [thinking, setThinking] = useState([]);
158
+ const { updateSmart } = useSmartThrottledState(setThinking, {
159
+ throttleDelay: 50,
160
+ immediateTypes: ['tool_start', 'tool_complete', 'thinking_signature', 'thinking_redacted']
161
+ });
162
+
163
+ const thinkingBufferRef = useRef('');
164
+ const lastThinkingUpdateRef = useRef(0);
165
+
166
+ if (progress.type === 'thinking') {
167
+ const delta = progress.delta || '';
168
+ thinkingBufferRef.current += delta;
169
+
170
+ const now = Date.now();
171
+ const accumulatedDelta = thinkingBufferRef.current;
172
+
173
+ // 只有当累积超过 10 个字符或超过 50ms 时才更新
174
+ if (accumulatedDelta.length > 10 || now - lastThinkingUpdateRef.current > 50) {
175
+ setThinking(prev => {
176
+ const newThinking = [...prev];
177
+ // 使用累积的 delta
178
+ const lastEntry = newThinking[newThinking.length - 1];
179
+ if (lastEntry && lastEntry.startsWith('🤔') && !lastEntry.includes('✅')) {
180
+ const timestamp = lastEntry.match(/\[.*?\]/)[0];
181
+ const currentContent = lastEntry.substring(lastEntry.indexOf('] ') + 2);
182
+ newThinking[newThinking.length - 1] = `🤔 ${timestamp} ${currentContent}${accumulatedDelta}`;
183
+ } else {
184
+ const timestamp = `[${new Date().toLocaleTimeString()}]`;
185
+ newThinking.push(`🤔 ${timestamp} ${accumulatedDelta}`);
186
+ }
187
+ return newThinking.slice(-30);
188
+ });
189
+
190
+ thinkingBufferRef.current = '';
191
+ lastThinkingUpdateRef.current = now;
192
+ }
193
+ } else {
194
+ // 其他类型的事件使用 updateSmart
195
+ updateSmart(newThinking, progress.type);
196
+ }
197
+ ```
198
+
199
+ ### 优化效果预估
200
+
201
+ 假设一个 1000 字符的 thinking 内容:
202
+
203
+ | 方案 | 更新次数 | 渲染次数 | 性能提升 |
204
+ |------|----------|----------|----------|
205
+ | **原始** | 1000 | 1000 | - |
206
+ | **仅 Throttling** | 1000 | ~20 | 98% ↓ |
207
+ | **仅 Delta 阈值** | 1000 | ~50 | 95% ↓ |
208
+ | **组合方案** | 1000 | ~10 | 99% ↓ |
209
+
210
+ ## 📝 实施清单
211
+
212
+ - [ ] 创建 `src/hooks/use-throttled-state.js`
213
+ - [ ] 在 `src/closer-cli.jsx` 中导入 Hook
214
+ - [ ] 修改 thinking 更新逻辑
215
+ - [ ] 测试验证
216
+ - [ ] 性能对比
217
+
218
+ ## 🎯 预期结果
219
+
220
+ ### 性能提升
221
+
222
+ - **渲染次数减少**:99%
223
+ - **CPU 使用降低**:约 80-90%
224
+ - **内存使用降低**:约 50%(减少临时对象创建)
225
+ - **用户体验提升**:更流畅,无明显卡顿
226
+
227
+ ### 兼容性
228
+
229
+ - ✅ 完全向后兼容
230
+ - ✅ 不影响功能
231
+ - ✅ 不影响最终显示内容
232
+ - ✅ 可配置的延迟参数
233
+
234
+ ## 📚 参考资料
235
+
236
+ - [React Performance Optimization](https://react.dev/learn/render-and-commit)
237
+ - [Throttling and Debouncing](https://www.freecodecamp.org/news/javascript-throttle-vs-debounce/)
238
+ - [requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame)
239
+
240
+ ---
241
+
242
+ **文档日期**: 2025年1月
243
+ **版本**: 1.0
244
+ **状态**: 📋 方案设计完成