claude-coder 1.5.0 → 1.5.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.
- package/README.md +1 -1
- package/docs/ARCHITECTURE.md +2 -2
- package/docs/README.en.md +1 -1
- package/package.json +1 -1
- package/src/indicator.js +2 -10
- package/src/prompts.js +67 -9
- package/src/session.js +6 -5
package/README.md
CHANGED
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -207,7 +207,7 @@ templates/
|
|
|
207
207
|
| `session_result.json` | 每次 session 结束 | 当前 session 结果(扁平格式,向后兼容旧 `current` 包装) |
|
|
208
208
|
| `playwright-auth.json` | `claude-coder auth` | Playwright 登录状态(cookies + localStorage) |
|
|
209
209
|
| `tests.json` | 首次测试时 | 验证记录(防止反复测试) |
|
|
210
|
-
| `.runtime/` | 运行时 | 临时文件(phase、step、logs
|
|
210
|
+
| `.runtime/` | 运行时 | 临时文件(phase、step、logs/);工具调用记录合并到 session log |
|
|
211
211
|
|
|
212
212
|
---
|
|
213
213
|
|
|
@@ -450,7 +450,7 @@ query({
|
|
|
450
450
|
### V2 迁移条件(等待稳定后)
|
|
451
451
|
|
|
452
452
|
1. V2 去掉 `unstable_` 前缀,正式发布
|
|
453
|
-
2. V2 支持 Hooks(当前项目依赖 PreToolUse 做 spinner
|
|
453
|
+
2. V2 支持 Hooks(当前项目依赖 PreToolUse 做 spinner 和日志记录)
|
|
454
454
|
3. V2 支持 Subagents(未来可能用于扫描 Agent / 编码 Agent 分离)
|
|
455
455
|
|
|
456
456
|
### 可利用但尚未使用的 V1 特性
|
package/docs/README.en.md
CHANGED
|
@@ -87,7 +87,7 @@ your-project/
|
|
|
87
87
|
test.env # Test credentials (API keys, optional)
|
|
88
88
|
playwright-auth.json # Playwright login state (optional, via auth command)
|
|
89
89
|
.runtime/ # Temp files
|
|
90
|
-
logs/ # Per-session logs
|
|
90
|
+
logs/ # Per-session logs (with tool call traces)
|
|
91
91
|
requirements.md # Requirements (optional)
|
|
92
92
|
```
|
|
93
93
|
|
package/package.json
CHANGED
package/src/indicator.js
CHANGED
|
@@ -18,9 +18,8 @@ class Indicator {
|
|
|
18
18
|
this.startTime = Date.now();
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
start(sessionNum
|
|
21
|
+
start(sessionNum) {
|
|
22
22
|
this.sessionNum = sessionNum;
|
|
23
|
-
this.activityLogPath = activityLogPath || null;
|
|
24
23
|
this.startTime = Date.now();
|
|
25
24
|
this.timer = setInterval(() => this._render(), 500);
|
|
26
25
|
}
|
|
@@ -44,14 +43,7 @@ class Indicator {
|
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
appendActivity(toolName, summary) {
|
|
47
|
-
|
|
48
|
-
const entry = `[${ts}] ${toolName}: ${summary}`;
|
|
49
|
-
this.lastActivity = entry;
|
|
50
|
-
try {
|
|
51
|
-
if (this.activityLogPath) {
|
|
52
|
-
fs.appendFileSync(this.activityLogPath, entry + '\n', 'utf8');
|
|
53
|
-
}
|
|
54
|
-
} catch { /* ignore */ }
|
|
46
|
+
this.lastActivity = `${toolName}: ${summary}`;
|
|
55
47
|
}
|
|
56
48
|
|
|
57
49
|
_writePhaseFile() {
|
package/src/prompts.js
CHANGED
|
@@ -211,25 +211,83 @@ function buildScanPrompt(projectType, requirement) {
|
|
|
211
211
|
|
|
212
212
|
/**
|
|
213
213
|
* Build user prompt for add sessions.
|
|
214
|
+
* Structure: Role (primacy) → Context → CoT → TaskGuide → Instruction (recency)
|
|
214
215
|
*/
|
|
215
216
|
function buildAddPrompt(instruction) {
|
|
217
|
+
const p = paths();
|
|
218
|
+
const projectRoot = getProjectRoot();
|
|
216
219
|
const taskGuide = buildTaskGuide();
|
|
220
|
+
|
|
221
|
+
// --- Context injection: pre-read project state ---
|
|
222
|
+
let profileContext = '';
|
|
223
|
+
if (fs.existsSync(p.profile)) {
|
|
224
|
+
try {
|
|
225
|
+
const profile = JSON.parse(fs.readFileSync(p.profile, 'utf8'));
|
|
226
|
+
const stack = profile.tech_stack || {};
|
|
227
|
+
const parts = [];
|
|
228
|
+
if (stack.backend?.framework) parts.push(`后端: ${stack.backend.framework}`);
|
|
229
|
+
if (stack.frontend?.framework) parts.push(`前端: ${stack.frontend.framework}`);
|
|
230
|
+
if (stack.backend?.language) parts.push(`语言: ${stack.backend.language}`);
|
|
231
|
+
if (parts.length) profileContext = `项目技术栈: ${parts.join(', ')}`;
|
|
232
|
+
} catch { /* ignore */ }
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
let taskContext = '';
|
|
236
|
+
let recentExamples = '';
|
|
237
|
+
try {
|
|
238
|
+
const taskData = loadTasks();
|
|
239
|
+
if (taskData) {
|
|
240
|
+
const stats = getStats(taskData);
|
|
241
|
+
const features = taskData.features || [];
|
|
242
|
+
const maxId = features.length ? features[features.length - 1].id : 'feat-000';
|
|
243
|
+
const maxPriority = features.length ? Math.max(...features.map(f => f.priority || 0)) : 0;
|
|
244
|
+
const categories = [...new Set(features.map(f => f.category))].join(', ');
|
|
245
|
+
|
|
246
|
+
taskContext = `已有 ${stats.total} 个任务(${stats.done} done, ${stats.pending} pending, ${stats.failed} failed)。` +
|
|
247
|
+
`最大 id: ${maxId}, 最大 priority: ${maxPriority}。已有 category: ${categories}。`;
|
|
248
|
+
|
|
249
|
+
const recent = features.slice(-3);
|
|
250
|
+
if (recent.length) {
|
|
251
|
+
recentExamples = '已有任务格式参考(保持一致性):\n' +
|
|
252
|
+
recent.map(f => ` ${f.id}: "${f.description}" (category=${f.category}, steps=${f.steps.length}步, depends_on=[${f.depends_on.join(',')}])`).join('\n');
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
} catch { /* ignore */ }
|
|
256
|
+
|
|
217
257
|
return [
|
|
218
|
-
|
|
258
|
+
// --- Primacy zone: role + identity ---
|
|
259
|
+
'你是资深需求分析师,擅长将模糊需求分解为可执行的原子任务。',
|
|
260
|
+
'这是任务追加 session,不是编码 session。你只分解任务,不实现代码。',
|
|
219
261
|
'',
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
262
|
+
|
|
263
|
+
// --- Context layer ---
|
|
264
|
+
profileContext,
|
|
265
|
+
taskContext,
|
|
266
|
+
recentExamples,
|
|
267
|
+
`项目绝对路径: ${projectRoot}`,
|
|
224
268
|
'',
|
|
269
|
+
|
|
270
|
+
// --- CoT: explicit thinking steps ---
|
|
271
|
+
'执行步骤(按顺序,不可跳过):',
|
|
272
|
+
'1. 读取 .claude-coder/tasks.json 和 .claude-coder/project_profile.json,全面了解项目现状',
|
|
273
|
+
'2. 分析用户指令:识别核心功能点,判断是单任务还是需要拆分为多任务',
|
|
274
|
+
'3. 检查重复:对比已有任务,避免功能重叠',
|
|
275
|
+
'4. 确定依赖:新任务的 depends_on 引用已有或新增任务的 id,形成 DAG',
|
|
276
|
+
'5. 分解任务:每个任务对应一个独立可测试的功能单元,description 简明(40字内),steps 具体可操作',
|
|
277
|
+
'6. 追加到 tasks.json,id 和 priority 从已有最大值递增,status: pending',
|
|
278
|
+
'7. git add -A && git commit -m "chore: add new tasks"',
|
|
279
|
+
'8. 写入 session_result.json',
|
|
280
|
+
'',
|
|
281
|
+
|
|
282
|
+
// --- Quality constraints ---
|
|
225
283
|
taskGuide,
|
|
226
284
|
'',
|
|
227
|
-
'
|
|
228
|
-
'git add -A && git commit -m "chore: add new tasks"',
|
|
229
|
-
'写入 session_result.json',
|
|
285
|
+
'不修改已有任务,不实现代码。',
|
|
230
286
|
'',
|
|
287
|
+
|
|
288
|
+
// --- Recency zone: user instruction (highest attention) ---
|
|
231
289
|
`用户指令:${instruction}`,
|
|
232
|
-
].join('\n');
|
|
290
|
+
].filter(Boolean).join('\n');
|
|
233
291
|
}
|
|
234
292
|
|
|
235
293
|
module.exports = {
|
package/src/session.js
CHANGED
|
@@ -99,10 +99,9 @@ async function runCodingSession(sessionNum, opts = {}) {
|
|
|
99
99
|
const taskId = opts.taskId || 'unknown';
|
|
100
100
|
const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, '');
|
|
101
101
|
const logFile = path.join(p.logsDir, `${taskId}_session_${sessionNum}_${dateStr}.log`);
|
|
102
|
-
const activityLogFile = path.join(p.logsDir, `session_${sessionNum}.activity.log`);
|
|
103
102
|
const logStream = fs.createWriteStream(logFile, { flags: 'a' });
|
|
104
103
|
|
|
105
|
-
indicator.start(sessionNum
|
|
104
|
+
indicator.start(sessionNum);
|
|
106
105
|
|
|
107
106
|
const editCounts = {};
|
|
108
107
|
const EDIT_THRESHOLD = 5;
|
|
@@ -127,9 +126,11 @@ async function runCodingSession(sessionNum, opts = {}) {
|
|
|
127
126
|
inferPhaseStep(indicator, input.tool_name, input.tool_input);
|
|
128
127
|
|
|
129
128
|
const target = input.tool_input?.file_path || input.tool_input?.path || '';
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
129
|
+
const cmd = input.tool_input?.command || '';
|
|
130
|
+
const pattern = input.tool_input?.pattern || '';
|
|
131
|
+
const detail = target || cmd.slice(0, 200) || (pattern ? `pattern: ${pattern}` : '');
|
|
132
|
+
if (detail) {
|
|
133
|
+
logStream.write(`[${new Date().toISOString()}] ${input.tool_name}: ${detail}\n`);
|
|
133
134
|
}
|
|
134
135
|
|
|
135
136
|
if (['Write', 'Edit', 'MultiEdit'].includes(input.tool_name) && target) {
|