@codebakers/cli 2.6.1 → 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.
@@ -53,6 +53,8 @@ class CodeBakersServer {
53
53
  server;
54
54
  apiKey;
55
55
  apiUrl;
56
+ autoUpdateChecked = false;
57
+ autoUpdateInProgress = false;
56
58
  constructor() {
57
59
  this.apiKey = (0, config_js_1.getApiKey)();
58
60
  this.apiUrl = (0, config_js_1.getApiUrl)();
@@ -65,6 +67,109 @@ class CodeBakersServer {
65
67
  },
66
68
  });
67
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
+ }
68
173
  }
69
174
  gatherProjectContext() {
70
175
  const cwd = process.cwd();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codebakers/cli",
3
- "version": "2.6.1",
3
+ "version": "2.6.2",
4
4
  "description": "CodeBakers CLI - Production patterns for AI-assisted development",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/src/mcp/server.ts CHANGED
@@ -61,6 +61,8 @@ class CodeBakersServer {
61
61
  private server: Server;
62
62
  private apiKey: string | null;
63
63
  private apiUrl: string;
64
+ private autoUpdateChecked = false;
65
+ private autoUpdateInProgress = false;
64
66
 
65
67
  constructor() {
66
68
  this.apiKey = getApiKey();
@@ -79,6 +81,128 @@ class CodeBakersServer {
79
81
  );
80
82
 
81
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
+ }
82
206
  }
83
207
 
84
208
  private gatherProjectContext(): ProjectContext {