zen-gitsync 2.11.33 → 2.11.35

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.
@@ -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-CEKbvGDC.js"></script>
13
+ <script type="module" crossorigin src="/assets/index-BMmj4tvE.js"></script>
14
14
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-BM3Ffeng.js">
15
- <link rel="modulepreload" crossorigin href="/assets/vendor-DTKP57oj.js">
16
- <link rel="stylesheet" crossorigin href="/assets/vendor-7wb-m8Qu.css">
17
- <link rel="stylesheet" crossorigin href="/assets/index-BU9ORmDD.css">
15
+ <link rel="modulepreload" crossorigin href="/assets/vendor-CoJ3pi_A.js">
16
+ <link rel="stylesheet" crossorigin href="/assets/vendor-hOO_r_AU.css">
17
+ <link rel="stylesheet" crossorigin href="/assets/index-DtH8KJk5.css">
18
18
  </head>
19
19
  <body>
20
20
  <div id="app"></div>
@@ -736,7 +736,7 @@ export function registerConfigRoutes({
736
736
 
737
737
  // 读取原始配置以保留项目设置
738
738
  const rawConfig = await configManager.readRawConfigFile()
739
-
739
+
740
740
  // 更新全局设置
741
741
  if (theme && ['light', 'dark', 'auto'].includes(theme)) {
742
742
  rawConfig.theme = theme
@@ -744,7 +744,7 @@ export function registerConfigRoutes({
744
744
  if (locale && ['zh-CN', 'en-US'].includes(locale)) {
745
745
  rawConfig.locale = locale
746
746
  }
747
-
747
+
748
748
  // 直接写入原始配置,避免覆盖项目设置
749
749
  await configManager.writeRawConfigFile(rawConfig)
750
750
  res.json({ success: true })
@@ -753,6 +753,31 @@ export function registerConfigRoutes({
753
753
  }
754
754
  })
755
755
 
756
+ // 保存 UI 状态(视图模式/分割比例/控制台状态/布局比例/编辑器自动保存等)
757
+ // 接受 partial body,浅合并到顶层 ui 对象。例:{ layout: {...} } / { commandConsole: {...} } / { fileListViewMode: 'tree' }
758
+ app.post('/api/config/save-ui-settings', express.json(), async (req, res) => {
759
+ try {
760
+ const partial = req.body && typeof req.body === 'object' ? req.body : {}
761
+
762
+ const rawConfig = await configManager.readRawConfigFile()
763
+
764
+ // 确保 ui 容器存在
765
+ if (!rawConfig.ui || typeof rawConfig.ui !== 'object' || Array.isArray(rawConfig.ui)) {
766
+ rawConfig.ui = {}
767
+ }
768
+
769
+ // 浅合并顶层 ui 字段(支持嵌套对象整体替换,如 commandConsole)
770
+ for (const key of Object.keys(partial)) {
771
+ rawConfig.ui[key] = partial[key]
772
+ }
773
+
774
+ await configManager.writeRawConfigFile(rawConfig)
775
+ res.json({ success: true })
776
+ } catch (error) {
777
+ res.status(500).json({ success: false, error: error.message })
778
+ }
779
+ })
780
+
756
781
  // 保存 AI 模型配置(models 是全局配置,存在配置文件顶层,跨项目共享)
757
782
  app.post('/api/config/save-models', express.json(), async (req, res) => {
758
783
  try {
@@ -264,4 +264,62 @@ export function registerGitDiffRoutes({
264
264
  });
265
265
  }
266
266
  });
267
+
268
+ // 批量撤回文件修改(未跟踪删除,已修改 checkout 还原)
269
+ // body: { filePaths: string[] }
270
+ // 返回: { success, count, results: [{ path, success, error? }] }
271
+ app.post('/api/revert_files', async (req, res) => {
272
+ const filePaths = Array.isArray(req.body?.filePaths) ? req.body.filePaths : []
273
+ if (filePaths.length === 0) {
274
+ return res.status(400).json({ success: false, error: '缺少文件路径参数' })
275
+ }
276
+
277
+ const results = []
278
+ let successCount = 0
279
+
280
+ for (const filePath of filePaths) {
281
+ try {
282
+ // 检查文件状态:未跟踪 ??、已暂存 A/M/D、已修改(空状态会返回空字符串)
283
+ const { stdout: statusOutput } = await execGitCommand(`git status --porcelain -- "${filePath}"`)
284
+
285
+ // 未跟踪的文件 (??) → 直接删除
286
+ if (statusOutput.startsWith('??')) {
287
+ try {
288
+ await fs.unlink(filePath)
289
+ results.push({ path: filePath, success: true, message: '未跟踪的文件已删除' })
290
+ successCount++
291
+ continue
292
+ } catch (err) {
293
+ results.push({ path: filePath, success: false, error: `删除文件失败: ${err?.message || err}` })
294
+ continue
295
+ }
296
+ }
297
+
298
+ // 已暂存的文件,先取消暂存(不影响工作区)
299
+ if (statusOutput.startsWith('A ') || statusOutput.startsWith('M ') || statusOutput.startsWith('D ')) {
300
+ await execGitCommand(`git reset HEAD -- "${filePath}"`)
301
+ }
302
+
303
+ // 已修改文件:丢弃工作区修改
304
+ if (statusOutput) {
305
+ await execGitCommand(`git checkout -- "${filePath}"`)
306
+ results.push({ path: filePath, success: true, message: '文件修改已撤回' })
307
+ successCount++
308
+ } else {
309
+ // 文件已无修改(可能在并发中被处理掉了)
310
+ results.push({ path: filePath, success: true, message: '文件无修改' })
311
+ successCount++
312
+ }
313
+ } catch (err) {
314
+ results.push({ path: filePath, success: false, error: err?.message || String(err) })
315
+ }
316
+ }
317
+
318
+ res.json({
319
+ success: true,
320
+ count: filePaths.length,
321
+ successCount,
322
+ results
323
+ })
324
+ });
267
325
  }
@@ -1,24 +1,24 @@
1
- // 实例注册表 API 路由
2
- // 当前只暴露只读列表;停止/启停他人实例属于 out-of-scope(v1 只做跳转导航)
3
-
4
- export function registerInstancesRoutes({ app, registry, getCurrentInstanceId }) {
5
- // 获取所有活跃实例(自动 prune 失效条目)
6
- app.get('/api/instances', async (req, res) => {
7
- try {
8
- const instances = await registry.list({ pruneStale: true });
9
- const currentInstanceId = typeof getCurrentInstanceId === 'function'
10
- ? getCurrentInstanceId()
11
- : null;
12
- res.json({
13
- success: true,
14
- instances,
15
- currentInstanceId
16
- });
17
- } catch (error) {
18
- res.status(500).json({
19
- success: false,
20
- error: error?.message || String(error)
21
- });
22
- }
23
- });
24
- }
1
+ // 实例注册表 API 路由
2
+ // 当前只暴露只读列表;停止/启停他人实例属于 out-of-scope(v1 只做跳转导航)
3
+
4
+ export function registerInstancesRoutes({ app, registry, getCurrentInstanceId }) {
5
+ // 获取所有活跃实例(自动 prune 失效条目)
6
+ app.get('/api/instances', async (req, res) => {
7
+ try {
8
+ const instances = await registry.list({ pruneStale: true });
9
+ const currentInstanceId = typeof getCurrentInstanceId === 'function'
10
+ ? getCurrentInstanceId()
11
+ : null;
12
+ res.json({
13
+ success: true,
14
+ instances,
15
+ currentInstanceId
16
+ });
17
+ } catch (error) {
18
+ res.status(500).json({
19
+ success: false,
20
+ error: error?.message || String(error)
21
+ });
22
+ }
23
+ });
24
+ }