@siteboon/claude-code-ui 1.16.4 → 1.17.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/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/assets/index-1FHLTpt_.js +1239 -0
- package/dist/assets/index-BZ3x0u4p.css +32 -0
- package/dist/assets/{vendor-codemirror-CJLzwpLB.js → vendor-codemirror-BXil-2fV.js} +1 -1
- package/dist/assets/{vendor-react-DcyRfQm3.js → vendor-react-DIN4KjD2.js} +1 -1
- package/dist/index.html +4 -4
- package/package.json +1 -1
- package/server/index.js +107 -75
- package/server/openai-codex.js +25 -12
- package/server/projects.js +117 -63
- package/server/routes/commands.js +80 -0
- package/server/routes/git.js +57 -17
- package/dist/assets/index-Cep8Annb.js +0 -1239
- package/dist/assets/index-DQad8ylc.css +0 -32
package/server/routes/git.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
|
-
import { exec } from 'child_process';
|
|
2
|
+
import { exec, spawn } from 'child_process';
|
|
3
3
|
import { promisify } from 'util';
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import { promises as fs } from 'fs';
|
|
@@ -10,6 +10,43 @@ import { spawnCursor } from '../cursor-cli.js';
|
|
|
10
10
|
const router = express.Router();
|
|
11
11
|
const execAsync = promisify(exec);
|
|
12
12
|
|
|
13
|
+
function spawnAsync(command, args, options = {}) {
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
const child = spawn(command, args, {
|
|
16
|
+
...options,
|
|
17
|
+
shell: false,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
let stdout = '';
|
|
21
|
+
let stderr = '';
|
|
22
|
+
|
|
23
|
+
child.stdout.on('data', (data) => {
|
|
24
|
+
stdout += data.toString();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
child.stderr.on('data', (data) => {
|
|
28
|
+
stderr += data.toString();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
child.on('error', (error) => {
|
|
32
|
+
reject(error);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
child.on('close', (code) => {
|
|
36
|
+
if (code === 0) {
|
|
37
|
+
resolve({ stdout, stderr });
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const error = new Error(`Command failed: ${command} ${args.join(' ')}`);
|
|
42
|
+
error.code = code;
|
|
43
|
+
error.stdout = stdout;
|
|
44
|
+
error.stderr = stderr;
|
|
45
|
+
reject(error);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
13
50
|
// Helper function to get the actual project path from the encoded project name
|
|
14
51
|
async function getActualProjectPath(projectName) {
|
|
15
52
|
try {
|
|
@@ -60,19 +97,16 @@ async function validateGitRepository(projectPath) {
|
|
|
60
97
|
}
|
|
61
98
|
|
|
62
99
|
try {
|
|
63
|
-
//
|
|
64
|
-
const { stdout:
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
// Ensure the git root matches our project path (prevent using parent git repos)
|
|
69
|
-
if (normalizedGitRoot !== normalizedProjectPath) {
|
|
70
|
-
throw new Error(`Project directory is not a git repository. This directory is inside a git repository at ${normalizedGitRoot}, but git operations should be run from the repository root.`);
|
|
71
|
-
}
|
|
72
|
-
} catch (error) {
|
|
73
|
-
if (error.message.includes('Project directory is not a git repository')) {
|
|
74
|
-
throw error;
|
|
100
|
+
// Allow any directory that is inside a work tree (repo root or nested folder).
|
|
101
|
+
const { stdout: insideWorkTreeOutput } = await execAsync('git rev-parse --is-inside-work-tree', { cwd: projectPath });
|
|
102
|
+
const isInsideWorkTree = insideWorkTreeOutput.trim() === 'true';
|
|
103
|
+
if (!isInsideWorkTree) {
|
|
104
|
+
throw new Error('Not inside a git work tree');
|
|
75
105
|
}
|
|
106
|
+
|
|
107
|
+
// Ensure git can resolve the repository root for this directory.
|
|
108
|
+
await execAsync('git rev-parse --show-toplevel', { cwd: projectPath });
|
|
109
|
+
} catch {
|
|
76
110
|
throw new Error('Not a git repository. This directory does not contain a .git folder. Initialize a git repository with "git init" to use source control features.');
|
|
77
111
|
}
|
|
78
112
|
}
|
|
@@ -445,11 +479,17 @@ router.get('/commits', async (req, res) => {
|
|
|
445
479
|
|
|
446
480
|
try {
|
|
447
481
|
const projectPath = await getActualProjectPath(project);
|
|
482
|
+
await validateGitRepository(projectPath);
|
|
483
|
+
const parsedLimit = Number.parseInt(String(limit), 10);
|
|
484
|
+
const safeLimit = Number.isFinite(parsedLimit) && parsedLimit > 0
|
|
485
|
+
? Math.min(parsedLimit, 100)
|
|
486
|
+
: 10;
|
|
448
487
|
|
|
449
488
|
// Get commit log with stats
|
|
450
|
-
const { stdout } = await
|
|
451
|
-
|
|
452
|
-
|
|
489
|
+
const { stdout } = await spawnAsync(
|
|
490
|
+
'git',
|
|
491
|
+
['log', '--pretty=format:%H|%an|%ae|%ad|%s', '--date=relative', '-n', String(safeLimit)],
|
|
492
|
+
{ cwd: projectPath },
|
|
453
493
|
);
|
|
454
494
|
|
|
455
495
|
const commits = stdout
|
|
@@ -1125,4 +1165,4 @@ router.post('/delete-untracked', async (req, res) => {
|
|
|
1125
1165
|
}
|
|
1126
1166
|
});
|
|
1127
1167
|
|
|
1128
|
-
export default router;
|
|
1168
|
+
export default router;
|