@jojonax/codex-copilot 1.0.3 → 1.2.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 +5 -0
- package/package.json +1 -1
- package/src/commands/init.js +44 -36
- package/src/commands/reset.js +16 -8
- package/src/commands/run.js +289 -161
- package/src/commands/status.js +24 -7
- package/src/utils/automator.js +279 -0
- package/src/utils/checkpoint.js +129 -0
- package/src/utils/git.js +6 -2
- package/src/utils/github.js +145 -8
- package/src/utils/provider.js +415 -0
package/bin/cli.js
CHANGED
|
@@ -79,6 +79,11 @@ async function main() {
|
|
|
79
79
|
console.log(' 2. codex-copilot init (auto-detect PRD and decompose tasks)');
|
|
80
80
|
console.log(' 3. codex-copilot run (start automated dev loop)');
|
|
81
81
|
console.log('');
|
|
82
|
+
console.log(' Update:');
|
|
83
|
+
console.log(' npm install -g @jojonax/codex-copilot@latest');
|
|
84
|
+
console.log('');
|
|
85
|
+
console.log(' \x1b[36mⓘ This is a help page. Exit and run the commands above directly in your terminal.\x1b[0m');
|
|
86
|
+
console.log('');
|
|
82
87
|
break;
|
|
83
88
|
}
|
|
84
89
|
} catch (err) {
|
package/package.json
CHANGED
package/src/commands/init.js
CHANGED
|
@@ -3,18 +3,19 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 1. Auto-detect PRD document
|
|
5
5
|
* 2. Let user confirm/select PRD
|
|
6
|
-
* 3.
|
|
7
|
-
* 4.
|
|
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
21
|
log.title('📋 Initializing Codex-Copilot');
|
|
@@ -98,6 +99,16 @@ export async function init(projectDir) {
|
|
|
98
99
|
const prdContent = readPRD(prdPath);
|
|
99
100
|
log.info(`PRD size: ${(prdContent.length / 1024).toFixed(1)} KB`);
|
|
100
101
|
|
|
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
|
+
|
|
101
112
|
// ===== Create .codex-copilot directory =====
|
|
102
113
|
log.step('Creating .codex-copilot/ directory...');
|
|
103
114
|
const copilotDir = resolve(projectDir, '.codex-copilot');
|
|
@@ -105,6 +116,7 @@ export async function init(projectDir) {
|
|
|
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,12 +126,16 @@ export async function init(projectDir) {
|
|
|
114
126
|
};
|
|
115
127
|
writeFileSync(resolve(copilotDir, 'config.json'), JSON.stringify(config, null, 2));
|
|
116
128
|
|
|
117
|
-
// Write initial state
|
|
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
|
|
|
@@ -170,48 +186,40 @@ You are an efficient automated development agent responsible for completing feat
|
|
|
170
186
|
// ===== Guide user to next steps =====
|
|
171
187
|
log.title('✅ Initialization complete!');
|
|
172
188
|
log.blank();
|
|
173
|
-
log.info(
|
|
174
|
-
log.blank();
|
|
175
|
-
console.log(' ┌───────────────────────────────────────────────────┐');
|
|
176
|
-
console.log(' │ 1. Open CodeX Desktop │');
|
|
177
|
-
console.log(' │ 2. Paste the following file content into CodeX: │');
|
|
178
|
-
console.log(' │ .codex-copilot/parse-prd-prompt.md │');
|
|
179
|
-
console.log(' │ 3. CodeX will generate .codex-copilot/tasks.json │');
|
|
180
|
-
console.log(' │ 4. Confirm the task list, then run: │');
|
|
181
|
-
console.log(' │ codex-copilot run │');
|
|
182
|
-
console.log(' └───────────────────────────────────────────────────┘');
|
|
189
|
+
log.info(`AI Provider: ${providerInfo.name}`);
|
|
183
190
|
log.blank();
|
|
184
191
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
log.info('CodeX CLI detected!');
|
|
189
|
-
const autoparse = await confirm('Auto-invoke CodeX to decompose 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(
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
stdio: 'inherit',
|
|
196
|
-
});
|
|
197
|
-
log.info('CodeX decomposition complete!');
|
|
198
|
-
} catch {
|
|
199
|
-
log.warn('CodeX CLI invocation failed. Please run manually.');
|
|
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
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
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) {
|
package/src/commands/reset.js
CHANGED
|
@@ -6,6 +6,7 @@ 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');
|
|
@@ -20,16 +21,19 @@ export async function reset(projectDir) {
|
|
|
20
21
|
log.title('🔄 Resetting Codex-Copilot state');
|
|
21
22
|
log.blank();
|
|
22
23
|
|
|
24
|
+
const checkpoint = createCheckpoint(projectDir);
|
|
25
|
+
const state = checkpoint.load();
|
|
26
|
+
|
|
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
|
+
|
|
23
33
|
const resetTasks = await confirm('Also reset all task statuses to pending?', false);
|
|
24
34
|
|
|
25
|
-
// Reset state
|
|
26
|
-
|
|
27
|
-
current_task: 0,
|
|
28
|
-
current_pr: null,
|
|
29
|
-
review_round: 0,
|
|
30
|
-
status: 'initialized',
|
|
31
|
-
};
|
|
32
|
-
writeFileSync(statePath, JSON.stringify(state, null, 2));
|
|
35
|
+
// Reset state using checkpoint manager
|
|
36
|
+
checkpoint.reset();
|
|
33
37
|
log.info('Execution state reset');
|
|
34
38
|
|
|
35
39
|
// Reset task statuses
|
|
@@ -46,6 +50,10 @@ export async function reset(projectDir) {
|
|
|
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
58
|
log.info('✅ Reset complete. You can now run: codex-copilot run');
|
|
51
59
|
closePrompt();
|