zen-gitsync 2.11.32 → 2.11.33
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/package.json +1 -1
- package/src/ui/public/assets/{index-DAGcNJIG.css → index-BU9ORmDD.css} +1 -1
- package/src/ui/public/assets/{index-BNd_56JT.js → index-CEKbvGDC.js} +7 -7
- package/src/ui/public/index.html +2 -2
- package/src/ui/server/index.js +10 -2
- package/src/ui/server/routes/fileOpen.js +17 -6
- package/src/ui/server/utils/randomStartPort.js +37 -0
package/src/ui/public/index.html
CHANGED
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
11
11
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
12
12
|
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,400&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
|
13
|
-
<script type="module" crossorigin src="/assets/index-
|
|
13
|
+
<script type="module" crossorigin src="/assets/index-CEKbvGDC.js"></script>
|
|
14
14
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-BM3Ffeng.js">
|
|
15
15
|
<link rel="modulepreload" crossorigin href="/assets/vendor-DTKP57oj.js">
|
|
16
16
|
<link rel="stylesheet" crossorigin href="/assets/vendor-7wb-m8Qu.css">
|
|
17
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
17
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BU9ORmDD.css">
|
|
18
18
|
</head>
|
|
19
19
|
<body>
|
|
20
20
|
<div id="app"></div>
|
package/src/ui/server/index.js
CHANGED
|
@@ -31,6 +31,7 @@ import { registerInstancesRoutes } from './routes/instances.js';
|
|
|
31
31
|
import { createInstanceRegistry } from './utils/instanceRegistry.js';
|
|
32
32
|
import { createSavePortToFile } from './utils/createSavePortToFile.js';
|
|
33
33
|
import { startServerOnAvailablePort } from './utils/startServerOnAvailablePort.js';
|
|
34
|
+
import { resolveStartPort } from './utils/randomStartPort.js';
|
|
34
35
|
import { createFilePickerMiddleware } from 'local-file-picker';
|
|
35
36
|
import { createAiModelMiddleware } from 'ai-model-form';
|
|
36
37
|
|
|
@@ -293,7 +294,14 @@ async function startUIServer(noOpen = false, savePort = false) {
|
|
|
293
294
|
}
|
|
294
295
|
|
|
295
296
|
// 启动服务器
|
|
296
|
-
|
|
297
|
+
// 端口策略:默认从 [4000, 6000) 随机挑起点,再顺序扫描 EADDRINUSE;
|
|
298
|
+
// 可通过 PORT 环境变量强制使用固定端口(向后兼容 + 便于书签/调试)
|
|
299
|
+
const portStrategy = resolveStartPort();
|
|
300
|
+
if (portStrategy.source === 'env') {
|
|
301
|
+
console.log(chalk.cyan(`[端口] 使用环境变量 PORT=${portStrategy.startPort}`));
|
|
302
|
+
} else {
|
|
303
|
+
console.log(chalk.cyan(`[端口] 随机起点 ${portStrategy.startPort}(范围 ${portStrategy.min}-${portStrategy.max},遇到占用会顺延)`));
|
|
304
|
+
}
|
|
297
305
|
|
|
298
306
|
// 创建一个函数来保存端口号到文件和环境变量
|
|
299
307
|
// 使用闭包保存端口状态,防止多次写入相同端口
|
|
@@ -315,7 +323,7 @@ async function startUIServer(noOpen = false, savePort = false) {
|
|
|
315
323
|
// 尝试在可用端口上启动服务器(不等待;listen 事件会驱动后续逻辑)
|
|
316
324
|
startServerOnAvailablePort({
|
|
317
325
|
httpServer,
|
|
318
|
-
startPort:
|
|
326
|
+
startPort: portStrategy.startPort,
|
|
319
327
|
chalk,
|
|
320
328
|
open,
|
|
321
329
|
noOpen,
|
|
@@ -19,14 +19,22 @@ function spawnDetached(command, args, options = {}) {
|
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
async function launchClaudeCode(dirPath) {
|
|
22
|
+
async function launchClaudeCode(dirPath, { permissionMode } = {}) {
|
|
23
|
+
// 透传可选的权限模式参数到 claude CLI(如 acceptEdits)
|
|
24
|
+
// 注意:permissionMode 必须是一个 token 字符串,避免 shell 注入
|
|
25
|
+
const SAFE_MODE = /^[a-zA-Z][a-zA-Z0-9_-]*$/;
|
|
26
|
+
const cliArgs = [];
|
|
27
|
+
if (permissionMode && typeof permissionMode === 'string' && SAFE_MODE.test(permissionMode)) {
|
|
28
|
+
cliArgs.push('--permission-mode', permissionMode);
|
|
29
|
+
}
|
|
30
|
+
|
|
23
31
|
if (process.platform === 'win32') {
|
|
24
|
-
return spawnDetached('cmd.exe', ['/c', 'start', '""', 'claude'], {
|
|
32
|
+
return spawnDetached('cmd.exe', ['/c', 'start', '""', 'claude', ...cliArgs], {
|
|
25
33
|
cwd: dirPath
|
|
26
34
|
});
|
|
27
35
|
}
|
|
28
36
|
|
|
29
|
-
return spawnDetached('claude',
|
|
37
|
+
return spawnDetached('claude', cliArgs, {
|
|
30
38
|
cwd: dirPath
|
|
31
39
|
});
|
|
32
40
|
}
|
|
@@ -227,7 +235,7 @@ export function registerFileOpenRoutes({
|
|
|
227
235
|
// 用 Claude Code 打开目录
|
|
228
236
|
app.post('/api/open-directory-with-claude-code', async (req, res) => {
|
|
229
237
|
try {
|
|
230
|
-
const { path: dirPath } = req.body;
|
|
238
|
+
const { path: dirPath, permissionMode } = req.body || {};
|
|
231
239
|
if (!dirPath) {
|
|
232
240
|
return res.status(400).json({ success: false, error: '目录路径不能为空' });
|
|
233
241
|
}
|
|
@@ -239,8 +247,11 @@ export function registerFileOpenRoutes({
|
|
|
239
247
|
}
|
|
240
248
|
|
|
241
249
|
try {
|
|
242
|
-
await launchClaudeCode(dirPath);
|
|
243
|
-
|
|
250
|
+
await launchClaudeCode(dirPath, { permissionMode });
|
|
251
|
+
const message = permissionMode
|
|
252
|
+
? `已用 Claude Code 打开目录(permission-mode=${permissionMode})`
|
|
253
|
+
: '已用 Claude Code 打开目录';
|
|
254
|
+
res.json({ success: true, message });
|
|
244
255
|
} catch (error) {
|
|
245
256
|
res.status(400).json({
|
|
246
257
|
success: false,
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// 随机起点端口选择
|
|
2
|
+
// 默认:避免与系统保留 / 常见服务端口重叠,在较宽的"用户态"范围里随机挑一个起点
|
|
3
|
+
// 然后由 startServerOnAvailablePort 在该起点基础上顺序往上扫描 EADDRINUSE
|
|
4
|
+
// 覆盖:环境变量 PORT 强制使用固定端口(向后兼容 + 便于书签/调试)
|
|
5
|
+
|
|
6
|
+
const DEFAULT_MIN = 4000;
|
|
7
|
+
const DEFAULT_MAX = 6000; // 2000 端口的池子;配合 maxTries 100 实际能覆盖 (max - min) 区间
|
|
8
|
+
|
|
9
|
+
function pickRandomInt(min, max) {
|
|
10
|
+
// 含 min,不含 max(与 Math.random 习惯一致)
|
|
11
|
+
return Math.floor(Math.random() * (max - min)) + min;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 解析本次启动应使用的起始端口
|
|
16
|
+
* @param {object} [opts]
|
|
17
|
+
* @param {number} [opts.min] 随机范围下界(默认 4000)
|
|
18
|
+
* @param {number} [opts.max] 随机范围上界(默认 6000)
|
|
19
|
+
* @returns {{ startPort: number, source: 'env'|'random', min: number, max: number }}
|
|
20
|
+
*/
|
|
21
|
+
export function resolveStartPort({ min = DEFAULT_MIN, max = DEFAULT_MAX } = {}) {
|
|
22
|
+
// 1) 环境变量优先:用户显式指定 > 一切
|
|
23
|
+
const envPort = Number(process.env.PORT);
|
|
24
|
+
if (Number.isInteger(envPort) && envPort > 0 && envPort < 65536) {
|
|
25
|
+
return { startPort: envPort, source: 'env', min, max };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// 2) 兜底:参数范围非法就回退到 [4000, 6000)
|
|
29
|
+
if (!Number.isInteger(min) || !Number.isInteger(max) || min < 1 || max > 65535 || min >= max) {
|
|
30
|
+
min = DEFAULT_MIN;
|
|
31
|
+
max = DEFAULT_MAX;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// 3) 随机挑一个起点
|
|
35
|
+
const startPort = pickRandomInt(min, max);
|
|
36
|
+
return { startPort, source: 'random', min, max };
|
|
37
|
+
}
|