@codebakers/cli 3.2.0 → 3.3.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 +54 -6
- package/dist/commands/upgrade.js +25 -0
- package/dist/config.d.ts +17 -0
- package/dist/config.js +47 -2
- package/dist/index.js +182 -20
- package/dist/lib/api.d.ts +10 -0
- package/dist/lib/api.js +73 -4
- package/dist/mcp/server.js +81 -0
- package/package.json +3 -2
- package/scripts/register-version.js +79 -0
- package/src/commands/go.ts +75 -6
- package/src/commands/upgrade.ts +34 -0
- package/src/config.ts +54 -3
- package/src/index.ts +220 -22
- package/src/lib/api.ts +83 -4
- package/src/mcp/server.ts +90 -0
package/dist/mcp/server.js
CHANGED
|
@@ -89,6 +89,30 @@ class CodeBakersServer {
|
|
|
89
89
|
}
|
|
90
90
|
return {};
|
|
91
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Confirm download to server (non-blocking analytics)
|
|
94
|
+
*/
|
|
95
|
+
async confirmDownload(version, moduleCount) {
|
|
96
|
+
try {
|
|
97
|
+
const headers = {
|
|
98
|
+
'Content-Type': 'application/json',
|
|
99
|
+
...this.getAuthHeaders(),
|
|
100
|
+
};
|
|
101
|
+
await fetch(`${this.apiUrl}/api/content/confirm`, {
|
|
102
|
+
method: 'POST',
|
|
103
|
+
headers,
|
|
104
|
+
body: JSON.stringify({
|
|
105
|
+
version,
|
|
106
|
+
moduleCount,
|
|
107
|
+
cliVersion: (0, api_js_1.getCliVersion)(),
|
|
108
|
+
command: 'auto-update',
|
|
109
|
+
}),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// Silently ignore - this is just for analytics
|
|
114
|
+
}
|
|
115
|
+
}
|
|
92
116
|
/**
|
|
93
117
|
* Automatically check for and apply pattern updates
|
|
94
118
|
* Runs silently in background - no user intervention needed
|
|
@@ -178,6 +202,19 @@ class CodeBakersServer {
|
|
|
178
202
|
cliVersion: (0, api_js_1.getCliVersion)(),
|
|
179
203
|
};
|
|
180
204
|
fs.writeFileSync(versionPath, JSON.stringify(versionInfo, null, 2));
|
|
205
|
+
// Write notification file for AI to read and show to user
|
|
206
|
+
const notificationPath = path.join(claudeDir, '.update-notification.json');
|
|
207
|
+
const notification = {
|
|
208
|
+
type: 'patterns_updated',
|
|
209
|
+
previousVersion: installed?.version || 'unknown',
|
|
210
|
+
newVersion: content.version,
|
|
211
|
+
moduleCount,
|
|
212
|
+
updatedAt: new Date().toISOString(),
|
|
213
|
+
message: `CodeBakers patterns have been automatically updated from v${installed?.version || 'unknown'} to v${content.version} (${moduleCount} modules). Your AI tools now have the latest production patterns.`,
|
|
214
|
+
};
|
|
215
|
+
fs.writeFileSync(notificationPath, JSON.stringify(notification, null, 2));
|
|
216
|
+
// Confirm to server (non-blocking, fire-and-forget)
|
|
217
|
+
this.confirmDownload(content.version, moduleCount).catch(() => { });
|
|
181
218
|
this.autoUpdateChecked = true;
|
|
182
219
|
this.autoUpdateInProgress = false;
|
|
183
220
|
// Log success (visible in MCP logs)
|
|
@@ -902,6 +939,14 @@ class CodeBakersServer {
|
|
|
902
939
|
required: ['request'],
|
|
903
940
|
},
|
|
904
941
|
},
|
|
942
|
+
{
|
|
943
|
+
name: 'check_update_notification',
|
|
944
|
+
description: 'ALWAYS CALL THIS AT THE START OF EACH SESSION. Checks if CodeBakers patterns were recently auto-updated and returns a notification message to show the user. If an update occurred, tell the user about it with the returned message. After showing, the notification is cleared.',
|
|
945
|
+
inputSchema: {
|
|
946
|
+
type: 'object',
|
|
947
|
+
properties: {},
|
|
948
|
+
},
|
|
949
|
+
},
|
|
905
950
|
],
|
|
906
951
|
}));
|
|
907
952
|
// Handle tool calls
|
|
@@ -987,6 +1032,8 @@ class CodeBakersServer {
|
|
|
987
1032
|
return this.handleAddPage(args);
|
|
988
1033
|
case 'add_api_route':
|
|
989
1034
|
return this.handleAddApiRoute(args);
|
|
1035
|
+
case 'check_update_notification':
|
|
1036
|
+
return this.handleCheckUpdateNotification();
|
|
990
1037
|
default:
|
|
991
1038
|
throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
992
1039
|
}
|
|
@@ -4266,6 +4313,40 @@ export default ${asyncKeyword}function ${pageName}Page() {${authCheck}
|
|
|
4266
4313
|
}],
|
|
4267
4314
|
};
|
|
4268
4315
|
}
|
|
4316
|
+
/**
|
|
4317
|
+
* Check for update notifications and return message to show user
|
|
4318
|
+
*/
|
|
4319
|
+
async handleCheckUpdateNotification() {
|
|
4320
|
+
const cwd = process.cwd();
|
|
4321
|
+
const notificationPath = path.join(cwd, '.claude', '.update-notification.json');
|
|
4322
|
+
try {
|
|
4323
|
+
if (!fs.existsSync(notificationPath)) {
|
|
4324
|
+
return {
|
|
4325
|
+
content: [{
|
|
4326
|
+
type: 'text',
|
|
4327
|
+
text: 'No update notification.',
|
|
4328
|
+
}],
|
|
4329
|
+
};
|
|
4330
|
+
}
|
|
4331
|
+
const notification = JSON.parse(fs.readFileSync(notificationPath, 'utf-8'));
|
|
4332
|
+
// Delete the notification file after reading (so it only shows once)
|
|
4333
|
+
fs.unlinkSync(notificationPath);
|
|
4334
|
+
return {
|
|
4335
|
+
content: [{
|
|
4336
|
+
type: 'text',
|
|
4337
|
+
text: `🍪 **CodeBakers Update**\n\n${notification.message}\n\n**Previous version:** ${notification.previousVersion}\n**New version:** ${notification.newVersion}\n**Modules:** ${notification.moduleCount}\n**Updated:** ${new Date(notification.updatedAt).toLocaleString()}`,
|
|
4338
|
+
}],
|
|
4339
|
+
};
|
|
4340
|
+
}
|
|
4341
|
+
catch {
|
|
4342
|
+
return {
|
|
4343
|
+
content: [{
|
|
4344
|
+
type: 'text',
|
|
4345
|
+
text: 'No update notification.',
|
|
4346
|
+
}],
|
|
4347
|
+
};
|
|
4348
|
+
}
|
|
4349
|
+
}
|
|
4269
4350
|
parseApiRouteRequest(request) {
|
|
4270
4351
|
const lower = request.toLowerCase();
|
|
4271
4352
|
// Detect webhook
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codebakers/cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.1",
|
|
4
4
|
"description": "CodeBakers CLI - Production patterns for AI-assisted development",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
"mcp": "tsx src/mcp/server.ts",
|
|
16
16
|
"test": "vitest run",
|
|
17
17
|
"test:watch": "vitest",
|
|
18
|
-
"test:coverage": "vitest run --coverage"
|
|
18
|
+
"test:coverage": "vitest run --coverage",
|
|
19
|
+
"postpublish": "node scripts/register-version.js"
|
|
19
20
|
},
|
|
20
21
|
"keywords": [
|
|
21
22
|
"codebakers",
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Automatically registers a new CLI version with the CodeBakers server
|
|
5
|
+
* Called automatically after npm publish via postpublish hook
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
const API_URL = process.env.CODEBAKERS_API_URL || 'https://codebakers.ai';
|
|
12
|
+
const ADMIN_API_KEY = process.env.CODEBAKERS_ADMIN_KEY;
|
|
13
|
+
|
|
14
|
+
async function registerVersion() {
|
|
15
|
+
// Read version from package.json
|
|
16
|
+
const packagePath = path.join(__dirname, '..', 'package.json');
|
|
17
|
+
const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf-8'));
|
|
18
|
+
const version = pkg.version;
|
|
19
|
+
|
|
20
|
+
console.log(`\n📦 Registering CLI version ${version} with CodeBakers server...\n`);
|
|
21
|
+
|
|
22
|
+
if (!ADMIN_API_KEY) {
|
|
23
|
+
console.log('⚠️ CODEBAKERS_ADMIN_KEY not set - skipping auto-registration');
|
|
24
|
+
console.log(' You can manually add this version in Admin → CLI Versions\n');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
// Read changelog if it exists
|
|
30
|
+
let changelog = '';
|
|
31
|
+
const changelogPath = path.join(__dirname, '..', 'CHANGELOG.md');
|
|
32
|
+
if (fs.existsSync(changelogPath)) {
|
|
33
|
+
const content = fs.readFileSync(changelogPath, 'utf-8');
|
|
34
|
+
// Extract the latest version's changes
|
|
35
|
+
const match = content.match(/## \[?\d+\.\d+\.\d+\]?[^\n]*\n([\s\S]*?)(?=## \[?\d+\.\d+\.\d+|$)/);
|
|
36
|
+
if (match) {
|
|
37
|
+
changelog = match[1].trim().slice(0, 2000); // Limit length
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const response = await fetch(`${API_URL}/api/cli/register-version`, {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
headers: {
|
|
44
|
+
'Content-Type': 'application/json',
|
|
45
|
+
'Authorization': `Bearer ${ADMIN_API_KEY}`,
|
|
46
|
+
},
|
|
47
|
+
body: JSON.stringify({
|
|
48
|
+
version,
|
|
49
|
+
npmTag: 'latest',
|
|
50
|
+
changelog,
|
|
51
|
+
minNodeVersion: '18',
|
|
52
|
+
}),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
if (response.ok) {
|
|
56
|
+
const data = await response.json();
|
|
57
|
+
console.log(`✅ Version ${version} registered successfully!`);
|
|
58
|
+
console.log(` Status: ${data.data?.version?.status || 'draft'}`);
|
|
59
|
+
console.log(`\n Next steps:`);
|
|
60
|
+
console.log(` 1. Test the version`);
|
|
61
|
+
console.log(` 2. Go to Admin → CLI Versions`);
|
|
62
|
+
console.log(` 3. Promote to "testing" then "stable"`);
|
|
63
|
+
console.log(` 4. Enable auto-update when ready\n`);
|
|
64
|
+
} else {
|
|
65
|
+
const error = await response.json().catch(() => ({}));
|
|
66
|
+
if (error.error?.includes('already exists')) {
|
|
67
|
+
console.log(`ℹ️ Version ${version} already registered\n`);
|
|
68
|
+
} else {
|
|
69
|
+
console.log(`⚠️ Failed to register: ${error.error || response.statusText}`);
|
|
70
|
+
console.log(` You can manually add this version in Admin → CLI Versions\n`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.log(`⚠️ Could not reach server: ${error.message}`);
|
|
75
|
+
console.log(` You can manually add this version in Admin → CLI Versions\n`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
registerVersion();
|
package/src/commands/go.ts
CHANGED
|
@@ -39,6 +39,57 @@ interface GoOptions {
|
|
|
39
39
|
verbose?: boolean;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
interface ConfirmData {
|
|
43
|
+
version: string;
|
|
44
|
+
moduleCount: number;
|
|
45
|
+
cliVersion?: string;
|
|
46
|
+
command: string;
|
|
47
|
+
projectName?: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface AuthInfo {
|
|
51
|
+
apiKey?: string;
|
|
52
|
+
trialId?: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Get CLI version from package.json
|
|
57
|
+
*/
|
|
58
|
+
function getCliVersion(): string {
|
|
59
|
+
try {
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
61
|
+
const pkg = require('../../package.json');
|
|
62
|
+
return pkg.version || '0.0.0';
|
|
63
|
+
} catch {
|
|
64
|
+
return '0.0.0';
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Confirm download to server (non-blocking, fire-and-forget)
|
|
70
|
+
*/
|
|
71
|
+
async function confirmDownload(apiUrl: string, auth: AuthInfo, data: ConfirmData): Promise<void> {
|
|
72
|
+
try {
|
|
73
|
+
const headers: Record<string, string> = {
|
|
74
|
+
'Content-Type': 'application/json',
|
|
75
|
+
};
|
|
76
|
+
if (auth.apiKey) {
|
|
77
|
+
headers['Authorization'] = `Bearer ${auth.apiKey}`;
|
|
78
|
+
}
|
|
79
|
+
if (auth.trialId) {
|
|
80
|
+
headers['X-Trial-ID'] = auth.trialId;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
await fetch(`${apiUrl}/api/content/confirm`, {
|
|
84
|
+
method: 'POST',
|
|
85
|
+
headers,
|
|
86
|
+
body: JSON.stringify(data),
|
|
87
|
+
});
|
|
88
|
+
} catch {
|
|
89
|
+
// Silently ignore - this is just for analytics
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
42
93
|
function log(message: string, options?: GoOptions): void {
|
|
43
94
|
if (options?.verbose) {
|
|
44
95
|
console.log(chalk.gray(` [verbose] ${message}`));
|
|
@@ -317,7 +368,7 @@ async function installPatternsWithApiKey(apiKey: string, options: GoOptions = {}
|
|
|
317
368
|
log('Response OK, parsing JSON...', options);
|
|
318
369
|
const content: ContentResponse = await response.json();
|
|
319
370
|
log(`Received version: ${content.version}, modules: ${Object.keys(content.modules || {}).length}`, options);
|
|
320
|
-
await writePatternFiles(cwd, content, spinner, options);
|
|
371
|
+
await writePatternFiles(cwd, content, spinner, options, { apiKey });
|
|
321
372
|
|
|
322
373
|
} catch (error) {
|
|
323
374
|
log(`Error: ${error instanceof Error ? error.message : String(error)}`, options);
|
|
@@ -363,13 +414,13 @@ async function installPatterns(trialId: string, options: GoOptions = {}): Promis
|
|
|
363
414
|
|
|
364
415
|
const content: ContentResponse = await publicResponse.json();
|
|
365
416
|
log(`Received version: ${content.version}, modules: ${Object.keys(content.modules || {}).length}`, options);
|
|
366
|
-
await writePatternFiles(cwd, content, spinner, options);
|
|
417
|
+
await writePatternFiles(cwd, content, spinner, options, { trialId });
|
|
367
418
|
return;
|
|
368
419
|
}
|
|
369
420
|
|
|
370
421
|
const content: ContentResponse = await response.json();
|
|
371
422
|
log(`Received version: ${content.version}, modules: ${Object.keys(content.modules || {}).length}`, options);
|
|
372
|
-
await writePatternFiles(cwd, content, spinner, options);
|
|
423
|
+
await writePatternFiles(cwd, content, spinner, options, { trialId });
|
|
373
424
|
|
|
374
425
|
} catch (error) {
|
|
375
426
|
log(`Error: ${error instanceof Error ? error.message : String(error)}`, options);
|
|
@@ -378,7 +429,13 @@ async function installPatterns(trialId: string, options: GoOptions = {}): Promis
|
|
|
378
429
|
}
|
|
379
430
|
}
|
|
380
431
|
|
|
381
|
-
async function writePatternFiles(
|
|
432
|
+
async function writePatternFiles(
|
|
433
|
+
cwd: string,
|
|
434
|
+
content: ContentResponse,
|
|
435
|
+
spinner: ReturnType<typeof ora>,
|
|
436
|
+
options: GoOptions = {},
|
|
437
|
+
auth?: AuthInfo
|
|
438
|
+
): Promise<void> {
|
|
382
439
|
log(`Writing pattern files to ${cwd}...`, options);
|
|
383
440
|
// Check if patterns already exist
|
|
384
441
|
const claudeMdPath = join(cwd, 'CLAUDE.md');
|
|
@@ -393,7 +450,8 @@ async function writePatternFiles(cwd: string, content: ContentResponse, spinner:
|
|
|
393
450
|
}
|
|
394
451
|
|
|
395
452
|
// Write pattern modules to .claude/
|
|
396
|
-
|
|
453
|
+
const moduleCount = Object.keys(content.modules || {}).length;
|
|
454
|
+
if (content.modules && moduleCount > 0) {
|
|
397
455
|
const modulesDir = join(cwd, '.claude');
|
|
398
456
|
if (!existsSync(modulesDir)) {
|
|
399
457
|
mkdirSync(modulesDir, { recursive: true });
|
|
@@ -415,5 +473,16 @@ async function writePatternFiles(cwd: string, content: ContentResponse, spinner:
|
|
|
415
473
|
}
|
|
416
474
|
|
|
417
475
|
spinner.succeed(`CodeBakers patterns installed (v${content.version})`);
|
|
418
|
-
console.log(chalk.gray(` ${
|
|
476
|
+
console.log(chalk.gray(` ${moduleCount} pattern modules ready\n`));
|
|
477
|
+
|
|
478
|
+
// Confirm download to server (non-blocking)
|
|
479
|
+
if (auth) {
|
|
480
|
+
const apiUrl = getApiUrl();
|
|
481
|
+
confirmDownload(apiUrl, auth, {
|
|
482
|
+
version: content.version,
|
|
483
|
+
moduleCount,
|
|
484
|
+
cliVersion: getCliVersion(),
|
|
485
|
+
command: 'go',
|
|
486
|
+
}).catch(() => {}); // Silently ignore
|
|
487
|
+
}
|
|
419
488
|
}
|
package/src/commands/upgrade.ts
CHANGED
|
@@ -11,6 +11,32 @@ interface ContentResponse {
|
|
|
11
11
|
modules: Record<string, string>;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
interface ConfirmData {
|
|
15
|
+
version: string;
|
|
16
|
+
moduleCount: number;
|
|
17
|
+
cliVersion: string;
|
|
18
|
+
command: string;
|
|
19
|
+
projectName?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Confirm download to server (non-blocking, fire-and-forget)
|
|
24
|
+
*/
|
|
25
|
+
async function confirmDownload(apiUrl: string, apiKey: string, data: ConfirmData): Promise<void> {
|
|
26
|
+
try {
|
|
27
|
+
await fetch(`${apiUrl}/api/content/confirm`, {
|
|
28
|
+
method: 'POST',
|
|
29
|
+
headers: {
|
|
30
|
+
'Content-Type': 'application/json',
|
|
31
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
32
|
+
},
|
|
33
|
+
body: JSON.stringify(data),
|
|
34
|
+
});
|
|
35
|
+
} catch {
|
|
36
|
+
// Silently ignore - this is just for analytics
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
14
40
|
/**
|
|
15
41
|
* Upgrade CodeBakers patterns to the latest version
|
|
16
42
|
*/
|
|
@@ -101,6 +127,14 @@ export async function upgrade(): Promise<void> {
|
|
|
101
127
|
writeFileSync(join(claudeDir, '.version.json'), JSON.stringify(versionInfo, null, 2));
|
|
102
128
|
console.log(chalk.green(' ✓ Version info saved'));
|
|
103
129
|
|
|
130
|
+
// Confirm download to server (non-blocking)
|
|
131
|
+
confirmDownload(apiUrl, apiKey, {
|
|
132
|
+
version: content.version,
|
|
133
|
+
moduleCount,
|
|
134
|
+
cliVersion: getCliVersion(),
|
|
135
|
+
command: 'upgrade',
|
|
136
|
+
}).catch(() => {}); // Silently ignore confirmation failures
|
|
137
|
+
|
|
104
138
|
console.log(chalk.green(`\n ✅ Upgraded to patterns v${content.version}!\n`));
|
|
105
139
|
|
|
106
140
|
// Show what's new if available
|
package/src/config.ts
CHANGED
|
@@ -116,9 +116,12 @@ interface ConfigSchema {
|
|
|
116
116
|
lastKeySync: string | null; // ISO date of last sync with server
|
|
117
117
|
// Trial state (for zero-friction onboarding)
|
|
118
118
|
trial: TrialState | null;
|
|
119
|
-
// Update notification cache
|
|
119
|
+
// Update notification cache (CLI updates)
|
|
120
120
|
lastUpdateCheck: string | null; // ISO date of last npm registry check
|
|
121
121
|
latestKnownVersion: string | null; // Cached latest version from npm
|
|
122
|
+
// Pattern auto-update cache
|
|
123
|
+
lastPatternCheck: string | null; // ISO date of last pattern version check
|
|
124
|
+
latestPatternVersion: string | null; // Cached latest pattern version from server
|
|
122
125
|
}
|
|
123
126
|
|
|
124
127
|
// Create default service keys object with all keys set to null
|
|
@@ -128,7 +131,7 @@ const defaultServiceKeys: ServiceKeys = Object.fromEntries(
|
|
|
128
131
|
|
|
129
132
|
const config = new Conf<ConfigSchema>({
|
|
130
133
|
projectName: 'codebakers',
|
|
131
|
-
projectVersion: '1.
|
|
134
|
+
projectVersion: '1.9.0',
|
|
132
135
|
defaults: {
|
|
133
136
|
apiKey: null,
|
|
134
137
|
apiUrl: 'https://codebakers.ai',
|
|
@@ -138,6 +141,8 @@ const config = new Conf<ConfigSchema>({
|
|
|
138
141
|
trial: null,
|
|
139
142
|
lastUpdateCheck: null,
|
|
140
143
|
latestKnownVersion: null,
|
|
144
|
+
lastPatternCheck: null,
|
|
145
|
+
latestPatternVersion: null,
|
|
141
146
|
},
|
|
142
147
|
// Migration to add new keys when upgrading from old version
|
|
143
148
|
migrations: {
|
|
@@ -160,6 +165,15 @@ const config = new Conf<ConfigSchema>({
|
|
|
160
165
|
store.set('trial', null);
|
|
161
166
|
}
|
|
162
167
|
},
|
|
168
|
+
'1.9.0': (store) => {
|
|
169
|
+
// Add pattern auto-update fields if not present
|
|
170
|
+
if (!store.has('lastPatternCheck')) {
|
|
171
|
+
store.set('lastPatternCheck', null);
|
|
172
|
+
}
|
|
173
|
+
if (!store.has('latestPatternVersion')) {
|
|
174
|
+
store.set('latestPatternVersion', null);
|
|
175
|
+
}
|
|
176
|
+
},
|
|
163
177
|
},
|
|
164
178
|
});
|
|
165
179
|
|
|
@@ -528,5 +542,42 @@ export function setCachedUpdateInfo(latestVersion: string): void {
|
|
|
528
542
|
* Get the current CLI version from package.json
|
|
529
543
|
*/
|
|
530
544
|
export function getCliVersion(): string {
|
|
531
|
-
return '3.
|
|
545
|
+
return '3.3.0'; // Keep in sync with package.json
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// ============================================
|
|
549
|
+
// Pattern Auto-Update Cache
|
|
550
|
+
// ============================================
|
|
551
|
+
|
|
552
|
+
const PATTERN_CHECK_INTERVAL_HOURS = 6; // Check more frequently than CLI
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Get cached pattern version info if still valid (within 6 hours)
|
|
556
|
+
*/
|
|
557
|
+
export function getCachedPatternInfo(): { latestVersion: string; checkedAt: string } | null {
|
|
558
|
+
const lastCheck = config.get('lastPatternCheck');
|
|
559
|
+
const latestVersion = config.get('latestPatternVersion');
|
|
560
|
+
|
|
561
|
+
if (!lastCheck || !latestVersion) return null;
|
|
562
|
+
|
|
563
|
+
const hoursSinceCheck = (Date.now() - new Date(lastCheck).getTime()) / (1000 * 60 * 60);
|
|
564
|
+
if (hoursSinceCheck > PATTERN_CHECK_INTERVAL_HOURS) return null;
|
|
565
|
+
|
|
566
|
+
return { latestVersion, checkedAt: lastCheck };
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* Cache the latest pattern version from server
|
|
571
|
+
*/
|
|
572
|
+
export function setCachedPatternInfo(latestVersion: string): void {
|
|
573
|
+
config.set('lastPatternCheck', new Date().toISOString());
|
|
574
|
+
config.set('latestPatternVersion', latestVersion);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Clear pattern cache to force a fresh check
|
|
579
|
+
*/
|
|
580
|
+
export function clearPatternCache(): void {
|
|
581
|
+
config.set('lastPatternCheck', null);
|
|
582
|
+
config.set('latestPatternVersion', null);
|
|
532
583
|
}
|