@codebakers/cli 2.6.0 → 2.6.2
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/install.js +10 -1
- package/dist/commands/upgrade.js +9 -0
- package/dist/mcp/server.js +162 -4
- package/package.json +1 -1
- package/src/commands/install.ts +11 -1
- package/src/commands/upgrade.ts +10 -0
- package/src/mcp/server.ts +200 -4
package/dist/commands/install.js
CHANGED
|
@@ -9,6 +9,7 @@ const ora_1 = __importDefault(require("ora"));
|
|
|
9
9
|
const fs_1 = require("fs");
|
|
10
10
|
const path_1 = require("path");
|
|
11
11
|
const config_js_1 = require("../config.js");
|
|
12
|
+
const api_js_1 = require("../lib/api.js");
|
|
12
13
|
async function install() {
|
|
13
14
|
console.log(chalk_1.default.blue('\n CodeBakers Install\n'));
|
|
14
15
|
const apiKey = (0, config_js_1.getApiKey)();
|
|
@@ -41,14 +42,22 @@ async function install() {
|
|
|
41
42
|
(0, fs_1.writeFileSync)((0, path_1.join)(cwd, 'CLAUDE.md'), content.router);
|
|
42
43
|
}
|
|
43
44
|
// Write modules
|
|
45
|
+
const modulesDir = (0, path_1.join)(cwd, '.claude');
|
|
44
46
|
if (content.modules && Object.keys(content.modules).length > 0) {
|
|
45
|
-
const modulesDir = (0, path_1.join)(cwd, '.claude');
|
|
46
47
|
if (!(0, fs_1.existsSync)(modulesDir)) {
|
|
47
48
|
(0, fs_1.mkdirSync)(modulesDir, { recursive: true });
|
|
48
49
|
}
|
|
49
50
|
for (const [name, data] of Object.entries(content.modules)) {
|
|
50
51
|
(0, fs_1.writeFileSync)((0, path_1.join)(modulesDir, name), data);
|
|
51
52
|
}
|
|
53
|
+
// Write version file for tracking
|
|
54
|
+
const versionInfo = {
|
|
55
|
+
version: content.version,
|
|
56
|
+
moduleCount: Object.keys(content.modules).length,
|
|
57
|
+
installedAt: new Date().toISOString(),
|
|
58
|
+
cliVersion: (0, api_js_1.getCliVersion)(),
|
|
59
|
+
};
|
|
60
|
+
(0, fs_1.writeFileSync)((0, path_1.join)(modulesDir, '.version.json'), JSON.stringify(versionInfo, null, 2));
|
|
52
61
|
}
|
|
53
62
|
// Add to .gitignore if not present
|
|
54
63
|
const gitignorePath = (0, path_1.join)(cwd, '.gitignore');
|
package/dist/commands/upgrade.js
CHANGED
|
@@ -74,6 +74,15 @@ async function upgrade() {
|
|
|
74
74
|
}
|
|
75
75
|
console.log(chalk_1.default.green(` ✓ Updated ${moduleCount} modules in .claude/`));
|
|
76
76
|
}
|
|
77
|
+
// Write version file for tracking
|
|
78
|
+
const versionInfo = {
|
|
79
|
+
version: content.version,
|
|
80
|
+
moduleCount,
|
|
81
|
+
updatedAt: new Date().toISOString(),
|
|
82
|
+
cliVersion: (0, api_js_1.getCliVersion)(),
|
|
83
|
+
};
|
|
84
|
+
(0, fs_1.writeFileSync)((0, path_1.join)(claudeDir, '.version.json'), JSON.stringify(versionInfo, null, 2));
|
|
85
|
+
console.log(chalk_1.default.green(' ✓ Version info saved'));
|
|
77
86
|
console.log(chalk_1.default.green(`\n ✅ Upgraded to patterns v${content.version}!\n`));
|
|
78
87
|
// Show what's new if available
|
|
79
88
|
console.log(chalk_1.default.gray(' Changes take effect in your next AI session.\n'));
|
package/dist/mcp/server.js
CHANGED
|
@@ -41,6 +41,7 @@ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
|
41
41
|
const config_js_1 = require("../config.js");
|
|
42
42
|
const audit_js_1 = require("../commands/audit.js");
|
|
43
43
|
const heal_js_1 = require("../commands/heal.js");
|
|
44
|
+
const api_js_1 = require("../lib/api.js");
|
|
44
45
|
const fs = __importStar(require("fs"));
|
|
45
46
|
const path = __importStar(require("path"));
|
|
46
47
|
const child_process_1 = require("child_process");
|
|
@@ -52,6 +53,8 @@ class CodeBakersServer {
|
|
|
52
53
|
server;
|
|
53
54
|
apiKey;
|
|
54
55
|
apiUrl;
|
|
56
|
+
autoUpdateChecked = false;
|
|
57
|
+
autoUpdateInProgress = false;
|
|
55
58
|
constructor() {
|
|
56
59
|
this.apiKey = (0, config_js_1.getApiKey)();
|
|
57
60
|
this.apiUrl = (0, config_js_1.getApiUrl)();
|
|
@@ -64,6 +67,109 @@ class CodeBakersServer {
|
|
|
64
67
|
},
|
|
65
68
|
});
|
|
66
69
|
this.setupHandlers();
|
|
70
|
+
// Trigger auto-update check on startup (non-blocking)
|
|
71
|
+
this.checkAndAutoUpdate().catch(() => {
|
|
72
|
+
// Silently ignore errors - don't interrupt user
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Automatically check for and apply pattern updates
|
|
77
|
+
* Runs silently in background - no user intervention needed
|
|
78
|
+
*/
|
|
79
|
+
async checkAndAutoUpdate() {
|
|
80
|
+
if (this.autoUpdateChecked || this.autoUpdateInProgress || !this.apiKey) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
this.autoUpdateInProgress = true;
|
|
84
|
+
try {
|
|
85
|
+
const cwd = process.cwd();
|
|
86
|
+
const versionPath = path.join(cwd, '.claude', '.version.json');
|
|
87
|
+
// Check if we should auto-update (once per 24 hours)
|
|
88
|
+
let lastCheck = null;
|
|
89
|
+
let installed = null;
|
|
90
|
+
if (fs.existsSync(versionPath)) {
|
|
91
|
+
try {
|
|
92
|
+
installed = JSON.parse(fs.readFileSync(versionPath, 'utf-8'));
|
|
93
|
+
const checkTime = installed?.updatedAt || installed?.installedAt;
|
|
94
|
+
if (checkTime) {
|
|
95
|
+
lastCheck = new Date(checkTime);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Ignore parse errors
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Skip if checked within last 24 hours
|
|
103
|
+
if (lastCheck) {
|
|
104
|
+
const hoursSinceCheck = (Date.now() - lastCheck.getTime()) / (1000 * 60 * 60);
|
|
105
|
+
if (hoursSinceCheck < 24) {
|
|
106
|
+
this.autoUpdateChecked = true;
|
|
107
|
+
this.autoUpdateInProgress = false;
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Fetch latest version
|
|
112
|
+
const response = await fetch(`${this.apiUrl}/api/content/version`, {
|
|
113
|
+
headers: { 'Authorization': `Bearer ${this.apiKey}` },
|
|
114
|
+
});
|
|
115
|
+
if (!response.ok) {
|
|
116
|
+
this.autoUpdateInProgress = false;
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const latest = await response.json();
|
|
120
|
+
// Check if update needed
|
|
121
|
+
if (installed && installed.version === latest.version) {
|
|
122
|
+
// Already up to date - update timestamp to avoid checking for 24h
|
|
123
|
+
installed.updatedAt = new Date().toISOString();
|
|
124
|
+
fs.writeFileSync(versionPath, JSON.stringify(installed, null, 2));
|
|
125
|
+
this.autoUpdateChecked = true;
|
|
126
|
+
this.autoUpdateInProgress = false;
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
// Fetch full content and update
|
|
130
|
+
const contentResponse = await fetch(`${this.apiUrl}/api/content`, {
|
|
131
|
+
headers: { 'Authorization': `Bearer ${this.apiKey}` },
|
|
132
|
+
});
|
|
133
|
+
if (!contentResponse.ok) {
|
|
134
|
+
this.autoUpdateInProgress = false;
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const content = await contentResponse.json();
|
|
138
|
+
const claudeDir = path.join(cwd, '.claude');
|
|
139
|
+
// Ensure .claude directory exists
|
|
140
|
+
if (!fs.existsSync(claudeDir)) {
|
|
141
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
142
|
+
}
|
|
143
|
+
// Write updated modules
|
|
144
|
+
let moduleCount = 0;
|
|
145
|
+
if (content.modules) {
|
|
146
|
+
for (const [name, data] of Object.entries(content.modules)) {
|
|
147
|
+
fs.writeFileSync(path.join(claudeDir, name), data);
|
|
148
|
+
moduleCount++;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// Update CLAUDE.md if router content exists
|
|
152
|
+
if (content.router || content.claudeMd) {
|
|
153
|
+
const routerContent = content.claudeMd || content.router;
|
|
154
|
+
fs.writeFileSync(path.join(cwd, 'CLAUDE.md'), routerContent);
|
|
155
|
+
}
|
|
156
|
+
// Write version file
|
|
157
|
+
const versionInfo = {
|
|
158
|
+
version: content.version,
|
|
159
|
+
moduleCount,
|
|
160
|
+
updatedAt: new Date().toISOString(),
|
|
161
|
+
cliVersion: (0, api_js_1.getCliVersion)(),
|
|
162
|
+
};
|
|
163
|
+
fs.writeFileSync(versionPath, JSON.stringify(versionInfo, null, 2));
|
|
164
|
+
this.autoUpdateChecked = true;
|
|
165
|
+
this.autoUpdateInProgress = false;
|
|
166
|
+
// Log success (visible in MCP logs)
|
|
167
|
+
console.error(`[CodeBakers] Auto-updated patterns to v${content.version} (${moduleCount} modules)`);
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
// Silently fail - don't interrupt user's workflow
|
|
171
|
+
this.autoUpdateInProgress = false;
|
|
172
|
+
}
|
|
67
173
|
}
|
|
68
174
|
gatherProjectContext() {
|
|
69
175
|
const cwd = process.cwd();
|
|
@@ -239,6 +345,46 @@ class CodeBakersServer {
|
|
|
239
345
|
}
|
|
240
346
|
return context;
|
|
241
347
|
}
|
|
348
|
+
async checkPatternVersion() {
|
|
349
|
+
const cwd = process.cwd();
|
|
350
|
+
const versionPath = path.join(cwd, '.claude', '.version.json');
|
|
351
|
+
// Read local version
|
|
352
|
+
let installed = null;
|
|
353
|
+
if (fs.existsSync(versionPath)) {
|
|
354
|
+
try {
|
|
355
|
+
installed = JSON.parse(fs.readFileSync(versionPath, 'utf-8'));
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
// Ignore parse errors
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
// Fetch latest version from API
|
|
362
|
+
let latest = null;
|
|
363
|
+
try {
|
|
364
|
+
const response = await fetch(`${this.apiUrl}/api/content/version`, {
|
|
365
|
+
headers: this.apiKey ? { 'Authorization': `Bearer ${this.apiKey}` } : {},
|
|
366
|
+
});
|
|
367
|
+
if (response.ok) {
|
|
368
|
+
latest = await response.json();
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
catch {
|
|
372
|
+
// Ignore fetch errors
|
|
373
|
+
}
|
|
374
|
+
// Compare versions
|
|
375
|
+
let updateAvailable = false;
|
|
376
|
+
let message = null;
|
|
377
|
+
if (installed && latest) {
|
|
378
|
+
if (installed.version !== latest.version) {
|
|
379
|
+
updateAvailable = true;
|
|
380
|
+
message = `⚠️ Pattern update available: v${installed.version} → v${latest.version} (${latest.moduleCount - installed.moduleCount} new modules)\n Run \`codebakers upgrade\` to update`;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
else if (!installed && latest) {
|
|
384
|
+
message = `ℹ️ No version tracking found. Run \`codebakers upgrade\` to sync patterns`;
|
|
385
|
+
}
|
|
386
|
+
return { installed, latest, updateAvailable, message };
|
|
387
|
+
}
|
|
242
388
|
formatContextForPrompt(context) {
|
|
243
389
|
const lines = [];
|
|
244
390
|
lines.push(`Project: ${context.projectName}`);
|
|
@@ -602,7 +748,7 @@ class CodeBakersServer {
|
|
|
602
748
|
case 'get_experience_level':
|
|
603
749
|
return this.handleGetExperienceLevel();
|
|
604
750
|
case 'get_status':
|
|
605
|
-
return this.handleGetStatus();
|
|
751
|
+
return await this.handleGetStatus();
|
|
606
752
|
case 'run_audit':
|
|
607
753
|
return this.handleRunAudit();
|
|
608
754
|
case 'heal':
|
|
@@ -1400,16 +1546,28 @@ phase: development
|
|
|
1400
1546
|
};
|
|
1401
1547
|
}
|
|
1402
1548
|
}
|
|
1403
|
-
handleGetStatus() {
|
|
1549
|
+
async handleGetStatus() {
|
|
1404
1550
|
const level = (0, config_js_1.getExperienceLevel)();
|
|
1405
1551
|
const context = this.gatherProjectContext();
|
|
1552
|
+
const versionCheck = await this.checkPatternVersion();
|
|
1553
|
+
const cliVersion = (0, api_js_1.getCliVersion)();
|
|
1554
|
+
// Build version status section
|
|
1555
|
+
let versionSection = `- **CLI Version:** ${cliVersion}`;
|
|
1556
|
+
if (versionCheck.installed) {
|
|
1557
|
+
versionSection += `\n- **Patterns Version:** ${versionCheck.installed.version} (${versionCheck.installed.moduleCount} modules)`;
|
|
1558
|
+
}
|
|
1559
|
+
// Build update alert if needed
|
|
1560
|
+
let updateAlert = '';
|
|
1561
|
+
if (versionCheck.message) {
|
|
1562
|
+
updateAlert = `\n\n## ${versionCheck.updateAvailable ? '⚠️ Update Available' : 'ℹ️ Version Info'}\n${versionCheck.message}\n`;
|
|
1563
|
+
}
|
|
1406
1564
|
const statusText = `# ✅ CodeBakers is Active!
|
|
1407
1565
|
|
|
1408
1566
|
## Connection Status
|
|
1409
1567
|
- **MCP Server:** Running
|
|
1410
1568
|
- **API Connected:** Yes
|
|
1411
|
-
|
|
1412
|
-
|
|
1569
|
+
${versionSection}
|
|
1570
|
+
${updateAlert}
|
|
1413
1571
|
## Current Settings
|
|
1414
1572
|
- **Experience Level:** ${level.charAt(0).toUpperCase() + level.slice(1)}
|
|
1415
1573
|
- **Project:** ${context.projectName}
|
package/package.json
CHANGED
package/src/commands/install.ts
CHANGED
|
@@ -3,6 +3,7 @@ import ora from 'ora';
|
|
|
3
3
|
import { writeFileSync, mkdirSync, existsSync } from 'fs';
|
|
4
4
|
import { join } from 'path';
|
|
5
5
|
import { getApiKey, getApiUrl } from '../config.js';
|
|
6
|
+
import { getCliVersion } from '../lib/api.js';
|
|
6
7
|
|
|
7
8
|
interface ContentResponse {
|
|
8
9
|
version: string;
|
|
@@ -51,8 +52,8 @@ export async function install(): Promise<void> {
|
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
// Write modules
|
|
55
|
+
const modulesDir = join(cwd, '.claude');
|
|
54
56
|
if (content.modules && Object.keys(content.modules).length > 0) {
|
|
55
|
-
const modulesDir = join(cwd, '.claude');
|
|
56
57
|
if (!existsSync(modulesDir)) {
|
|
57
58
|
mkdirSync(modulesDir, { recursive: true });
|
|
58
59
|
}
|
|
@@ -60,6 +61,15 @@ export async function install(): Promise<void> {
|
|
|
60
61
|
for (const [name, data] of Object.entries(content.modules)) {
|
|
61
62
|
writeFileSync(join(modulesDir, name), data);
|
|
62
63
|
}
|
|
64
|
+
|
|
65
|
+
// Write version file for tracking
|
|
66
|
+
const versionInfo = {
|
|
67
|
+
version: content.version,
|
|
68
|
+
moduleCount: Object.keys(content.modules).length,
|
|
69
|
+
installedAt: new Date().toISOString(),
|
|
70
|
+
cliVersion: getCliVersion(),
|
|
71
|
+
};
|
|
72
|
+
writeFileSync(join(modulesDir, '.version.json'), JSON.stringify(versionInfo, null, 2));
|
|
63
73
|
}
|
|
64
74
|
|
|
65
75
|
// Add to .gitignore if not present
|
package/src/commands/upgrade.ts
CHANGED
|
@@ -91,6 +91,16 @@ export async function upgrade(): Promise<void> {
|
|
|
91
91
|
console.log(chalk.green(` ✓ Updated ${moduleCount} modules in .claude/`));
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
// Write version file for tracking
|
|
95
|
+
const versionInfo = {
|
|
96
|
+
version: content.version,
|
|
97
|
+
moduleCount,
|
|
98
|
+
updatedAt: new Date().toISOString(),
|
|
99
|
+
cliVersion: getCliVersion(),
|
|
100
|
+
};
|
|
101
|
+
writeFileSync(join(claudeDir, '.version.json'), JSON.stringify(versionInfo, null, 2));
|
|
102
|
+
console.log(chalk.green(' ✓ Version info saved'));
|
|
103
|
+
|
|
94
104
|
console.log(chalk.green(`\n ✅ Upgraded to patterns v${content.version}!\n`));
|
|
95
105
|
|
|
96
106
|
// Show what's new if available
|
package/src/mcp/server.ts
CHANGED
|
@@ -11,11 +11,21 @@ import {
|
|
|
11
11
|
import { getApiKey, getApiUrl, getExperienceLevel, setExperienceLevel, type ExperienceLevel } from '../config.js';
|
|
12
12
|
import { audit as runAudit } from '../commands/audit.js';
|
|
13
13
|
import { heal as runHeal } from '../commands/heal.js';
|
|
14
|
+
import { getCliVersion } from '../lib/api.js';
|
|
14
15
|
import * as fs from 'fs';
|
|
15
16
|
import * as path from 'path';
|
|
16
17
|
import { execSync } from 'child_process';
|
|
17
18
|
import * as templates from '../templates/nextjs-supabase.js';
|
|
18
19
|
|
|
20
|
+
// Version info type
|
|
21
|
+
interface VersionInfo {
|
|
22
|
+
version: string;
|
|
23
|
+
moduleCount: number;
|
|
24
|
+
installedAt?: string;
|
|
25
|
+
updatedAt?: string;
|
|
26
|
+
cliVersion: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
19
29
|
// Pattern cache to avoid repeated API calls
|
|
20
30
|
const patternCache = new Map<string, { content: string; timestamp: number }>();
|
|
21
31
|
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
|
|
@@ -51,6 +61,8 @@ class CodeBakersServer {
|
|
|
51
61
|
private server: Server;
|
|
52
62
|
private apiKey: string | null;
|
|
53
63
|
private apiUrl: string;
|
|
64
|
+
private autoUpdateChecked = false;
|
|
65
|
+
private autoUpdateInProgress = false;
|
|
54
66
|
|
|
55
67
|
constructor() {
|
|
56
68
|
this.apiKey = getApiKey();
|
|
@@ -69,6 +81,128 @@ class CodeBakersServer {
|
|
|
69
81
|
);
|
|
70
82
|
|
|
71
83
|
this.setupHandlers();
|
|
84
|
+
|
|
85
|
+
// Trigger auto-update check on startup (non-blocking)
|
|
86
|
+
this.checkAndAutoUpdate().catch(() => {
|
|
87
|
+
// Silently ignore errors - don't interrupt user
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Automatically check for and apply pattern updates
|
|
93
|
+
* Runs silently in background - no user intervention needed
|
|
94
|
+
*/
|
|
95
|
+
private async checkAndAutoUpdate(): Promise<void> {
|
|
96
|
+
if (this.autoUpdateChecked || this.autoUpdateInProgress || !this.apiKey) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
this.autoUpdateInProgress = true;
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
const cwd = process.cwd();
|
|
104
|
+
const versionPath = path.join(cwd, '.claude', '.version.json');
|
|
105
|
+
|
|
106
|
+
// Check if we should auto-update (once per 24 hours)
|
|
107
|
+
let lastCheck: Date | null = null;
|
|
108
|
+
let installed: VersionInfo | null = null;
|
|
109
|
+
|
|
110
|
+
if (fs.existsSync(versionPath)) {
|
|
111
|
+
try {
|
|
112
|
+
installed = JSON.parse(fs.readFileSync(versionPath, 'utf-8'));
|
|
113
|
+
const checkTime = installed?.updatedAt || installed?.installedAt;
|
|
114
|
+
if (checkTime) {
|
|
115
|
+
lastCheck = new Date(checkTime);
|
|
116
|
+
}
|
|
117
|
+
} catch {
|
|
118
|
+
// Ignore parse errors
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Skip if checked within last 24 hours
|
|
123
|
+
if (lastCheck) {
|
|
124
|
+
const hoursSinceCheck = (Date.now() - lastCheck.getTime()) / (1000 * 60 * 60);
|
|
125
|
+
if (hoursSinceCheck < 24) {
|
|
126
|
+
this.autoUpdateChecked = true;
|
|
127
|
+
this.autoUpdateInProgress = false;
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Fetch latest version
|
|
133
|
+
const response = await fetch(`${this.apiUrl}/api/content/version`, {
|
|
134
|
+
headers: { 'Authorization': `Bearer ${this.apiKey}` },
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
if (!response.ok) {
|
|
138
|
+
this.autoUpdateInProgress = false;
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const latest = await response.json();
|
|
143
|
+
|
|
144
|
+
// Check if update needed
|
|
145
|
+
if (installed && installed.version === latest.version) {
|
|
146
|
+
// Already up to date - update timestamp to avoid checking for 24h
|
|
147
|
+
installed.updatedAt = new Date().toISOString();
|
|
148
|
+
fs.writeFileSync(versionPath, JSON.stringify(installed, null, 2));
|
|
149
|
+
this.autoUpdateChecked = true;
|
|
150
|
+
this.autoUpdateInProgress = false;
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Fetch full content and update
|
|
155
|
+
const contentResponse = await fetch(`${this.apiUrl}/api/content`, {
|
|
156
|
+
headers: { 'Authorization': `Bearer ${this.apiKey}` },
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
if (!contentResponse.ok) {
|
|
160
|
+
this.autoUpdateInProgress = false;
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const content = await contentResponse.json();
|
|
165
|
+
const claudeDir = path.join(cwd, '.claude');
|
|
166
|
+
|
|
167
|
+
// Ensure .claude directory exists
|
|
168
|
+
if (!fs.existsSync(claudeDir)) {
|
|
169
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Write updated modules
|
|
173
|
+
let moduleCount = 0;
|
|
174
|
+
if (content.modules) {
|
|
175
|
+
for (const [name, data] of Object.entries(content.modules)) {
|
|
176
|
+
fs.writeFileSync(path.join(claudeDir, name), data as string);
|
|
177
|
+
moduleCount++;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Update CLAUDE.md if router content exists
|
|
182
|
+
if (content.router || content.claudeMd) {
|
|
183
|
+
const routerContent = content.claudeMd || content.router;
|
|
184
|
+
fs.writeFileSync(path.join(cwd, 'CLAUDE.md'), routerContent);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Write version file
|
|
188
|
+
const versionInfo: VersionInfo = {
|
|
189
|
+
version: content.version,
|
|
190
|
+
moduleCount,
|
|
191
|
+
updatedAt: new Date().toISOString(),
|
|
192
|
+
cliVersion: getCliVersion(),
|
|
193
|
+
};
|
|
194
|
+
fs.writeFileSync(versionPath, JSON.stringify(versionInfo, null, 2));
|
|
195
|
+
|
|
196
|
+
this.autoUpdateChecked = true;
|
|
197
|
+
this.autoUpdateInProgress = false;
|
|
198
|
+
|
|
199
|
+
// Log success (visible in MCP logs)
|
|
200
|
+
console.error(`[CodeBakers] Auto-updated patterns to v${content.version} (${moduleCount} modules)`);
|
|
201
|
+
|
|
202
|
+
} catch {
|
|
203
|
+
// Silently fail - don't interrupt user's workflow
|
|
204
|
+
this.autoUpdateInProgress = false;
|
|
205
|
+
}
|
|
72
206
|
}
|
|
73
207
|
|
|
74
208
|
private gatherProjectContext(): ProjectContext {
|
|
@@ -243,6 +377,54 @@ class CodeBakersServer {
|
|
|
243
377
|
return context;
|
|
244
378
|
}
|
|
245
379
|
|
|
380
|
+
private async checkPatternVersion(): Promise<{
|
|
381
|
+
installed: VersionInfo | null;
|
|
382
|
+
latest: { version: string; moduleCount: number } | null;
|
|
383
|
+
updateAvailable: boolean;
|
|
384
|
+
message: string | null;
|
|
385
|
+
}> {
|
|
386
|
+
const cwd = process.cwd();
|
|
387
|
+
const versionPath = path.join(cwd, '.claude', '.version.json');
|
|
388
|
+
|
|
389
|
+
// Read local version
|
|
390
|
+
let installed: VersionInfo | null = null;
|
|
391
|
+
if (fs.existsSync(versionPath)) {
|
|
392
|
+
try {
|
|
393
|
+
installed = JSON.parse(fs.readFileSync(versionPath, 'utf-8'));
|
|
394
|
+
} catch {
|
|
395
|
+
// Ignore parse errors
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Fetch latest version from API
|
|
400
|
+
let latest: { version: string; moduleCount: number } | null = null;
|
|
401
|
+
try {
|
|
402
|
+
const response = await fetch(`${this.apiUrl}/api/content/version`, {
|
|
403
|
+
headers: this.apiKey ? { 'Authorization': `Bearer ${this.apiKey}` } : {},
|
|
404
|
+
});
|
|
405
|
+
if (response.ok) {
|
|
406
|
+
latest = await response.json();
|
|
407
|
+
}
|
|
408
|
+
} catch {
|
|
409
|
+
// Ignore fetch errors
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// Compare versions
|
|
413
|
+
let updateAvailable = false;
|
|
414
|
+
let message: string | null = null;
|
|
415
|
+
|
|
416
|
+
if (installed && latest) {
|
|
417
|
+
if (installed.version !== latest.version) {
|
|
418
|
+
updateAvailable = true;
|
|
419
|
+
message = `⚠️ Pattern update available: v${installed.version} → v${latest.version} (${latest.moduleCount - installed.moduleCount} new modules)\n Run \`codebakers upgrade\` to update`;
|
|
420
|
+
}
|
|
421
|
+
} else if (!installed && latest) {
|
|
422
|
+
message = `ℹ️ No version tracking found. Run \`codebakers upgrade\` to sync patterns`;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
return { installed, latest, updateAvailable, message };
|
|
426
|
+
}
|
|
427
|
+
|
|
246
428
|
private formatContextForPrompt(context: ProjectContext): string {
|
|
247
429
|
const lines: string[] = [];
|
|
248
430
|
|
|
@@ -651,7 +833,7 @@ class CodeBakersServer {
|
|
|
651
833
|
return this.handleGetExperienceLevel();
|
|
652
834
|
|
|
653
835
|
case 'get_status':
|
|
654
|
-
return this.handleGetStatus();
|
|
836
|
+
return await this.handleGetStatus();
|
|
655
837
|
|
|
656
838
|
case 'run_audit':
|
|
657
839
|
return this.handleRunAudit();
|
|
@@ -1579,17 +1761,31 @@ phase: development
|
|
|
1579
1761
|
}
|
|
1580
1762
|
}
|
|
1581
1763
|
|
|
1582
|
-
private handleGetStatus() {
|
|
1764
|
+
private async handleGetStatus() {
|
|
1583
1765
|
const level = getExperienceLevel();
|
|
1584
1766
|
const context = this.gatherProjectContext();
|
|
1767
|
+
const versionCheck = await this.checkPatternVersion();
|
|
1768
|
+
const cliVersion = getCliVersion();
|
|
1769
|
+
|
|
1770
|
+
// Build version status section
|
|
1771
|
+
let versionSection = `- **CLI Version:** ${cliVersion}`;
|
|
1772
|
+
if (versionCheck.installed) {
|
|
1773
|
+
versionSection += `\n- **Patterns Version:** ${versionCheck.installed.version} (${versionCheck.installed.moduleCount} modules)`;
|
|
1774
|
+
}
|
|
1775
|
+
|
|
1776
|
+
// Build update alert if needed
|
|
1777
|
+
let updateAlert = '';
|
|
1778
|
+
if (versionCheck.message) {
|
|
1779
|
+
updateAlert = `\n\n## ${versionCheck.updateAvailable ? '⚠️ Update Available' : 'ℹ️ Version Info'}\n${versionCheck.message}\n`;
|
|
1780
|
+
}
|
|
1585
1781
|
|
|
1586
1782
|
const statusText = `# ✅ CodeBakers is Active!
|
|
1587
1783
|
|
|
1588
1784
|
## Connection Status
|
|
1589
1785
|
- **MCP Server:** Running
|
|
1590
1786
|
- **API Connected:** Yes
|
|
1591
|
-
|
|
1592
|
-
|
|
1787
|
+
${versionSection}
|
|
1788
|
+
${updateAlert}
|
|
1593
1789
|
## Current Settings
|
|
1594
1790
|
- **Experience Level:** ${level.charAt(0).toUpperCase() + level.slice(1)}
|
|
1595
1791
|
- **Project:** ${context.projectName}
|