@jojonax/codex-copilot 1.0.2 → 1.1.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/bin/cli.js CHANGED
@@ -1,31 +1,39 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * codex-copilot CLI - PRD → 自动开发 → PR → Review → 修复合并
4
+ * codex-copilot CLI - PRD → Auto Dev → PR → Review → FixMerge
5
5
  *
6
- * 用法:
7
- * codex-copilot init # 初始化项目(自动检测 PRD,生成任务)
8
- * codex-copilot run # 启动自动化开发循环
9
- * codex-copilot status # 查看当前进度
10
- * codex-copilot reset # 重置状态(重新开始)
6
+ * Usage:
7
+ * codex-copilot init # Initialize project (auto-detect PRD, generate tasks)
8
+ * codex-copilot run # Start automated development loop
9
+ * codex-copilot status # View current progress
10
+ * codex-copilot reset # Reset state (start over)
11
11
  */
12
12
 
13
- import { resolve } from 'path';
14
- import { existsSync } from 'fs';
13
+ import { resolve, dirname } from 'path';
14
+ import { existsSync, readFileSync } from 'fs';
15
+ import { fileURLToPath } from 'url';
15
16
 
16
17
  import { init } from '../src/commands/init.js';
17
18
  import { run } from '../src/commands/run.js';
18
19
  import { status } from '../src/commands/status.js';
19
20
  import { reset } from '../src/commands/reset.js';
20
21
  import { log } from '../src/utils/logger.js';
22
+ import { checkForUpdates } from '../src/utils/update-check.js';
21
23
 
22
24
  const command = process.argv[2];
23
25
  const projectDir = process.cwd();
24
26
 
27
+ // Read version from package.json
28
+ const __filename = fileURLToPath(import.meta.url);
29
+ const __dirname = dirname(__filename);
30
+ const pkg = JSON.parse(readFileSync(resolve(__dirname, '..', 'package.json'), 'utf-8'));
31
+ const version = pkg.version;
32
+
25
33
  // Banner
26
34
  console.log('');
27
35
  console.log(' ╔══════════════════════════════════════════╗');
28
- console.log(' ║ 🤖 Codex-Copilot v1.0 ║');
36
+ console.log(` ║ 🤖 Codex-Copilot v${version.padEnd(18)}║`);
29
37
  console.log(' ║ PRD-Driven Auto Development ║');
30
38
  console.log(' ╚══════════════════════════════════════════╝');
31
39
  console.log('');
@@ -39,7 +47,7 @@ async function main() {
39
47
 
40
48
  case 'run':
41
49
  if (!existsSync(resolve(projectDir, '.codex-copilot/tasks.json'))) {
42
- log.error('尚未初始化,请先运行: codex-copilot init');
50
+ log.error('Not initialized. Run: codex-copilot init');
43
51
  process.exit(1);
44
52
  }
45
53
  await run(projectDir);
@@ -47,7 +55,7 @@ async function main() {
47
55
 
48
56
  case 'status':
49
57
  if (!existsSync(resolve(projectDir, '.codex-copilot/tasks.json'))) {
50
- log.error('尚未初始化,请先运行: codex-copilot init');
58
+ log.error('Not initialized. Run: codex-copilot init');
51
59
  process.exit(1);
52
60
  }
53
61
  await status(projectDir);
@@ -58,26 +66,29 @@ async function main() {
58
66
  break;
59
67
 
60
68
  default:
61
- console.log(' 用法: codex-copilot <command>');
69
+ console.log(' Usage: codex-copilot <command>');
62
70
  console.log('');
63
- console.log(' 命令:');
64
- console.log(' init 初始化项目(自动检测 PRD,生成任务队列)');
65
- console.log(' run 启动自动化开发循环');
66
- console.log(' status 查看当前任务进度');
67
- console.log(' reset 重置状态,重新开始');
71
+ console.log(' Commands:');
72
+ console.log(' init Initialize project (auto-detect PRD, generate task queue)');
73
+ console.log(' run Start automated development loop');
74
+ console.log(' status View current task progress');
75
+ console.log(' reset Reset state and start over');
68
76
  console.log('');
69
- console.log(' 工作流程:');
70
- console.log(' 1. cd 到你的项目目录');
71
- console.log(' 2. codex-copilot init (自动检测 PRD 并拆解任务)');
72
- console.log(' 3. codex-copilot run (开始自动开发循环)');
77
+ console.log(' Workflow:');
78
+ console.log(' 1. cd into your project directory');
79
+ console.log(' 2. codex-copilot init (auto-detect PRD and decompose tasks)');
80
+ console.log(' 3. codex-copilot run (start automated dev loop)');
73
81
  console.log('');
74
82
  break;
75
83
  }
76
84
  } catch (err) {
77
- log.error(`执行失败: ${err.message}`);
85
+ log.error(`Execution failed: ${err.message}`);
78
86
  if (process.env.DEBUG) console.error(err);
79
87
  process.exit(1);
80
88
  }
81
89
  }
82
90
 
91
+ // Check for updates (non-blocking, cached 24h)
92
+ checkForUpdates(version);
93
+
83
94
  main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jojonax/codex-copilot",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "PRD-driven automated development orchestrator for CodeX / Cursor",
5
5
  "bin": {
6
6
  "codex-copilot": "./bin/cli.js"
@@ -1,50 +1,51 @@
1
1
  /**
2
- * codex-copilot init - 初始化项目
2
+ * codex-copilot init - Initialize project
3
3
  *
4
- * 1. 自动检测 PRD 文档
5
- * 2. 让用户确认/选择 PRD
6
- * 3. 生成 CodeX 可执行的任务拆解 Prompt
7
- * 4. 创建 .codex-copilot/ 目录结构
4
+ * 1. Auto-detect PRD document
5
+ * 2. Let user confirm/select PRD
6
+ * 3. Select AI provider (Codex, Claude Code, Cursor, etc.)
7
+ * 4. Generate task decomposition prompt
8
+ * 5. Create .codex-copilot/ directory structure
8
9
  */
9
10
 
10
11
  import { mkdirSync, writeFileSync, readFileSync, existsSync } from 'fs';
11
12
  import { resolve } from 'path';
12
- import { execSync } from 'child_process';
13
13
  import { detectPRD, readPRD } from '../utils/detect-prd.js';
14
14
  import { log } from '../utils/logger.js';
15
15
  import { ask, confirm, select, closePrompt } from '../utils/prompt.js';
16
16
  import { git } from '../utils/git.js';
17
17
  import { github } from '../utils/github.js';
18
+ import { provider } from '../utils/provider.js';
18
19
 
19
20
  export async function init(projectDir) {
20
- log.title('📋 初始化 Codex-Copilot');
21
+ log.title('📋 Initializing Codex-Copilot');
21
22
  log.blank();
22
23
 
23
- // ===== 前置检查 =====
24
- log.step('检查环境...');
24
+ // ===== Pre-flight checks =====
25
+ log.step('Checking environment...');
25
26
 
26
- // 检查是否在 git 仓库中
27
+ // Check if in a git repo
27
28
  try {
28
29
  git.currentBranch(projectDir);
29
- log.info('Git 仓库 ✓');
30
+ log.info('Git repository ✓');
30
31
  } catch {
31
- log.error('当前目录不是 Git 仓库,请先 git init');
32
+ log.error('Not a Git repository. Run: git init');
32
33
  closePrompt();
33
34
  process.exit(1);
34
35
  }
35
36
 
36
- // 检查 gh CLI
37
+ // Check gh CLI
37
38
  if (!github.checkGhAuth()) {
38
- log.error('GitHub CLI 未登录,请先运行: gh auth login');
39
+ log.error('GitHub CLI not authenticated. Run: gh auth login');
39
40
  closePrompt();
40
41
  process.exit(1);
41
42
  }
42
43
  log.info('GitHub CLI ✓');
43
44
 
44
- // 检查 GitHub remote
45
+ // Check GitHub remote
45
46
  try {
46
47
  const repo = git.getRepoInfo(projectDir);
47
- log.info(`GitHub 仓库: ${repo.owner}/${repo.repo} ✓`);
48
+ log.info(`GitHub repo: ${repo.owner}/${repo.repo} ✓`);
48
49
  } catch (err) {
49
50
  log.error(err.message);
50
51
  closePrompt();
@@ -53,58 +54,69 @@ export async function init(projectDir) {
53
54
 
54
55
  log.blank();
55
56
 
56
- // ===== 检测 PRD =====
57
- log.step('扫描 PRD 文档...');
57
+ // ===== Detect PRD =====
58
+ log.step('Scanning for PRD documents...');
58
59
  const candidates = detectPRD(projectDir);
59
60
 
60
61
  let prdPath;
61
62
 
62
63
  if (candidates.length === 0) {
63
- log.warn('未自动检测到 PRD 文档');
64
- const manualPath = await ask('请输入 PRD 文件路径(相对或绝对路径):');
64
+ log.warn('No PRD document detected automatically');
65
+ const manualPath = await ask('Enter PRD file path (relative or absolute):');
65
66
  prdPath = resolve(projectDir, manualPath);
66
- // 防止路径穿越:确保 PRD 路径在项目目录内或是绝对路径
67
+ // Prevent path traversal
67
68
  if (!prdPath.startsWith(resolve(projectDir)) && !manualPath.startsWith('/')) {
68
- log.error('PRD 路径不在项目目录内');
69
+ log.error('PRD path is outside the project directory');
69
70
  closePrompt();
70
71
  process.exit(1);
71
72
  }
72
73
  if (!existsSync(prdPath)) {
73
- log.error(`文件不存在: ${prdPath}`);
74
+ log.error(`File not found: ${prdPath}`);
74
75
  closePrompt();
75
76
  process.exit(1);
76
77
  }
77
78
  } else if (candidates.length === 1) {
78
79
  prdPath = candidates[0].path;
79
- log.info(`找到 PRD: ${candidates[0].relativePath}`);
80
- const ok = await confirm('使用该文件?');
80
+ log.info(`Found PRD: ${candidates[0].relativePath}`);
81
+ const ok = await confirm('Use this file?');
81
82
  if (!ok) {
82
- const manualPath = await ask('请输入 PRD 文件路径:');
83
+ const manualPath = await ask('Enter PRD file path:');
83
84
  prdPath = resolve(projectDir, manualPath);
84
85
  }
85
86
  } else {
86
- log.info(`找到 ${candidates.length} 个候选 PRD 文件:`);
87
- const choice = await select('请选择要使用的 PRD:', candidates.map(c => ({
88
- label: `${c.relativePath} (匹配度: ${c.score})`,
87
+ log.info(`Found ${candidates.length} candidate PRD files:`);
88
+ const choice = await select('Select the PRD to use:', candidates.map(c => ({
89
+ label: `${c.relativePath} (score: ${c.score})`,
89
90
  value: c.path,
90
91
  })));
91
92
  prdPath = choice.value;
92
93
  }
93
94
 
94
- log.info(`使用 PRD: ${prdPath}`);
95
+ log.info(`Using PRD: ${prdPath}`);
95
96
  log.blank();
96
97
 
97
- // ===== 读取 PRD =====
98
+ // ===== Read PRD =====
98
99
  const prdContent = readPRD(prdPath);
99
- log.info(`PRD 大小: ${(prdContent.length / 1024).toFixed(1)} KB`);
100
+ log.info(`PRD size: ${(prdContent.length / 1024).toFixed(1)} KB`);
100
101
 
101
- // ===== 创建 .codex-copilot 目录 =====
102
- log.step('创建 .codex-copilot/ 目录...');
102
+ // ===== Select AI Provider =====
103
+ log.step('Select AI coding tool...');
104
+ log.blank();
105
+ const providerChoices = provider.buildProviderChoices();
106
+ const selectedProvider = await select('Which AI tool will you use?', providerChoices);
107
+ const providerId = selectedProvider.value;
108
+ const providerInfo = provider.getProvider(providerId);
109
+ log.info(`Selected: ${providerInfo.name}`);
110
+ log.blank();
111
+
112
+ // ===== Create .codex-copilot directory =====
113
+ log.step('Creating .codex-copilot/ directory...');
103
114
  const copilotDir = resolve(projectDir, '.codex-copilot');
104
115
  mkdirSync(copilotDir, { recursive: true });
105
116
 
106
- // 写入配置文件
117
+ // Write config file
107
118
  const config = {
119
+ provider: providerId,
108
120
  prd_path: prdPath,
109
121
  base_branch: git.currentBranch(projectDir) || 'main',
110
122
  max_review_rounds: 2,
@@ -114,37 +126,41 @@ export async function init(projectDir) {
114
126
  };
115
127
  writeFileSync(resolve(copilotDir, 'config.json'), JSON.stringify(config, null, 2));
116
128
 
117
- // 写入初始状态
129
+ // Write initial state (matches checkpoint.js schema)
118
130
  const state = {
119
131
  current_task: 0,
132
+ phase: null,
133
+ phase_step: null,
120
134
  current_pr: null,
121
135
  review_round: 0,
136
+ branch: null,
122
137
  status: 'initialized',
138
+ last_updated: new Date().toISOString(),
123
139
  };
124
140
  writeFileSync(resolve(copilotDir, 'state.json'), JSON.stringify(state, null, 2));
125
141
 
126
- // 写入 CodeX 指令模板
127
- const instructions = `# Codex-Copilot 开发指令
142
+ // Write CodeX instruction template
143
+ const instructions = `# Codex-Copilot Development Instructions
128
144
 
129
- ## 角色
130
- 你是一个高效的自动开发 Agent,负责按照任务描述完成功能开发。
145
+ ## Role
146
+ You are an efficient automated development agent responsible for completing feature development according to task descriptions.
131
147
 
132
- ## 规则
133
- 1. **严格遵循项目技术栈**:使用项目已有的框架、工具和代码风格
134
- 2. **自测优先**:开发完成前确保代码可以编译/运行
135
- 3. **Git 规范**:提交信息格式 \`feat(task-N): 简要描述\` \`fix(task-N): 简要描述\`
136
- 4. **不要修改无关文件**:只修改当前任务需要的文件
137
- 5. **完成后执行 git commit**:\`git add -A && git commit -m "..."\`
148
+ ## Rules
149
+ 1. **Follow the project tech stack**: Use the existing frameworks, tools, and code style
150
+ 2. **Test first**: Ensure code compiles/runs before finishing
151
+ 3. **Git conventions**: Commit message format \`feat(task-N): brief description\` or \`fix(task-N): brief description\`
152
+ 4. **Don't modify unrelated files**: Only change files required by the current task
153
+ 5. **Commit when done**: \`git add -A && git commit -m "..."\`
138
154
 
139
- ## 修复 Review 时的规则
140
- 1. 逐条阅读 Review 意见
141
- 2. 区分必须修复 vs 建议性意见
142
- 3. 对于不认同的意见,在 commit message 中说明原因
143
- 4. 修复后确保不引入新问题
155
+ ## Rules for fixing reviews
156
+ 1. Read each review comment carefully
157
+ 2. Distinguish between must-fix vs. suggestions
158
+ 3. If you disagree with a comment, explain why in the commit message
159
+ 4. Ensure fixes don't introduce new issues
144
160
  `;
145
161
  writeFileSync(resolve(copilotDir, 'codex-instructions.md'), instructions);
146
162
 
147
- // 添加 .gitignore
163
+ // Add .gitignore entries
148
164
  const gitignorePath = resolve(projectDir, '.gitignore');
149
165
  const gitignoreEntry = '\n# Codex-Copilot state\n.codex-copilot/state.json\n';
150
166
  if (existsSync(gitignorePath)) {
@@ -154,88 +170,80 @@ export async function init(projectDir) {
154
170
  }
155
171
  }
156
172
 
157
- log.info('.codex-copilot/ 目录已创建');
173
+ log.info('.codex-copilot/ directory created');
158
174
  log.blank();
159
175
 
160
- // ===== 生成任务拆解 Prompt =====
161
- log.step('生成任务拆解 Prompt...');
176
+ // ===== Generate task decomposition prompt =====
177
+ log.step('Generating task decomposition prompt...');
162
178
 
163
179
  const parsePrompt = buildParsePrompt(prdContent, copilotDir);
164
180
  const promptPath = resolve(copilotDir, 'parse-prd-prompt.md');
165
181
  writeFileSync(promptPath, parsePrompt);
166
182
 
167
- log.info(`任务拆解 Prompt 已保存到: .codex-copilot/parse-prd-prompt.md`);
183
+ log.info('Task decomposition prompt saved to: .codex-copilot/parse-prd-prompt.md');
168
184
  log.blank();
169
185
 
170
- // ===== 提示用户下一步 =====
171
- log.title('✅ 初始化完成!');
172
- log.blank();
173
- log.info('接下来请执行以下步骤:');
186
+ // ===== Guide user to next steps =====
187
+ log.title('✅ Initialization complete!');
174
188
  log.blank();
175
- console.log(' ┌───────────────────────────────────────────────────┐');
176
- console.log(' │ 1. 打开 CodeX 桌面版 │');
177
- console.log(' │ 2. 将以下文件内容粘贴给 CodeX 执行: │');
178
- console.log(' │ .codex-copilot/parse-prd-prompt.md │');
179
- console.log(' │ 3. CodeX 会生成 .codex-copilot/tasks.json │');
180
- console.log(' │ 4. 确认任务列表后运行: │');
181
- console.log(' │ codex-copilot run │');
182
- console.log(' └───────────────────────────────────────────────────┘');
189
+ log.info(`AI Provider: ${providerInfo.name}`);
183
190
  log.blank();
184
191
 
185
- // 询问是否尝试自动拆解(如果 codex CLI 可用)
186
- const hasCodexCLI = checkCodexCLI();
187
- if (hasCodexCLI) {
188
- log.info('检测到 CodeX CLI 可用!');
189
- const autoparse = await confirm('是否自动调用 CodeX 拆解 PRD?');
192
+ if (providerInfo.type === 'cli') {
193
+ // CLI provider: offer auto-decompose
194
+ const autoparse = await confirm(`Auto-invoke ${providerInfo.name} to decompose PRD?`);
190
195
  if (autoparse) {
191
- log.step('调用 CodeX CLI 拆解 PRD...');
192
- try {
193
- execSync(`codex -q --file .codex-copilot/parse-prd-prompt.md`, {
194
- cwd: projectDir,
195
- stdio: 'inherit',
196
- });
197
- log.info('CodeX 拆解完成!');
198
- } catch {
199
- log.warn('CodeX CLI 调用失败,请手动执行');
196
+ log.step(`Invoking ${providerInfo.name} to decompose PRD...`);
197
+ const ok = await provider.executePrompt(providerId, promptPath, projectDir);
198
+ if (ok) {
199
+ log.info('PRD decomposition complete!');
200
200
  }
201
+ } else {
202
+ showManualInstructions(providerInfo);
201
203
  }
204
+ } else {
205
+ // IDE provider: show manual instructions
206
+ showManualInstructions(providerInfo);
202
207
  }
203
208
 
204
209
  closePrompt();
205
210
  }
206
211
 
207
- function checkCodexCLI() {
208
- try {
209
- const cmd = process.platform === 'win32' ? 'where codex' : 'which codex';
210
- execSync(cmd, { stdio: 'pipe' });
211
- return true;
212
- } catch {
213
- return false;
214
- }
212
+ function showManualInstructions(providerInfo) {
213
+ log.info('Next steps:');
214
+ log.blank();
215
+ console.log(' ┌───────────────────────────────────────────────────┐');
216
+ console.log(` │ 1. Open ${providerInfo.name.padEnd(40)}│`);
217
+ console.log(' │ 2. Paste the file content: │');
218
+ console.log(' │ .codex-copilot/parse-prd-prompt.md │');
219
+ console.log(' │ 3. AI will generate .codex-copilot/tasks.json │');
220
+ console.log(' │ 4. Then run: codex-copilot run │');
221
+ console.log(' └───────────────────────────────────────────────────┘');
222
+ log.blank();
215
223
  }
216
224
 
217
225
  function buildParsePrompt(prdContent, copilotDir) {
218
- return `请阅读以下 PRD 文档,将其拆解为独立的开发任务。
226
+ return `Read the following PRD document and break it down into independent development tasks.
219
227
 
220
- ## 要求
221
- 1. 每个任务在一个 PR 中可以完成(粒度适中,不要太大也不要太碎)
222
- 2. 有明确的验收标准
223
- 3. 按依赖关系排序(被依赖的任务排在前面)
224
- 4. 第一个任务通常是"项目初始化 / 基础框架搭建"
228
+ ## Requirements
229
+ 1. Each task should be completable in a single PR (moderate granularity — not too large, not too small)
230
+ 2. Each task must have clear acceptance criteria
231
+ 3. Tasks should be ordered by dependency (dependent tasks first)
232
+ 4. The first task is usually "Project initialization / base framework setup"
225
233
 
226
- ## 输出格式
227
- 将结果输出到 \`.codex-copilot/tasks.json\`,格式如下:
234
+ ## Output Format
235
+ Write the result to \`.codex-copilot/tasks.json\` in the following format:
228
236
 
229
237
  \`\`\`json
230
238
  {
231
- "project": "项目名称",
239
+ "project": "Project Name",
232
240
  "total": 5,
233
241
  "tasks": [
234
242
  {
235
243
  "id": 1,
236
- "title": "任务标题(简短)",
237
- "description": "详细的任务描述,包含需要实现的具体功能和技术细节",
238
- "acceptance": ["验收条件1", "验收条件2"],
244
+ "title": "Task title (brief)",
245
+ "description": "Detailed task description with specific features and technical details",
246
+ "acceptance": ["Acceptance criteria 1", "Acceptance criteria 2"],
239
247
  "branch": "feature/001-task-slug",
240
248
  "status": "pending",
241
249
  "depends_on": []
@@ -253,7 +261,7 @@ function buildParsePrompt(prdContent, copilotDir) {
253
261
  }
254
262
  \`\`\`
255
263
 
256
- ## PRD 文档内容
264
+ ## PRD Document Content
257
265
 
258
266
  ${prdContent}
259
267
  `;
@@ -1,52 +1,60 @@
1
1
  /**
2
- * codex-copilot reset - 重置状态
2
+ * codex-copilot reset - Reset state
3
3
  */
4
4
 
5
5
  import { readFileSync, writeFileSync, existsSync, unlinkSync } from 'fs';
6
6
  import { resolve } from 'path';
7
7
  import { log } from '../utils/logger.js';
8
8
  import { confirm, closePrompt } from '../utils/prompt.js';
9
+ import { createCheckpoint } from '../utils/checkpoint.js';
9
10
 
10
11
  export async function reset(projectDir) {
11
12
  const statePath = resolve(projectDir, '.codex-copilot/state.json');
12
13
  const tasksPath = resolve(projectDir, '.codex-copilot/tasks.json');
13
14
 
14
15
  if (!existsSync(statePath)) {
15
- log.warn('项目未初始化,无需重置');
16
+ log.warn('Project not initialized, nothing to reset');
16
17
  closePrompt();
17
18
  return;
18
19
  }
19
20
 
20
- log.title('🔄 重置 Codex-Copilot 状态');
21
+ log.title('🔄 Resetting Codex-Copilot state');
21
22
  log.blank();
22
23
 
23
- const resetTasks = await confirm('是否同时重置任务状态 (所有任务标记为 pending)?', false);
24
+ const checkpoint = createCheckpoint(projectDir);
25
+ const state = checkpoint.load();
24
26
 
25
- // 重置 state
26
- const state = {
27
- current_task: 0,
28
- current_pr: null,
29
- review_round: 0,
30
- status: 'initialized',
31
- };
32
- writeFileSync(statePath, JSON.stringify(state, null, 2));
33
- log.info('执行状态已重置');
27
+ // Show current checkpoint before reset
28
+ if (state.phase) {
29
+ log.info(`Current checkpoint: Task #${state.current_task} — ${state.phase} → ${state.phase_step}`);
30
+ log.blank();
31
+ }
32
+
33
+ const resetTasks = await confirm('Also reset all task statuses to pending?', false);
34
34
 
35
- // 重置任务状态
35
+ // Reset state using checkpoint manager
36
+ checkpoint.reset();
37
+ log.info('Execution state reset');
38
+
39
+ // Reset task statuses
36
40
  if (resetTasks && existsSync(tasksPath)) {
37
41
  const tasks = JSON.parse(readFileSync(tasksPath, 'utf-8'));
38
42
  for (const task of tasks.tasks) {
39
43
  task.status = 'pending';
40
44
  }
41
45
  writeFileSync(tasksPath, JSON.stringify(tasks, null, 2));
42
- log.info('任务状态已重置');
46
+ log.info('Task statuses reset');
43
47
  }
44
48
 
45
- // 清理临时文件
49
+ // Clean up temp files
46
50
  const promptPath = resolve(projectDir, '.codex-copilot/_current_prompt.md');
47
51
  if (existsSync(promptPath)) unlinkSync(promptPath);
48
52
 
53
+ // Clean up temp state file if exists
54
+ const tempPath = resolve(projectDir, '.codex-copilot/state.json.tmp');
55
+ if (existsSync(tempPath)) unlinkSync(tempPath);
56
+
49
57
  log.blank();
50
- log.info('✅ 重置完成,可以重新运行 codex-copilot run');
58
+ log.info('✅ Reset complete. You can now run: codex-copilot run');
51
59
  closePrompt();
52
60
  }