zen-gitsync 2.13.25 → 2.13.27

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.
Files changed (48) hide show
  1. package/package.json +1 -1
  2. package/scripts/README_COLOR_CONVERTER.md +196 -196
  3. package/scripts/README_FONTSIZE_CONVERTER.md +278 -278
  4. package/scripts/README_SPACING_CONVERTER.md +126 -126
  5. package/scripts/README_STYLE_VARS.md +180 -180
  6. package/src/config.js +14 -1
  7. package/src/ui/public/assets/{AppVersionBadge-CIAzLihu.js → AppVersionBadge-V4NxO9cu.js} +2 -2
  8. package/src/ui/public/assets/{BranchSelector-BoztZ6c2.js → BranchSelector-2uX5HSm5.js} +1 -1
  9. package/src/ui/public/assets/{CommandConsole-CZA9PDIm.js → CommandConsole-BwejhA4f.js} +2 -2
  10. package/src/ui/public/assets/CommitForm-COb6kHLF.js +6 -0
  11. package/src/ui/public/assets/{CommitForm-CCBME4F0.css → CommitForm-DIGVx-uM.css} +1 -1
  12. package/src/ui/public/assets/{CustomCommandManager-CieZYBTz.js → CustomCommandManager-B8Qjz_eU.js} +1 -1
  13. package/src/ui/public/assets/EditorView-BFke8nSV.js +0 -0
  14. package/src/ui/public/assets/{EditorView-BoRRJEFO.css → EditorView-Do_aRkqm.css} +1 -1
  15. package/src/ui/public/assets/{FileDiffViewer-DhpNUTJt.js → FileDiffViewer-D3PiL3r9.js} +1 -1
  16. package/src/ui/public/assets/FlowExecutionViewer-B5kh7VxS.css +1 -0
  17. package/src/ui/public/assets/{FlowExecutionViewer-DlYmmGkP.js → FlowExecutionViewer-BJPlBrrT.js} +1 -1
  18. package/src/ui/public/assets/FlowOrchestrationWorkspace-0BR-Uf93.js +21 -0
  19. package/src/ui/public/assets/{FlowOrchestrationWorkspace-DmBxt5nC.css → FlowOrchestrationWorkspace-BAQDU9Jd.css} +1 -1
  20. package/src/ui/public/assets/{GitStatus-B4hnJzqy.js → GitStatus--jezFZl6.js} +2 -2
  21. package/src/ui/public/assets/{GitStatus-CGnFB5Iq.css → GitStatus-7pgefQUu.css} +1 -1
  22. package/src/ui/public/assets/{ImagePreview-Cil0rDfG.js → ImagePreview-yFJVtpwT.js} +1 -1
  23. package/src/ui/public/assets/{LogList-BKqV6ERt.js → LogList-Bd5tlqhN.js} +1 -1
  24. package/src/ui/public/assets/{ProjectStartupButton-CPXyIqHS.js → ProjectStartupButton-Bf-htfPw.js} +1 -1
  25. package/src/ui/public/assets/RemoteRepoCard-BJtZtGu9.js +1 -0
  26. package/src/ui/public/assets/RemoteRepoCard-d0klonVb.css +1 -0
  27. package/src/ui/public/assets/{ResetToRemoteButton-CAHhKkZ5.js → ResetToRemoteButton-BedpKd_z.js} +1 -1
  28. package/src/ui/public/assets/{SourceMapView-Bb8pfASG.js → SourceMapView-4KZkPsZ5.js} +3 -3
  29. package/src/ui/public/assets/{TemplateManager-WSreg-op.js → TemplateManager-BELcp36h.js} +1 -1
  30. package/src/ui/public/assets/{UserInputNode-DR6fUbfy.js → UserInputNode-DQky_rGr.js} +1 -1
  31. package/src/ui/public/assets/{WorkbenchView-402ZzsT0.js → WorkbenchView-bJR8tgXK.js} +1 -1
  32. package/src/ui/public/assets/_plugin-vue_export-helper-Cpm3JOKV.js +9 -0
  33. package/src/ui/public/assets/{index-CDa9xf0V.css → index-Cn3n2mx6.css} +1 -1
  34. package/src/ui/public/assets/index-SLuwYU5Z.js +7 -0
  35. package/src/ui/public/favicon.svg +75 -75
  36. package/src/ui/public/index.html +22 -20
  37. package/src/ui/public/logo.svg +74 -74
  38. package/src/ui/server/routes/config.js +9 -7
  39. package/src/ui/server/routes/workbench.js +2 -2
  40. package/src/utils/index.js +11 -2
  41. package/src/ui/public/assets/CommitForm-DZ8aU8PB.js +0 -6
  42. package/src/ui/public/assets/EditorView-BzTJPZPp.js +0 -0
  43. package/src/ui/public/assets/FlowExecutionViewer-DhmllmKH.css +0 -1
  44. package/src/ui/public/assets/FlowOrchestrationWorkspace-gdihO9k1.js +0 -21
  45. package/src/ui/public/assets/RemoteRepoCard-CspjnxaZ.js +0 -1
  46. package/src/ui/public/assets/RemoteRepoCard-DkcYbJtw.css +0 -1
  47. package/src/ui/public/assets/_plugin-vue_export-helper-BVVLmyjZ.js +0 -9
  48. package/src/ui/public/assets/index-D_T4XWSf.js +0 -7
@@ -1,75 +1,75 @@
1
- <svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
2
- <defs>
3
- <radialGradient id="bgGrad" cx="38%" cy="32%" r="70%">
4
- <stop offset="0%" stop-color="#1e1b4b"/>
5
- <stop offset="100%" stop-color="#0d0b1e"/>
6
- </radialGradient>
7
- <linearGradient id="mainGrad" x1="0%" y1="0%" x2="0%" y2="100%">
8
- <stop offset="0%" stop-color="#c4b5fd"/>
9
- <stop offset="100%" stop-color="#7c3aed"/>
10
- </linearGradient>
11
- <linearGradient id="featGrad" x1="0%" y1="0%" x2="100%" y2="100%">
12
- <stop offset="0%" stop-color="#7dd3fc"/>
13
- <stop offset="100%" stop-color="#0284c7"/>
14
- </linearGradient>
15
- <filter id="glow" x="-40%" y="-40%" width="180%" height="180%">
16
- <feGaussianBlur in="SourceGraphic" stdDeviation="2.5" result="blur"/>
17
- <feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
18
- </filter>
19
- <filter id="softGlow" x="-20%" y="-20%" width="140%" height="140%">
20
- <feGaussianBlur in="SourceGraphic" stdDeviation="1.5" result="blur"/>
21
- <feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
22
- </filter>
23
- </defs>
24
-
25
- <!-- 背景圆 -->
26
- <circle cx="100" cy="100" r="96" fill="url(#bgGrad)"/>
27
-
28
- <!-- 同步外弧(上半,代表 sync 循环) -->
29
- <path d="M 100,20 A 80,80 0 1,1 36,153"
30
- stroke="rgba(167,139,250,0.18)" stroke-width="4.5" fill="none" stroke-linecap="round"/>
31
- <!-- 同步外弧(下半) -->
32
- <path d="M 36,153 A 80,80 0 0,1 164,153"
33
- stroke="rgba(56,189,248,0.18)" stroke-width="4.5" fill="none" stroke-linecap="round"/>
34
- <!-- 同步箭头(上) -->
35
- <path d="M 91,17 L 100,20 L 96,29"
36
- stroke="rgba(167,139,250,0.55)" stroke-width="2.5" fill="none"
37
- stroke-linecap="round" stroke-linejoin="round"/>
38
- <!-- 同步箭头(下) -->
39
- <path d="M 163,145 L 164,154 L 155,151"
40
- stroke="rgba(56,189,248,0.55)" stroke-width="2.5" fill="none"
41
- stroke-linecap="round" stroke-linejoin="round"/>
42
-
43
- <!-- 主分支竖线 -->
44
- <line x1="76" y1="44" x2="76" y2="156"
45
- stroke="url(#mainGrad)" stroke-width="5.5" stroke-linecap="round"
46
- filter="url(#softGlow)"/>
47
-
48
- <!-- 特性分支曲线(分出) -->
49
- <path d="M 76,80 C 98,80 130,96 130,120 L 130,140"
50
- stroke="url(#featGrad)" stroke-width="4.5" fill="none"
51
- stroke-linecap="round" filter="url(#softGlow)"/>
52
- <!-- 特性分支合并回主分支 -->
53
- <path d="M 130,140 C 130,156 105,159 76,155"
54
- stroke="url(#featGrad)" stroke-width="4.5" fill="none" stroke-linecap="round"/>
55
-
56
- <!-- 主分支节点 -->
57
- <circle cx="76" cy="48" r="11" fill="#13103a" stroke="#c4b5fd" stroke-width="3" filter="url(#glow)"/>
58
- <circle cx="76" cy="48" r="5" fill="#ddd6fe"/>
59
-
60
- <circle cx="76" cy="84" r="11" fill="#13103a" stroke="#a78bfa" stroke-width="3"/>
61
- <circle cx="76" cy="84" r="5" fill="#c4b5fd"/>
62
-
63
- <circle cx="76" cy="120" r="11" fill="#13103a" stroke="#8b5cf6" stroke-width="3"/>
64
- <circle cx="76" cy="120" r="5" fill="#a78bfa"/>
65
-
66
- <circle cx="76" cy="155" r="11" fill="#13103a" stroke="#7c3aed" stroke-width="3" filter="url(#glow)"/>
67
- <circle cx="76" cy="155" r="5" fill="#8b5cf6"/>
68
-
69
- <!-- 特性分支节点 -->
70
- <circle cx="130" cy="115" r="11" fill="#13103a" stroke="#38bdf8" stroke-width="3" filter="url(#glow)"/>
71
- <circle cx="130" cy="115" r="5" fill="#7dd3fc"/>
72
-
73
- <circle cx="130" cy="143" r="11" fill="#13103a" stroke="#0ea5e9" stroke-width="3" filter="url(#glow)"/>
74
- <circle cx="130" cy="143" r="5" fill="#38bdf8"/>
75
- </svg>
1
+ <svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
2
+ <defs>
3
+ <radialGradient id="bgGrad" cx="38%" cy="32%" r="70%">
4
+ <stop offset="0%" stop-color="#1e1b4b"/>
5
+ <stop offset="100%" stop-color="#0d0b1e"/>
6
+ </radialGradient>
7
+ <linearGradient id="mainGrad" x1="0%" y1="0%" x2="0%" y2="100%">
8
+ <stop offset="0%" stop-color="#c4b5fd"/>
9
+ <stop offset="100%" stop-color="#7c3aed"/>
10
+ </linearGradient>
11
+ <linearGradient id="featGrad" x1="0%" y1="0%" x2="100%" y2="100%">
12
+ <stop offset="0%" stop-color="#7dd3fc"/>
13
+ <stop offset="100%" stop-color="#0284c7"/>
14
+ </linearGradient>
15
+ <filter id="glow" x="-40%" y="-40%" width="180%" height="180%">
16
+ <feGaussianBlur in="SourceGraphic" stdDeviation="2.5" result="blur"/>
17
+ <feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
18
+ </filter>
19
+ <filter id="softGlow" x="-20%" y="-20%" width="140%" height="140%">
20
+ <feGaussianBlur in="SourceGraphic" stdDeviation="1.5" result="blur"/>
21
+ <feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
22
+ </filter>
23
+ </defs>
24
+
25
+ <!-- 背景圆 -->
26
+ <circle cx="100" cy="100" r="96" fill="url(#bgGrad)"/>
27
+
28
+ <!-- 同步外弧(上半,代表 sync 循环) -->
29
+ <path d="M 100,20 A 80,80 0 1,1 36,153"
30
+ stroke="rgba(167,139,250,0.18)" stroke-width="4.5" fill="none" stroke-linecap="round"/>
31
+ <!-- 同步外弧(下半) -->
32
+ <path d="M 36,153 A 80,80 0 0,1 164,153"
33
+ stroke="rgba(56,189,248,0.18)" stroke-width="4.5" fill="none" stroke-linecap="round"/>
34
+ <!-- 同步箭头(上) -->
35
+ <path d="M 91,17 L 100,20 L 96,29"
36
+ stroke="rgba(167,139,250,0.55)" stroke-width="2.5" fill="none"
37
+ stroke-linecap="round" stroke-linejoin="round"/>
38
+ <!-- 同步箭头(下) -->
39
+ <path d="M 163,145 L 164,154 L 155,151"
40
+ stroke="rgba(56,189,248,0.55)" stroke-width="2.5" fill="none"
41
+ stroke-linecap="round" stroke-linejoin="round"/>
42
+
43
+ <!-- 主分支竖线 -->
44
+ <line x1="76" y1="44" x2="76" y2="156"
45
+ stroke="url(#mainGrad)" stroke-width="5.5" stroke-linecap="round"
46
+ filter="url(#softGlow)"/>
47
+
48
+ <!-- 特性分支曲线(分出) -->
49
+ <path d="M 76,80 C 98,80 130,96 130,120 L 130,140"
50
+ stroke="url(#featGrad)" stroke-width="4.5" fill="none"
51
+ stroke-linecap="round" filter="url(#softGlow)"/>
52
+ <!-- 特性分支合并回主分支 -->
53
+ <path d="M 130,140 C 130,156 105,159 76,155"
54
+ stroke="url(#featGrad)" stroke-width="4.5" fill="none" stroke-linecap="round"/>
55
+
56
+ <!-- 主分支节点 -->
57
+ <circle cx="76" cy="48" r="11" fill="#13103a" stroke="#c4b5fd" stroke-width="3" filter="url(#glow)"/>
58
+ <circle cx="76" cy="48" r="5" fill="#ddd6fe"/>
59
+
60
+ <circle cx="76" cy="84" r="11" fill="#13103a" stroke="#a78bfa" stroke-width="3"/>
61
+ <circle cx="76" cy="84" r="5" fill="#c4b5fd"/>
62
+
63
+ <circle cx="76" cy="120" r="11" fill="#13103a" stroke="#8b5cf6" stroke-width="3"/>
64
+ <circle cx="76" cy="120" r="5" fill="#a78bfa"/>
65
+
66
+ <circle cx="76" cy="155" r="11" fill="#13103a" stroke="#7c3aed" stroke-width="3" filter="url(#glow)"/>
67
+ <circle cx="76" cy="155" r="5" fill="#8b5cf6"/>
68
+
69
+ <!-- 特性分支节点 -->
70
+ <circle cx="130" cy="115" r="11" fill="#13103a" stroke="#38bdf8" stroke-width="3" filter="url(#glow)"/>
71
+ <circle cx="130" cy="115" r="5" fill="#7dd3fc"/>
72
+
73
+ <circle cx="130" cy="143" r="11" fill="#13103a" stroke="#0ea5e9" stroke-width="3" filter="url(#glow)"/>
74
+ <circle cx="130" cy="143" r="5" fill="#38bdf8"/>
75
+ </svg>
@@ -1,28 +1,30 @@
1
- <!doctype html>
2
- <html lang="zh-CN" translate="no">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="google" content="notranslate" />
6
- <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
7
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
- <title>Zen GitSync</title>
9
- <!-- Premium fonts: Plus Jakarta Sans (UI) + JetBrains Mono (code) -->
10
- <link rel="preconnect" href="https://fonts.googleapis.com" />
11
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
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-D_T4XWSf.js"></script>
1
+ <!doctype html>
2
+ <html lang="zh-CN" translate="no">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="google" content="notranslate" />
6
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
+ <title>Zen GitSync</title>
9
+ <!-- Premium fonts: Plus Jakarta Sans (UI) + JetBrains Mono (code) -->
10
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
11
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
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-SLuwYU5Z.js"></script>
14
14
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-CMxvf4Kt.js">
15
15
  <link rel="modulepreload" crossorigin href="/assets/monaco-DC7mqInI.js">
16
16
  <link rel="modulepreload" crossorigin href="/assets/element-plus-CJjFCgLP.js">
17
17
  <link rel="modulepreload" crossorigin href="/assets/vendor-0YbzMuxw.js">
18
- <link rel="modulepreload" crossorigin href="/assets/_plugin-vue_export-helper-BVVLmyjZ.js">
18
+ <link rel="modulepreload" crossorigin href="/assets/_plugin-vue_export-helper-Cpm3JOKV.js">
19
19
  <link rel="modulepreload" crossorigin href="/assets/socket-io-z4n873W1.js">
20
+ <link rel="modulepreload" crossorigin href="/assets/vue-flow-HHfhvx4N.js">
20
21
  <link rel="stylesheet" crossorigin href="/assets/monaco-UXx6YYK1.css">
21
22
  <link rel="stylesheet" crossorigin href="/assets/element-plus-D36sOm0a.css">
22
23
  <link rel="stylesheet" crossorigin href="/assets/vendor-DNI_idR2.css">
23
- <link rel="stylesheet" crossorigin href="/assets/index-CDa9xf0V.css">
24
- </head>
25
- <body>
26
- <div id="app"></div>
27
- </body>
28
- </html>
24
+ <link rel="stylesheet" crossorigin href="/assets/vue-flow-CavUTEzp.css">
25
+ <link rel="stylesheet" crossorigin href="/assets/index-Cn3n2mx6.css">
26
+ </head>
27
+ <body>
28
+ <div id="app"></div>
29
+ </body>
30
+ </html>
@@ -1,75 +1,75 @@
1
- <svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
2
- <defs>
3
- <radialGradient id="bgGrad" cx="38%" cy="32%" r="70%">
4
- <stop offset="0%" stop-color="#1e1b4b"/>
5
- <stop offset="100%" stop-color="#0d0b1e"/>
6
- </radialGradient>
7
- <linearGradient id="mainGrad" x1="0%" y1="0%" x2="0%" y2="100%">
8
- <stop offset="0%" stop-color="#c4b5fd"/>
9
- <stop offset="100%" stop-color="#7c3aed"/>
10
- </linearGradient>
11
- <linearGradient id="featGrad" x1="0%" y1="0%" x2="100%" y2="100%">
12
- <stop offset="0%" stop-color="#7dd3fc"/>
13
- <stop offset="100%" stop-color="#0284c7"/>
14
- </linearGradient>
15
- <filter id="glow" x="-40%" y="-40%" width="180%" height="180%">
16
- <feGaussianBlur in="SourceGraphic" stdDeviation="2.5" result="blur"/>
17
- <feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
18
- </filter>
19
- <filter id="softGlow" x="-20%" y="-20%" width="140%" height="140%">
20
- <feGaussianBlur in="SourceGraphic" stdDeviation="1.5" result="blur"/>
21
- <feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
22
- </filter>
23
- </defs>
24
-
25
- <!-- 背景�?-->
26
- <circle cx="100" cy="100" r="96" fill="url(#bgGrad)"/>
27
-
28
- <!-- 同步外弧(上半,代表 sync 循环�?-->
29
- <path d="M 100,20 A 80,80 0 1,1 36,153"
30
- stroke="rgba(167,139,250,0.18)" stroke-width="4.5" fill="none" stroke-linecap="round"/>
31
- <!-- 同步外弧(下半) -->
32
- <path d="M 36,153 A 80,80 0 0,1 164,153"
33
- stroke="rgba(56,189,248,0.18)" stroke-width="4.5" fill="none" stroke-linecap="round"/>
34
- <!-- 同步箭头(上�?-->
35
- <path d="M 91,17 L 100,20 L 96,29"
36
- stroke="rgba(167,139,250,0.55)" stroke-width="2.5" fill="none"
37
- stroke-linecap="round" stroke-linejoin="round"/>
38
- <!-- 同步箭头(下�?-->
39
- <path d="M 163,145 L 164,154 L 155,151"
40
- stroke="rgba(56,189,248,0.55)" stroke-width="2.5" fill="none"
41
- stroke-linecap="round" stroke-linejoin="round"/>
42
-
43
- <!-- 主分支竖�?-->
44
- <line x1="76" y1="44" x2="76" y2="156"
45
- stroke="url(#mainGrad)" stroke-width="5.5" stroke-linecap="round"
46
- filter="url(#softGlow)"/>
47
-
48
- <!-- 特性分支曲线(分出�?-->
49
- <path d="M 76,80 C 98,80 130,96 130,120 L 130,140"
50
- stroke="url(#featGrad)" stroke-width="4.5" fill="none"
51
- stroke-linecap="round" filter="url(#softGlow)"/>
52
- <!-- 特性分支合并回主分�?-->
53
- <path d="M 130,140 C 130,156 105,159 76,155"
54
- stroke="url(#featGrad)" stroke-width="4.5" fill="none" stroke-linecap="round"/>
55
-
56
- <!-- 主分支节�?-->
57
- <circle cx="76" cy="48" r="11" fill="#13103a" stroke="#c4b5fd" stroke-width="3" filter="url(#glow)"/>
58
- <circle cx="76" cy="48" r="5" fill="#ddd6fe"/>
59
-
60
- <circle cx="76" cy="84" r="11" fill="#13103a" stroke="#a78bfa" stroke-width="3"/>
61
- <circle cx="76" cy="84" r="5" fill="#c4b5fd"/>
62
-
63
- <circle cx="76" cy="120" r="11" fill="#13103a" stroke="#8b5cf6" stroke-width="3"/>
64
- <circle cx="76" cy="120" r="5" fill="#a78bfa"/>
65
-
66
- <circle cx="76" cy="155" r="11" fill="#13103a" stroke="#7c3aed" stroke-width="3" filter="url(#glow)"/>
67
- <circle cx="76" cy="155" r="5" fill="#8b5cf6"/>
68
-
69
- <!-- 特性分支节�?-->
70
- <circle cx="130" cy="115" r="11" fill="#13103a" stroke="#38bdf8" stroke-width="3" filter="url(#glow)"/>
71
- <circle cx="130" cy="115" r="5" fill="#7dd3fc"/>
72
-
73
- <circle cx="130" cy="143" r="11" fill="#13103a" stroke="#0ea5e9" stroke-width="3" filter="url(#glow)"/>
74
- <circle cx="130" cy="143" r="5" fill="#38bdf8"/>
1
+ <svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
2
+ <defs>
3
+ <radialGradient id="bgGrad" cx="38%" cy="32%" r="70%">
4
+ <stop offset="0%" stop-color="#1e1b4b"/>
5
+ <stop offset="100%" stop-color="#0d0b1e"/>
6
+ </radialGradient>
7
+ <linearGradient id="mainGrad" x1="0%" y1="0%" x2="0%" y2="100%">
8
+ <stop offset="0%" stop-color="#c4b5fd"/>
9
+ <stop offset="100%" stop-color="#7c3aed"/>
10
+ </linearGradient>
11
+ <linearGradient id="featGrad" x1="0%" y1="0%" x2="100%" y2="100%">
12
+ <stop offset="0%" stop-color="#7dd3fc"/>
13
+ <stop offset="100%" stop-color="#0284c7"/>
14
+ </linearGradient>
15
+ <filter id="glow" x="-40%" y="-40%" width="180%" height="180%">
16
+ <feGaussianBlur in="SourceGraphic" stdDeviation="2.5" result="blur"/>
17
+ <feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
18
+ </filter>
19
+ <filter id="softGlow" x="-20%" y="-20%" width="140%" height="140%">
20
+ <feGaussianBlur in="SourceGraphic" stdDeviation="1.5" result="blur"/>
21
+ <feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
22
+ </filter>
23
+ </defs>
24
+
25
+ <!-- 背景�?-->
26
+ <circle cx="100" cy="100" r="96" fill="url(#bgGrad)"/>
27
+
28
+ <!-- 同步外弧(上半,代表 sync 循环�?-->
29
+ <path d="M 100,20 A 80,80 0 1,1 36,153"
30
+ stroke="rgba(167,139,250,0.18)" stroke-width="4.5" fill="none" stroke-linecap="round"/>
31
+ <!-- 同步外弧(下半) -->
32
+ <path d="M 36,153 A 80,80 0 0,1 164,153"
33
+ stroke="rgba(56,189,248,0.18)" stroke-width="4.5" fill="none" stroke-linecap="round"/>
34
+ <!-- 同步箭头(上�?-->
35
+ <path d="M 91,17 L 100,20 L 96,29"
36
+ stroke="rgba(167,139,250,0.55)" stroke-width="2.5" fill="none"
37
+ stroke-linecap="round" stroke-linejoin="round"/>
38
+ <!-- 同步箭头(下�?-->
39
+ <path d="M 163,145 L 164,154 L 155,151"
40
+ stroke="rgba(56,189,248,0.55)" stroke-width="2.5" fill="none"
41
+ stroke-linecap="round" stroke-linejoin="round"/>
42
+
43
+ <!-- 主分支竖�?-->
44
+ <line x1="76" y1="44" x2="76" y2="156"
45
+ stroke="url(#mainGrad)" stroke-width="5.5" stroke-linecap="round"
46
+ filter="url(#softGlow)"/>
47
+
48
+ <!-- 特性分支曲线(分出�?-->
49
+ <path d="M 76,80 C 98,80 130,96 130,120 L 130,140"
50
+ stroke="url(#featGrad)" stroke-width="4.5" fill="none"
51
+ stroke-linecap="round" filter="url(#softGlow)"/>
52
+ <!-- 特性分支合并回主分�?-->
53
+ <path d="M 130,140 C 130,156 105,159 76,155"
54
+ stroke="url(#featGrad)" stroke-width="4.5" fill="none" stroke-linecap="round"/>
55
+
56
+ <!-- 主分支节�?-->
57
+ <circle cx="76" cy="48" r="11" fill="#13103a" stroke="#c4b5fd" stroke-width="3" filter="url(#glow)"/>
58
+ <circle cx="76" cy="48" r="5" fill="#ddd6fe"/>
59
+
60
+ <circle cx="76" cy="84" r="11" fill="#13103a" stroke="#a78bfa" stroke-width="3"/>
61
+ <circle cx="76" cy="84" r="5" fill="#c4b5fd"/>
62
+
63
+ <circle cx="76" cy="120" r="11" fill="#13103a" stroke="#8b5cf6" stroke-width="3"/>
64
+ <circle cx="76" cy="120" r="5" fill="#a78bfa"/>
65
+
66
+ <circle cx="76" cy="155" r="11" fill="#13103a" stroke="#7c3aed" stroke-width="3" filter="url(#glow)"/>
67
+ <circle cx="76" cy="155" r="5" fill="#8b5cf6"/>
68
+
69
+ <!-- 特性分支节�?-->
70
+ <circle cx="130" cy="115" r="11" fill="#13103a" stroke="#38bdf8" stroke-width="3" filter="url(#glow)"/>
71
+ <circle cx="130" cy="115" r="5" fill="#7dd3fc"/>
72
+
73
+ <circle cx="130" cy="143" r="11" fill="#13103a" stroke="#0ea5e9" stroke-width="3" filter="url(#glow)"/>
74
+ <circle cx="130" cy="143" r="5" fill="#38bdf8"/>
75
75
  </svg>
@@ -1027,6 +1027,7 @@ export function registerConfigRoutes({
1027
1027
  await configManager.writeRawConfigFile(rawConfig)
1028
1028
  res.json({ success: true })
1029
1029
  } catch (error) {
1030
+ logger.error('[save-ui-settings] failed:', error)
1030
1031
  res.status(500).json({ success: false, error: error.message })
1031
1032
  }
1032
1033
  })
@@ -1094,7 +1095,7 @@ export function registerConfigRoutes({
1094
1095
  const models = Array.isArray(rawConfig.models) ? rawConfig.models : []
1095
1096
  const defaultModel = models.find(m => m.isDefault) || models[0]
1096
1097
  if (!defaultModel) {
1097
- return res.json({ success: false, error: '未配置 AI 模型,请先在通用设置中添加模型' })
1098
+ return res.json({ success: false, error: '未配置 AI 模型,请先在通用设置中添加模型', code: 'NO_MODEL' })
1098
1099
  }
1099
1100
 
1100
1101
  // 后端自己收集 diff,确保 untracked 文件也能进 prompt
@@ -1152,7 +1153,7 @@ ${diffText || '(no staged content, please infer from the file list)'}`
1152
1153
  stream: false
1153
1154
  })
1154
1155
  const controller = new AbortController()
1155
- const timer = setTimeout(() => controller.abort(), 30000)
1156
+ const timer = setTimeout(() => controller.abort(), 60000)
1156
1157
  let response
1157
1158
  try {
1158
1159
  response = await fetch(url, { method: 'POST', headers, body, signal: controller.signal })
@@ -1162,7 +1163,7 @@ ${diffText || '(no staged content, please infer from the file list)'}`
1162
1163
  const data = await response.json().catch(() => ({}))
1163
1164
  if (!response.ok) {
1164
1165
  const msg = data?.error?.message || data?.message || `HTTP ${response.status}`
1165
- return res.json({ success: false, error: msg })
1166
+ return res.json({ success: false, error: msg, code: 'HTTP_ERR' })
1166
1167
  }
1167
1168
  const content = data?.choices?.[0]?.message?.content || ''
1168
1169
  // 响应内容只走 debug(默认关闭),前 600 字截断防 token 泄露
@@ -1175,7 +1176,7 @@ ${diffText || '(no staged content, please infer from the file list)'}`
1175
1176
 
1176
1177
  if (!jsonMatch) {
1177
1178
  console.error('[generate-commit] no JSON found, full content:', content)
1178
- return res.json({ success: false, error: 'model returned no valid JSON' })
1179
+ return res.json({ success: false, error: 'model returned no valid JSON', code: 'NO_JSON' })
1179
1180
  }
1180
1181
  let parsed
1181
1182
  try {
@@ -1192,7 +1193,7 @@ ${diffText || '(no staged content, please infer from the file list)'}`
1192
1193
  description: (descM?.[1] || '').trim()
1193
1194
  })
1194
1195
  }
1195
- return res.json({ success: false, error: 'JSON parse failed' })
1196
+ return res.json({ success: false, error: 'JSON parse failed', code: 'PARSE_FAILED' })
1196
1197
  }
1197
1198
  res.json({
1198
1199
  success: true,
@@ -1201,8 +1202,9 @@ ${diffText || '(no staged content, please infer from the file list)'}`
1201
1202
  description: String(parsed.description || '').trim()
1202
1203
  })
1203
1204
  } catch (error) {
1204
- const msg = error.name === 'AbortError' ? 'timeout 30s' : error.message
1205
- res.json({ success: false, error: msg })
1205
+ const isTimeout = error.name === 'AbortError'
1206
+ const msg = isTimeout ? 'AI 请求超时(60s),请重试或检查模型响应速度' : error.message
1207
+ res.json({ success: false, error: msg, code: isTimeout ? 'TIMEOUT' : 'GENERATE_FAILED' })
1206
1208
  }
1207
1209
  })
1208
1210
  }
@@ -1961,7 +1961,7 @@ ${desc ? `描述:${desc}` : '描述:(无)'}${attachmentBlock}${templateB
1961
1961
  if (delta.thinking) send({ type: 'thinking', delta: delta.thinking });
1962
1962
  if (delta.content) send({ type: 'content', delta: delta.content });
1963
1963
  },
1964
- { maxTokens: 16000, timeoutMs: 600000, images: imageDataUrls, signal: abortController.signal }
1964
+ { maxTokens: 32000, timeoutMs: 600000, images: imageDataUrls, signal: abortController.signal }
1965
1965
  );
1966
1966
 
1967
1967
  if (aborted) {
@@ -2230,7 +2230,7 @@ ${desc ? `描述:${desc}` : '描述:(无)'}${attachmentBlock}${templateB
2230
2230
  if (delta.thinking) send({ type: 'thinking', delta: delta.thinking });
2231
2231
  if (delta.content) send({ type: 'content', delta: delta.content });
2232
2232
  },
2233
- { maxTokens: 16000, timeoutMs: 600000, signal: abortController.signal }
2233
+ { maxTokens: 32000, timeoutMs: 600000, signal: abortController.signal }
2234
2234
  );
2235
2235
 
2236
2236
  if (aborted) {
@@ -315,8 +315,10 @@ function execGitCommand(command, options = {}) {
315
315
  }
316
316
 
317
317
  // Add command to history
318
+ // 用 head(已 join)而不是原始 command,确保历史里的 command 永远是字符串
319
+ // 防止 execGitCommand(['status']) 这类数组调用把数组塞进历史 → 前端 item.command.trim() 崩
318
320
  const historyItem = {
319
- command,
321
+ command: head,
320
322
  stdout: truncatedStdout || '',
321
323
  stderr: truncatedStderr || '',
322
324
  error: error ? error.message : null,
@@ -415,7 +417,14 @@ function getCommandHistory() {
415
417
  // Function to manually add command to history (for commands not using execGitCommand)
416
418
  function addCommandToHistory(command, stdout = '', stderr = '', error = null, executionTime = 0) {
417
419
  const MAX_OUTPUT_LENGTH = 5000;
418
-
420
+
421
+ // 防御:历史里的 command 必须始终是字符串,防止前端 item.command.trim() 抛错
422
+ if (Array.isArray(command)) {
423
+ command = command.join(' ')
424
+ } else if (typeof command !== 'string') {
425
+ command = String(command ?? '')
426
+ }
427
+
419
428
  // Truncate outputs if too long
420
429
  const isStdoutTruncated = stdout.length > MAX_OUTPUT_LENGTH;
421
430
  const isStderrTruncated = stderr.length > MAX_OUTPUT_LENGTH;