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.
- package/.env.example +83 -0
- package/API_GUIDE.md +1411 -0
- package/AUTO_MKDIR_IMPROVEMENT.md +354 -0
- package/CLAUDE.md +55 -0
- package/CTRL_C_EXPERIMENT.md +90 -0
- package/PROJECT_CLEANUP_SUMMARY.md +121 -0
- package/README.md +686 -0
- package/cloco.md +51 -0
- package/config.example.json +116 -0
- package/dist/bash-runner.js +128 -0
- package/dist/batch-cli.js +20736 -0
- package/dist/closer-cli.js +21190 -0
- package/dist/index.js +31228 -0
- package/docs/EXPORT_COMMAND.md +152 -0
- package/docs/FILE_NAMING_IMPROVEMENT.md +168 -0
- package/docs/GLOBAL_CONFIG.md +128 -0
- package/docs/LONG_MESSAGE_DISPLAY_FIX.md +202 -0
- package/docs/PROJECT_HISTORY_ISOLATION.md +315 -0
- package/docs/QUICK_START_HISTORY.md +207 -0
- package/docs/TASK_PROGRESS_FEATURE.md +190 -0
- package/docs/THINKING_CONTENT_RESEARCH.md +267 -0
- package/docs/THINKING_FEATURE.md +187 -0
- package/docs/THINKING_IMPROVEMENT_COMPARISON.md +193 -0
- package/docs/THINKING_OPTIMIZATION_SUMMARY.md +242 -0
- package/docs/UI_IMPROVEMENTS_2025-01-18.md +256 -0
- package/docs/WHY_THINKING_SHORT.md +201 -0
- package/package.json +49 -0
- package/scenarios/README.md +234 -0
- package/scenarios/run-all-scenarios.js +342 -0
- package/scenarios/scenario1-batch-converter.js +247 -0
- package/scenarios/scenario2-code-analyzer.js +375 -0
- package/scenarios/scenario3-doc-generator.js +371 -0
- package/scenarios/scenario4-log-analyzer.js +496 -0
- package/scenarios/scenario5-tdd-helper.js +681 -0
- package/src/ai-client-legacy.js +171 -0
- package/src/ai-client.js +221 -0
- package/src/bash-runner.js +148 -0
- package/src/batch-cli.js +327 -0
- package/src/cli.jsx +166 -0
- package/src/closer-cli.jsx +1103 -0
- package/src/closer-cli.jsx.backup +948 -0
- package/src/commands/batch.js +62 -0
- package/src/commands/chat.js +10 -0
- package/src/commands/config.js +154 -0
- package/src/commands/help.js +76 -0
- package/src/commands/history.js +192 -0
- package/src/commands/setup.js +17 -0
- package/src/commands/upgrade.js +101 -0
- package/src/commands/workflow-tests.js +125 -0
- package/src/config.js +343 -0
- package/src/conversation.js +962 -0
- package/src/git-helper.js +349 -0
- package/src/index.js +88 -0
- package/src/logger.js +347 -0
- package/src/plan.js +193 -0
- package/src/planner.js +397 -0
- package/src/search.js +195 -0
- package/src/setup.js +147 -0
- package/src/shortcuts.js +269 -0
- package/src/snippets.js +430 -0
- package/src/test-modules.js +118 -0
- package/src/tools.js +398 -0
- package/src/utils/cli.js +124 -0
- package/src/utils/validator.js +184 -0
- package/src/utils/version.js +33 -0
- package/src/utils/workflow-test.js +271 -0
- package/src/utils/workflow.js +268 -0
- package/test/demo-file-naming.js +92 -0
- package/test/demo-thinking.js +124 -0
- package/test/final-verification-report.md +303 -0
- package/test/research-thinking.js +130 -0
- package/test/test-auto-mkdir.js +123 -0
- package/test/test-e2e-empty-dir.md +108 -0
- package/test/test-export-logic.js +119 -0
- package/test/test-global-cloco.js +126 -0
- package/test/test-history-isolation.js +291 -0
- package/test/test-improved-thinking.js +43 -0
- package/test/test-long-message.js +65 -0
- package/test/test-plan-functionality.js +95 -0
- package/test/test-real-scenario.js +216 -0
- package/test/test-thinking-display.js +65 -0
- package/test/ui-verification-test.js +203 -0
- package/test/verify-history-isolation.sh +71 -0
- package/test/verify-thinking.js +339 -0
- package/test/workflows/empty-dir-creation.md +51 -0
- package/test/workflows/inventor/ascii-teacup.js +199 -0
- package/test/workflows/inventor/ascii-teacup.mjs +199 -0
- package/test/workflows/inventor/ascii_apple.hs +84 -0
- package/test/workflows/inventor/ascii_apple.py +91 -0
- package/test/workflows/inventor/cloco.md +3 -0
- package/test/workflows/longtalk/cloco.md +19 -0
- package/test/workflows/longtalk/emoji_500.txt +63 -0
- package/test/workflows/longtalk/emoji_list.txt +20 -0
- package/test/workflows/programmer/adder.md +33 -0
- package/test/workflows/programmer/expect.md +2 -0
- package/test/workflows/programmer/prompt.md +3 -0
- package/test/workflows/test-empty-dir-creation.js +113 -0
- package/test-ctrl-c.jsx +126 -0
- package/test-manual-file-creation.js +151 -0
- package/winfix.md +3 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# /export 命令使用说明
|
|
2
|
+
|
|
3
|
+
## 功能描述
|
|
4
|
+
|
|
5
|
+
`/export` 命令用于将当前对话历史导出为文本文件,方便保存和分享对话内容。
|
|
6
|
+
|
|
7
|
+
## 使用方法
|
|
8
|
+
|
|
9
|
+
### 基本用法
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
/export <filename>
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### 示例
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# 导出对话到 my-conversation.txt
|
|
19
|
+
/export my-conversation
|
|
20
|
+
|
|
21
|
+
# 导出对话到 chat-2024-01-18.txt(会自动添加 .txt 扩展名)
|
|
22
|
+
/export chat-2024-01-18
|
|
23
|
+
|
|
24
|
+
# 如果文件名已包含 .txt 扩展名,则不会重复添加
|
|
25
|
+
/export conversation.txt
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 导出格式
|
|
29
|
+
|
|
30
|
+
导出的文本文件包含以下内容:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
================================================================================
|
|
34
|
+
Closer Code - Conversation Export
|
|
35
|
+
================================================================================
|
|
36
|
+
Export Date: 2024-01-18 14:30:00
|
|
37
|
+
Total Messages: 15
|
|
38
|
+
================================================================================
|
|
39
|
+
|
|
40
|
+
[1] 👤 User
|
|
41
|
+
--------------------------------------------------------------------------------
|
|
42
|
+
你好,请帮我写一个 Python 脚本
|
|
43
|
+
|
|
44
|
+
[2] 🤖 Assistant
|
|
45
|
+
--------------------------------------------------------------------------------
|
|
46
|
+
好的,我来帮你写一个 Python 脚本。请告诉我你需要什么功能...
|
|
47
|
+
|
|
48
|
+
[3] 👤 User
|
|
49
|
+
--------------------------------------------------------------------------------
|
|
50
|
+
需要一个读取 CSV 文件的脚本
|
|
51
|
+
|
|
52
|
+
...
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 特性
|
|
56
|
+
|
|
57
|
+
- ✅ 自动添加 `.txt` 扩展名(如果未指定)
|
|
58
|
+
- ✅ 包含导出日期和消息统计
|
|
59
|
+
- ✅ 清晰的消息分隔符
|
|
60
|
+
- ✅ 支持用户、助手、系统消息
|
|
61
|
+
- ✅ 支持工具调用和结果显示
|
|
62
|
+
- ✅ UTF-8 编码,支持中文
|
|
63
|
+
|
|
64
|
+
## 注意事项
|
|
65
|
+
|
|
66
|
+
1. 文件会保存在当前工作目录
|
|
67
|
+
2. 如果文件已存在,会被覆盖
|
|
68
|
+
3. 导出的是当前会话的所有对话历史
|
|
69
|
+
4. 包括从历史记录中加载的旧对话
|
|
70
|
+
|
|
71
|
+
## 完整命令列表
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
/clear - 清除对话历史
|
|
75
|
+
/export <filename> - 导出对话到文本文件
|
|
76
|
+
/plan <task> - 创建并执行任务计划
|
|
77
|
+
/learn - 学习项目模式
|
|
78
|
+
/status - 显示对话统计
|
|
79
|
+
/help - 显示帮助信息
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## 快捷键
|
|
83
|
+
|
|
84
|
+
- `Ctrl+C` (双击) - 退出程序
|
|
85
|
+
- `ESC` - 同双击 Ctrl+C
|
|
86
|
+
- `↑/↓` - 滚动查看历史消息
|
|
87
|
+
- `Page Up/Down` - 快速滚动
|
|
88
|
+
- `Enter` - 回到底部
|
|
89
|
+
|
|
90
|
+
## 示例场景
|
|
91
|
+
|
|
92
|
+
### 场景1:保存重要的对话
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
你: /export api-design-discussion
|
|
96
|
+
系统: ✅ Conversation exported to: api-design-discussion.txt
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 场景2:导出调试会话
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
你: /export debug-session-$(date +%Y%m%d)
|
|
103
|
+
系统: ✅ Conversation exported to: debug-session-20240118.txt
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 场景3:备份对话历史
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
你: /export conversation-backup-before-clear
|
|
110
|
+
系统: ✅ Conversation exported to: conversation-backup-before-clear.txt
|
|
111
|
+
你: /clear
|
|
112
|
+
系统: 🗑️ 清除对话历史...
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## 技术细节
|
|
116
|
+
|
|
117
|
+
### 实现位置
|
|
118
|
+
|
|
119
|
+
- 命令处理:`src/closer-cli.jsx` 中的 `handleCommand` 函数
|
|
120
|
+
- 导出逻辑:`exportConversation` 函数
|
|
121
|
+
|
|
122
|
+
### 支持的消息类型
|
|
123
|
+
|
|
124
|
+
- `user` - 用户消息(👤)
|
|
125
|
+
- `assistant` - AI 助手消息(🤖)
|
|
126
|
+
- `system` - 系统消息(ℹ️)
|
|
127
|
+
- `error` - 错误消息(❌)
|
|
128
|
+
|
|
129
|
+
### 复杂内容处理
|
|
130
|
+
|
|
131
|
+
对于包含工具调用的消息,导出时会格式化为:
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
[Tool: bash]
|
|
135
|
+
{
|
|
136
|
+
"command": "ls -la"
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
[Tool Result]
|
|
140
|
+
total 16
|
|
141
|
+
drwxr-xr-x 4 user staff 128 Jan 18 14:30 .
|
|
142
|
+
...
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## 未来改进
|
|
146
|
+
|
|
147
|
+
可能的增强功能:
|
|
148
|
+
- 支持更多导出格式(Markdown、JSON、HTML)
|
|
149
|
+
- 添加过滤选项(按日期、关键词)
|
|
150
|
+
- 支持导出部分消息(指定范围)
|
|
151
|
+
- 添加导出预览功能
|
|
152
|
+
- 支持批量导出多个项目
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# 文件命名改进说明
|
|
2
|
+
|
|
3
|
+
## 改进内容
|
|
4
|
+
|
|
5
|
+
### 之前的问题
|
|
6
|
+
只用哈希值命名文件,虽然保证了唯一性,但不便于人类查阅:
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
❌ 旧命名: 06aecb89a562f1a6038cca327538315e.json
|
|
10
|
+
❌ 旧命名: e902bcc2a63d1efb2d3c879517a255a3.json
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
当你在 `~/.closer-code/history/` 目录下查看文件时,无法直接知道哪个文件对应哪个项目。
|
|
14
|
+
|
|
15
|
+
### 改进后的方案
|
|
16
|
+
在哈希值后面加上目录名,既保证唯一性又便于识别:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
✅ 新命名: 06aecb89a562f1a6038cca327538315e-project-beta.json
|
|
20
|
+
✅ 新命名: f5617862fb3ca8fbbc2f3ff26b106cf6-my-awesome-app.json
|
|
21
|
+
✅ 新命名: aed557b877e451758c55c4d3f7306497-api-server.json
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 命名规则
|
|
25
|
+
|
|
26
|
+
### 格式
|
|
27
|
+
```
|
|
28
|
+
{md5-hash}-{directory-name}.json
|
|
29
|
+
{md5-hash}-{directory-name}.meta.json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 组成部分
|
|
33
|
+
|
|
34
|
+
1. **MD5哈希前缀** (32个字符)
|
|
35
|
+
- 基于完整项目路径生成
|
|
36
|
+
- 确保文件名唯一性
|
|
37
|
+
- 避免路径冲突
|
|
38
|
+
|
|
39
|
+
2. **目录名后缀**
|
|
40
|
+
- 提取项目路径的最后一级目录名
|
|
41
|
+
- 便于人类识别和查阅
|
|
42
|
+
- 特殊字符自动处理
|
|
43
|
+
|
|
44
|
+
3. **特殊字符处理**
|
|
45
|
+
- 非字母数字字符替换为下划线
|
|
46
|
+
- 例如:`data.processor` → `data_processor`
|
|
47
|
+
|
|
48
|
+
## 实际示例
|
|
49
|
+
|
|
50
|
+
### 示例1: 简单项目名
|
|
51
|
+
```
|
|
52
|
+
项目路径: /home/user/project-alpha
|
|
53
|
+
文件名: 90e42e971156247007484e3a455f62ed-project-alpha.json
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 示例2: 带连字符的项目名
|
|
57
|
+
```
|
|
58
|
+
项目路径: /home/user/my-awesome-app
|
|
59
|
+
文件名: f5617862fb3ca8fbbc2f3ff26b106cf6-my-awesome-app.json
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 示例3: 带点号的项目名
|
|
63
|
+
```
|
|
64
|
+
项目路径: /home/user/data.processor
|
|
65
|
+
文件名: d8af9338aa986877bcea3aa9d4c1e915-data_processor.json
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 示例4: Windows路径
|
|
69
|
+
```
|
|
70
|
+
项目路径: S:\bld\opencode\closer_code
|
|
71
|
+
文件名: 83545f14f3db2e01ee2669719bc705fe-closer_code.json
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## 优势对比
|
|
75
|
+
|
|
76
|
+
| 特性 | 旧方案 | 新方案 |
|
|
77
|
+
|------|--------|--------|
|
|
78
|
+
| 唯一性 | ✅ | ✅ |
|
|
79
|
+
| 可读性 | ❌ | ✅ |
|
|
80
|
+
| 可识别性 | ❌ | ✅ |
|
|
81
|
+
| 特殊字符处理 | ✅ | ✅ |
|
|
82
|
+
| 查阅便利性 | ❌ 需要查看元数据 | ✅ 直接从文件名识别 |
|
|
83
|
+
|
|
84
|
+
## 使用场景
|
|
85
|
+
|
|
86
|
+
### 场景1: 手动查看历史文件
|
|
87
|
+
```bash
|
|
88
|
+
# 列出历史目录
|
|
89
|
+
ls ~/.closer-code/history/
|
|
90
|
+
|
|
91
|
+
# 输出:
|
|
92
|
+
# 06aecb89a562f1a6038cca327538315e-project-beta.json
|
|
93
|
+
# f5617862fb3ca8fbbc2f3ff26b106cf6-my-awesome-app.json
|
|
94
|
+
# aed557b877e451758c55c4d3f7306497-api-server.json
|
|
95
|
+
|
|
96
|
+
# 现在可以直接看出每个文件对应的项目!
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 场景2: 备份特定项目历史
|
|
100
|
+
```bash
|
|
101
|
+
# 备份 my-awesome-app 项目
|
|
102
|
+
cp ~/.closer-code/history/*-my-awesome-app.* ~/backup/
|
|
103
|
+
|
|
104
|
+
# 旧方案需要先查看元数据才知道哪个文件是哪个项目
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 场景3: 清理特定项目历史
|
|
108
|
+
```bash
|
|
109
|
+
# 删除 api-server 项目历史
|
|
110
|
+
rm ~/.closer-code/history/*-api-server.*
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## 技术实现
|
|
114
|
+
|
|
115
|
+
### 代码片段 (src/config.js)
|
|
116
|
+
```javascript
|
|
117
|
+
function getProjectHistoryPath(projectPath) {
|
|
118
|
+
const normalizedPath = path.normalize(projectPath);
|
|
119
|
+
const hash = crypto.createHash('md5').update(normalizedPath).digest('hex');
|
|
120
|
+
const dirName = path.basename(normalizedPath);
|
|
121
|
+
const cleanDirName = dirName.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
122
|
+
return path.join(HISTORY_DIR, `${hash}-${cleanDirName}.json`);
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 关键点
|
|
127
|
+
1. `path.basename()` - 提取最后一级目录名
|
|
128
|
+
2. `replace(/[^a-zA-Z0-9_-]/g, '_')` - 清理特殊字符
|
|
129
|
+
3. 保留哈希前缀 - 确保唯一性
|
|
130
|
+
|
|
131
|
+
## 向后兼容
|
|
132
|
+
|
|
133
|
+
### 旧文件处理
|
|
134
|
+
如果你有旧版本的哈希文件(不带目录名),系统会:
|
|
135
|
+
1. 继续读取旧文件(向后兼容)
|
|
136
|
+
2. 新保存的文件使用新格式
|
|
137
|
+
3. 建议运行迁移工具统一格式
|
|
138
|
+
|
|
139
|
+
### 迁移建议
|
|
140
|
+
```bash
|
|
141
|
+
# 旧文件会继续工作
|
|
142
|
+
# 新文件使用改进的命名
|
|
143
|
+
# 无需立即迁移,可以逐步过渡
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## 常见问题
|
|
147
|
+
|
|
148
|
+
**Q: 为什么保留哈希值?**
|
|
149
|
+
A: 哈希值确保唯一性,避免不同路径但相同目录名导致的冲突。
|
|
150
|
+
|
|
151
|
+
**Q: 目录名太长怎么办?**
|
|
152
|
+
A: 文件系统通常支持长文件名(255字符),目录名一般不会超过限制。
|
|
153
|
+
|
|
154
|
+
**Q: 特殊字符会被如何处理?**
|
|
155
|
+
A: 非字母数字字符(除了 `-` 和 `_`)会被替换为下划线。
|
|
156
|
+
|
|
157
|
+
**Q: 如何查看完整的项目路径?**
|
|
158
|
+
A: 查看 `.meta.json` 文件,其中包含完整的原始路径。
|
|
159
|
+
|
|
160
|
+
## 总结
|
|
161
|
+
|
|
162
|
+
这个改进在保持技术优势(唯一性、安全性)的同时,大大提升了用户体验(可读性、可识别性),是一个简单但有效的改进!
|
|
163
|
+
|
|
164
|
+
**核心原则**:
|
|
165
|
+
- ✅ 机器可读(哈希前缀)
|
|
166
|
+
- ✅ 人类可读(目录名后缀)
|
|
167
|
+
- ✅ 安全可靠(特殊字符处理)
|
|
168
|
+
- ✅ 向后兼容(旧文件仍可用)
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# 全局配置功能说明
|
|
2
|
+
|
|
3
|
+
## 功能概述
|
|
4
|
+
|
|
5
|
+
Closer Code 现在支持全局行为规范配置,允许你在所有项目中共享统一的行为规范。
|
|
6
|
+
|
|
7
|
+
## 配置文件位置
|
|
8
|
+
|
|
9
|
+
### 全局配置
|
|
10
|
+
- **路径**: `~/.closer-code/cloco.md`
|
|
11
|
+
- **作用域**: 所有 Closer Code 项目
|
|
12
|
+
- **优先级**: 低于项目级配置
|
|
13
|
+
|
|
14
|
+
### 项目配置
|
|
15
|
+
- **路径**: `./cloco.md`(项目根目录)
|
|
16
|
+
- **作用域**: 当前项目
|
|
17
|
+
- **优先级**: 高于全局配置
|
|
18
|
+
|
|
19
|
+
## 工作原理
|
|
20
|
+
|
|
21
|
+
当启动 Closer Code 时:
|
|
22
|
+
|
|
23
|
+
1. **读取全局配置**(如果存在)
|
|
24
|
+
- 从 `~/.closer-code/cloco.md` 读取全局行为规范
|
|
25
|
+
- 显示:`✅ 已加载全局行为规范: ~/.closer-code/cloco.md`
|
|
26
|
+
|
|
27
|
+
2. **读取项目配置**(如果存在)
|
|
28
|
+
- 从当前项目的 `./cloco.md` 读取项目特定规范
|
|
29
|
+
- 显示:`✅ 已加载项目行为规范: ./cloco.md`
|
|
30
|
+
|
|
31
|
+
3. **构建系统提示词**
|
|
32
|
+
- 全局配置和项目配置都会被添加到系统提示词中
|
|
33
|
+
- 两者不会互相覆盖,而是共同生效
|
|
34
|
+
- 如果都不存在,使用默认行为规范
|
|
35
|
+
|
|
36
|
+
## 配置示例
|
|
37
|
+
|
|
38
|
+
### 全局配置示例 (`~/.closer-code/cloco.md`)
|
|
39
|
+
|
|
40
|
+
```markdown
|
|
41
|
+
# Closer Code - 全局行为规范
|
|
42
|
+
|
|
43
|
+
## 编码风格
|
|
44
|
+
- 使用 2 空格缩进
|
|
45
|
+
- 优先使用 const/let,避免 var
|
|
46
|
+
- 函数名使用驼峰命名
|
|
47
|
+
|
|
48
|
+
## 工具使用偏好
|
|
49
|
+
- 优先使用 bash 工具执行命令
|
|
50
|
+
- 使用 searchFiles 查找文件
|
|
51
|
+
- 使用 readFile 查看文件内容
|
|
52
|
+
|
|
53
|
+
## 代码审查要点
|
|
54
|
+
- 检查安全漏洞
|
|
55
|
+
- 确保错误处理完善
|
|
56
|
+
- 验证边界条件
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 项目配置示例 (`./cloco.md`)
|
|
60
|
+
|
|
61
|
+
```markdown
|
|
62
|
+
# 项目特定规范
|
|
63
|
+
|
|
64
|
+
## 架构约定
|
|
65
|
+
- 使用 MVC 模式组织代码
|
|
66
|
+
- 数据库操作使用 ORM
|
|
67
|
+
|
|
68
|
+
## 工作流程
|
|
69
|
+
- 提交代码前必须运行测试
|
|
70
|
+
- 使用 git flow 分支管理
|
|
71
|
+
|
|
72
|
+
## 团队规范
|
|
73
|
+
- 代码审查必须由至少 2 人完成
|
|
74
|
+
- 使用中文编写注释
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## 使用建议
|
|
78
|
+
|
|
79
|
+
### 适合放在全局配置的内容
|
|
80
|
+
- 通用的编码风格
|
|
81
|
+
- 代码审查标准
|
|
82
|
+
- 工具使用偏好
|
|
83
|
+
- 响应格式要求
|
|
84
|
+
- 安全最佳实践
|
|
85
|
+
|
|
86
|
+
### 适合放在项目配置的内容
|
|
87
|
+
- 项目特定的架构约定
|
|
88
|
+
- 特定库的使用规范
|
|
89
|
+
- 项目内的工作流程
|
|
90
|
+
- 团队协作规范
|
|
91
|
+
- 项目特定的业务规则
|
|
92
|
+
|
|
93
|
+
## 测试验证
|
|
94
|
+
|
|
95
|
+
运行测试脚本验证配置是否生效:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
node test/test-global-cloco.js
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
测试会检查:
|
|
102
|
+
- ✅ 全局配置文件是否存在
|
|
103
|
+
- ✅ 项目配置文件是否存在
|
|
104
|
+
- ✅ 配置是否正确加载
|
|
105
|
+
- ✅ 系统提示词是否包含配置内容
|
|
106
|
+
|
|
107
|
+
## 注意事项
|
|
108
|
+
|
|
109
|
+
1. **配置文件支持任何语言**(中文、英文等)
|
|
110
|
+
2. **配置实时生效**,无需重启
|
|
111
|
+
3. **如果配置文件不存在**,会使用默认行为(不会报错)
|
|
112
|
+
4. **项目级和全局级配置会同时生效**(不会覆盖)
|
|
113
|
+
5. **配置文件必须是 Markdown 格式**
|
|
114
|
+
|
|
115
|
+
## 升级说明
|
|
116
|
+
|
|
117
|
+
如果你之前使用项目级的 `cloco.md`,升级后:
|
|
118
|
+
- ✅ 项目配置继续有效
|
|
119
|
+
- ✅ 可以添加全局配置
|
|
120
|
+
- ✅ 两者会同时生效
|
|
121
|
+
- ✅ 无需修改现有配置
|
|
122
|
+
|
|
123
|
+
## 相关文件
|
|
124
|
+
|
|
125
|
+
- 全局配置: `~/.closer-code/cloco.md`
|
|
126
|
+
- 全局说明: `~/.closer-code/README.md`
|
|
127
|
+
- 项目配置: `./cloco.md`
|
|
128
|
+
- 测试脚本: `test/test-global-cloco.js`
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# 长消息显示改进
|
|
2
|
+
|
|
3
|
+
## 问题描述
|
|
4
|
+
|
|
5
|
+
之前 Conversation 区域对长文本有硬编码的限制:
|
|
6
|
+
- 最多显示 10 行
|
|
7
|
+
- 最多显示 1000 个字符
|
|
8
|
+
- 超过限制会显示 "... (truncated)" 提示
|
|
9
|
+
|
|
10
|
+
这导致:
|
|
11
|
+
- 长代码被截断
|
|
12
|
+
- 长日志不完整
|
|
13
|
+
- AI 的详细回复被截断
|
|
14
|
+
- 用户需要多次要求 AI "继续显示"
|
|
15
|
+
|
|
16
|
+
## 解决方案
|
|
17
|
+
|
|
18
|
+
**方案1:完全移除限制** ✅ 已实施
|
|
19
|
+
|
|
20
|
+
### 代码变更
|
|
21
|
+
|
|
22
|
+
删除了 `MessageItem` 组件中的所有限制逻辑:
|
|
23
|
+
|
|
24
|
+
```javascript
|
|
25
|
+
// 之前(有限制)
|
|
26
|
+
function MessageItem({ message }) {
|
|
27
|
+
// ...
|
|
28
|
+
const maxLines = 10; // ❌ 硬编码限制
|
|
29
|
+
const maxChars = 1000; // ❌ 硬编码限制
|
|
30
|
+
|
|
31
|
+
let displayContent = content;
|
|
32
|
+
let isTruncated = false;
|
|
33
|
+
|
|
34
|
+
if (content.length > maxChars) {
|
|
35
|
+
displayContent = content.slice(0, maxChars);
|
|
36
|
+
isTruncated = true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (displayLines.length > maxLines) {
|
|
40
|
+
displayContent = displayLines.slice(0, maxLines).join('\n');
|
|
41
|
+
isTruncated = true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<Box>
|
|
46
|
+
<Text>{displayContent}</Text>
|
|
47
|
+
{isTruncated && <Text>... (truncated)</Text>}
|
|
48
|
+
</Box>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 现在(无限制)
|
|
53
|
+
function MessageItem({ message }) {
|
|
54
|
+
// ...
|
|
55
|
+
// 直接显示完整内容
|
|
56
|
+
return (
|
|
57
|
+
<Box>
|
|
58
|
+
<Text>{content}</Text>
|
|
59
|
+
</Box>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 优点
|
|
65
|
+
|
|
66
|
+
✅ **完整性**
|
|
67
|
+
- 100% 显示所有内容
|
|
68
|
+
- 不会丢失任何信息
|
|
69
|
+
- 代码、日志、长回复都能完整查看
|
|
70
|
+
|
|
71
|
+
✅ **简单性**
|
|
72
|
+
- 代码更简洁
|
|
73
|
+
- 无需额外逻辑
|
|
74
|
+
- 易于维护
|
|
75
|
+
|
|
76
|
+
✅ **用户体验**
|
|
77
|
+
- 用户已习惯滚动(上下箭头)
|
|
78
|
+
- PageUp/PageDown 快速导航
|
|
79
|
+
- Enter 回到底部
|
|
80
|
+
|
|
81
|
+
✅ **可预测性**
|
|
82
|
+
- 行为一致
|
|
83
|
+
- 无隐藏内容
|
|
84
|
+
- 不会有"为什么被截断"的困惑
|
|
85
|
+
|
|
86
|
+
### 滚动功能
|
|
87
|
+
|
|
88
|
+
用户可以使用以下键盘快捷键滚动查看长消息:
|
|
89
|
+
|
|
90
|
+
- **↑ (上箭头)**: 向上滚动 5 行
|
|
91
|
+
- **↓ (下箭头)**: 向下滚动 5 行
|
|
92
|
+
- **PageUp**: 向上滚动 10 行
|
|
93
|
+
- **PageDown**: 向下滚动 10 行
|
|
94
|
+
- **Enter**: 快速回到底部
|
|
95
|
+
|
|
96
|
+
当向上滚动时,会显示提示:
|
|
97
|
+
```
|
|
98
|
+
↑ Scrolled up (20 lines hidden) - Press ↓/Enter to return
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## 测试
|
|
102
|
+
|
|
103
|
+
### 测试文件
|
|
104
|
+
|
|
105
|
+
运行测试生成超长消息:
|
|
106
|
+
```bash
|
|
107
|
+
node test/test-long-message.js
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
这会生成一个包含:
|
|
111
|
+
- 100 行文本
|
|
112
|
+
- 5000 字符的长字符串
|
|
113
|
+
- 50 行代码块
|
|
114
|
+
- 混合内容
|
|
115
|
+
|
|
116
|
+
### 手动测试
|
|
117
|
+
|
|
118
|
+
1. 启动 `cloco`
|
|
119
|
+
2. 让 AI 生成大量内容,例如:
|
|
120
|
+
```
|
|
121
|
+
生成一个包含 100 个方法的 JavaScript 类
|
|
122
|
+
```
|
|
123
|
+
3. 检查是否完整显示
|
|
124
|
+
4. 使用上下箭头滚动查看
|
|
125
|
+
5. 确认没有 "... (truncated)" 提示
|
|
126
|
+
|
|
127
|
+
## 性能考虑
|
|
128
|
+
|
|
129
|
+
### 渲染性能
|
|
130
|
+
|
|
131
|
+
- Ink 使用虚拟 DOM,差异更新
|
|
132
|
+
- 超长文本渲染时间通常 < 100ms
|
|
133
|
+
- 对于极端情况(1000+ 行),可能稍慢但仍可接受
|
|
134
|
+
|
|
135
|
+
### 内存占用
|
|
136
|
+
|
|
137
|
+
- 每条消息完整存储在内存中
|
|
138
|
+
- 对于超长对话,可能占用较多内存
|
|
139
|
+
- 但现代计算机通常有足够内存
|
|
140
|
+
|
|
141
|
+
### 优化建议(如果需要)
|
|
142
|
+
|
|
143
|
+
如果未来发现性能问题,可以考虑:
|
|
144
|
+
|
|
145
|
+
1. **虚拟滚动**:只渲染可见部分
|
|
146
|
+
2. **分页显示**:将超长消息分页
|
|
147
|
+
3. **懒加载**:滚动到时才加载
|
|
148
|
+
|
|
149
|
+
但目前不需要这些优化。
|
|
150
|
+
|
|
151
|
+
## 未来增强
|
|
152
|
+
|
|
153
|
+
虽然当前方案已经很好,但未来可以考虑:
|
|
154
|
+
|
|
155
|
+
### 方案4:智能截断 + 展开/收起
|
|
156
|
+
|
|
157
|
+
```javascript
|
|
158
|
+
function MessageItem({ message }) {
|
|
159
|
+
const [isExpanded, setIsExpanded] = useState(false);
|
|
160
|
+
|
|
161
|
+
const THRESHOLD_LINES = 50;
|
|
162
|
+
const lines = content.split('\n');
|
|
163
|
+
|
|
164
|
+
const shouldTruncate = !isExpanded && lines.length > THRESHOLD_LINES;
|
|
165
|
+
const displayContent = shouldTruncate
|
|
166
|
+
? lines.slice(0, THRESHOLD_LINES).join('\n')
|
|
167
|
+
: content;
|
|
168
|
+
|
|
169
|
+
return (
|
|
170
|
+
<Box>
|
|
171
|
+
<Text>{displayContent}</Text>
|
|
172
|
+
{lines.length > THRESHOLD_LINES && (
|
|
173
|
+
<Text>
|
|
174
|
+
{isExpanded
|
|
175
|
+
? `[收起 - 按 Space] (${lines.length} 行)`
|
|
176
|
+
: `[展开 - 按 Space] (还有 ${lines.length - THRESHOLD_LINES} 行)`}
|
|
177
|
+
</Text>
|
|
178
|
+
)}
|
|
179
|
+
</Box>
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
但这需要:
|
|
185
|
+
- 状态管理
|
|
186
|
+
- 键盘事件处理
|
|
187
|
+
- 焦点管理
|
|
188
|
+
- 用户教育
|
|
189
|
+
|
|
190
|
+
目前不需要这种复杂度。
|
|
191
|
+
|
|
192
|
+
## 总结
|
|
193
|
+
|
|
194
|
+
**采用方案1(完全移除限制)是正确的决定**,因为:
|
|
195
|
+
|
|
196
|
+
1. ✅ 简单有效,立即解决问题
|
|
197
|
+
2. ✅ 用户已有滚动习惯
|
|
198
|
+
3. ✅ 不会丢失任何信息
|
|
199
|
+
4. ✅ 代码更简洁
|
|
200
|
+
5. ✅ 为未来增强留出空间
|
|
201
|
+
|
|
202
|
+
这是一个"少即是多"的典型案例。
|