claude-coder 1.5.4 → 1.5.6
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 +2 -1
- package/docs/ARCHITECTURE.md +8 -5
- package/docs/PLAYWRIGHT_CREDENTIALS.md +57 -66
- package/docs/README.en.md +2 -1
- package/package.json +1 -1
- package/src/auth.js +16 -11
- package/src/config.js +1 -0
- package/src/indicator.js +12 -0
- package/src/prompts.js +5 -3
- package/templates/CLAUDE.md +2 -1
package/README.md
CHANGED
|
@@ -97,7 +97,8 @@ your-project/
|
|
|
97
97
|
progress.json # 会话历史 + 成本
|
|
98
98
|
tests.json # 验证记录
|
|
99
99
|
test.env # 测试凭证(API Key 等,可选)
|
|
100
|
-
playwright-auth.json #
|
|
100
|
+
playwright-auth.json # 登录状态快照(备份参考,auth 命令生成)
|
|
101
|
+
browser-profile/ # 持久化浏览器 Profile(MCP 实际使用)
|
|
101
102
|
.runtime/ # 临时文件
|
|
102
103
|
logs/ # 每 session 独立日志(含工具调用记录)
|
|
103
104
|
requirements.md # 需求文档(可选)
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -31,7 +31,7 @@ Agent 在单次 session 中应最大化推进任务进度。**任何非致命问
|
|
|
31
31
|
|
|
32
32
|
`git reset --hard` 是全量回滚,不做部分文件保护。
|
|
33
33
|
|
|
34
|
-
- 凭证文件(`test.env`、`playwright-auth.json
|
|
34
|
+
- 凭证文件(`test.env`、`playwright-auth.json`、`browser-profile/`)应通过 `.gitignore` 排除在 git 之外
|
|
35
35
|
- 如果回滚发生,说明 session 确实失败,代码应全部还原
|
|
36
36
|
- 不需要 backup/restore 机制 — 这是过度设计
|
|
37
37
|
|
|
@@ -51,7 +51,8 @@ Agent 在单次 session 中应最大化推进任务进度。**任何非致命问
|
|
|
51
51
|
| 文件 | git 状态 | 说明 |
|
|
52
52
|
|------|---------|------|
|
|
53
53
|
| `test.env` | .gitignore | Agent 可写入发现的 API Key、测试账号 |
|
|
54
|
-
| `playwright-auth.json` | .gitignore |
|
|
54
|
+
| `playwright-auth.json` | .gitignore | 登录状态快照备份(`claude-coder auth` 生成) |
|
|
55
|
+
| `browser-profile/` | .gitignore | 持久化浏览器 Profile(MCP 实际使用) |
|
|
55
56
|
| `session_result.json` | git-tracked | Agent 每次 session 覆盖写入 |
|
|
56
57
|
| `tasks.json` | git-tracked | Agent 修改 status 字段 |
|
|
57
58
|
|
|
@@ -207,7 +208,8 @@ templates/
|
|
|
207
208
|
| `tasks.json` | 首次扫描 | 任务列表 + 状态跟踪 |
|
|
208
209
|
| `progress.json` | 每次 session 结束 | 结构化会话日志 + 成本记录 |
|
|
209
210
|
| `session_result.json` | 每次 session 结束 | 当前 session 结果(扁平格式,向后兼容旧 `current` 包装) |
|
|
210
|
-
| `playwright-auth.json` | `claude-coder auth` |
|
|
211
|
+
| `playwright-auth.json` | `claude-coder auth` | 登录状态快照(备份参考) |
|
|
212
|
+
| `browser-profile/` | `claude-coder auth` | 持久化浏览器 Profile(MCP 通过 `--user-data-dir` 使用) |
|
|
211
213
|
| `tests.json` | 首次测试时 | 验证记录(防止反复测试) |
|
|
212
214
|
| `.runtime/` | 运行时 | 临时文件(phase、step、logs/);工具调用记录合并到 session log |
|
|
213
215
|
|
|
@@ -265,7 +267,7 @@ flowchart TB
|
|
|
265
267
|
| 5 | `docsHint` | profile.existing_docs 非空或 profile 有缺陷 | Step 4:读文档后再编码;profile 缺陷时提示 Agent 在 Step 6 补全 services/docs |
|
|
266
268
|
| 6 | `taskHint` | tasks.json 存在且有待办任务 | Step 1:跳过读取 tasks.json,harness 已注入当前任务上下文 + 项目绝对路径 |
|
|
267
269
|
| 6b | `testEnvHint` | 始终注入(内容因 test.env 是否存在而不同) | Step 5:存在时提示加载;不存在时告知可创建 |
|
|
268
|
-
| 6c | `playwrightAuthHint` | .claude-coder/
|
|
270
|
+
| 6c | `playwrightAuthHint` | .claude-coder/browser-profile/ 存在 | Step 5:提示 Agent MCP 使用持久化浏览器 Profile,首次需手动登录 |
|
|
269
271
|
| 7 | `memoryHint` | session_result.json 存在(扁平格式) | Step 1:跳过读取 session_result.json,harness 已注入上次会话摘要 |
|
|
270
272
|
| 8 | `serviceHint` | 始终注入 | Step 6:单次模式停止服务,连续模式保持服务运行 |
|
|
271
273
|
| 9 | `toolGuidance` | 始终注入 | 全局:工具使用规范(Grep/Glob/Read/LS/MultiEdit/Task 替代 bash 命令),非 Claude 模型必需 |
|
|
@@ -406,7 +408,8 @@ Harness 在 `buildCodingPrompt()` 中预读 `session_result.json`,将上次会
|
|
|
406
408
|
| `tasks.json` | Agent(仅 `status` 字段) | 修改 `status` | tracked |
|
|
407
409
|
| `project_profile.json` | Agent(仅扫描阶段) | 扫描时写入 | tracked |
|
|
408
410
|
| `test.env` | Agent + 用户 | 可追加写入 | .gitignore |
|
|
409
|
-
| `playwright-auth.json` | 用户(`claude-coder auth`) |
|
|
411
|
+
| `playwright-auth.json` | 用户(`claude-coder auth`) | 快照备份 | .gitignore |
|
|
412
|
+
| `browser-profile/` | 用户(`claude-coder auth`) | MCP 自动维护 | .gitignore |
|
|
410
413
|
|
|
411
414
|
---
|
|
412
415
|
|
|
@@ -13,7 +13,7 @@ claude-coder 的核心目标是让 Agent **完全自主测试**,不因凭证
|
|
|
13
13
|
**核心原则**:
|
|
14
14
|
1. **Agent 可自行发现并持久化凭证** — 测试中发现需要的 API Key 或账号,直接写入 `test.env`
|
|
15
15
|
2. **凭证不受回滚影响** — `git reset --hard` 不会摧毁已保存的凭证
|
|
16
|
-
3. **零手动干预** —
|
|
16
|
+
3. **零手动干预** — 首次浏览器登录后,后续由持久化 profile 自动处理
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
@@ -23,7 +23,8 @@ claude-coder 的核心目标是让 Agent **完全自主测试**,不因凭证
|
|
|
23
23
|
.claude-coder/
|
|
24
24
|
.env ← 模型配置(ANTHROPIC_API_KEY 等) [用户配置]
|
|
25
25
|
test.env ← 测试凭证(API Key、测试账号等) [Agent 可写]
|
|
26
|
-
playwright-auth.json ←
|
|
26
|
+
playwright-auth.json ← 登录状态快照(备份参考) [auth 命令生成]
|
|
27
|
+
browser-profile/ ← 持久化浏览器 Profile(MCP 实际使用) [auth 命令创建]
|
|
27
28
|
```
|
|
28
29
|
|
|
29
30
|
### 文件生命周期
|
|
@@ -32,17 +33,25 @@ claude-coder 的核心目标是让 Agent **完全自主测试**,不因凭证
|
|
|
32
33
|
|------|--------|--------|----------|----------|
|
|
33
34
|
| `.env` | `claude-coder setup` | 用户 | 是 | 长期 |
|
|
34
35
|
| `test.env` | Agent 或用户 | Agent + 用户 | 是 | 长期,按需更新 |
|
|
35
|
-
| `playwright-auth.json` | `claude-coder auth` | auth 命令 | 是 |
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
36
|
+
| `playwright-auth.json` | `claude-coder auth` | auth 命令 | 是 | 快照备份,不被 MCP 直接使用 |
|
|
37
|
+
| `browser-profile/` | `claude-coder auth` | MCP 自动维护 | 是 | 长期,自动续期 |
|
|
38
|
+
|
|
39
|
+
### 技术实现:为什么用 `--user-data-dir` 而不是 `--storage-state`
|
|
40
|
+
|
|
41
|
+
| 维度 | `--storage-state`(旧方案) | `--user-data-dir`(当前方案) |
|
|
42
|
+
|------|-------------------------|--------------------------|
|
|
43
|
+
| 上下文类型 | 隔离上下文(isolated) | 持久化上下文(persistent) |
|
|
44
|
+
| 状态保持 | 每次从 JSON 文件加载,会话结束丢弃 | Profile 自动保存,跨会话保持 |
|
|
45
|
+
| Cookies 续期 | 不支持(JSON 文件静态) | 支持(浏览器自动刷新的 cookies 被保留) |
|
|
46
|
+
| localStorage | 从 JSON 注入(可靠) | 持久保存在 Profile 中 |
|
|
47
|
+
| Google OAuth | 每次创建新上下文 → Google 检测到自动化 | 持久 Profile → Google 视为常规浏览器 |
|
|
48
|
+
| 长期运行 | 差(cookies 过期后必须重新 auth) | 优(Profile 随浏览器使用自动演进) |
|
|
49
|
+
|
|
50
|
+
> **源码依据**:Playwright MCP `contextFactory()` 在 `isolated=false` 时使用 `PersistentContextFactory`,
|
|
51
|
+
> 调用 `launchPersistentContext(userDataDir, options)` 创建持久化浏览器上下文。
|
|
52
|
+
> `--storage-state` 虽然不强制 `isolated=true`,但官方文档明确描述其为 "load into an isolated browser context",
|
|
53
|
+
> 且 `launchPersistentContext` 的 `storageState` 参数存在已知缺陷(Issue #14949):localStorage 不注入,
|
|
54
|
+
> 旧 cookies 可能覆盖 Profile 中已刷新的 cookies。
|
|
46
55
|
|
|
47
56
|
---
|
|
48
57
|
|
|
@@ -54,56 +63,47 @@ Harness 在 `git reset --hard` 前备份、后恢复以下文件:
|
|
|
54
63
|
Agent 测试 → 发现需要 API Key → 写入 test.env → 下次 session 自动加载
|
|
55
64
|
```
|
|
56
65
|
|
|
57
|
-
Agent 在 CLAUDE.md Step 5 中被指导:测试中发现的凭证追加到 `.claude-coder/test.env`。Harness 在每次 session 的 prompt 中注入 hint,告知 Agent `test.env` 的存在和用法。
|
|
58
|
-
|
|
59
66
|
### 流程 2:用户预配置浏览器登录态
|
|
60
67
|
|
|
61
68
|
```
|
|
62
|
-
用户运行 claude-coder auth
|
|
69
|
+
用户运行 claude-coder auth url
|
|
70
|
+
→ playwright codegen 打开浏览器 → 手动登录 → 关闭浏览器
|
|
71
|
+
→ cookies + localStorage 保存为快照备份(playwright-auth.json)
|
|
72
|
+
→ 创建 browser-profile/ 目录
|
|
73
|
+
→ 更新 .mcp.json(--user-data-dir 指向 browser-profile/)
|
|
74
|
+
→ 首次 MCP 会话时在浏览器窗口中登录一次
|
|
75
|
+
→ 之后 MCP 自动使用持久化 Profile,无需再次登录
|
|
63
76
|
```
|
|
64
77
|
|
|
65
|
-
适用于需要已登录状态才能测试的前端页面(如后台管理、需要 cookie 的 SPA)。
|
|
66
|
-
|
|
67
78
|
### 流程 3:用户预配置 API Key
|
|
68
79
|
|
|
69
80
|
```
|
|
70
81
|
用户编辑 test.env → 填入 API Key → Agent 测试前 source 加载
|
|
71
82
|
```
|
|
72
83
|
|
|
73
|
-
适用于后端功能依赖真实 API 调用的场景。
|
|
74
|
-
|
|
75
84
|
---
|
|
76
85
|
|
|
77
86
|
## CLI 命令
|
|
78
87
|
|
|
79
88
|
### `claude-coder auth [url]`
|
|
80
89
|
|
|
81
|
-
|
|
90
|
+
配置持久化浏览器认证:
|
|
82
91
|
|
|
83
92
|
```bash
|
|
84
93
|
# 默认打开 http://localhost:3000
|
|
85
94
|
claude-coder auth
|
|
86
95
|
|
|
87
|
-
# 指定 URL
|
|
88
|
-
claude-coder auth http://
|
|
96
|
+
# 指定 URL(如内部 API 文档平台)
|
|
97
|
+
claude-coder auth http://testyapi.example.com/group/2245
|
|
89
98
|
```
|
|
90
99
|
|
|
91
100
|
**自动完成**:
|
|
92
|
-
1.
|
|
93
|
-
2.
|
|
94
|
-
3. 创建/更新 `.mcp.json`,配置 `--
|
|
95
|
-
4. 添加 `.gitignore`
|
|
101
|
+
1. 创建 `.claude-coder/browser-profile/` 持久化 Profile 目录
|
|
102
|
+
2. 启动 `playwright codegen`,用户手动登录后关闭浏览器(保存快照备份)
|
|
103
|
+
3. 创建/更新 `.mcp.json`,配置 `--user-data-dir=.claude-coder/browser-profile`
|
|
104
|
+
4. 添加 `.gitignore` 条目(`playwright-auth.json` + `browser-profile/`)
|
|
96
105
|
5. 启用 `.claude-coder/.env` 中 `MCP_PLAYWRIGHT=true`
|
|
97
106
|
|
|
98
|
-
### `claude-coder setup`(相关)
|
|
99
|
-
|
|
100
|
-
配置模型时可启用 Playwright MCP:
|
|
101
|
-
|
|
102
|
-
```bash
|
|
103
|
-
claude-coder setup
|
|
104
|
-
# 选择启用 MCP_PLAYWRIGHT=true
|
|
105
|
-
```
|
|
106
|
-
|
|
107
107
|
---
|
|
108
108
|
|
|
109
109
|
## 场景示例
|
|
@@ -111,51 +111,42 @@ claude-coder setup
|
|
|
111
111
|
### 场景 1:全栈项目首次测试
|
|
112
112
|
|
|
113
113
|
```bash
|
|
114
|
-
# 1. 配置模型
|
|
115
114
|
claude-coder setup
|
|
116
|
-
|
|
117
|
-
# 2. 填入后端测试需要的 API Key
|
|
118
115
|
cat >> .claude-coder/test.env << 'EOF'
|
|
119
116
|
OPENAI_API_KEY=sk-xxx
|
|
120
|
-
ZHIPU_API_KEY=xxx.xxx
|
|
121
117
|
EOF
|
|
122
|
-
|
|
123
|
-
# 3. 导出前端登录态(可选,Agent 也能用 Playwright MCP 自动登录)
|
|
124
118
|
claude-coder auth http://localhost:3000
|
|
125
|
-
|
|
126
|
-
# 4. 开始自动编码和测试
|
|
127
119
|
claude-coder run
|
|
120
|
+
# 首次 MCP 访问需登录的页面时,在浏览器窗口登录一次
|
|
121
|
+
# 之后所有 session 自动保持登录状态
|
|
128
122
|
```
|
|
129
123
|
|
|
130
|
-
### 场景 2
|
|
131
|
-
|
|
132
|
-
Agent 在测试 feat-005(AI 内容生成)时发现需要 `OPENAI_API_KEY`:
|
|
133
|
-
|
|
134
|
-
1. Agent 尝试调用 API → 报错 "API key required"
|
|
135
|
-
2. Agent **不中断任务**,改用替代验证方式(如 mock 响应、检查代码逻辑是否正确、验证接口可达性)
|
|
136
|
-
3. Agent 将凭证需求写入 `test.env`:`echo 'OPENAI_API_KEY=需要配置' >> .claude-coder/test.env`
|
|
137
|
-
4. Agent 在 `session_result.json` 的 notes 中记录:"AI 内容生成功能已实现,但需要真实 OPENAI_API_KEY 才能完整测试,已记录到 test.env"
|
|
138
|
-
5. Agent 完成其他可验证的步骤后标记任务为 `done`(功能已实现)或 `testing`(等待凭证后完整验证)
|
|
124
|
+
### 场景 2:内部系统(Google OAuth / SSO)
|
|
139
125
|
|
|
140
|
-
|
|
126
|
+
```bash
|
|
127
|
+
claude-coder auth http://testyapi.example.com/group/2245
|
|
128
|
+
# 在弹出的浏览器中完成 Google 登录(快照备份)
|
|
129
|
+
# 首次 MCP 会话时在浏览器窗口中再次登录
|
|
130
|
+
# 之后持久化 Profile 自动保持 Google 登录状态
|
|
131
|
+
```
|
|
141
132
|
|
|
142
|
-
|
|
133
|
+
> **关于 Google OAuth 检测**:使用 `--user-data-dir` 持久化 Profile 后,Google 将浏览器视为
|
|
134
|
+
> "回访用户"而非"新自动化会话",大幅降低重复登录要求。如果仍被检测,可在 `.mcp.json` 中
|
|
135
|
+
> 添加 `--browser chrome` 使用真实 Chrome 进一步降低检测率。
|
|
143
136
|
|
|
144
|
-
|
|
137
|
+
### 场景 3:长期运行(核心优势)
|
|
145
138
|
|
|
146
139
|
```bash
|
|
147
|
-
|
|
148
|
-
#
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
#
|
|
152
|
-
# 后续 Agent 使用 Playwright MCP 测试时自动加载这些配置
|
|
140
|
+
claude-coder run --max-sessions 50
|
|
141
|
+
# 浏览器 Profile 自动保持:
|
|
142
|
+
# - cookies 被网站刷新时,新 cookies 自动写入 Profile
|
|
143
|
+
# - 不依赖静态 JSON 文件,状态持续演进
|
|
144
|
+
# - 即使中途重启 claude-coder,Profile 中的登录状态仍然有效
|
|
153
145
|
```
|
|
154
146
|
|
|
155
|
-
### 场景 4
|
|
147
|
+
### 场景 4:清除登录状态
|
|
156
148
|
|
|
157
149
|
```bash
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
# 新的 cookies 覆盖旧文件,立即生效
|
|
150
|
+
rm -rf .claude-coder/browser-profile/
|
|
151
|
+
# 下次 MCP 会话时将创建全新 Profile,需重新登录
|
|
161
152
|
```
|
package/docs/README.en.md
CHANGED
|
@@ -85,7 +85,8 @@ your-project/
|
|
|
85
85
|
progress.json # Session history + costs
|
|
86
86
|
tests.json # Verification records
|
|
87
87
|
test.env # Test credentials (API keys, optional)
|
|
88
|
-
playwright-auth.json #
|
|
88
|
+
playwright-auth.json # Login state snapshot (backup, via auth command)
|
|
89
|
+
browser-profile/ # Persistent browser profile (used by MCP)
|
|
89
90
|
.runtime/ # Temp files
|
|
90
91
|
logs/ # Per-session logs (with tool call traces)
|
|
91
92
|
requirements.md # Requirements (optional)
|
package/package.json
CHANGED
package/src/auth.js
CHANGED
|
@@ -18,7 +18,7 @@ function updateGitignore(entry) {
|
|
|
18
18
|
log('ok', `.gitignore 已添加: ${entry}`);
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
function updateMcpConfig(
|
|
21
|
+
function updateMcpConfig(browserProfileDir) {
|
|
22
22
|
const p = paths();
|
|
23
23
|
let mcpConfig = {};
|
|
24
24
|
if (fs.existsSync(p.mcpConfig)) {
|
|
@@ -31,17 +31,17 @@ function updateMcpConfig(authFilePath) {
|
|
|
31
31
|
|
|
32
32
|
if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
|
|
33
33
|
|
|
34
|
-
const
|
|
34
|
+
const relProfileDir = path.relative(getProjectRoot(), browserProfileDir);
|
|
35
35
|
mcpConfig.mcpServers.playwright = {
|
|
36
36
|
command: 'npx',
|
|
37
37
|
args: [
|
|
38
38
|
'@playwright/mcp@latest',
|
|
39
|
-
`--
|
|
39
|
+
`--user-data-dir=${relProfileDir}`,
|
|
40
40
|
],
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
fs.writeFileSync(p.mcpConfig, JSON.stringify(mcpConfig, null, 2) + '\n', 'utf8');
|
|
44
|
-
log('ok', `.mcp.json 已配置 Playwright MCP (
|
|
44
|
+
log('ok', `.mcp.json 已配置 Playwright MCP (user-data-dir: ${relProfileDir})`);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
function enableMcpPlaywrightEnv() {
|
|
@@ -64,14 +64,17 @@ async function auth(url) {
|
|
|
64
64
|
const p = paths();
|
|
65
65
|
const targetUrl = url || 'http://localhost:3000';
|
|
66
66
|
|
|
67
|
+
if (!fs.existsSync(p.browserProfile))
|
|
68
|
+
fs.mkdirSync(p.browserProfile, { recursive: true });
|
|
69
|
+
|
|
67
70
|
log('info', '启动 Playwright 浏览器,请手动登录...');
|
|
68
71
|
log('info', `目标 URL: ${targetUrl}`);
|
|
69
|
-
log('info',
|
|
72
|
+
log('info', `浏览器配置将持久化到: ${p.browserProfile}`);
|
|
70
73
|
console.log('');
|
|
71
74
|
console.log('操作步骤:');
|
|
72
75
|
console.log(' 1. 浏览器将自动打开,请手动完成登录');
|
|
73
76
|
console.log(' 2. 登录成功后关闭浏览器窗口');
|
|
74
|
-
console.log(' 3. 登录状态(cookies + localStorage
|
|
77
|
+
console.log(' 3. 登录状态(cookies + localStorage)将保存为快照备份');
|
|
75
78
|
console.log('');
|
|
76
79
|
|
|
77
80
|
try {
|
|
@@ -92,16 +95,18 @@ async function auth(url) {
|
|
|
92
95
|
return;
|
|
93
96
|
}
|
|
94
97
|
|
|
95
|
-
log('ok', '
|
|
98
|
+
log('ok', '登录状态快照已保存(备份参考)');
|
|
96
99
|
|
|
97
|
-
updateMcpConfig(p.
|
|
100
|
+
updateMcpConfig(p.browserProfile);
|
|
98
101
|
updateGitignore('.claude-coder/playwright-auth.json');
|
|
102
|
+
updateGitignore('.claude-coder/browser-profile/');
|
|
99
103
|
enableMcpPlaywrightEnv();
|
|
100
104
|
|
|
101
105
|
console.log('');
|
|
102
|
-
log('ok', '
|
|
103
|
-
log('info', '
|
|
104
|
-
log('info', '
|
|
106
|
+
log('ok', '持久化浏览器配置完成!');
|
|
107
|
+
log('info', 'MCP 使用 --user-data-dir 持久化模式,登录状态跨会话保持');
|
|
108
|
+
log('info', '首次 MCP 会话时需在浏览器窗口中登录一次,之后永久保持');
|
|
109
|
+
log('info', 'cookies 自动续期,无需手动重新运行 claude-coder auth');
|
|
105
110
|
}
|
|
106
111
|
|
|
107
112
|
module.exports = { auth };
|
package/src/config.js
CHANGED
|
@@ -57,6 +57,7 @@ function paths() {
|
|
|
57
57
|
testsFile: path.join(loopDir, 'tests.json'),
|
|
58
58
|
testEnvFile: path.join(loopDir, 'test.env'),
|
|
59
59
|
playwrightAuth: path.join(loopDir, 'playwright-auth.json'),
|
|
60
|
+
browserProfile: path.join(loopDir, 'browser-profile'),
|
|
60
61
|
mcpConfig: path.join(getProjectRoot(), '.mcp.json'),
|
|
61
62
|
claudeMd: getTemplatePath('CLAUDE.md'),
|
|
62
63
|
scanProtocol: getTemplatePath('SCAN_PROTOCOL.md'),
|
package/src/indicator.js
CHANGED
|
@@ -17,11 +17,13 @@ class Indicator {
|
|
|
17
17
|
this.sessionNum = 0;
|
|
18
18
|
this.startTime = Date.now();
|
|
19
19
|
this._lastContentKey = '';
|
|
20
|
+
this._lastRenderTime = 0;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
start(sessionNum) {
|
|
23
24
|
this.sessionNum = sessionNum;
|
|
24
25
|
this.startTime = Date.now();
|
|
26
|
+
this._lastRenderTime = Date.now();
|
|
25
27
|
this.timer = setInterval(() => this._render(), 500);
|
|
26
28
|
}
|
|
27
29
|
|
|
@@ -87,6 +89,16 @@ class Indicator {
|
|
|
87
89
|
|
|
88
90
|
_render() {
|
|
89
91
|
this.spinnerIndex++;
|
|
92
|
+
const contentKey = `${this.phase}|${this.step}|${this.toolTarget}`;
|
|
93
|
+
const now = Date.now();
|
|
94
|
+
const contentChanged = contentKey !== this._lastContentKey;
|
|
95
|
+
|
|
96
|
+
if (!contentChanged && now - this._lastRenderTime < 3000) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
this._lastContentKey = contentKey;
|
|
100
|
+
this._lastRenderTime = now;
|
|
101
|
+
|
|
90
102
|
const line = this.getStatusLine();
|
|
91
103
|
const maxWidth = process.stderr.columns || 80;
|
|
92
104
|
const truncated = line.length > maxWidth + 20 ? line.slice(0, maxWidth + 20) : line;
|
package/src/prompts.js
CHANGED
|
@@ -97,10 +97,12 @@ function buildCodingPrompt(sessionNum, opts = {}) {
|
|
|
97
97
|
testEnvHint = `如需持久化测试凭证(API Key、测试账号密码等),写入 ${projectRoot}/.claude-coder/test.env(KEY=value 格式,每行一个)。后续 session 会自动感知。`;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
// Hint 6c: Playwright
|
|
100
|
+
// Hint 6c: Playwright persistent browser profile
|
|
101
101
|
let playwrightAuthHint = '';
|
|
102
|
-
if (
|
|
103
|
-
playwrightAuthHint =
|
|
102
|
+
if (fs.existsSync(p.browserProfile)) {
|
|
103
|
+
playwrightAuthHint = `已检测到持久化浏览器配置(${projectRoot}/.claude-coder/browser-profile/),MCP 使用 --user-data-dir 模式,登录状态跨会话自动保持。首次访问需登录的页面时,用户需在浏览器窗口中手动完成登录。`;
|
|
104
|
+
} else if (fs.existsSync(p.playwrightAuth)) {
|
|
105
|
+
playwrightAuthHint = `已检测到 Playwright 登录状态快照(${projectRoot}/.claude-coder/playwright-auth.json),建议运行 claude-coder auth 升级到持久化浏览器模式以获得更好的登录保持效果。`;
|
|
104
106
|
}
|
|
105
107
|
|
|
106
108
|
// Hint 7: Session memory (read flat session_result.json)
|
package/templates/CLAUDE.md
CHANGED
|
@@ -51,7 +51,8 @@
|
|
|
51
51
|
| `.claude-coder/session_result.json` | 本次会话的结构化输出 | 每次会话结束时覆盖写入 |
|
|
52
52
|
| `.claude-coder/tests.json` | 功能验证记录(轻量) | 可新增和更新;仅当功能涉及 API 或核心逻辑时记录 |
|
|
53
53
|
| `.claude-coder/test.env` | 测试凭证(API Key、测试账号等) | **可追加写入**;发现测试需要的凭证时持久化到此文件 |
|
|
54
|
-
| `.claude-coder/playwright-auth.json` |
|
|
54
|
+
| `.claude-coder/playwright-auth.json` | 登录状态快照(备份参考) | 只读;由 `claude-coder auth` 生成 |
|
|
55
|
+
| `.claude-coder/browser-profile/` | 持久化浏览器 Profile | MCP 自动维护;首次需手动登录,之后永久保持 |
|
|
55
56
|
|
|
56
57
|
### requirements.md 处理原则
|
|
57
58
|
|