@siteboon/claude-code-ui 1.10.2 → 1.10.4

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/index.html CHANGED
@@ -25,7 +25,7 @@
25
25
 
26
26
  <!-- Prevent zoom on iOS -->
27
27
  <meta name="format-detection" content="telephone=no" />
28
- <script type="module" crossorigin src="/assets/index-DZdjqoE4.js"></script>
28
+ <script type="module" crossorigin src="/assets/index-CJDQ69DP.js"></script>
29
29
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-7V_UDHjJ.js">
30
30
  <link rel="modulepreload" crossorigin href="/assets/vendor-codemirror-B7BYDWj-.js">
31
31
  <link rel="modulepreload" crossorigin href="/assets/vendor-xterm-jI4BCHEb.js">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@siteboon/claude-code-ui",
3
- "version": "1.10.2",
3
+ "version": "1.10.4",
4
4
  "description": "A web-based UI for Claude Code CLI",
5
5
  "type": "module",
6
6
  "main": "server/index.js",
package/server/index.js CHANGED
@@ -237,6 +237,71 @@ app.get('/api/config', authenticateToken, (req, res) => {
237
237
  });
238
238
  });
239
239
 
240
+ // System update endpoint
241
+ app.post('/api/system/update', authenticateToken, async (req, res) => {
242
+ try {
243
+ // Get the project root directory (parent of server directory)
244
+ const projectRoot = path.join(__dirname, '..');
245
+
246
+ console.log('Starting system update from directory:', projectRoot);
247
+
248
+ // Run the update command
249
+ const updateCommand = 'git checkout main && git pull && npm install';
250
+
251
+ const child = spawn('sh', ['-c', updateCommand], {
252
+ cwd: projectRoot,
253
+ env: process.env
254
+ });
255
+
256
+ let output = '';
257
+ let errorOutput = '';
258
+
259
+ child.stdout.on('data', (data) => {
260
+ const text = data.toString();
261
+ output += text;
262
+ console.log('Update output:', text);
263
+ });
264
+
265
+ child.stderr.on('data', (data) => {
266
+ const text = data.toString();
267
+ errorOutput += text;
268
+ console.error('Update error:', text);
269
+ });
270
+
271
+ child.on('close', (code) => {
272
+ if (code === 0) {
273
+ res.json({
274
+ success: true,
275
+ output: output || 'Update completed successfully',
276
+ message: 'Update completed. Please restart the server to apply changes.'
277
+ });
278
+ } else {
279
+ res.status(500).json({
280
+ success: false,
281
+ error: 'Update command failed',
282
+ output: output,
283
+ errorOutput: errorOutput
284
+ });
285
+ }
286
+ });
287
+
288
+ child.on('error', (error) => {
289
+ console.error('Update process error:', error);
290
+ res.status(500).json({
291
+ success: false,
292
+ error: error.message
293
+ });
294
+ });
295
+
296
+ } catch (error) {
297
+ console.error('System update error:', error);
298
+ res.status(500).json({
299
+ success: false,
300
+ error: error.message
301
+ });
302
+ }
303
+ });
304
+
240
305
  app.get('/api/projects', authenticateToken, async (req, res) => {
241
306
  try {
242
307
  const projects = await getProjects();
@@ -90,13 +90,13 @@ function normalizeGitHubUrl(url) {
90
90
  function parseGitHubUrl(url) {
91
91
  // Handle HTTPS URLs: https://github.com/owner/repo or https://github.com/owner/repo.git
92
92
  // Handle SSH URLs: git@github.com:owner/repo or git@github.com:owner/repo.git
93
- const match = url.match(/github\.com[:/]([^/]+)\/([^/.]+)/);
93
+ const match = url.match(/github\.com[:/]([^/]+)\/([^/]+?)(?:\.git)?$/);
94
94
  if (!match) {
95
95
  throw new Error('Invalid GitHub URL format');
96
96
  }
97
97
  return {
98
98
  owner: match[1],
99
- repo: match[2].replace('.git', '')
99
+ repo: match[2].replace(/\.git$/, '')
100
100
  };
101
101
  }
102
102
 
@@ -114,14 +114,37 @@ function autogenerateBranchName(message) {
114
114
  .replace(/-+/g, '-') // Replace multiple hyphens with single
115
115
  .replace(/^-|-$/g, ''); // Remove leading/trailing hyphens
116
116
 
117
- // Limit length to 50 characters
118
- if (branchName.length > 50) {
119
- branchName = branchName.substring(0, 50).replace(/-$/, '');
117
+ // Ensure non-empty fallback
118
+ if (!branchName) {
119
+ branchName = 'task';
120
120
  }
121
121
 
122
- // Add timestamp suffix to ensure uniqueness
123
- const timestamp = Date.now().toString(36).substring(-6);
124
- branchName = `${branchName}-${timestamp}`;
122
+ // Generate timestamp suffix (last 6 chars of base36 timestamp)
123
+ const timestamp = Date.now().toString(36).slice(-6);
124
+ const suffix = `-${timestamp}`;
125
+
126
+ // Limit length to ensure total length including suffix fits within 50 characters
127
+ const maxBaseLength = 50 - suffix.length;
128
+ if (branchName.length > maxBaseLength) {
129
+ branchName = branchName.substring(0, maxBaseLength);
130
+ }
131
+
132
+ // Remove any trailing hyphen after truncation and ensure no leading hyphen
133
+ branchName = branchName.replace(/-$/, '').replace(/^-+/, '');
134
+
135
+ // If still empty or starts with hyphen after cleanup, use fallback
136
+ if (!branchName || branchName.startsWith('-')) {
137
+ branchName = 'task';
138
+ }
139
+
140
+ // Combine base name with timestamp suffix
141
+ branchName = `${branchName}${suffix}`;
142
+
143
+ // Final validation: ensure it matches safe pattern
144
+ if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(branchName)) {
145
+ // Fallback to deterministic safe name
146
+ return `branch-${timestamp}`;
147
+ }
125
148
 
126
149
  return branchName;
127
150
  }