@codebakers/cli 3.6.0 → 3.7.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/dist/commands/go.js +87 -72
- package/package.json +1 -1
- package/src/commands/go.ts +101 -83
package/dist/commands/go.js
CHANGED
|
@@ -129,93 +129,108 @@ async function go(options = {}) {
|
|
|
129
129
|
}
|
|
130
130
|
// New user - ask how they want to proceed
|
|
131
131
|
console.log(chalk_1.default.white(' How would you like to get started?\n'));
|
|
132
|
-
console.log(chalk_1.default.cyan(' [1] Start free 7-day trial') + chalk_1.default.gray(' (
|
|
132
|
+
console.log(chalk_1.default.cyan(' [1] Start free 7-day trial') + chalk_1.default.gray(' (GitHub login required)'));
|
|
133
133
|
console.log(chalk_1.default.cyan(' [2] Login with API key') + chalk_1.default.gray(' (I have an account)\n'));
|
|
134
134
|
const choice = await prompt(chalk_1.default.gray(' Enter 1 or 2: '));
|
|
135
135
|
if (choice === '2') {
|
|
136
136
|
await handleApiKeyLogin(options);
|
|
137
137
|
return;
|
|
138
138
|
}
|
|
139
|
-
// Start new trial
|
|
140
|
-
|
|
139
|
+
// Start new trial via GitHub OAuth
|
|
140
|
+
await startTrialWithGitHub(options);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Open a URL in the default browser
|
|
144
|
+
*/
|
|
145
|
+
function openBrowser(url) {
|
|
146
|
+
const platform = process.platform;
|
|
141
147
|
try {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const response = await fetch(`${apiUrl}/api/trial/start`, {
|
|
145
|
-
method: 'POST',
|
|
146
|
-
headers: { 'Content-Type': 'application/json' },
|
|
147
|
-
body: JSON.stringify({
|
|
148
|
-
deviceHash: fingerprint.deviceHash,
|
|
149
|
-
machineId: fingerprint.machineId,
|
|
150
|
-
platform: fingerprint.platform,
|
|
151
|
-
hostname: fingerprint.hostname,
|
|
152
|
-
}),
|
|
153
|
-
});
|
|
154
|
-
const data = await response.json();
|
|
155
|
-
if (data.error === 'trial_not_available') {
|
|
156
|
-
spinner.fail('Trial not available');
|
|
157
|
-
console.log(chalk_1.default.yellow(`
|
|
158
|
-
It looks like you've already used a CodeBakers trial.
|
|
159
|
-
|
|
160
|
-
Ready to upgrade? $49/month for unlimited access.
|
|
161
|
-
|
|
162
|
-
${chalk_1.default.cyan('codebakers upgrade')} or visit ${chalk_1.default.underline('https://codebakers.ai/pricing')}
|
|
163
|
-
`));
|
|
164
|
-
return;
|
|
148
|
+
if (platform === 'win32') {
|
|
149
|
+
(0, child_process_1.execSync)(`start "" "${url}"`, { stdio: 'ignore', shell: 'cmd.exe' });
|
|
165
150
|
}
|
|
166
|
-
if (
|
|
167
|
-
|
|
151
|
+
else if (platform === 'darwin') {
|
|
152
|
+
(0, child_process_1.execSync)(`open "${url}"`, { stdio: 'ignore' });
|
|
168
153
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
console.log(chalk_1.default.cyan(' codebakers extend\n'));
|
|
176
|
-
}
|
|
177
|
-
else {
|
|
178
|
-
console.log(chalk_1.default.white(' Ready to upgrade? $49/month for unlimited access:\n'));
|
|
179
|
-
console.log(chalk_1.default.cyan(' codebakers upgrade\n'));
|
|
180
|
-
}
|
|
181
|
-
return;
|
|
154
|
+
else {
|
|
155
|
+
// Linux - try common browsers
|
|
156
|
+
(0, child_process_1.execSync)(`xdg-open "${url}" || sensible-browser "${url}" || x-www-browser "${url}"`, {
|
|
157
|
+
stdio: 'ignore',
|
|
158
|
+
shell: '/bin/sh',
|
|
159
|
+
});
|
|
182
160
|
}
|
|
183
|
-
// Save trial state
|
|
184
|
-
const trialState = {
|
|
185
|
-
trialId: data.trialId,
|
|
186
|
-
stage: data.stage,
|
|
187
|
-
deviceHash: fingerprint.deviceHash,
|
|
188
|
-
expiresAt: data.expiresAt,
|
|
189
|
-
startedAt: data.startedAt,
|
|
190
|
-
...(data.githubUsername && { githubUsername: data.githubUsername }),
|
|
191
|
-
...(data.projectId && { projectId: data.projectId }),
|
|
192
|
-
...(data.projectName && { projectName: data.projectName }),
|
|
193
|
-
};
|
|
194
|
-
(0, config_js_1.setTrialState)(trialState);
|
|
195
|
-
spinner.succeed(`Trial started (${data.daysRemaining} days free)`);
|
|
196
|
-
console.log('');
|
|
197
|
-
// Install v6.0 bootstrap files (CLAUDE.md and .cursorrules only)
|
|
198
|
-
await installPatterns(data.trialId, options);
|
|
199
|
-
// Configure MCP
|
|
200
|
-
await configureMCP(options);
|
|
201
|
-
// Show success and restart
|
|
202
|
-
await showSuccessAndRestart();
|
|
203
161
|
}
|
|
204
|
-
catch
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
162
|
+
catch {
|
|
163
|
+
console.log(chalk_1.default.yellow(`\n Could not open browser automatically.`));
|
|
164
|
+
console.log(chalk_1.default.gray(` Please open this URL manually:\n`));
|
|
165
|
+
console.log(chalk_1.default.cyan(` ${url}\n`));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Sleep for a specified number of milliseconds
|
|
170
|
+
*/
|
|
171
|
+
function sleep(ms) {
|
|
172
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Start a new trial via GitHub OAuth
|
|
176
|
+
* This ensures one trial per GitHub account
|
|
177
|
+
*/
|
|
178
|
+
async function startTrialWithGitHub(options = {}) {
|
|
179
|
+
const fingerprint = (0, fingerprint_js_1.getDeviceFingerprint)();
|
|
180
|
+
const apiUrl = (0, config_js_1.getApiUrl)();
|
|
181
|
+
const authUrl = `${apiUrl}/api/auth/github/trial?device_hash=${fingerprint.deviceHash}`;
|
|
182
|
+
console.log(chalk_1.default.white('\n Opening browser for GitHub authorization...\n'));
|
|
183
|
+
console.log(chalk_1.default.gray(' This links your trial to your GitHub account to prevent abuse.\n'));
|
|
184
|
+
openBrowser(authUrl);
|
|
185
|
+
console.log(chalk_1.default.gray(' Waiting for authorization...'));
|
|
186
|
+
console.log(chalk_1.default.gray(' (This may take a moment)\n'));
|
|
187
|
+
// Poll for trial creation
|
|
188
|
+
const spinner = (0, ora_1.default)('Checking authorization status...').start();
|
|
189
|
+
let trialCreated = false;
|
|
190
|
+
let pollCount = 0;
|
|
191
|
+
const maxPolls = 60; // 2 minutes max
|
|
192
|
+
while (pollCount < maxPolls && !trialCreated) {
|
|
193
|
+
await sleep(2000);
|
|
194
|
+
pollCount++;
|
|
195
|
+
try {
|
|
196
|
+
const response = await fetch(`${apiUrl}/api/trial/status?deviceHash=${fingerprint.deviceHash}`);
|
|
197
|
+
const data = await response.json();
|
|
198
|
+
if (response.ok && data.trialId) {
|
|
199
|
+
trialCreated = true;
|
|
200
|
+
// Save trial state
|
|
201
|
+
const trialState = {
|
|
202
|
+
trialId: data.trialId,
|
|
203
|
+
stage: data.stage,
|
|
204
|
+
deviceHash: fingerprint.deviceHash,
|
|
205
|
+
expiresAt: data.expiresAt,
|
|
206
|
+
startedAt: data.startedAt,
|
|
207
|
+
...(data.githubUsername && { githubUsername: data.githubUsername }),
|
|
208
|
+
...(data.projectId && { projectId: data.projectId }),
|
|
209
|
+
...(data.projectName && { projectName: data.projectName }),
|
|
210
|
+
};
|
|
211
|
+
(0, config_js_1.setTrialState)(trialState);
|
|
212
|
+
const username = data.githubUsername ? ` Welcome, @${data.githubUsername}!` : '';
|
|
213
|
+
spinner.succeed(`Trial started (${data.daysRemaining} days free)${username}`);
|
|
214
|
+
console.log('');
|
|
215
|
+
// Install v6.0 bootstrap files
|
|
216
|
+
await installPatterns(data.trialId, options);
|
|
217
|
+
// Configure MCP
|
|
218
|
+
await configureMCP(options);
|
|
219
|
+
// Show success and restart
|
|
220
|
+
await showSuccessAndRestart();
|
|
221
|
+
return;
|
|
213
222
|
}
|
|
214
223
|
}
|
|
215
|
-
|
|
216
|
-
|
|
224
|
+
catch {
|
|
225
|
+
// Ignore polling errors - continue waiting
|
|
226
|
+
log(`Poll ${pollCount} failed, retrying...`, options);
|
|
217
227
|
}
|
|
218
228
|
}
|
|
229
|
+
if (!trialCreated) {
|
|
230
|
+
spinner.warn('Authorization timed out');
|
|
231
|
+
console.log(chalk_1.default.yellow('\n Please try again or authorize manually:\n'));
|
|
232
|
+
console.log(chalk_1.default.cyan(` ${authUrl}\n`));
|
|
233
|
+
}
|
|
219
234
|
}
|
|
220
235
|
async function configureMCP(options = {}) {
|
|
221
236
|
log('Configuring MCP integration...', options);
|
package/package.json
CHANGED
package/src/commands/go.ts
CHANGED
|
@@ -165,7 +165,7 @@ export async function go(options: GoOptions = {}): Promise<void> {
|
|
|
165
165
|
|
|
166
166
|
// New user - ask how they want to proceed
|
|
167
167
|
console.log(chalk.white(' How would you like to get started?\n'));
|
|
168
|
-
console.log(chalk.cyan(' [1] Start free 7-day trial') + chalk.gray(' (
|
|
168
|
+
console.log(chalk.cyan(' [1] Start free 7-day trial') + chalk.gray(' (GitHub login required)'));
|
|
169
169
|
console.log(chalk.cyan(' [2] Login with API key') + chalk.gray(' (I have an account)\n'));
|
|
170
170
|
|
|
171
171
|
const choice = await prompt(chalk.gray(' Enter 1 or 2: '));
|
|
@@ -175,96 +175,114 @@ export async function go(options: GoOptions = {}): Promise<void> {
|
|
|
175
175
|
return;
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
// Start new trial
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
try {
|
|
182
|
-
const fingerprint = getDeviceFingerprint();
|
|
183
|
-
const apiUrl = getApiUrl();
|
|
184
|
-
|
|
185
|
-
const response = await fetch(`${apiUrl}/api/trial/start`, {
|
|
186
|
-
method: 'POST',
|
|
187
|
-
headers: { 'Content-Type': 'application/json' },
|
|
188
|
-
body: JSON.stringify({
|
|
189
|
-
deviceHash: fingerprint.deviceHash,
|
|
190
|
-
machineId: fingerprint.machineId,
|
|
191
|
-
platform: fingerprint.platform,
|
|
192
|
-
hostname: fingerprint.hostname,
|
|
193
|
-
}),
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
const data = await response.json();
|
|
197
|
-
|
|
198
|
-
if (data.error === 'trial_not_available') {
|
|
199
|
-
spinner.fail('Trial not available');
|
|
200
|
-
console.log(chalk.yellow(`
|
|
201
|
-
It looks like you've already used a CodeBakers trial.
|
|
178
|
+
// Start new trial via GitHub OAuth
|
|
179
|
+
await startTrialWithGitHub(options);
|
|
180
|
+
}
|
|
202
181
|
|
|
203
|
-
|
|
182
|
+
/**
|
|
183
|
+
* Open a URL in the default browser
|
|
184
|
+
*/
|
|
185
|
+
function openBrowser(url: string): void {
|
|
186
|
+
const platform = process.platform;
|
|
204
187
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
188
|
+
try {
|
|
189
|
+
if (platform === 'win32') {
|
|
190
|
+
execSync(`start "" "${url}"`, { stdio: 'ignore', shell: 'cmd.exe' });
|
|
191
|
+
} else if (platform === 'darwin') {
|
|
192
|
+
execSync(`open "${url}"`, { stdio: 'ignore' });
|
|
193
|
+
} else {
|
|
194
|
+
// Linux - try common browsers
|
|
195
|
+
execSync(`xdg-open "${url}" || sensible-browser "${url}" || x-www-browser "${url}"`, {
|
|
196
|
+
stdio: 'ignore',
|
|
197
|
+
shell: '/bin/sh',
|
|
198
|
+
});
|
|
208
199
|
}
|
|
200
|
+
} catch {
|
|
201
|
+
console.log(chalk.yellow(`\n Could not open browser automatically.`));
|
|
202
|
+
console.log(chalk.gray(` Please open this URL manually:\n`));
|
|
203
|
+
console.log(chalk.cyan(` ${url}\n`));
|
|
204
|
+
}
|
|
205
|
+
}
|
|
209
206
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
207
|
+
/**
|
|
208
|
+
* Sleep for a specified number of milliseconds
|
|
209
|
+
*/
|
|
210
|
+
function sleep(ms: number): Promise<void> {
|
|
211
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
212
|
+
}
|
|
213
213
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
214
|
+
/**
|
|
215
|
+
* Start a new trial via GitHub OAuth
|
|
216
|
+
* This ensures one trial per GitHub account
|
|
217
|
+
*/
|
|
218
|
+
async function startTrialWithGitHub(options: GoOptions = {}): Promise<void> {
|
|
219
|
+
const fingerprint = getDeviceFingerprint();
|
|
220
|
+
const apiUrl = getApiUrl();
|
|
221
|
+
const authUrl = `${apiUrl}/api/auth/github/trial?device_hash=${fingerprint.deviceHash}`;
|
|
222
|
+
|
|
223
|
+
console.log(chalk.white('\n Opening browser for GitHub authorization...\n'));
|
|
224
|
+
console.log(chalk.gray(' This links your trial to your GitHub account to prevent abuse.\n'));
|
|
225
|
+
|
|
226
|
+
openBrowser(authUrl);
|
|
227
|
+
|
|
228
|
+
console.log(chalk.gray(' Waiting for authorization...'));
|
|
229
|
+
console.log(chalk.gray(' (This may take a moment)\n'));
|
|
230
|
+
|
|
231
|
+
// Poll for trial creation
|
|
232
|
+
const spinner = ora('Checking authorization status...').start();
|
|
233
|
+
let trialCreated = false;
|
|
234
|
+
let pollCount = 0;
|
|
235
|
+
const maxPolls = 60; // 2 minutes max
|
|
236
|
+
|
|
237
|
+
while (pollCount < maxPolls && !trialCreated) {
|
|
238
|
+
await sleep(2000);
|
|
239
|
+
pollCount++;
|
|
240
|
+
|
|
241
|
+
try {
|
|
242
|
+
const response = await fetch(`${apiUrl}/api/trial/status?deviceHash=${fingerprint.deviceHash}`);
|
|
243
|
+
const data = await response.json();
|
|
244
|
+
|
|
245
|
+
if (response.ok && data.trialId) {
|
|
246
|
+
trialCreated = true;
|
|
247
|
+
|
|
248
|
+
// Save trial state
|
|
249
|
+
const trialState: TrialState = {
|
|
250
|
+
trialId: data.trialId,
|
|
251
|
+
stage: data.stage,
|
|
252
|
+
deviceHash: fingerprint.deviceHash,
|
|
253
|
+
expiresAt: data.expiresAt,
|
|
254
|
+
startedAt: data.startedAt,
|
|
255
|
+
...(data.githubUsername && { githubUsername: data.githubUsername }),
|
|
256
|
+
...(data.projectId && { projectId: data.projectId }),
|
|
257
|
+
...(data.projectName && { projectName: data.projectName }),
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
setTrialState(trialState);
|
|
261
|
+
|
|
262
|
+
const username = data.githubUsername ? ` Welcome, @${data.githubUsername}!` : '';
|
|
263
|
+
spinner.succeed(`Trial started (${data.daysRemaining} days free)${username}`);
|
|
264
|
+
console.log('');
|
|
265
|
+
|
|
266
|
+
// Install v6.0 bootstrap files
|
|
267
|
+
await installPatterns(data.trialId, options);
|
|
268
|
+
|
|
269
|
+
// Configure MCP
|
|
270
|
+
await configureMCP(options);
|
|
271
|
+
|
|
272
|
+
// Show success and restart
|
|
273
|
+
await showSuccessAndRestart();
|
|
274
|
+
return;
|
|
225
275
|
}
|
|
226
|
-
|
|
276
|
+
} catch {
|
|
277
|
+
// Ignore polling errors - continue waiting
|
|
278
|
+
log(`Poll ${pollCount} failed, retrying...`, options);
|
|
227
279
|
}
|
|
280
|
+
}
|
|
228
281
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
deviceHash: fingerprint.deviceHash,
|
|
234
|
-
expiresAt: data.expiresAt,
|
|
235
|
-
startedAt: data.startedAt,
|
|
236
|
-
...(data.githubUsername && { githubUsername: data.githubUsername }),
|
|
237
|
-
...(data.projectId && { projectId: data.projectId }),
|
|
238
|
-
...(data.projectName && { projectName: data.projectName }),
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
setTrialState(trialState);
|
|
242
|
-
|
|
243
|
-
spinner.succeed(`Trial started (${data.daysRemaining} days free)`);
|
|
244
|
-
console.log('');
|
|
245
|
-
|
|
246
|
-
// Install v6.0 bootstrap files (CLAUDE.md and .cursorrules only)
|
|
247
|
-
await installPatterns(data.trialId, options);
|
|
248
|
-
|
|
249
|
-
// Configure MCP
|
|
250
|
-
await configureMCP(options);
|
|
251
|
-
|
|
252
|
-
// Show success and restart
|
|
253
|
-
await showSuccessAndRestart();
|
|
254
|
-
|
|
255
|
-
} catch (error) {
|
|
256
|
-
spinner.fail('Failed to start trial');
|
|
257
|
-
|
|
258
|
-
if (error instanceof Error) {
|
|
259
|
-
if (error.message.includes('fetch') || error.message.includes('network')) {
|
|
260
|
-
console.log(chalk.red('\n Could not connect to CodeBakers server.'));
|
|
261
|
-
console.log(chalk.gray(' Check your internet connection and try again.\n'));
|
|
262
|
-
} else {
|
|
263
|
-
console.log(chalk.red(`\n ${error.message}\n`));
|
|
264
|
-
}
|
|
265
|
-
} else {
|
|
266
|
-
console.log(chalk.red('\n An unexpected error occurred.\n'));
|
|
267
|
-
}
|
|
282
|
+
if (!trialCreated) {
|
|
283
|
+
spinner.warn('Authorization timed out');
|
|
284
|
+
console.log(chalk.yellow('\n Please try again or authorize manually:\n'));
|
|
285
|
+
console.log(chalk.cyan(` ${authUrl}\n`));
|
|
268
286
|
}
|
|
269
287
|
}
|
|
270
288
|
|