@codebakers/cli 2.9.0 → 3.0.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/dist/commands/billing.d.ts +4 -0
- package/dist/commands/billing.js +91 -0
- package/dist/commands/extend.d.ts +4 -0
- package/dist/commands/extend.js +141 -0
- package/dist/commands/go.d.ts +4 -0
- package/dist/commands/go.js +173 -0
- package/dist/config.d.ts +33 -0
- package/dist/config.js +83 -1
- package/dist/index.js +23 -5
- package/dist/lib/fingerprint.d.ts +23 -0
- package/dist/lib/fingerprint.js +136 -0
- package/dist/mcp/server.js +49 -16
- package/package.json +1 -1
- package/src/commands/billing.ts +99 -0
- package/src/commands/extend.ts +157 -0
- package/src/commands/go.ts +197 -0
- package/src/config.ts +101 -1
- package/src/index.ts +26 -5
- package/src/lib/fingerprint.ts +122 -0
- package/src/mcp/server.ts +60 -17
package/src/mcp/server.ts
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
ErrorCode,
|
|
9
9
|
McpError,
|
|
10
10
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
11
|
-
import { getApiKey, getApiUrl, getExperienceLevel, setExperienceLevel, getServiceKey, setServiceKey, type ExperienceLevel } from '../config.js';
|
|
11
|
+
import { getApiKey, getApiUrl, getExperienceLevel, setExperienceLevel, getServiceKey, setServiceKey, getTrialState, isTrialExpired, getTrialDaysRemaining, hasValidAccess, getAuthMode, type ExperienceLevel, type TrialState } from '../config.js';
|
|
12
12
|
import { audit as runAudit } from '../commands/audit.js';
|
|
13
13
|
import { heal as runHeal } from '../commands/heal.js';
|
|
14
14
|
import { getCliVersion } from '../lib/api.js';
|
|
@@ -61,12 +61,16 @@ class CodeBakersServer {
|
|
|
61
61
|
private server: Server;
|
|
62
62
|
private apiKey: string | null;
|
|
63
63
|
private apiUrl: string;
|
|
64
|
+
private trialState: TrialState | null;
|
|
65
|
+
private authMode: 'apiKey' | 'trial' | 'none';
|
|
64
66
|
private autoUpdateChecked = false;
|
|
65
67
|
private autoUpdateInProgress = false;
|
|
66
68
|
|
|
67
69
|
constructor() {
|
|
68
70
|
this.apiKey = getApiKey();
|
|
69
71
|
this.apiUrl = getApiUrl();
|
|
72
|
+
this.trialState = getTrialState();
|
|
73
|
+
this.authMode = getAuthMode();
|
|
70
74
|
|
|
71
75
|
this.server = new Server(
|
|
72
76
|
{
|
|
@@ -88,12 +92,28 @@ class CodeBakersServer {
|
|
|
88
92
|
});
|
|
89
93
|
}
|
|
90
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Get authorization headers for API requests
|
|
97
|
+
* Supports both API key (paid users) and trial ID (free users)
|
|
98
|
+
*/
|
|
99
|
+
private getAuthHeaders(): Record<string, string> {
|
|
100
|
+
if (this.apiKey) {
|
|
101
|
+
return { 'Authorization': `Bearer ${this.apiKey}` };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (this.trialState?.trialId) {
|
|
105
|
+
return { 'X-Trial-Id': this.trialState.trialId };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return {};
|
|
109
|
+
}
|
|
110
|
+
|
|
91
111
|
/**
|
|
92
112
|
* Automatically check for and apply pattern updates
|
|
93
113
|
* Runs silently in background - no user intervention needed
|
|
94
114
|
*/
|
|
95
115
|
private async checkAndAutoUpdate(): Promise<void> {
|
|
96
|
-
if (this.autoUpdateChecked || this.autoUpdateInProgress ||
|
|
116
|
+
if (this.autoUpdateChecked || this.autoUpdateInProgress || this.authMode === 'none') {
|
|
97
117
|
return;
|
|
98
118
|
}
|
|
99
119
|
|
|
@@ -131,7 +151,7 @@ class CodeBakersServer {
|
|
|
131
151
|
|
|
132
152
|
// Fetch latest version
|
|
133
153
|
const response = await fetch(`${this.apiUrl}/api/content/version`, {
|
|
134
|
-
headers:
|
|
154
|
+
headers: this.getAuthHeaders(),
|
|
135
155
|
});
|
|
136
156
|
|
|
137
157
|
if (!response.ok) {
|
|
@@ -153,7 +173,7 @@ class CodeBakersServer {
|
|
|
153
173
|
|
|
154
174
|
// Fetch full content and update
|
|
155
175
|
const contentResponse = await fetch(`${this.apiUrl}/api/content`, {
|
|
156
|
-
headers:
|
|
176
|
+
headers: this.getAuthHeaders(),
|
|
157
177
|
});
|
|
158
178
|
|
|
159
179
|
if (!contentResponse.ok) {
|
|
@@ -400,7 +420,7 @@ class CodeBakersServer {
|
|
|
400
420
|
let latest: { version: string; moduleCount: number } | null = null;
|
|
401
421
|
try {
|
|
402
422
|
const response = await fetch(`${this.apiUrl}/api/content/version`, {
|
|
403
|
-
headers: this.
|
|
423
|
+
headers: this.getAuthHeaders(),
|
|
404
424
|
});
|
|
405
425
|
if (response.ok) {
|
|
406
426
|
latest = await response.json();
|
|
@@ -879,13 +899,38 @@ class CodeBakersServer {
|
|
|
879
899
|
|
|
880
900
|
// Handle tool calls
|
|
881
901
|
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
882
|
-
|
|
902
|
+
// Check access: API key OR valid trial
|
|
903
|
+
if (this.authMode === 'none') {
|
|
883
904
|
throw new McpError(
|
|
884
905
|
ErrorCode.InvalidRequest,
|
|
885
|
-
'Not logged in. Run `codebakers
|
|
906
|
+
'Not logged in. Run `codebakers go` to start a free trial, or `codebakers setup` if you have an account.'
|
|
886
907
|
);
|
|
887
908
|
}
|
|
888
909
|
|
|
910
|
+
// Check if trial expired
|
|
911
|
+
if (this.authMode === 'trial' && isTrialExpired()) {
|
|
912
|
+
const trialState = getTrialState();
|
|
913
|
+
if (trialState?.stage === 'anonymous') {
|
|
914
|
+
throw new McpError(
|
|
915
|
+
ErrorCode.InvalidRequest,
|
|
916
|
+
'Trial expired. Run `codebakers extend` to add 7 more days with GitHub, or `codebakers billing` to upgrade.'
|
|
917
|
+
);
|
|
918
|
+
} else {
|
|
919
|
+
throw new McpError(
|
|
920
|
+
ErrorCode.InvalidRequest,
|
|
921
|
+
'Trial expired. Run `codebakers billing` to upgrade to a paid plan.'
|
|
922
|
+
);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
// Show warning if trial expiring soon
|
|
927
|
+
if (this.authMode === 'trial') {
|
|
928
|
+
const daysRemaining = getTrialDaysRemaining();
|
|
929
|
+
if (daysRemaining <= 2) {
|
|
930
|
+
console.error(`[CodeBakers] Trial expires in ${daysRemaining} day${daysRemaining !== 1 ? 's' : ''}. Run 'codebakers extend' or 'codebakers billing'.`);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
|
|
889
934
|
const { name, arguments: args } = request.params;
|
|
890
935
|
|
|
891
936
|
switch (name) {
|
|
@@ -977,7 +1022,7 @@ class CodeBakersServer {
|
|
|
977
1022
|
method: 'POST',
|
|
978
1023
|
headers: {
|
|
979
1024
|
'Content-Type': 'application/json',
|
|
980
|
-
|
|
1025
|
+
...this.getAuthHeaders(),
|
|
981
1026
|
},
|
|
982
1027
|
body: JSON.stringify({
|
|
983
1028
|
prompt: userRequest,
|
|
@@ -1103,9 +1148,7 @@ Show the user what their simple request was expanded into, then proceed with the
|
|
|
1103
1148
|
private async handleListPatterns() {
|
|
1104
1149
|
const response = await fetch(`${this.apiUrl}/api/patterns`, {
|
|
1105
1150
|
method: 'GET',
|
|
1106
|
-
headers:
|
|
1107
|
-
Authorization: `Bearer ${this.apiKey}`,
|
|
1108
|
-
},
|
|
1151
|
+
headers: this.getAuthHeaders(),
|
|
1109
1152
|
});
|
|
1110
1153
|
|
|
1111
1154
|
if (!response.ok) {
|
|
@@ -1164,7 +1207,7 @@ Show the user what their simple request was expanded into, then proceed with the
|
|
|
1164
1207
|
method: 'POST',
|
|
1165
1208
|
headers: {
|
|
1166
1209
|
'Content-Type': 'application/json',
|
|
1167
|
-
|
|
1210
|
+
...this.getAuthHeaders(),
|
|
1168
1211
|
},
|
|
1169
1212
|
body: JSON.stringify({ patterns }),
|
|
1170
1213
|
});
|
|
@@ -1188,7 +1231,7 @@ Show the user what their simple request was expanded into, then proceed with the
|
|
|
1188
1231
|
method: 'POST',
|
|
1189
1232
|
headers: {
|
|
1190
1233
|
'Content-Type': 'application/json',
|
|
1191
|
-
|
|
1234
|
+
...this.getAuthHeaders(),
|
|
1192
1235
|
},
|
|
1193
1236
|
body: JSON.stringify({ query }),
|
|
1194
1237
|
});
|
|
@@ -1475,7 +1518,7 @@ Show the user what their simple request was expanded into, then proceed with the
|
|
|
1475
1518
|
|
|
1476
1519
|
const response = await fetch(`${this.apiUrl}/api/content`, {
|
|
1477
1520
|
method: 'GET',
|
|
1478
|
-
headers:
|
|
1521
|
+
headers: this.getAuthHeaders(),
|
|
1479
1522
|
});
|
|
1480
1523
|
|
|
1481
1524
|
if (response.ok) {
|
|
@@ -1881,7 +1924,7 @@ Or if user declines, call without fullDeploy:
|
|
|
1881
1924
|
try {
|
|
1882
1925
|
const response = await fetch(`${this.apiUrl}/api/content`, {
|
|
1883
1926
|
method: 'GET',
|
|
1884
|
-
headers:
|
|
1927
|
+
headers: this.getAuthHeaders(),
|
|
1885
1928
|
});
|
|
1886
1929
|
|
|
1887
1930
|
if (!response.ok) {
|
|
@@ -2991,7 +3034,7 @@ Just describe what you want to build! I'll automatically:
|
|
|
2991
3034
|
method: 'POST',
|
|
2992
3035
|
headers: {
|
|
2993
3036
|
'Content-Type': 'application/json',
|
|
2994
|
-
|
|
3037
|
+
...this.getAuthHeaders(),
|
|
2995
3038
|
},
|
|
2996
3039
|
body: JSON.stringify({
|
|
2997
3040
|
category,
|
|
@@ -3043,7 +3086,7 @@ Just describe what you want to build! I'll automatically:
|
|
|
3043
3086
|
method: 'POST',
|
|
3044
3087
|
headers: {
|
|
3045
3088
|
'Content-Type': 'application/json',
|
|
3046
|
-
|
|
3089
|
+
...this.getAuthHeaders(),
|
|
3047
3090
|
},
|
|
3048
3091
|
body: JSON.stringify({
|
|
3049
3092
|
eventType,
|