zen-gitsync 2.17.35 → 2.17.37

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 (125) hide show
  1. package/README.md +10 -8
  2. package/package.json +4 -1
  3. package/src/cli/ai/turn.js +3 -1
  4. package/src/config.js +7 -4
  5. package/src/ui/public/assets/AgentEngineSelector-6AuDAPpq.js +1 -0
  6. package/src/ui/public/assets/AgentEngineSelector-DR3r5eQE.css +1 -0
  7. package/src/ui/public/assets/AgentView-BGI9kblY.js +1 -0
  8. package/src/ui/public/assets/AgentView-D87GB-H9.css +1 -0
  9. package/src/ui/public/assets/{AppVersionBadge-DDYQqoy7.css → AppVersionBadge--5If494j.css} +1 -1
  10. package/src/ui/public/assets/AppVersionBadge-B3ek5H8N.js +2 -0
  11. package/src/ui/public/assets/{BranchSelector-F4ibldMN.css → BranchSelector-BTCMYwG0.css} +1 -1
  12. package/src/ui/public/assets/BranchSelector-ClbaZCt4.js +1 -0
  13. package/src/ui/public/assets/CommitForm-94maYxfo.css +1 -0
  14. package/src/ui/public/assets/CommitForm-Ca3LcOEs.js +6 -0
  15. package/src/ui/public/assets/CommonDialog-Bzi5ISqT.css +1 -0
  16. package/src/ui/public/assets/CommonDialog-Dr_pxL_S.js +1 -0
  17. package/src/ui/public/assets/EditorView-BsuQfcO4.css +1 -0
  18. package/src/ui/public/assets/EditorView-Do6ElPzK.js +1 -0
  19. package/src/ui/public/assets/FileDiffViewer-B6zy6NiA.css +1 -0
  20. package/src/ui/public/assets/FileDiffViewer-C8iCjp0b.js +14 -0
  21. package/src/ui/public/assets/FlowExecutionViewer-B5kh7VxS.css +1 -0
  22. package/src/ui/public/assets/FlowExecutionViewer-C2fRNSgo.js +1 -0
  23. package/src/ui/public/assets/FlowOrchestrationWorkspace-CM2_9TW3.css +1 -0
  24. package/src/ui/public/assets/FlowOrchestrationWorkspace-HGEqGXIO.js +21 -0
  25. package/src/ui/public/assets/IconButton-BQoiw2kt.js +1 -0
  26. package/src/ui/public/assets/IconButton-W2X09OKH.css +1 -0
  27. package/src/ui/public/assets/LogList-DLxxk9NX.css +1 -0
  28. package/src/ui/public/assets/LogList-DSJgEW8A.js +7 -0
  29. package/src/ui/public/assets/MindmapView-BVW2OJQ3.js +1 -0
  30. package/src/ui/public/assets/MindmapView-C4xg3TwX.css +1 -0
  31. package/src/ui/public/assets/MonitorView-BQdQRjQm.js +1 -0
  32. package/src/ui/public/assets/MonitorView-BWOQfPtI.css +1 -0
  33. package/src/ui/public/assets/ProjectStartupButton-BW7Vsx8W.js +1 -0
  34. package/src/ui/public/assets/ProjectStartupButton-VoQqFee4.css +1 -0
  35. package/src/ui/public/assets/RecentDirectoriesChat-DC9caI5w.js +1 -0
  36. package/src/ui/public/assets/RecentDirectoriesChat-o4xK1Koc.css +1 -0
  37. package/src/ui/public/assets/RemoteManagerDialog-BHkQFhBt.js +1 -0
  38. package/src/ui/public/assets/RemoteManagerDialog-BSOph2h2.css +1 -0
  39. package/src/ui/public/assets/RemoteRepoCard-CG9WPcA_.css +1 -0
  40. package/src/ui/public/assets/RemoteRepoCard-DHz83XX6.js +1 -0
  41. package/src/ui/public/assets/SourceMapView-CO_BZJKu.css +1 -0
  42. package/src/ui/public/assets/SourceMapView-DnLbPaD0.js +3 -0
  43. package/src/ui/public/assets/{SvgIcon-CDNsk4-Q.css → SvgIcon-BQ6bR7l0.css} +1 -1
  44. package/src/ui/public/assets/SvgIcon-C6FSwsPi.js +1 -0
  45. package/src/ui/public/assets/TemplateManager-DDra_oc5.js +1 -0
  46. package/src/ui/public/assets/TemplateManager-DiM3vrbf.css +1 -0
  47. package/src/ui/public/assets/UserInputNode-Dv1ZBb-W.js +1 -0
  48. package/src/ui/public/assets/UserInputNode-d-oRXM_J.css +1 -0
  49. package/src/ui/public/assets/WorkbenchView-Crn6t-sY.css +1 -0
  50. package/src/ui/public/assets/WorkbenchView-DHPISzJx.js +20 -0
  51. package/src/ui/public/assets/{_plugin-vue_export-helper-DvoTHxai.js → _plugin-vue_export-helper-Dvl5RVR5.js} +3 -3
  52. package/src/ui/public/assets/{agentConversations-d3MNOUwO.js → agentConversations-CCdYrr3U.js} +1 -1
  53. package/src/ui/public/assets/{configStore-CzEthAKM.js → configStore-CvhtdIpo.js} +1 -1
  54. package/src/ui/public/assets/element-plus-Its1910i.js +28 -0
  55. package/src/ui/public/assets/flow-mindmap-CmV7Vqq-.js +257 -0
  56. package/src/ui/public/assets/{gitStore-CcOHgW0C.js → gitStore-D1nNBH9M.js} +1 -1
  57. package/src/ui/public/assets/{index-BaV4YcQ6.css → index-BOiFlLyR.css} +1 -1
  58. package/src/ui/public/assets/index-COkSxOTE.js +29 -0
  59. package/src/ui/public/assets/office-docx-DbsvPavE.js +31 -0
  60. package/src/ui/public/assets/{office-excel-DpZn5My2.js → office-excel-Dvz98kcs.js} +1 -1
  61. package/src/ui/public/assets/office-pptx-BIkpqGxu.js +60 -0
  62. package/src/ui/public/assets/previewSandbox-Mqz64Wve.js +9 -0
  63. package/src/ui/public/assets/{previewSandbox-PYnM6Paz.css → previewSandbox-SqNQvuHv.css} +1 -1
  64. package/src/ui/public/assets/socket-io-TBtw0msS.js +1 -0
  65. package/src/ui/public/assets/{toolsStore-DeDyDHay.js → toolsStore-C_7ulEYI.js} +1 -1
  66. package/src/ui/public/assets/{useThemeObserver-CGbhdyNi.js → useThemeObserver-OMbC_fpt.js} +1 -1
  67. package/src/ui/public/assets/{vendor-CUTaFm6P.js → vendor-C68rVcVv.js} +173 -180
  68. package/src/ui/public/assets/vue-flow-lQ4VORM5.js +39 -0
  69. package/src/ui/public/index.html +24 -24
  70. package/src/ui/server/routes/workbench/agentChat.js +1 -1
  71. package/src/ui/server/routes/workbench/hiddenProjects.js +87 -0
  72. package/src/ui/server/routes/workbench/hiddenProjects.test.js +60 -0
  73. package/src/ui/server/routes/workbench/index.js +69 -1
  74. package/src/ui/server/routes/workbench/shared.js +8 -0
  75. package/src/ui/public/assets/AgentEngineSelector-BxBfCF7n.js +0 -2
  76. package/src/ui/public/assets/AgentEngineSelector-DUf0TfaU.css +0 -1
  77. package/src/ui/public/assets/AgentView-Bebv5xk6.css +0 -1
  78. package/src/ui/public/assets/AgentView-C237fPz8.js +0 -11
  79. package/src/ui/public/assets/AppVersionBadge-B7Lx-Wd9.js +0 -2
  80. package/src/ui/public/assets/BranchSelector-DTq7wLkq.js +0 -1
  81. package/src/ui/public/assets/CommitForm-BZKY-bFa.css +0 -1
  82. package/src/ui/public/assets/CommitForm-fgUEUcf2.js +0 -6
  83. package/src/ui/public/assets/CommonDialog-BLTKW3S3.js +0 -1
  84. package/src/ui/public/assets/CommonDialog-w6EmBEXv.css +0 -1
  85. package/src/ui/public/assets/EditorView-Bw-yztBn.js +0 -37
  86. package/src/ui/public/assets/EditorView-CftLj8-x.css +0 -1
  87. package/src/ui/public/assets/FileDiffViewer-BaWbgCjI.js +0 -15
  88. package/src/ui/public/assets/FileDiffViewer-n5ea9qMe.css +0 -1
  89. package/src/ui/public/assets/FlowExecutionViewer-CvEGvNKn.js +0 -1
  90. package/src/ui/public/assets/FlowExecutionViewer-jNHI5zdm.css +0 -1
  91. package/src/ui/public/assets/FlowOrchestrationWorkspace-DGYHORvw.js +0 -21
  92. package/src/ui/public/assets/FlowOrchestrationWorkspace-DwuSSxJ1.css +0 -1
  93. package/src/ui/public/assets/IconButton-CgAeGupL.js +0 -1
  94. package/src/ui/public/assets/IconButton-RlXqKOeu.css +0 -1
  95. package/src/ui/public/assets/LogList-DTS9I7RT.js +0 -7
  96. package/src/ui/public/assets/LogList-XspUhx-C.css +0 -1
  97. package/src/ui/public/assets/MindmapView-Df_09zEe.js +0 -2
  98. package/src/ui/public/assets/MindmapView-Diq2Cu4O.css +0 -1
  99. package/src/ui/public/assets/MonitorView-CMDvh6gL.js +0 -1
  100. package/src/ui/public/assets/MonitorView-DwUwJXnY.css +0 -1
  101. package/src/ui/public/assets/ProjectStartupButton-CB8IOg1E.css +0 -1
  102. package/src/ui/public/assets/ProjectStartupButton-NVjoxicj.js +0 -1
  103. package/src/ui/public/assets/RecentDirectoriesChat-BMkc7fS1.css +0 -1
  104. package/src/ui/public/assets/RecentDirectoriesChat-CIMMRY37.js +0 -3
  105. package/src/ui/public/assets/RemoteManagerDialog-D4WphMtO.css +0 -1
  106. package/src/ui/public/assets/RemoteManagerDialog-Dhql7teH.js +0 -4
  107. package/src/ui/public/assets/RemoteRepoCard-DgNODBrP.js +0 -7
  108. package/src/ui/public/assets/RemoteRepoCard-o01IrbVz.css +0 -1
  109. package/src/ui/public/assets/SourceMapView-CfDydtsu.css +0 -1
  110. package/src/ui/public/assets/SourceMapView-DKlmuq6S.js +0 -3
  111. package/src/ui/public/assets/SvgIcon-NgXqyNp2.js +0 -1
  112. package/src/ui/public/assets/TemplateManager-DO7EPfj8.css +0 -1
  113. package/src/ui/public/assets/TemplateManager-DYhEXJyL.js +0 -1
  114. package/src/ui/public/assets/UserInputNode-CtEOFJSR.js +0 -1
  115. package/src/ui/public/assets/UserInputNode-DDNSarag.css +0 -1
  116. package/src/ui/public/assets/WorkbenchView-Bx5r6sZ5.css +0 -1
  117. package/src/ui/public/assets/WorkbenchView-Ca1l-LUu.js +0 -220
  118. package/src/ui/public/assets/element-plus-D7LDHcAn.js +0 -48
  119. package/src/ui/public/assets/flow-mindmap-B3900Z4K.js +0 -257
  120. package/src/ui/public/assets/index-DijN2LKE.js +0 -150
  121. package/src/ui/public/assets/office-docx-C8sYW8O1.js +0 -32
  122. package/src/ui/public/assets/office-pptx-BnYBTwT7.js +0 -74
  123. package/src/ui/public/assets/previewSandbox-CJ4aiQCE.js +0 -9
  124. package/src/ui/public/assets/socket-io-BFqQXqAp.js +0 -1
  125. package/src/ui/public/assets/vue-flow-CxnoC7Uq.js +0 -39
@@ -10,38 +10,38 @@
10
10
  <meta name="theme-color" content="#141820" media="(prefers-color-scheme: dark)" />
11
11
  <title>Zen GitSync</title>
12
12
  <!-- 字体改为自托管(@font-face 见 src/main.css),不再依赖 Google Fonts 外链 -->
13
- <script type="module" crossorigin src="/assets/index-DijN2LKE.js"></script>
13
+ <script type="module" crossorigin src="/assets/index-COkSxOTE.js"></script>
14
14
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-C0FnF6B9.js">
15
- <link rel="modulepreload" crossorigin href="/assets/element-plus-D7LDHcAn.js">
15
+ <link rel="modulepreload" crossorigin href="/assets/element-plus-Its1910i.js">
16
16
  <link rel="modulepreload" crossorigin href="/assets/monaco-BScz9v63.js">
17
- <link rel="modulepreload" crossorigin href="/assets/vendor-CUTaFm6P.js">
18
- <link rel="modulepreload" crossorigin href="/assets/_plugin-vue_export-helper-DvoTHxai.js">
19
- <link rel="modulepreload" crossorigin href="/assets/SvgIcon-NgXqyNp2.js">
20
- <link rel="modulepreload" crossorigin href="/assets/IconButton-CgAeGupL.js">
21
- <link rel="modulepreload" crossorigin href="/assets/configStore-CzEthAKM.js">
22
- <link rel="modulepreload" crossorigin href="/assets/socket-io-BFqQXqAp.js">
23
- <link rel="modulepreload" crossorigin href="/assets/gitStore-CcOHgW0C.js">
17
+ <link rel="modulepreload" crossorigin href="/assets/vendor-C68rVcVv.js">
18
+ <link rel="modulepreload" crossorigin href="/assets/_plugin-vue_export-helper-Dvl5RVR5.js">
19
+ <link rel="modulepreload" crossorigin href="/assets/SvgIcon-C6FSwsPi.js">
20
+ <link rel="modulepreload" crossorigin href="/assets/IconButton-BQoiw2kt.js">
21
+ <link rel="modulepreload" crossorigin href="/assets/configStore-CvhtdIpo.js">
22
+ <link rel="modulepreload" crossorigin href="/assets/socket-io-TBtw0msS.js">
23
+ <link rel="modulepreload" crossorigin href="/assets/gitStore-D1nNBH9M.js">
24
24
  <link rel="modulepreload" crossorigin href="/assets/fileIcon-B5p5pGN9.js">
25
- <link rel="modulepreload" crossorigin href="/assets/flow-mindmap-B3900Z4K.js">
26
- <link rel="modulepreload" crossorigin href="/assets/previewSandbox-CJ4aiQCE.js">
27
- <link rel="modulepreload" crossorigin href="/assets/useThemeObserver-CGbhdyNi.js">
28
- <link rel="modulepreload" crossorigin href="/assets/CommonDialog-BLTKW3S3.js">
29
- <link rel="modulepreload" crossorigin href="/assets/FileDiffViewer-BaWbgCjI.js">
30
- <link rel="modulepreload" crossorigin href="/assets/toolsStore-DeDyDHay.js">
31
- <link rel="modulepreload" crossorigin href="/assets/TemplateManager-DYhEXJyL.js">
32
- <link rel="modulepreload" crossorigin href="/assets/vue-flow-CxnoC7Uq.js">
25
+ <link rel="modulepreload" crossorigin href="/assets/flow-mindmap-CmV7Vqq-.js">
26
+ <link rel="modulepreload" crossorigin href="/assets/previewSandbox-Mqz64Wve.js">
27
+ <link rel="modulepreload" crossorigin href="/assets/useThemeObserver-OMbC_fpt.js">
28
+ <link rel="modulepreload" crossorigin href="/assets/CommonDialog-Dr_pxL_S.js">
29
+ <link rel="modulepreload" crossorigin href="/assets/FileDiffViewer-C8iCjp0b.js">
30
+ <link rel="modulepreload" crossorigin href="/assets/toolsStore-C_7ulEYI.js">
31
+ <link rel="modulepreload" crossorigin href="/assets/TemplateManager-DDra_oc5.js">
32
+ <link rel="modulepreload" crossorigin href="/assets/vue-flow-lQ4VORM5.js">
33
33
  <link rel="stylesheet" crossorigin href="/assets/element-plus-C1xzgNSR.css">
34
34
  <link rel="stylesheet" crossorigin href="/assets/monaco-B2lPvkrc.css">
35
35
  <link rel="stylesheet" crossorigin href="/assets/vendor-Bwl4dT-P.css">
36
- <link rel="stylesheet" crossorigin href="/assets/SvgIcon-CDNsk4-Q.css">
37
- <link rel="stylesheet" crossorigin href="/assets/IconButton-RlXqKOeu.css">
36
+ <link rel="stylesheet" crossorigin href="/assets/SvgIcon-BQ6bR7l0.css">
37
+ <link rel="stylesheet" crossorigin href="/assets/IconButton-W2X09OKH.css">
38
38
  <link rel="stylesheet" crossorigin href="/assets/flow-mindmap-BMpmHdqh.css">
39
- <link rel="stylesheet" crossorigin href="/assets/previewSandbox-PYnM6Paz.css">
40
- <link rel="stylesheet" crossorigin href="/assets/CommonDialog-w6EmBEXv.css">
41
- <link rel="stylesheet" crossorigin href="/assets/FileDiffViewer-n5ea9qMe.css">
42
- <link rel="stylesheet" crossorigin href="/assets/TemplateManager-DO7EPfj8.css">
39
+ <link rel="stylesheet" crossorigin href="/assets/previewSandbox-SqNQvuHv.css">
40
+ <link rel="stylesheet" crossorigin href="/assets/CommonDialog-Bzi5ISqT.css">
41
+ <link rel="stylesheet" crossorigin href="/assets/FileDiffViewer-B6zy6NiA.css">
42
+ <link rel="stylesheet" crossorigin href="/assets/TemplateManager-DiM3vrbf.css">
43
43
  <link rel="stylesheet" crossorigin href="/assets/vue-flow-CavUTEzp.css">
44
- <link rel="stylesheet" crossorigin href="/assets/index-BaV4YcQ6.css">
44
+ <link rel="stylesheet" crossorigin href="/assets/index-BOiFlLyR.css">
45
45
  </head>
46
46
  <body>
47
47
  <div id="app"></div>
@@ -50,7 +50,7 @@ import configManager from '../../../../config.js';
50
50
 
51
51
  // 单轮工具调用循环数的兜底值(防失控);实际值取全局配置 aiMaxToolIterations,
52
52
  // 与 CLI 侧 src/cli/ai/agent.js 共用同一个配置项。
53
- const DEFAULT_MAX_TOOL_ITERATIONS = 200;
53
+ const DEFAULT_MAX_TOOL_ITERATIONS = 1000;
54
54
 
55
55
  // 读取全局配置里的单轮工具调用上限。
56
56
  // 读配置失败不该把整轮对话打挂 —— 退回默认值继续跑,比用户消息直接发不出去好。
@@ -0,0 +1,87 @@
1
+ // Copyright 2026 xz333221
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ //
15
+ // 「用户从工作台清单里移除掉的死项目」——一份很小的落盘名单。
16
+ //
17
+ // 为什么需要它(而不是只从常用目录里删掉那一条就完事):
18
+ // 项目清单是**两份来源的并集**(projectRegistry.buildProjectEntries)——
19
+ // config.json 的 recentDirectories,加上 tasks.json 里任务自带的 projectPath。
20
+ // 一个目录被删/被移走之后,只删常用目录那一份通常**根本不会让这行消失**:
21
+ // 只要还有任务记着这个路径,它照样从任务那半边被重新生成(实测用户点完删除,
22
+ // 那行原地不动 —— 看起来就像按钮坏了)。想让它真正从清单里走掉,
23
+ // 就必须有一份"用户明确表示不要看见它"的记录。
24
+ //
25
+ // 为什么不改任务(把 projectPath 清空)来达到同样效果:
26
+ // 那是把**一条会失败的事实改成一条会静默成功的事实**。任务带着一个不存在的目录时,
27
+ // 执行会当场报「项目目录不存在」;清空之后 resolveTaskRepoPath 会回退到当前项目,
28
+ // 于是"点执行 → 代码改到了另一个仓库里",而界面上没有任何提示。
29
+ // projectRegistry.js 开头那段注释把这个回退称为"比直接报错危险得多",这里不能自己破它。
30
+ // 隐藏只动"看不看得见",一条任务、一个 job、一份历史都不碰。
31
+ //
32
+ // 为什么只在目录**仍然不存在**期间隐藏(filterHiddenProjects 的第二个条件):
33
+ // 目录哪天被重新克隆回来了,这一行就该自己回来 —— 用户没有永久放弃这个项目,
34
+ // 只是清掉了一条死条目。没有这条自愈,用户就得手动把隐藏名单清一次才能再见它。
35
+
36
+ import { HIDDEN_PROJECTS_FILE, readJson, writeJson } from './shared.js';
37
+
38
+ /** 上限:只可能积累"被删掉的死目录",几十条足够。满了丢最旧的(下面 unshift 的顺序即新旧) */
39
+ export const MAX_HIDDEN_PROJECTS = 200;
40
+
41
+ /**
42
+ * 读隐藏名单。文件不存在 / 读失败 / 结构不对,一律当"没藏过任何项目"——
43
+ * 这是纯展示层的偏好,坏了最多回到"死目录又出现在清单里"的原状,
44
+ * 绝不能因此让 /api/workbench/projects 整个 500(它是 5s 轮询的)。
45
+ *
46
+ * @returns {Promise<string[]>} canonicalProjectPath 之后的项目 key
47
+ */
48
+ export async function readHiddenProjects() {
49
+ try {
50
+ const data = await readJson(HIDDEN_PROJECTS_FILE, { projects: [] });
51
+ const list = Array.isArray(data?.projects) ? data.projects : [];
52
+ return list.filter(k => typeof k === 'string' && k);
53
+ } catch {
54
+ return [];
55
+ }
56
+ }
57
+
58
+ /**
59
+ * 记下一个被移除的项目(幂等)。
60
+ * @returns {Promise<string[]>} 落盘后的名单
61
+ */
62
+ export async function hideProject(key) {
63
+ if (typeof key !== 'string' || !key) return readHiddenProjects();
64
+ const current = await readHiddenProjects();
65
+ const next = [key, ...current.filter(k => k !== key)].slice(0, MAX_HIDDEN_PROJECTS);
66
+ await writeJson(HIDDEN_PROJECTS_FILE, { projects: next });
67
+ return next;
68
+ }
69
+
70
+ /**
71
+ * 从项目清单里滤掉"藏起来且目录仍然不存在"的那几条。纯函数,单测覆盖。
72
+ *
73
+ * @param {Array<{key: string, exists: boolean|null}>} projects listProjects 的产物
74
+ * @param {Iterable<string>} hidden readHiddenProjects 的结果
75
+ * @returns {Array} 原样返回入参里的条目(不复制、不改字段),只调整顺序与数量
76
+ *
77
+ * `exists === null`(没探到)**不隐藏**:那是"不知道",不是"用户不要看"。
78
+ * 按 `=== false` 判,与 projectRegistry 输出的三态口径一致。
79
+ */
80
+ export function filterHiddenProjects(projects, hidden) {
81
+ const set = hidden instanceof Set ? hidden : new Set(Array.isArray(hidden) ? hidden : []);
82
+ if (set.size === 0) return Array.isArray(projects) ? projects : [];
83
+ return (Array.isArray(projects) ? projects : []).filter(
84
+ p => !(p && set.has(p.key) && p.exists === false),
85
+ );
86
+ }
87
+
@@ -0,0 +1,60 @@
1
+ // Copyright 2026 xz333221
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ //
15
+ // 「已移除项目」名单的纯函数单测:filterHiddenProjects。
16
+ // 落盘那半(readHiddenProjects / hideProject)要真写 DATA_DIR,不在单测里跑。
17
+
18
+ import { test } from 'node:test';
19
+ import assert from 'node:assert/strict';
20
+
21
+ import { filterHiddenProjects } from './hiddenProjects.js';
22
+
23
+ const P = (key, exists) => ({ key, path: key, name: key.split(/[\\/]/).pop(), exists });
24
+
25
+ test('filterHiddenProjects: 藏起来且目录不存在 → 滤掉', () => {
26
+ const list = [P('a', true), P('b', false)];
27
+ assert.deepEqual(filterHiddenProjects(list, ['b']).map(p => p.key), ['a']);
28
+ });
29
+
30
+ test('filterHiddenProjects: 没在隐藏名单里的一律留着', () => {
31
+ const list = [P('a', false), P('b', false)];
32
+ assert.equal(filterHiddenProjects(list, ['c']).length, 2);
33
+ assert.equal(filterHiddenProjects(list, []).length, 2);
34
+ });
35
+
36
+ test('filterHiddenProjects: 目录回来了就自己现身(自愈,不做永久隐藏)', () => {
37
+ // 这条是"不硬改任务 projectPath"那套设计的兜底:用户清掉的只是死条目,
38
+ // 不是永久放弃这个项目。目录哪天被重新克隆回来,它必须自己回到清单里。
39
+ assert.equal(filterHiddenProjects([P('b', true)], ['b']).length, 1);
40
+ });
41
+
42
+ test('filterHiddenProjects: exists === null(没探到)不隐藏 —— 不知道 ≠ 用户不要看', () => {
43
+ // 与 projectRegistry 的三态口径一致:只有明确探到 false 才算"目录没了"。
44
+ // 把 null 当 false 会让一次探测超时的项目从清单里凭空消失,比多显示一行更糟。
45
+ assert.equal(filterHiddenProjects([P('b', null)], ['b']).length, 1);
46
+ });
47
+
48
+ test('filterHiddenProjects: 空名单直接原样返回,不复制数组', () => {
49
+ const list = [P('a', true)];
50
+ assert.equal(filterHiddenProjects(list, new Set()), list);
51
+ // 名单为空时没有逐条过滤的必要,也就不该因为过滤而产生新数组引用
52
+ // (board 那边拿它跟 selectedKey 比对,少一次引用变更少一次无谓的 watch 触发)
53
+ assert.equal(filterHiddenProjects(list, null), list);
54
+ });
55
+
56
+ test('filterHiddenProjects: 入参不是数组时返回空数组,不抛', () => {
57
+ assert.deepEqual(filterHiddenProjects(undefined, ['a']), []);
58
+ assert.deepEqual(filterHiddenProjects(null, ['a']), []);
59
+ assert.deepEqual(filterHiddenProjects([P('a', true)], undefined).length, 1);
60
+ });
@@ -115,6 +115,7 @@ import {
115
115
  canonicalProjectPath,
116
116
  } from './projectRegistry.js';
117
117
  import { buildEnvContextBlock } from './envContext.js';
118
+ import { readHiddenProjects, hideProject, filterHiddenProjects } from './hiddenProjects.js';
118
119
  import { ensureMemoryStore } from '../../../../memory/store.js';
119
120
  import { createJobSettledRefresher } from '../aiContext/jobRefresh.js';
120
121
  import {
@@ -1251,6 +1252,7 @@ ${subSummaries.map((s, i) => `\n### [${i + 1}] ${s.name} (${s.root})\n${s.summar
1251
1252
  // ════════════════════════════════════════════════════════════════════════
1252
1253
  // §16. 多项目编排台(L1 看板 + 主 Agent 控制台)
1253
1254
  // GET /api/workbench/projects 项目清单 + 看板任务
1255
+ // POST /api/workbench/projects/remove 从清单里移除一个项目条目
1254
1256
  // GET /api/workbench/orchestrator 调度开关 + 指令存档 + 活动流 + 默认提示词
1255
1257
  // POST /api/workbench/orchestrator/state 暂停 / 恢复调度
1256
1258
  // POST /api/workbench/orchestrator/dispatch 派发一条人类干预指令
@@ -1292,7 +1294,13 @@ ${subSummaries.map((s, i) => `\n### [${i + 1}] ${s.name} (${s.root})\n${s.summar
1292
1294
  const currentProjectPath = typeof getCurrentProjectPath === 'function' ? getCurrentProjectPath() : '';
1293
1295
  // Git 探测自带 15s TTL 缓存(directoryGitState.js),看板 5s 轮询里有 2/3 是命中缓存,
1294
1296
  // 实际 spawn 频率被自然限制在 15s 一次,不需要再给这个接口加"跳过一次探测"的开关。
1295
- const projects = await listProjects({ recentDirs, tasks, jobs: jobsSnap, currentProjectPath });
1297
+ const allProjects = await listProjects({ recentDirs, tasks, jobs: jobsSnap, currentProjectPath });
1298
+ // 滤掉用户手动移除、且目录确实已经不在了的那些条目(语义见 hiddenProjects.js)。
1299
+ // 放在 listProjects 之后而不是之前:Git 探测得照常跑完 —— 目录有没有回来,
1300
+ // 正是"该不该继续藏着"这条判据的依据。
1301
+ let projects = allProjects;
1302
+ const hidden = await readHiddenProjects();
1303
+ if (hidden.length) projects = filterHiddenProjects(allProjects, hidden);
1296
1304
  const jobsByTask = groupJobsByTask(jobsSnap);
1297
1305
  const boardTasks = tasks.map(t => decorateTaskForBoard(t, jobsByTask.get(t.id) || []));
1298
1306
  return { projects, tasks: boardTasks, currentProjectPath };
@@ -1387,6 +1395,66 @@ ${subSummaries.map((s, i) => `\n### [${i + 1}] ${s.name} (${s.root})\n${s.summar
1387
1395
  res.json({ success: true, ...payload });
1388
1396
  }));
1389
1397
 
1398
+ /**
1399
+ * 把一个项目条目从工作台清单里移除(左栏「目录不存在」那一行的删除按钮)。
1400
+ *
1401
+ * 做两件事,缺一不可:
1402
+ * ① 从常用目录(config.json 的 recentDirectories)里摘掉;
1403
+ * ② 记进 hidden-projects.json —— 只删 ① 的话,只要还有任务记着这个路径,
1404
+ * 它会立刻从「任务」那半边被重新生成,用户看到的是"点了没反应"。
1405
+ * 语义、为什么不去改任务的 projectPath,见 hiddenProjects.js 的文件头注释。
1406
+ *
1407
+ * **不删任何任务/job/历史**:只是让这一行不再出现在清单里。
1408
+ * 它在目录仍然不存在期间一直藏着;哪天目录被重新克隆回来,它会自己回来。
1409
+ *
1410
+ * 路径只认"当前清单里确实有"的那一个(用与 buildProjectEntries 同一份归一口径比对),
1411
+ * 不接受任意路径 —— 与 GET /projects 的安全边界一致,这个端点不是任意路径写配置的入口。
1412
+ */
1413
+ app.post('/api/workbench/projects/remove', asyncRoute(async (req, res) => {
1414
+ const rawPath = typeof req.body?.path === 'string' ? req.body.path.trim() : '';
1415
+ const key = canonicalProjectPath(rawPath);
1416
+ if (!key) throw new HttpError(400, '缺少项目路径');
1417
+ if (!configManager || typeof configManager.removeRecentDirectory !== 'function') {
1418
+ throw new HttpError(500, '配置管理不可用,无法移除项目');
1419
+ }
1420
+
1421
+ const tasksData = await readJson(TASKS_FILE, { tasks: [] });
1422
+ const tasks = tasksData.tasks || [];
1423
+ let recentDirs = [];
1424
+ try {
1425
+ recentDirs = (await configManager.getRecentDirectories()) || [];
1426
+ } catch (err) {
1427
+ logger.warn('[workbench] 移除项目时读取最近目录失败:', err?.message || err);
1428
+ }
1429
+
1430
+ // 只承认清单里真实存在的条目:key 归一后必须命中 buildProjectEntries 的某一条,
1431
+ // 否则 404 —— 否则这个端点就成了"往 config.json 删任意字符串"的通道。
1432
+ const entry = buildProjectEntries({ recentDirs, tasks }).find(e => e.key === key);
1433
+ if (!entry) throw new HttpError(404, '项目不在清单里,可能已经被移除');
1434
+
1435
+ // ① 常用目录。同一目录可能有多种写法(大小写 / 斜杠),逐条摘干净 ——
1436
+ // 漏掉任何一种,那一条就会在下一轮轮询里把项目重新"复活"成 source:'recent'。
1437
+ let removedFromRecent = 0;
1438
+ for (const dir of recentDirs) {
1439
+ if (canonicalProjectPath(dir) !== key) continue;
1440
+ await configManager.removeRecentDirectory(dir);
1441
+ removedFromRecent += 1;
1442
+ }
1443
+
1444
+ // ② 隐藏名单。idempotent:重复点第二次不会把它顶到最前面之外的地方。
1445
+ await hideProject(key);
1446
+
1447
+ // 通知别的 g ui 实例:它们的看板是 5s 轮询,晚一轮刷新而已,不值得推 SSE。
1448
+ publish('projects:removed', { key, path: entry.path, removedFromRecent });
1449
+
1450
+ res.json({
1451
+ success: true,
1452
+ removedFromRecent,
1453
+ // 回给前端说清楚"任务一条都没删",好让它把这句话原样讲给用户听
1454
+ keptTasks: tasks.filter(t => canonicalProjectPath(t.projectPath) === key).length,
1455
+ });
1456
+ }));
1457
+
1390
1458
  /**
1391
1459
  * 单个任务的详情 —— 点看板卡片弹出的那个框用它。
1392
1460
  *
@@ -65,6 +65,14 @@ export const MAX_ORCHESTRATOR_INSTRUCTIONS = 200;
65
65
  export const ORCHESTRATOR_REPORTS_FILE = path.join(DATA_DIR, 'orchestrator-reports.json');
66
66
  export const MAX_PROGRESS_REPORTS = 20;
67
67
 
68
+ /**
69
+ * 用户从工作台项目清单里手动移除掉的那些条目(存的是归一化后的项目 key)。
70
+ * 独立成文件而不是塞进 config.json:它一份最多几百字节,却会被 5s 轮询的项目清单
71
+ * 接口读到 —— 走 config.json 就得让每次读项目列表都解析一遍主配置。
72
+ * 语义与"为什么不能靠改任务达成"见 hiddenProjects.js 的文件头注释。
73
+ */
74
+ export const HIDDEN_PROJECTS_FILE = path.join(DATA_DIR, 'hidden-projects.json');
75
+
68
76
  /**
69
77
  * 自动进度报告允许的间隔(毫秒),0 = 关闭。
70
78
  *
@@ -1,2 +0,0 @@
1
- import"./rolldown-runtime-C0FnF6B9.js";import{$ as e,C as t,Cn as n,Dn as r,En as i,Gn as a,Hn as o,K as s,Kr as c,Mn as l,Nr as u,Pn as d,Qr as f,Rn as p,S as m,Tn as h,Yn as g,Zn as _,dr as v,or as y,q as b,qn as x,vr as S,w as C,wn as w,yn as T}from"./element-plus-D7LDHcAn.js";import{n as E,t as D}from"./_plugin-vue_export-helper-DvoTHxai.js";import{t as O}from"./SvgIcon-NgXqyNp2.js";import{t as k}from"./toolsStore-DeDyDHay.js";import{s as A,v as j}from"./index-DijN2LKE.js";import{c as M,d as N,l as P,u as F}from"./agentConversations-d3MNOUwO.js";p(),v();function I(e,t=680){let r=S(0),i=null;function s(){let t=e.value;return t?(r.value=t.clientWidth,typeof ResizeObserver>`u`||(i=new ResizeObserver(e=>{let t=e[0]?.contentRect?.width;typeof t==`number`&&(r.value=t)}),i.observe(t),!0)):!1}return x(()=>{s()||o(()=>s())}),a(()=>{i?.disconnect(),i=null}),{width:r,narrow:n(()=>r.value>0&&r.value<t)}}p(),v();var L=d({__name:`AgentEngineSelector`,props:{engine:{type:String,required:!0},locked:{type:Boolean,required:!1}},emits:[`select`],setup(r,{expose:i,emit:a}){i();let o=r,c=a,l=k(),u=n(()=>F(o.engine)),d=n(()=>({gai:!0,claude:l.claudeAvailable,opencode:l.opencodeAvailable,codex:l.codexAvailable})),f=S(!1),p=S(null);function h(e){if(!o.locked){if(!d.value[e]){if(!N(e))return;p.value=e,f.value=!0;return}c(`select`,e)}}let g={props:o,emit:c,toolsStore:l,engineName:u,engineAvailability:d,installDialogVisible:f,installTool:p,onCommand:h,get $t(){return E},get ElIcon(){return s},get ElDropdown(){return m},get ElDropdownMenu(){return C},get ElDropdownItem(){return t},get ArrowDown(){return b},get Check(){return e},get AGENT_ENGINE_OPTIONS(){return M},get BUILTIN_ENGINE_ICON(){return P},get isExternalAgentEngine(){return N},SvgIcon:O,TaskExecutorIcon:A,ToolInstallDialog:j};return Object.defineProperty(g,"__isScriptSetup",{enumerable:!1,value:!0}),g}});p(),u();var R={class:`agent-engine`},z=[`disabled`,`title`,`aria-label`],B={class:`agent-engine__name`},V={class:`agent-engine__item`},H={class:`agent-engine__item-name`},U={key:3,class:`agent-engine__item-missing`};function W(e,t,n,a,o,s){return g(),r(T,null,[i(` 单根包一层:父级传下来的 class(Tab 行的 margin-left:auto、面板的 flex:none)
2
- 才能可靠落到这里 —— 多根组件会丢掉 fallthrough class。 `),w(`div`,R,[l(a.ElDropdown,{trigger:`click`,onCommand:a.onCommand},{dropdown:y(()=>[l(a.ElDropdownMenu,null,{default:y(()=>[(g(!0),r(T,null,_(a.AGENT_ENGINE_OPTIONS,e=>(g(),h(a.ElDropdownItem,{key:e.id,command:e.id},{default:y(()=>[w(`span`,V,[a.isExternalAgentEngine(e.id)?(g(),h(a.TaskExecutorIcon,{key:0,executor:e.id,class:`agent-engine__item-icon`},null,8,[`executor`])):(g(),h(a.SvgIcon,{key:1,"icon-class":a.BUILTIN_ENGINE_ICON,class:`agent-engine__item-icon`},null,8,[`icon-class`])),w(`span`,H,f(e.name),1),n.engine===e.id?(g(),h(a.ElIcon,{key:2,class:`agent-engine__item-check`},{default:y(()=>[l(a.Check)]),_:1})):a.engineAvailability[e.id]?i(`v-if`,!0):(g(),r(`span`,U,f(a.$t(`@42BB9:未安装`)),1))])]),_:2},1032,[`command`]))),128))]),_:1})]),default:y(()=>[w(`button`,{type:`button`,class:c([`agent-engine__btn`,{"is-locked":n.locked}]),disabled:n.locked,title:n.locked?a.$t(`@AGENT:本会话的引擎已锁定;要换引擎请新建会话`):a.$t(`@AGENT:新建会话使用的引擎`),"aria-label":a.$t(`@AGENT:智能体引擎`)},[a.isExternalAgentEngine(n.engine)?(g(),h(a.TaskExecutorIcon,{key:0,executor:n.engine,class:`agent-engine__icon`},null,8,[`executor`])):(g(),h(a.SvgIcon,{key:1,"icon-class":a.BUILTIN_ENGINE_ICON,class:`agent-engine__icon`},null,8,[`icon-class`])),w(`span`,B,f(a.engineName),1),l(a.ElIcon,{class:`agent-engine__caret`},{default:y(()=>[l(a.ArrowDown)]),_:1})],10,z)]),_:1}),l(a.ToolInstallDialog,{modelValue:a.installDialogVisible,"onUpdate:modelValue":t[0]||=e=>a.installDialogVisible=e,tool:a.installTool},null,8,[`modelValue`,`tool`])])],2112)}var G=D(L,[[`render`,W],[`__scopeId`,`data-v-c67a4d14`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/AgentEngineSelector.vue`]]);export{I as n,G as t};
@@ -1 +0,0 @@
1
- .agent-engine[data-v-c67a4d14]{vertical-align:middle}.agent-engine__btn[data-v-c67a4d14]{border:1px solid var(--border-color);border-radius:var(--radius-base);color:var(--text-secondary);font-size:var(--font-size-sm);cursor:pointer;transition:border-color var(--transition-fast) ease, color var(--transition-fast) ease;background:0 0;align-items:center;gap:6px;padding:4px 8px;font-family:inherit;line-height:1.5;display:inline-flex}.agent-engine__btn[data-v-c67a4d14]:hover:not(:disabled){border-color:var(--color-primary);color:var(--text-primary)}.agent-engine__btn[data-v-c67a4d14]:disabled{cursor:not-allowed;color:var(--text-tertiary)}.agent-engine__icon[data-v-c67a4d14],.agent-engine__item-icon[data-v-c67a4d14]{flex:none;font-size:14px}.agent-engine__caret[data-v-c67a4d14]{color:var(--text-tertiary);font-size:12px}.agent-engine__item[data-v-c67a4d14]{align-items:center;gap:8px;min-width:148px;display:inline-flex}.agent-engine__item-name[data-v-c67a4d14]{flex:1}.agent-engine__item-check[data-v-c67a4d14]{color:var(--color-primary);font-size:13px}.agent-engine__item-missing[data-v-c67a4d14]{font-size:var(--font-size-sm);color:var(--text-tertiary)}
@@ -1 +0,0 @@
1
- .marketplace-panel[data-v-e9f9e851]{background:var(--bg-container);flex-direction:column;height:100%;min-height:0;display:flex}.mp-toolbar[data-v-e9f9e851]{flex-shrink:0;align-items:center;gap:12px;padding:12px 16px 8px;display:flex}.mp-search[data-v-e9f9e851]{border:1px solid var(--border-color);border-radius:var(--radius-md);background:var(--bg-panel);max-width:420px;height:32px;transition:border-color var(--transition-fast) ease;flex:1;align-items:center;gap:6px;padding:0 10px;display:flex}.mp-search[data-v-e9f9e851]:focus-within{border-color:var(--color-primary)}.mp-search .mp-search-icon[data-v-e9f9e851]{color:var(--text-tertiary);flex-shrink:0}.mp-search .mp-search-input[data-v-e9f9e851]{color:var(--text-primary);font-size:var(--font-size-mid);background:0 0;border:none;outline:none;flex:1;font-family:inherit}.mp-search .mp-search-input[data-v-e9f9e851]::placeholder{color:var(--text-tertiary)}.mp-target[data-v-e9f9e851]{flex-shrink:0}.mp-refresh[data-v-e9f9e851]{border:1px solid var(--border-color);border-radius:var(--radius-md);background:var(--bg-panel);width:30px;height:30px;color:var(--text-secondary);cursor:pointer;transition:var(--transition-ui-fast);justify-content:center;align-items:center;display:flex}.mp-refresh[data-v-e9f9e851]:hover{color:var(--color-primary);border-color:var(--color-primary)}.mp-refresh.spinning svg[data-v-e9f9e851]{animation:.9s linear infinite mkt-spin-e9f9e851}@keyframes mkt-spin-e9f9e851{to{transform:rotate(360deg)}}.mp-toolbar-sub[data-v-e9f9e851]{flex-wrap:wrap;flex-shrink:0;align-items:center;gap:12px;padding:0 16px 10px;display:flex}.mp-target-hint[data-v-e9f9e851]{font-size:var(--font-size-sm);color:var(--text-tertiary)}.mp-target-hint b[data-v-e9f9e851]{color:var(--color-primary);font-weight:600}.mp-source-filter[data-v-e9f9e851]{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.mp-chip[data-v-e9f9e851]{font-size:var(--font-size-sm);border:1px solid var(--border-color);border-radius:var(--radius-xl);color:var(--text-tertiary);cursor:pointer;transition:var(--transition-ui-fast);background:0 0;padding:2px 10px;font-family:inherit}.mp-chip[data-v-e9f9e851]:hover{color:var(--text-secondary);border-color:var(--text-tertiary)}.mp-chip.active[data-v-e9f9e851]{color:var(--color-primary);border-color:var(--color-primary);background:color-mix(in srgb, var(--color-primary) 8%, transparent)}.mp-chip.clear[data-v-e9f9e851]{color:var(--text-tertiary);border-style:dashed}.mp-body[data-v-e9f9e851]{flex:1;min-height:0;padding:0 16px 20px;overflow-y:auto}.mp-group[data-v-e9f9e851]{margin-bottom:20px}.mp-group.installed[data-v-e9f9e851]{border-top:1px dashed var(--border-color);padding-top:14px}.mp-group-header[data-v-e9f9e851]{align-items:center;gap:8px;margin-bottom:10px;display:flex}.mp-group-title[data-v-e9f9e851]{font-size:var(--font-size-mid);color:var(--text-primary);margin:0;font-weight:600}.mp-group-count[data-v-e9f9e851]{min-width:20px;height:18px;font-size:var(--font-size-xs);border-radius:var(--radius-lg);background:var(--bg-hover);color:var(--text-tertiary);justify-content:center;align-items:center;padding:0 6px;display:inline-flex}.mp-group-error[data-v-e9f9e851]{font-size:var(--font-size-sm);color:var(--color-warning);align-items:center;gap:4px;display:inline-flex}.mp-group-link[data-v-e9f9e851]{color:var(--text-tertiary);transition:color var(--transition-fast) ease;display:inline-flex}.mp-group-link[data-v-e9f9e851]:hover{color:var(--color-primary)}.mp-grid[data-v-e9f9e851]{grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:10px;display:grid}.mp-card[data-v-e9f9e851]{border:1px solid var(--border-color);border-radius:var(--radius-md);background:var(--bg-panel);transition:border-color var(--transition-fast) ease, box-shadow var(--transition-fast) ease;flex-direction:column;gap:6px;padding:12px;display:flex}.mp-card[data-v-e9f9e851]:hover{border-color:color-mix(in srgb, var(--color-primary) 40%, var(--border-color));box-shadow:var(--shadow-sm)}.mp-card-head[data-v-e9f9e851]{align-items:center;gap:8px;display:flex}.mp-card-name[data-v-e9f9e851]{min-width:0;font-size:var(--font-size-mid);color:var(--text-primary);white-space:nowrap;text-overflow:ellipsis;flex:1;font-weight:600;overflow:hidden}.mp-card-metric[data-v-e9f9e851]{font-size:var(--font-size-xs);color:var(--text-tertiary);flex-shrink:0;align-items:center;gap:3px;display:inline-flex}.mp-card-desc[data-v-e9f9e851]{font-size:var(--font-size-sm);color:var(--text-secondary);-webkit-line-clamp:2;-webkit-box-orient:vertical;min-height:36px;margin:0;line-height:1.5;display:-webkit-box;overflow:hidden}.mp-card-meta[data-v-e9f9e851]{flex-wrap:wrap;align-items:center;gap:6px;min-height:18px;display:flex}.mp-meta-pkg[data-v-e9f9e851],.mp-meta-repo[data-v-e9f9e851]{font-size:var(--font-size-xs);color:var(--text-tertiary);white-space:nowrap;text-overflow:ellipsis;max-width:220px;overflow:hidden}.mp-tag[data-v-e9f9e851]{font-size:var(--font-size-xs);border-radius:var(--radius-lg);background:var(--bg-hover);color:var(--text-tertiary);flex-shrink:0;padding:1px 6px}.mp-tag.remote[data-v-e9f9e851]{background:color-mix(in srgb, var(--color-info,var(--action-teal)) 14%, transparent);color:var(--color-info,var(--action-teal))}.mp-tag.warn[data-v-e9f9e851]{background:color-mix(in srgb, var(--color-warning) 14%, transparent);color:var(--color-warning)}.mp-card-foot[data-v-e9f9e851]{align-items:center;gap:8px;margin-top:2px;display:flex}.mp-card-link[data-v-e9f9e851]{font-size:var(--font-size-xs);color:var(--text-tertiary);text-decoration:none}.mp-card-link[data-v-e9f9e851]:hover{color:var(--color-primary);text-decoration:underline}.mp-foot-spacer[data-v-e9f9e851]{flex:1}.mp-install-btn[data-v-e9f9e851]{font-size:var(--font-size-sm);border:1px solid var(--color-primary);border-radius:var(--radius-base);color:var(--color-primary);cursor:pointer;transition:var(--transition-ui-fast);background:0 0;padding:4px 14px;font-family:inherit}.mp-install-btn[data-v-e9f9e851]:hover:not(:disabled){background:var(--color-primary);color:#fff}.mp-install-btn[data-v-e9f9e851]:disabled{opacity:.5;cursor:not-allowed}.mp-installed-chip[data-v-e9f9e851]{font-size:var(--font-size-xs);color:var(--color-success,var(--action-emerald));align-items:center;gap:3px;display:inline-flex}.mp-not-installable[data-v-e9f9e851]{font-size:var(--font-size-xs);color:var(--text-tertiary)}.mp-empty[data-v-e9f9e851]{font-size:var(--font-size-sm);color:var(--text-tertiary);padding:16px 0}.mp-empty.all[data-v-e9f9e851]{text-align:center;padding:48px 0}.mp-installed-block[data-v-e9f9e851]{margin-bottom:12px}.mp-installed-target[data-v-e9f9e851]{font-size:var(--font-size-xs);color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.4px;margin-bottom:6px;font-weight:600}.mp-installed-list[data-v-e9f9e851]{flex-direction:column;gap:4px;display:flex}.mp-installed-row[data-v-e9f9e851]{border:1px solid var(--border-color);border-radius:var(--radius-base);background:var(--bg-panel);align-items:center;gap:10px;padding:6px 10px;display:flex}.mp-installed-name[data-v-e9f9e851]{font-size:var(--font-size-sm);color:var(--text-primary);white-space:nowrap;text-overflow:ellipsis;min-width:0;font-weight:500;overflow:hidden}.mp-installed-id[data-v-e9f9e851]{font-size:var(--font-size-xs);font-family:var(--font-mono);color:var(--text-tertiary);white-space:nowrap;text-overflow:ellipsis;max-width:40%;overflow:hidden}.mp-reveal-btn[data-v-e9f9e851],.mp-remove-btn[data-v-e9f9e851]{font-size:var(--font-size-xs);border:1px solid var(--border-color);border-radius:var(--radius-xs);color:var(--text-tertiary);cursor:pointer;white-space:nowrap;transition:var(--transition-ui-fast);background:0 0;align-items:center;gap:4px;padding:3px 10px;font-family:inherit;display:inline-flex}.mp-reveal-btn[data-v-e9f9e851]:disabled,.mp-remove-btn[data-v-e9f9e851]:disabled{opacity:.5;cursor:not-allowed}.mp-reveal-btn[data-v-e9f9e851]:hover:not(:disabled){color:var(--text-primary);border-color:var(--text-tertiary)}.mp-remove-btn[data-v-e9f9e851]:hover:not(:disabled){color:var(--color-danger);border-color:var(--color-danger)}@media (prefers-reduced-motion:reduce){.mp-refresh.spinning svg[data-v-e9f9e851]{animation:none}}.mkt-form[data-v-e9f9e851]{flex-direction:column;gap:12px;display:flex}.mkt-form-name[data-v-e9f9e851]{font-size:var(--font-size-mid);color:var(--text-primary);margin:0;font-weight:600}.mkt-field[data-v-e9f9e851]{flex-direction:column;gap:4px;display:flex}.mkt-field label[data-v-e9f9e851]{font-size:var(--font-size-sm);color:var(--text-secondary);font-weight:600}.mkt-field input[data-v-e9f9e851]{border:1px solid var(--border-color);border-radius:var(--radius-md);background:var(--bg-container);height:30px;color:var(--text-primary);font-size:var(--font-size-mid);transition:border-color var(--transition-fast) ease;padding:0 8px;font-family:inherit}.mkt-field input[data-v-e9f9e851]:focus{border-color:var(--color-primary);outline:none}.mkt-hint[data-v-e9f9e851]{font-size:var(--font-size-xs);color:var(--text-tertiary);margin:0}.mkt-cancel[data-v-e9f9e851],.mkt-confirm[data-v-e9f9e851]{font-size:var(--font-size-mid);border-radius:var(--radius-base);cursor:pointer;transition:var(--transition-ui-fast);padding:6px 16px;font-family:inherit}.mkt-cancel[data-v-e9f9e851]{border:1px solid var(--border-color);color:var(--text-secondary);background:0 0;margin-right:8px}.mkt-cancel[data-v-e9f9e851]:hover{color:var(--text-primary);border-color:var(--text-tertiary)}.mkt-confirm[data-v-e9f9e851]{border:1px solid var(--color-primary);background:var(--color-primary);color:#fff}.mkt-confirm[data-v-e9f9e851]:hover{opacity:.9}.agent-view[data-v-bd681ddd]{background:var(--bg-container);height:100%;min-height:0;display:flex}.agent-sidebar[data-v-bd681ddd]{background:var(--bg-panel);border-right:1px solid var(--border-color);flex-direction:column;flex-shrink:0;display:flex;overflow:hidden}.agent-conversations[data-v-bd681ddd]{flex:1;min-height:0;padding:10px 6px 8px 12px}.sidebar-resizer[data-v-bd681ddd]{cursor:col-resize;width:4px;transition:background var(--transition-fast) ease;background:0 0;flex-shrink:0}.sidebar-resizer[data-v-bd681ddd]:hover,.sidebar-resizer.active[data-v-bd681ddd]{background:var(--color-primary);opacity:.3}.agent-chat-area[data-v-bd681ddd]{flex-direction:column;flex:1;min-width:0;display:flex;position:relative;overflow:hidden}.agent-engine[data-v-bd681ddd]{margin-bottom:7px;margin-left:auto}.agent-tabs[data-v-bd681ddd]{border-bottom:1px solid var(--border-color);background:var(--bg-panel);flex-shrink:0;align-items:center;gap:4px;padding:8px 12px 0;display:flex}.agent-tab[data-v-bd681ddd]{color:var(--text-tertiary);font-size:var(--font-size-mid);cursor:pointer;transition:color var(--transition-fast) ease, border-color var(--transition-fast) ease, background var(--transition-fast) ease;border-radius:var(--radius-base) var(--radius-base) 0 0;background:0 0;border:none;border-bottom:2px solid #0000;align-items:center;gap:6px;padding:7px 14px 9px;font-family:inherit;display:inline-flex}.agent-tab[data-v-bd681ddd]:hover{color:var(--text-secondary);background:var(--bg-hover)}.agent-tab.active[data-v-bd681ddd]{color:var(--color-primary);border-bottom-color:var(--color-primary);font-weight:600}.agent-tab-body[data-v-bd681ddd]{flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.agent-chat-pane[data-v-bd681ddd]{flex-direction:column;flex:1;min-height:0;display:flex;position:relative;overflow:hidden}.agent-tab-body[data-v-bd681ddd]>.marketplace-panel{flex:1;min-height:0}.chat-loading[data-v-bd681ddd]{color:var(--text-tertiary);font-size:var(--font-size-base);flex-direction:column;flex:1;justify-content:center;align-items:center;gap:12px;display:flex}.agent-list-page[data-v-bd681ddd]{background:var(--bg-panel);flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.agent-list-page .agent-conversations[data-v-bd681ddd]{padding:12px 12px 10px 14px}.agent-page-bar[data-v-bd681ddd]{border-bottom:1px solid var(--border-color);background:var(--bg-panel);flex-shrink:0;align-items:center;gap:6px;height:34px;padding:0 12px 0 6px;display:flex}.agent-page-back[data-v-bd681ddd]{border-radius:var(--radius-xs);width:24px;height:24px;color:var(--text-tertiary);cursor:pointer;transition:var(--transition-ui-fast);background:0 0;border:none;flex-shrink:0;justify-content:center;align-items:center;padding:0;display:flex}.agent-page-back[data-v-bd681ddd]:hover{background:var(--bg-hover);color:var(--text-secondary)}.agent-page-title[data-v-bd681ddd]{min-width:0;font-size:var(--font-size-mid);color:var(--text-secondary);white-space:nowrap;text-overflow:ellipsis;flex:1;overflow:hidden}.agent-chat-host[data-v-bd681ddd]{flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.agent-chat-host[data-v-bd681ddd] .acu-avatar--left{background:0 0}.agent-chat-host[data-v-bd681ddd] .acu-welcome-logo{background:var(--welcome-avatar) center/46px 46px no-repeat;width:56px;height:56px;box-shadow:none}.agent-chat-host[data-v-bd681ddd] .acu-welcome-logo>svg{display:none}.agent-chat-host[data-v-bd681ddd] .acu-welcome-grid{flex-wrap:wrap;display:flex}.agent-chat-host[data-v-bd681ddd] .acu-welcome-grid>.acu-preset-q{flex:260px;min-width:0}[data-theme=dark]{background:var(--bg-panel)}
@@ -1,11 +0,0 @@
1
- import"./rolldown-runtime-C0FnF6B9.js";import{$ as e,A as t,Bt as n,Cn as r,Ct as i,Dn as a,Dt as o,En as s,H as c,Hn as l,Jr as u,K as d,Kr as f,Mn as p,Nr as m,Ot as h,Pn as g,Q as _,Qr as v,Rn as y,Tn as b,Ut as x,Yn as S,Zn as C,a as w,at as T,dr as E,er as D,ft as O,gr as k,hn as A,i as j,ir as M,j as N,jn as P,ln as F,or as I,qt as ee,r as L,rn as te,sr as R,st as z,vr as B,wn as V,xt as H,yn as U}from"./element-plus-D7LDHcAn.js";import{o as W,s as G}from"./vendor-CUTaFm6P.js";import{n as K,t as q}from"./_plugin-vue_export-helper-DvoTHxai.js";import{t as J}from"./configStore-CzEthAKM.js";import{t as ne}from"./CommonDialog-BLTKW3S3.js";import{a as re,i as ie,n as ae,o as oe,r as se,s as ce,t as le}from"./agentConversations-d3MNOUwO.js";import{n as ue,t as de}from"./AgentEngineSelector-BxBfCF7n.js";y(),E();var fe=g({__name:`MarketplacePanel`,props:{type:{type:String,required:!0}},setup(t,{expose:i}){i();let a=t,s=J(),c=B([]),l=B([]),u=B(!1),d=B(``),f=B(``),p=B([]),m=B(`project`),h=B(new Set),g=B(new Set),_=B(new Set),v=r(()=>s.currentDirectory||``),y=null;async function b(){if(!u.value){u.value=!0;try{let e=new URLSearchParams({type:a.type,cwd:v.value});f.value&&e.set(`q`,f.value),p.value.length&&e.set(`sources`,p.value.join(`,`));let t=await(await fetch(`/api/agent/marketplace/catalog?${e}`)).json();t?.success?(c.value=t.groups||[],l.value=t.installed||[]):j.error(t?.error||K(`@MKT:加载失败`))}catch{j.error(K(`@MKT:加载失败`))}finally{u.value=!1}}}M(d,e=>{y&&clearTimeout(y),y=setTimeout(()=>{f.value=e.trim(),b()},400)}),M(p,()=>b()),M(()=>a.type,()=>{p.value=[],f.value=``,d.value=``,b()}),M(v,()=>b()),b();let S=r(()=>{let e=v.value?v.value.split(/[\\/]/).filter(Boolean).pop():``;return m.value===`project`?e||K(`@MKT:当前项目`):K(`@MKT:g ai 智能体`)});function C(e){return e.stars?`${w(e.stars)} ★`:e.downloads?`${w(e.downloads)} ${K(`@MKT:周下载`)}`:e.uses?`${w(e.uses)} ${K(`@MKT:次使用`)}`:``}function w(e){return e>=1e3?`${(e/1e3).toFixed(e>=1e4?0:1)}k`:String(e)}function T(e){return`${e.id}`}function E(e){return h.value.has(T(e))}let D=r(()=>{let e={project:[],global:[]};for(let t of l.value)(e[t.target]||=[]).push(t);return e}),A=k({visible:!1,item:null,env:{},args:``});function N(e){return a.type===`mcp`&&(!!e.envKeys?.length||!!e.args?.length)}function P(e){A.item=e,A.env=Object.fromEntries((e.envKeys||[]).map(e=>[e,``])),A.args=(e.args||[]).join(` `),A.visible=!0}function F(){let e=A.item;if(A.visible=!1,!e)return;let t=Object.fromEntries(Object.entries(A.env).filter(([,e])=>e.trim()!==``)),n=A.args.trim()?A.args.trim().match(/(?:[^\s"]+|"[^"]*")+/g)?.map(e=>e.replace(/^"|"$/g,``))??void 0:void 0;R(e,{env:t,...n?{args:n}:{}})}async function I(e){if(!e.installed||await V(e)){if(N(e)){P(e);return}await R(e,{})}}async function R(e,t){let n=T(e);h.value.add(n);try{let n=await fetch(`/api/agent/marketplace/install`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({type:a.type,target:m.value,cwd:v.value,item:{...e,...t}})}),r=await n.json().catch(()=>null);if(!n.ok||!r?.success){j.error(r?.error||K(`@MKT:安装失败`));return}r.item?.warning&&j.warning(r.item.warning),r.item?.envKeys?.length?j.warning(`${K(`@MKT:还缺环境变量`)}: ${r.item.envKeys.join(`, `)}`):j.success(K(`@MKT:安装成功`)),await b()}catch{j.error(K(`@MKT:安装失败`))}finally{h.value.delete(n)}}async function V(e){try{return await L.confirm(`${e.name} ${K(`@MKT:已安装,要重新安装吗?`)}`,K(`@MKT:重新安装`),{confirmButtonText:K(`@MKT:重装`),cancelButtonText:K(`@MKT:取消`),type:`warning`}),!0}catch{return!1}}async function U(e){let t=`${e.target}:${e.id}`;_.value.add(t);try{let t=await fetch(`/api/agent/marketplace/reveal`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({type:a.type,target:e.target,cwd:v.value,id:e.id})}),n=await t.json().catch(()=>null);(!t.ok||!n?.success)&&j.error(n?.error||K(`@MKT:打开失败`))}catch{j.error(K(`@MKT:打开失败`))}finally{_.value.delete(t)}}async function W(e){try{await L.confirm(`${K(`@MKT:确定卸载`)} ${e.name}?`,K(`@MKT:卸载`),{confirmButtonText:K(`@MKT:卸载`),cancelButtonText:K(`@MKT:取消`),type:`warning`})}catch{return}let t=`${e.target}:${e.id}`;g.value.add(t);try{let t=new URLSearchParams({target:e.target,cwd:v.value}),n=await fetch(`/api/agent/marketplace/item/${a.type}/${encodeURIComponent(e.id)}?${t}`,{method:`DELETE`}),r=await n.json().catch(()=>null);if(!n.ok||!r?.success){j.error(r?.error||K(`@MKT:卸载失败`));return}j.success(K(`@MKT:已卸载`)),await b()}catch{j.error(K(`@MKT:卸载失败`))}finally{g.value.delete(t)}}let G={props:a,configStore:s,groups:c,installed:l,loading:u,searchInput:d,query:f,selectedSources:p,installTarget:m,installing:h,removing:g,revealing:_,cwd:v,get searchTimer(){return y},set searchTimer(e){y=e},loadCatalog:b,targetLabel:S,metricText:C,formatCount:w,cardKey:T,isBusy:E,installedByTarget:D,configDialog:A,needsConfig:N,openConfigDialog:P,confirmConfig:F,onInstall:I,doInstall:R,confirmReinstall:V,onReveal:U,onRemove:W,get $t(){return K},get Search(){return x},get Refresh(){return n},get Delete(){return z},get Link(){return o},get Check(){return e},get Star(){return ee},get Download(){return O},get Warning(){return te},get FolderOpened(){return H},CommonDialog:ne};return Object.defineProperty(G,"__isScriptSetup",{enumerable:!1,value:!0}),G}});y(),F(),m();var pe={class:`marketplace-panel`},Y={class:`mp-toolbar`},X={class:`mp-search`},me=[`placeholder`],he={class:`mp-toolbar-sub`},Z={class:`mp-target-hint`},Q={class:`mp-source-filter`},ge=[`onClick`],$={class:`mp-body`},_e={class:`mp-group-header`},ve={class:`mp-group-title`},ye={key:0,class:`mp-group-count`},be={key:1,class:`mp-group-error`},xe=[`href`,`title`],Se={key:0,class:`mp-grid`},Ce={class:`mp-card-head`},we=[`title`],Te={key:0,class:`mp-card-metric`},Ee=[`title`],De={class:`mp-card-meta`},Oe=[`title`],ke=[`title`],Ae={key:2,class:`mp-tag remote`},je={class:`mp-card-foot`},Me=[`href`],Ne={key:1,class:`mp-installed-chip`},Pe=[`disabled`,`onClick`],Fe={key:3,class:`mp-not-installable`},Ie={key:1,class:`mp-empty`},Le={key:0,class:`mp-group installed`},Re={class:`mp-group-header`},ze={class:`mp-group-title`},Be={class:`mp-group-count`},Ve={key:0,class:`mp-installed-block`},He={class:`mp-installed-target`},Ue={class:`mp-installed-list`},We=[`title`],Ge=[`title`],Ke={key:1,class:`mp-meta-pkg`},qe={key:2,class:`mp-tag warn`},Je=[`disabled`,`title`,`onClick`],Ye=[`disabled`,`onClick`],Xe={key:1,class:`mp-empty all`},Ze={key:0,class:`mkt-form`},Qe={class:`mkt-form-name`},$e=[`onUpdate:modelValue`,`placeholder`],et={key:0,class:`mkt-field`},tt={class:`mkt-hint`};function nt(e,n,r,i,o,l){let u=d,m=t,h=N,g=c,_=w;return S(),a(`div`,pe,[s(` ── 工具栏 ───────────────────────────────── `),V(`div`,Y,[V(`div`,X,[p(u,{class:`mp-search-icon`},{default:I(()=>[p(i.Search)]),_:1}),R(V(`input`,{"onUpdate:modelValue":n[0]||=e=>i.searchInput=e,class:`mp-search-input`,type:`text`,placeholder:r.type===`skill`?i.$t(`@MKT:搜索 Skill...`):i.$t(`@MKT:搜索 MCP 服务...`)},null,8,me),[[A,i.searchInput]])]),p(h,{modelValue:i.installTarget,"onUpdate:modelValue":n[1]||=e=>i.installTarget=e,size:`small`,class:`mp-target`},{default:I(()=>[p(m,{value:`project`},{default:I(()=>[P(v(i.$t(`@MKT:当前项目`)),1)]),_:1}),p(m,{value:`global`},{default:I(()=>[P(v(i.$t(`@MKT:g ai 智能体`)),1)]),_:1})]),_:1},8,[`modelValue`]),p(g,{content:i.$t(`@MKT:刷新`),placement:`top`,"show-after":300},{default:I(()=>[V(`button`,{class:f([`mp-refresh`,{spinning:i.loading}]),onClick:i.loadCatalog},[p(u,null,{default:I(()=>[p(i.Refresh)]),_:1})],2)]),_:1},8,[`content`])]),V(`div`,he,[V(`span`,Z,[P(v(i.$t(`@MKT:安装到`))+` `,1),V(`b`,null,v(i.targetLabel),1)]),V(`div`,Q,[(S(!0),a(U,null,C(i.groups,e=>(S(),a(`button`,{key:e.id,class:f([`mp-chip`,{active:i.selectedSources.includes(e.id)}]),onClick:()=>{let t=i.selectedSources.indexOf(e.id);t>=0?i.selectedSources.splice(t,1):i.selectedSources.push(e.id)}},v(e.label),11,ge))),128)),i.selectedSources.length?(S(),a(`button`,{key:0,class:`mp-chip clear`,onClick:n[2]||=e=>i.selectedSources=[]},v(i.$t(`@MKT:全部来源`)),1)):s(`v-if`,!0)])]),s(` ── 内容 ─────────────────────────────────── `),R((S(),a(`div`,$,[(S(!0),a(U,null,C(i.groups,e=>(S(),a(`section`,{key:e.id,class:`mp-group`},[V(`header`,_e,[V(`h3`,ve,v(e.label),1),e.status===`ok`?(S(),a(`span`,ye,v(e.items.length),1)):(S(),a(`span`,be,[p(u,null,{default:I(()=>[p(i.Warning)]),_:1}),P(` `+v(e.error||i.$t(`@MKT:来源不可用`)),1)])),e.homepage?(S(),a(`a`,{key:2,class:`mp-group-link`,href:e.homepage,target:`_blank`,rel:`noopener noreferrer`,title:e.homepage},[p(u,null,{default:I(()=>[p(i.Link)]),_:1})],8,xe)):s(`v-if`,!0)]),e.status===`ok`&&e.items.length?(S(),a(`div`,Se,[(S(!0),a(U,null,C(e.items,e=>(S(),a(`article`,{key:i.cardKey(e),class:`mp-card`},[V(`div`,Ce,[V(`span`,{class:`mp-card-name`,title:e.name},v(e.name),9,we),i.metricText(e)?(S(),a(`span`,Te,[p(u,null,{default:I(()=>[e.stars?(S(),b(i.Star,{key:0})):(S(),b(i.Download,{key:1}))]),_:2},1024),P(` `+v(i.metricText(e)),1)])):s(`v-if`,!0)]),V(`p`,{class:`mp-card-desc`,title:e.description},v(e.description||i.$t(`@MKT:暂无描述`)),9,Ee),V(`div`,De,[e.package?(S(),a(`code`,{key:0,class:`mp-meta-pkg`,title:e.package},v(e.package),9,Oe)):e.repository?(S(),a(`span`,{key:1,class:`mp-meta-repo`,title:e.repository+(e.subpath?` · `+e.subpath:``)},[P(v(e.repository),1),e.subpath?(S(),a(U,{key:0},[P(` · `+v(e.subpath),1)],64)):s(`v-if`,!0)],8,ke)):s(`v-if`,!0),e.transport===`remote`?(S(),a(`span`,Ae,v(i.$t(`@MKT:远程服务`)),1)):s(`v-if`,!0),(S(!0),a(U,null,C((e.tags||[]).slice(0,2),e=>(S(),a(`span`,{key:e,class:`mp-tag`},v(e),1))),128))]),V(`div`,je,[e.upstream?(S(),a(`a`,{key:0,class:`mp-card-link`,href:e.upstream,target:`_blank`,rel:`noopener noreferrer`},v(i.$t(`@MKT:查看来源`)),9,Me)):s(`v-if`,!0),n[6]||=V(`span`,{class:`mp-foot-spacer`},null,-1),e.installed?(S(),a(`span`,Ne,[p(u,null,{default:I(()=>[p(i.Check)]),_:1}),P(v(i.$t(`@MKT:已安装`)),1)])):e.installable===!1?(S(),a(`span`,Fe,v(i.$t(`@MKT:暂不支持一键安装`)),1)):(S(),a(`button`,{key:2,class:`mp-install-btn`,disabled:i.isBusy(e),onClick:t=>i.onInstall(e)},v(i.isBusy(e)?i.$t(`@MKT:安装中...`):i.$t(`@MKT:安装`)),9,Pe))])]))),128))])):e.status===`ok`?(S(),a(`div`,Ie,v(i.$t(`@MKT:该来源暂无结果`)),1)):s(`v-if`,!0)]))),128)),s(` ── 已安装 ─────────────────────────────── `),i.installed.length?(S(),a(`section`,Le,[V(`header`,Re,[V(`h3`,ze,v(i.$t(`@MKT:已安装`)),1),V(`span`,Be,v(i.installed.length),1)]),(S(),a(U,null,C([`project`,`global`],e=>V(`div`,{key:e},[i.installedByTarget[e]?.length?(S(),a(`div`,Ve,[V(`div`,He,v(e===`project`?i.$t(`@MKT:当前项目`):i.$t(`@MKT:g ai 智能体`)),1),V(`div`,Ue,[(S(!0),a(U,null,C(i.installedByTarget[e],t=>(S(),a(`div`,{key:e+t.id,class:`mp-installed-row`},[V(`span`,{class:`mp-installed-name`,title:t.name},v(t.name),9,We),s(` 实际落盘的标识:SKILL.md 里的 name 常与仓库名不同(如仓库 taste-skill
2
- 里的 skill 自称 brandkit),不显示这个用户就对不上广场卡片上的名字 `),t.id&&t.id!==t.name?(S(),a(`code`,{key:0,class:`mp-installed-id`,title:t.dir||t.file||t.id},v(t.id),9,Ge)):s(`v-if`,!0),t.package?(S(),a(`code`,Ke,v(t.package),1)):s(`v-if`,!0),t.requiredEnv?.length?(S(),a(`span`,qe,v(i.$t(`@MKT:待配置`))+`: `+v(t.requiredEnv.join(`, `)),1)):s(`v-if`,!0),n[7]||=V(`span`,{class:`mp-foot-spacer`},null,-1),V(`button`,{class:`mp-reveal-btn`,disabled:i.revealing.has(e+t.id),title:t.dir||t.file||``,onClick:e=>i.onReveal(t)},[p(u,null,{default:I(()=>[p(i.FolderOpened)]),_:1}),P(` `+v(i.$t(`@MKT:打开文件夹`)),1)],8,Je),V(`button`,{class:`mp-remove-btn`,disabled:i.removing.has(e+t.id),onClick:e=>i.onRemove(t)},[p(u,null,{default:I(()=>[p(i.Delete)]),_:1}),P(` `+v(i.removing.has(e+t.id)?i.$t(`@MKT:卸载中...`):i.$t(`@MKT:卸载`)),1)],8,Ye)]))),128))])])):s(`v-if`,!0)])),64))])):s(`v-if`,!0),!i.loading&&!i.groups.length?(S(),a(`div`,Xe,v(i.$t(`@MKT:加载失败`)),1)):s(`v-if`,!0)])),[[_,i.loading]]),s(` ── MCP 安装前配置 ───────────────────────── `),p(i.CommonDialog,{modelValue:i.configDialog.visible,"onUpdate:modelValue":n[5]||=e=>i.configDialog.visible=e,title:i.$t(`@MKT:配置 MCP`),width:`460px`,type:`flex`,"close-on-click-modal":!1,"append-to-body":``},{footer:I(()=>[V(`button`,{class:`mkt-cancel`,onClick:n[4]||=e=>i.configDialog.visible=!1},v(i.$t(`@MKT:取消`)),1),V(`button`,{class:`mkt-confirm`,onClick:i.confirmConfig},v(i.$t(`@MKT:安装`)),1)]),default:I(()=>[i.configDialog.item?(S(),a(`div`,Ze,[V(`p`,Qe,v(i.configDialog.item.name),1),(S(!0),a(U,null,C(Object.keys(i.configDialog.env),e=>(S(),a(`div`,{key:e,class:`mkt-field`},[V(`label`,null,v(e),1),R(V(`input`,{"onUpdate:modelValue":t=>i.configDialog.env[e]=t,type:`text`,autocomplete:`off`,placeholder:i.$t(`@MKT:环境变量值`),spellcheck:`false`},null,8,$e),[[A,i.configDialog.env[e]]])]))),128)),i.configDialog.item.args?.length?(S(),a(`div`,et,[V(`label`,null,v(i.$t(`@MKT:启动参数`)),1),R(V(`input`,{"onUpdate:modelValue":n[3]||=e=>i.configDialog.args=e,type:`text`,autocomplete:`off`,spellcheck:`false`},null,512),[[A,i.configDialog.args]]),V(`p`,tt,v(i.$t(`@MKT:参数提示`)),1)])):s(`v-if`,!0)])):s(`v-if`,!0)]),_:1},8,[`modelValue`,`title`])])}var rt=q(fe,[[`render`,nt],[`__scopeId`,`data-v-e9f9e851`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/MarketplacePanel.vue`]]);y(),E();var it=g({__name:`AgentView`,setup(e,{expose:t}){t();let n=J(),a=B(null),{narrow:o}=ue(a),s=B(`chat`),c=B(`chat`),u=r(()=>c.value===`mcp`?`mcp`:`skill`),f=r(()=>[{id:`chat`,label:K(`@AGENT:对话`),icon:_},{id:`skill`,label:K(`@AGENT:Skill 广场`),icon:i},{id:`mcp`,label:K(`@AGENT:MCP 广场`),icon:T}]),{sessions:p,sessionsLoading:m,currentSessionId:g,messages:v,isStreaming:y,sessionLoading:b,loadSessions:x,loadSession:S,deleteSession:C,renameSession:w,newSession:E,sendMessage:D,pendingQuestion:O,answeringQuestion:k,answerQuestion:A,isSessionGenerating:j,currentEngine:N,pendingEngine:P,isEngineLocked:F,pickEngine:I,stop:ee}=ce(),L=r(()=>F.value?N.value:P.value);function te(e){F.value||I(e)}let R=r(()=>{let e=n.theme;return e===`dark`||e===`auto`&&window.matchMedia(`(prefers-color-scheme: dark)`).matches?`dark`:`light`}),z=r(()=>re(p.value,j)),V=se(),H=r(()=>z.value.find(e=>e.id===g.value)?.title||K(`@AGENT:对话`)),U={"--welcome-avatar":`url("${le}")`},q=r(()=>[{id:`p1`,label:K(`@AGENT:查看项目结构`),prompt:K(`@AGENT:prompt_p1`)},{id:`p2`,label:K(`@AGENT:分析代码质量`),prompt:K(`@AGENT:prompt_p2`)},{id:`p3`,label:K(`@AGENT:帮我写测试`),prompt:K(`@AGENT:prompt_p3`)},{id:`p4`,label:K(`@AGENT:Git 状态检查`),prompt:K(`@AGENT:prompt_p4`)},{id:`p5`,label:K(`@AGENT:帮我启动项目`),prompt:K(`@AGENT:prompt_p5`)}]);async function ne(e){await D(e.text,e.files),await l(),X()}async function fe(e){await D(e.prompt),await l(),X()}let pe=ie(),Y=B(null);function X(e=!0){Y.value?.scrollToBottom(e)}M(()=>v.value.length,()=>{l(()=>X(!1))});function me(e){S(e),s.value=`chat`}function he(){E(),s.value=`chat`}let Z=B(280),Q=B(!1);function ge(e){Q.value=!0;let t=e.clientX,n=Z.value,r=e=>{let r=e.clientX-t,i=Math.max(200,Math.min(500,n+r));Z.value=i},i=()=>{Q.value=!1,document.removeEventListener(`mousemove`,r),document.removeEventListener(`mouseup`,i)};document.addEventListener(`mousemove`,r),document.addEventListener(`mouseup`,i)}M(o,e=>{e||(s.value=`chat`)}),M(()=>[n.currentDirectory,y.value],async([e,t],n)=>{let r=!n||e!==n[0],i=!!n&&n[1]===!0&&!t;(r||i)&&await x(),g.value&&!y.value&&!p.value.some(e=>e.sessionId===g.value)&&E()},{immediate:!0});let $={configStore:n,rootRef:a,narrow:o,chatPage:s,activeTab:c,marketplaceType:u,tabs:f,sessions:p,sessionsLoading:m,currentSessionId:g,messages:v,isStreaming:y,sessionLoading:b,loadSessions:x,loadSession:S,deleteSession:C,renameSession:w,newSession:E,sendMessage:D,pendingQuestion:O,answeringQuestion:k,answerQuestion:A,isSessionGenerating:j,currentEngine:N,pendingEngine:P,isEngineLocked:F,pickEngine:I,stop:ee,displayEngine:L,handleEngineSelect:te,chatTheme:R,conversationItems:z,conversationLabels:V,currentSessionTitle:H,welcomeAvatarStyle:U,presetQuestions:q,onSend:ne,onSelectPreset:fe,questionLabels:pe,chatContainerRef:Y,scrollToBottom:X,selectSession:me,handleNewSession:he,sidebarWidth:Z,isResizing:Q,startResize:ge,get $t(){return K},get ElIcon(){return d},get Loading(){return h},get ChatContainer(){return G},get ConversationList(){return W},get AGENT_UPLOAD_ACCEPT(){return oe},get AGENT_ASSISTANT_NAME(){return ae},get AGENT_ASSISTANT_AVATAR(){return le},MarketplacePanel:rt,AgentEngineSelector:de};return Object.defineProperty($,"__isScriptSetup",{enumerable:!1,value:!0}),$}});y(),m();var at={ref:`rootRef`,class:`agent-view`},ot={class:`agent-chat-area`},st={class:`agent-tabs`,role:`tablist`},ct=[`aria-selected`,`onClick`],lt={class:`agent-tab-body`},ut={key:0,class:`agent-chat-pane`},dt={key:0,class:`agent-list-page`},ft={key:0,class:`agent-page-bar`},pt=[`title`,`aria-label`],mt={class:`agent-page-title`},ht={key:0,class:`chat-loading`};function gt(e,t,n,r,i,o){return S(),a(`div`,at,[s(` ═══ 宽屏:左侧会话列表(只在「对话」Tab 显示)═══
3
- 窄屏时这一整块不渲染,会话列表改成 body 里的一个整页(见 .agent-list-page) `),r.activeTab===`chat`&&!r.narrow?(S(),a(U,{key:0},[V(`aside`,{class:`agent-sidebar`,style:u({width:r.sidebarWidth+`px`})},[s(` 会话列表:UI 与交互都在组件库的 ConversationList 里 `),p(r.ConversationList,{class:`agent-conversations`,items:r.conversationItems,"active-id":r.currentSessionId,loading:r.sessionsLoading,labels:r.conversationLabels,onSelect:r.selectSession,onNew:r.handleNewSession,onRename:r.renameSession,onDelete:r.deleteSession},null,8,[`items`,`active-id`,`loading`,`labels`,`onRename`,`onDelete`])],4),s(` 拖拽分隔条 `),V(`div`,{class:f([`sidebar-resizer`,{active:r.isResizing}]),onMousedown:r.startResize},null,34)],64)):s(`v-if`,!0),s(` ═══ 右侧:Tab 栏 + 内容区 ═══ `),V(`main`,ot,[V(`nav`,st,[(S(!0),a(U,null,C(r.tabs,e=>(S(),a(`button`,{key:e.id,type:`button`,class:f([`agent-tab`,{active:r.activeTab===e.id}]),role:`tab`,"aria-selected":r.activeTab===e.id,onClick:t=>r.activeTab=e.id},[p(r.ElIcon,null,{default:I(()=>[(S(),b(D(e.icon)))]),_:2},1024),V(`span`,null,v(e.label),1)],10,ct))),128)),s(` ═══ 引擎选择器 ═══
4
- 与工作台执行器下拉同一套交互(点击展开、未安装标出来、点了直接开安装弹窗)。
5
- 下拉本体收口在 AgentEngineSelector,文件空间 g ai 面板复用同一份实现。
6
- 会话一旦落盘就置灰:引擎在会话建立时锁定(三家续聊标识互不通用),要换请新建。 `),r.activeTab===`chat`?(S(),b(r.AgentEngineSelector,{key:0,class:`agent-engine`,engine:r.displayEngine,locked:r.isEngineLocked,onSelect:r.handleEngineSelect},null,8,[`engine`,`locked`])):s(`v-if`,!0)]),V(`div`,lt,[s(` ── 对话 ── `),r.activeTab===`chat`?(S(),a(`div`,ut,[s(` 窄屏 · 会话列表页:列表独占整页 `),r.narrow&&r.chatPage===`list`?(S(),a(`div`,dt,[p(r.ConversationList,{class:`agent-conversations`,items:r.conversationItems,"active-id":r.currentSessionId,loading:r.sessionsLoading,labels:r.conversationLabels,onSelect:r.selectSession,onNew:r.handleNewSession,onRename:r.renameSession,onDelete:r.deleteSession},null,8,[`items`,`active-id`,`loading`,`labels`,`onRename`,`onDelete`])])):(S(),a(U,{key:1},[s(` 对话页(窄屏时顶上多一条返回条;宽屏左侧就摆着列表,不需要) `),r.narrow?(S(),a(`div`,ft,[V(`button`,{type:`button`,class:`agent-page-back`,title:r.$t(`@AGENT:返回会话列表`),"aria-label":r.$t(`@AGENT:返回会话列表`),onClick:t[0]||=e=>r.chatPage=`list`},[...t[1]||=[V(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[V(`line`,{x1:`19`,y1:`12`,x2:`5`,y2:`12`}),V(`polyline`,{points:`12 19 5 12 12 5`})],-1)]],8,pt),V(`span`,mt,v(r.currentSessionTitle),1)])):s(`v-if`,!0),s(`
7
- 对话宿主:单独开一层裁剪边界。
8
- 欢迎页在矮/窄窗口里会比可用高度还高,而它是垂直居中的 —— 溢出的部分
9
- 会**向上**跑出 .acu-chat,盖到刚加的返回条上(把返回条的点击也一起吃掉,
10
- e2e 实测就是这个症状)。宿主的 overflow:hidden 把它裁在自己这一格里。
11
- `),V(`div`,{class:`agent-chat-host`,style:r.welcomeAvatarStyle},[s(` 加载中 `),r.sessionLoading?(S(),a(`div`,ht,[p(r.ElIcon,{class:`is-loading`,size:32},{default:I(()=>[p(r.Loading)]),_:1}),V(`span`,null,v(r.$t(`@AGENT:加载会话中...`)),1)])):(S(),a(U,{key:1},[s(` ChatContainer `),p(r.ChatContainer,{ref:`chatContainerRef`,messages:r.messages,"preset-questions":r.presetQuestions,"welcome-title":r.$t(`@AGENT:智能体助手`),"welcome-description":r.$t(`@AGENT:我可以帮你阅读代码、执行命令、修改文件。选择下方话题或直接输入你的问题。`),"assistant-name":r.AGENT_ASSISTANT_NAME,"assistant-avatar":r.AGENT_ASSISTANT_AVATAR,theme:r.chatTheme,disabled:r.isStreaming,generating:r.isStreaming,"upload-config":{accept:r.AGENT_UPLOAD_ACCEPT},placeholder:r.isStreaming?r.$t(`@AGENT:正在生成中...`):r.$t(`@AGENT:输入消息,Enter 发送`),question:r.pendingQuestion,"question-submitting":r.answeringQuestion,"question-labels":r.questionLabels,"plan-config":{labels:{title:r.$t(`@AGENT:计划`),raw:r.$t(`@AGENT:原始参数`)}},onSend:r.onSend,onSelect:r.onSelectPreset,onStop:r.stop,onAnswer:r.answerQuestion},null,8,[`messages`,`preset-questions`,`welcome-title`,`welcome-description`,`assistant-name`,`assistant-avatar`,`theme`,`disabled`,`generating`,`upload-config`,`placeholder`,`question`,`question-submitting`,`question-labels`,`plan-config`,`onStop`,`onAnswer`])],2112))])],64))])):(S(),a(U,{key:1},[s(` ── Skill 广场 / MCP 广场 ── `),p(r.MarketplacePanel,{type:r.marketplaceType},null,8,[`type`])],2112))])])],512)}var _t=q(it,[[`render`,gt],[`__scopeId`,`data-v-bd681ddd`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/AgentView.vue`]]);export{_t as default};
@@ -1,2 +0,0 @@
1
- import"./rolldown-runtime-C0FnF6B9.js";import{Cn as e,Dn as t,En as n,Gn as r,H as i,Hn as a,K as o,Kr as s,L as c,Mn as l,Nr as u,Ot as d,Pn as f,Qr as p,Rn as m,Tn as h,Yn as g,dr as _,et as v,i as y,ir as b,jn as x,or as S,qn as C,r as w,tt as T,vr as E,wn as D}from"./element-plus-D7LDHcAn.js";import{n as O,t as k}from"./_plugin-vue_export-helper-DvoTHxai.js";import{t as A}from"./CommonDialog-BLTKW3S3.js";async function j(e,t){let n=e.body.getReader(),r=new TextDecoder(`utf-8`),i=``;for(;;){let{done:e,value:a}=await n.read();if(e)break;i+=r.decode(a,{stream:!0});let o=i.split(`
2
- `);i=o.pop()??``;for(let e of o)e.trim()&&t(e)}i.trim()&&t(i)}async function M(){let e=await fetch(`/api/app-version`);return e.ok?e.json():{success:!1,current:``,latest:null,hasUpdate:!1,error:`HTTP ${e.status}`}}async function N(e){let t=await fetch(`/api/app-upgrade`,{method:`POST`});if(!t.ok){let n=`HTTP ${t.status}`;try{let e=await t.json();e?.error&&(n=e.error)}catch{}e({type:`error`,message:n}),e({type:`done`,code:t.status});return}if(!t.body){e({type:`error`,message:`响应无 body`}),e({type:`done`,code:-1});return}await j(t,t=>{try{e(JSON.parse(t))}catch{}})}async function P(){let e=await fetch(`/api/app-restart`,{method:`POST`});if(!e.ok){let t=`HTTP ${e.status}`;try{let n=await e.json();n?.error&&(t=n.error)}catch{}throw Error(t)}if(!e.body)throw Error(`响应无 body`);return new Promise((t,n)=>{let r=!1,i=e=>{r||(r=!0,e())};j(e,e=>{try{let r=JSON.parse(e);r.type===`ready`&&typeof r.port==`number`&&r.port>0?i(()=>t(r.port)):r.type===`timeout`?i(()=>n(Error(`restart.timeout`))):r.type===`error`&&i(()=>n(Error(r.message||`restart.failed`)))}catch{}}).then(()=>{i(()=>n(Error(`restart.stream-closed`)))}).catch(()=>{})})}m(),_();var F=`npm install -g zen-gitsync --registry https://registry.npmjs.org/`,I=f({__name:`UpgradeDialog`,props:{modelValue:{type:Boolean,required:!0},logs:{type:String,required:!0},status:{type:String,required:!0},countdown:{type:Number,required:!1,default:0}},emits:[`update:modelValue`,`retry`,`restart`,`cancel`],setup(e,{expose:t,emit:n}){t();let r=e,i=n,o=E(null);b(()=>r.logs,async()=>{await a(),o.value&&(o.value.scrollTop=o.value.scrollHeight)});function s(){r.status!==`running`&&(r.status===`success`&&r.countdown>0&&i(`cancel`),i(`update:modelValue`,!1))}function c(){i(`retry`)}function l(){i(`restart`)}function u(){i(`cancel`),i(`update:modelValue`,!1)}async function f(){try{await navigator.clipboard.writeText(F),y.success(O(`@F13B4:已复制升级命令`))}catch{y.warning(O(`@F13B4:复制失败,请手动复制`))}}let p={MANUAL_COMMAND:F,props:r,emit:i,logEl:o,close:s,onRetry:c,onRestart:l,onLater:u,onCopyCommand:f,get Loading(){return d},get CircleCheck(){return v},get CircleClose(){return T},get $t(){return O},CommonDialog:A};return Object.defineProperty(p,"__isScriptSetup",{enumerable:!1,value:!0}),p}});m(),u();var L={key:3},R={key:4},z={key:5},B={key:0,class:`upgrade-hint`},V={key:0,class:`upgrade-countdown`},H={key:1,class:`upgrade-manual`},U={class:`upgrade-manual__label`};function W(e,r,i,a,u,d){let f=o,m=c;return g(),h(a.CommonDialog,{"model-value":i.modelValue,"onUpdate:modelValue":r[0]||=e=>a.emit(`update:modelValue`,e),title:a.$t(`@F13B4:升级`),width:`680px`,type:`flex`,"close-on-click-modal":!1,"close-on-press-escape":!1,"show-close":i.status!==`running`,"append-to-body":``,onClose:a.close},{footer:S(()=>[i.status===`failed`?(g(),h(m,{key:0,type:`primary`,onClick:a.onRetry},{default:S(()=>[x(p(a.$t(`@F13B4:重试`)),1)]),_:1})):n(`v-if`,!0),i.status===`failed`?(g(),h(m,{key:1,onClick:a.onCopyCommand},{default:S(()=>[x(p(a.$t(`@F13B4:复制升级命令`)),1)]),_:1})):n(`v-if`,!0),i.status===`success`?(g(),h(m,{key:2,type:`primary`,onClick:a.onRestart},{default:S(()=>[x(p(a.$t(`@F13B4:立即重启并刷新`)),1)]),_:1})):n(`v-if`,!0),i.status===`success`?(g(),h(m,{key:3,onClick:a.onLater},{default:S(()=>[x(p(a.$t(`@F13B4:稍后手动重启`)),1)]),_:1})):n(`v-if`,!0),i.status===`running`?(g(),h(m,{key:4,disabled:``},{default:S(()=>[x(p(a.$t(`@F13B4:升级中`))+`... `,1)]),_:1})):n(`v-if`,!0)]),default:S(()=>[D(`div`,{class:s([`upgrade-status`,`is-${i.status}`])},[i.status===`running`?(g(),h(f,{key:0,class:`is-loading`},{default:S(()=>[l(a.Loading)]),_:1})):i.status===`success`?(g(),h(f,{key:1,color:`var(--color-success)`},{default:S(()=>[l(a.CircleCheck)]),_:1})):(g(),h(f,{key:2,color:`var(--color-danger)`},{default:S(()=>[l(a.CircleClose)]),_:1})),i.status===`running`?(g(),t(`span`,L,p(a.$t(`@F13B4:升级中`)),1)):i.status===`success`?(g(),t(`span`,R,p(a.$t(`@F13B4:升级完成`)),1)):(g(),t(`span`,z,p(a.$t(`@F13B4:升级失败`)),1))],2),i.status===`success`?(g(),t(`p`,B,[x(p(a.$t(`@F13B4:新版本已全局安装,需要重启服务才能生效`))+` `,1),i.countdown>0?(g(),t(`span`,V,p(a.$t(`@F13B4:{seconds} 秒后自动刷新`,{seconds:i.countdown})),1)):n(`v-if`,!0)])):n(`v-if`,!0),i.status===`failed`?(g(),t(`p`,H,[D(`span`,U,p(a.$t(`@F13B4:手动升级命令`)),1),D(`code`,{class:`upgrade-manual__cmd`},p(a.MANUAL_COMMAND))])):n(`v-if`,!0),D(`pre`,{ref:`logEl`,class:`upgrade-log`},p(i.logs||a.$t(`@F13B4:等待日志输出`)),513)]),_:1},8,[`model-value`,`title`,`show-close`])}var G=k(I,[[`render`,W],[`__scopeId`,`data-v-bc566bba`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/UpgradeDialog.vue`]]);m(),_();var K=`https://github.com/xz333221/zen-gitsync/releases`,q=5,J=`app-version-check`,Y=36e5,X=f({__name:`AppVersionBadge`,setup(t,{expose:n}){n();let i=`2.17.35`,a=E(i),o=e(()=>a.value||i),s=E(null),c=E(!1),l=E(``),u=E(`running`),d=E(0),f=null,p=E(!1);function m(){try{let e=sessionStorage.getItem(J);if(!e)return null;let{at:t,data:n}=JSON.parse(e);return Date.now()-t>Y?null:n}catch{return null}}function h(e){try{sessionStorage.setItem(J,JSON.stringify({at:Date.now(),data:e}))}catch{}}async function g(e=!1){let t=m();t&&(s.value=t);try{let t=await M();s.value=t,h(t),t.current&&(a.value=t.current),!e&&t.success&&t.hasUpdate&&y({type:`success`,message:O(`@F13B4:发现新版本 {version}`,{version:t.latest??``}),duration:4e3})}catch(t){e||y({type:`warning`,message:O(`@F13B4:检查更新失败 {error}`,{error:t?.message||``})})}}async function _(){if(s.value?.hasUpdate){try{await w.confirm(O(`@F13B4:确定要从 {current} 升级到 {latest} 吗?`,{current:s.value.current,latest:s.value.latest}),O(`@F13B4:升级`),{confirmButtonText:O(`@F13B4:确定升级`),cancelButtonText:O(`@F13B4:取消`),type:`info`})}catch{return}l.value=``,u.value=`running`,c.value=!0,await N(e=>{if(e.type===`done`){if(u.value=e.code===0?`success`:`failed`,e.code===0){try{sessionStorage.removeItem(J)}catch{}s.value?.latest&&(a.value=s.value.latest),v()}}else e.message&&(l.value+=e.message)})}}function v(){b(),d.value=q,f=setInterval(()=>{--d.value,d.value<=0&&(f&&=(clearInterval(f),null),S())},1e3)}function b(){f&&=(clearInterval(f),null),d.value=0}function x(){b()}async function S(){if(b(),!p.value){p.value=!0;try{let e=await P(),{pathname:t,search:n,hash:r}=window.location;window.location.href=`http://localhost:${e}${t}${n}${r}`}catch(e){let t=e?.message||``,n={"restart.timeout":`@F13B4:重启超时`,"restart.stream-closed":`@F13B4:重启失败,请刷新页面重试`,"restart.failed":`@F13B4:重启失败`}[t];y({type:`warning`,message:n?O(n):O(`@F13B4:重启失败 {error}`,{error:t})}),p.value=!1}}}r(()=>{b()}),C(()=>{g(!0)});let T={buildVersion:i,releasesUrl:K,runtimeVersion:a,displayVersion:o,latestInfo:s,upgradeDialogVisible:c,upgradeLogs:l,upgradeStatus:u,AUTO_REFRESH_SECONDS:q,countdown:d,get countdownTimer(){return f},set countdownTimer(e){f=e},restartInFlight:p,CACHE_KEY:J,CACHE_TTL_MS:Y,readCache:m,writeCache:h,checkUpdate:g,handleUpgrade:_,startAutoRefreshCountdown:v,cancelAutoRefreshCountdown:b,handleCancelAutoRefresh:x,handleRestart:S,get $t(){return O},UpgradeDialog:G};return Object.defineProperty(T,"__isScriptSetup",{enumerable:!1,value:!0}),T}});m(),u();var Z={class:`app-version-badge`},Q=[`aria-label`],$=[`aria-label`],ee=[`title`,`aria-label`],te={class:`upgrade-btn__label`},ne={class:`upgrade-btn__version`};function re(e,r,a,o,s,c){let u=i;return g(),t(`div`,Z,[n(` GitHub 链接 `),l(u,{content:o.$t(`@F13B4:在 GitHub 上查看源码`),placement:`top`,effect:`dark`,"show-after":300},{default:S(()=>[D(`a`,{href:`https://github.com/xz333221/zen-gitsync`,target:`_blank`,rel:`noopener noreferrer`,class:`badge-icon-link`,"aria-label":o.$t(`@F13B4:在 GitHub 上查看源码`)},[...r[1]||=[D(`svg`,{viewBox:`0 0 24 24`,width:`15`,height:`15`,"aria-hidden":`true`,fill:`currentColor`,xmlns:`http://www.w3.org/2000/svg`},[D(`path`,{d:`M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0 1 12 6.844a9.59 9.59 0 0 1 2.504.337c1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.02 10.02 0 0 0 22 12.017C22 6.484 17.522 2 12 2z`})],-1)]],8,Q)]),_:1},8,[`content`]),n(` NPM 链接 `),l(u,{content:o.$t(`@F13B4:在 npm 上查看包`),placement:`top`,effect:`dark`,"show-after":300},{default:S(()=>[D(`a`,{href:`https://www.npmjs.com/package/zen-gitsync`,target:`_blank`,rel:`noopener noreferrer`,class:`badge-icon-link badge-icon-link--npm`,"aria-label":o.$t(`@F13B4:在 npm 上查看包`)},[...r[2]||=[D(`svg`,{viewBox:`0 0 24 24`,width:`15`,height:`15`,"aria-hidden":`true`,fill:`currentColor`,xmlns:`http://www.w3.org/2000/svg`},[D(`path`,{d:`M2 2v20h20V2H2zm17.167 17.167H12.5v-10h-3.333v10H4.833V4.833h14.334v14.334z`})],-1)]],8,$)]),_:1},8,[`content`]),n(` 版本号 `),l(u,{content:o.$t(`@F13B4:查看更新`),placement:`top`,effect:`dark`,"show-after":300},{default:S(()=>[D(`a`,{href:o.releasesUrl,target:`_blank`,rel:`noopener noreferrer`,class:`version-link`},`v`+p(o.displayVersion),1)]),_:1},8,[`content`]),o.latestInfo?.hasUpdate?(g(),t(`button`,{key:0,type:`button`,class:`upgrade-btn`,title:o.$t(`@F13B4:发现新版本 {version},点击升级`,{version:o.latestInfo.latest??``}),"aria-label":o.$t(`@F13B4:发现新版本 {version},点击升级`,{version:o.latestInfo.latest??``}),onClick:o.handleUpgrade},[r[3]||=D(`span`,{class:`upgrade-btn__dot`,"aria-hidden":`true`},null,-1),D(`span`,te,p(o.$t(`@F13B4:升级`)),1),D(`span`,ne,`v`+p(o.latestInfo.latest),1)],8,ee)):n(`v-if`,!0),l(o.UpgradeDialog,{modelValue:o.upgradeDialogVisible,"onUpdate:modelValue":r[0]||=e=>o.upgradeDialogVisible=e,logs:o.upgradeLogs,status:o.upgradeStatus,countdown:o.countdown,onRetry:o.handleUpgrade,onRestart:o.handleRestart,onCancel:o.handleCancelAutoRefresh},null,8,[`modelValue`,`logs`,`status`,`countdown`])])}var ie=k(X,[[`render`,re],[`__scopeId`,`data-v-7e0300ec`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/AppVersionBadge.vue`]]);export{ie as default};
@@ -1 +0,0 @@
1
- import"./rolldown-runtime-C0FnF6B9.js";import{$ as e,Bt as t,Cn as n,Dn as r,En as i,F as a,K as o,Kr as s,Lt as c,Mn as l,Nr as u,P as d,Pn as f,Qr as p,Rn as m,Tn as h,U as g,V as _,W as v,Yn as y,Zn as b,_ as x,_n as S,dr as C,jt as w,ln as T,or as E,vr as D,wn as O,yn as k}from"./element-plus-D7LDHcAn.js";import{n as A,t as j}from"./_plugin-vue_export-helper-DvoTHxai.js";import{t as M}from"./SvgIcon-NgXqyNp2.js";import{t as N}from"./IconButton-CgAeGupL.js";import{r as P}from"./gitStore-CcOHgW0C.js";import{t as F}from"./CommonDialog-BLTKW3S3.js";m(),C();var I=f({__name:`BranchSelector`,emits:[`branchChanged`],setup(r,{expose:i,emit:a}){i();let o=P(),s=a,l=D(!1),u=D(``),d=n(()=>{let e=u.value.trim().toLowerCase();return e?o.allBranches.filter(t=>t.toLowerCase().includes(e)):o.allBranches});async function f(e){if(e===o.currentBranch){l.value=!1;return}l.value=!1,await o.changeBranch(e)&&(s(`branchChanged`),o.refreshLog())}let p=D(!1),m=D(``),h=D(``);function g(){l.value=!1,h.value=o.currentBranch,p.value=!0}async function _(){await o.createBranch(m.value,h.value)&&(p.value=!1,m.value=``,s(`branchChanged`))}let v=D(!1);async function y(){if(!v.value){v.value=!0;try{await Promise.all([o.getCurrentBranch(!0),o.getBranchStatus(!0),o.getAllBranches()]),s(`branchChanged`),o.refreshLog()}finally{v.value=!1}}}let b={gitStore:o,emit:s,branchPopoverVisible:l,branchFilter:u,filteredBranches:d,selectBranch:f,createBranchDialogVisible:p,newBranchName:m,selectedBaseBranch:h,openCreateBranchDialog:g,createNewBranch:_,isRefreshingBranch:v,refreshCurrentBranch:y,get $t(){return A},get Plus(){return c},get Menu(){return w},get Check(){return e},get Refresh(){return t},CommonDialog:F,IconButton:N,SvgIcon:M};return Object.defineProperty(b,"__isScriptSetup",{enumerable:!1,value:!0}),b}});m(),u(),T();var L={key:0,class:`branch-info`},R={class:`branch-wrapper`},z={class:`branch-btn`},B={class:`branch-btn-name`},V={class:`branch-btn-caret`},H={class:`branch-popover-inner`},U={class:`branch-search`},W={class:`branch-list`},G=[`onClick`],K={key:1,class:`branch-item-check-placeholder`},q={class:`branch-item-name`},J={key:0,class:`branch-empty`},Y={class:`branch-popover-footer`},X={class:`create-branch-content`},Z={class:`form-label`},Q={class:`form-label`},$={class:`dialog-footer`},ee={class:`footer-actions`},te=[`disabled`];function ne(e,t,n,c,u,f){let m=o,C=_,w=x,T=v,D=d,A=a,j=g;return c.gitStore.currentBranch?(y(),r(`div`,L,[O(`div`,R,[i(` VSCode 风格分支按钮 + 弹出列表 `),l(w,{visible:c.branchPopoverVisible,"onUpdate:visible":t[1]||=e=>c.branchPopoverVisible=e,placement:`top-start`,width:260,trigger:`click`,"popper-class":`branch-popover`,"show-arrow":!1,onShow:t[2]||=e=>c.branchFilter=``},{reference:E(()=>[O(`button`,z,[l(c.SvgIcon,{"icon-class":`git-branch`,"class-name":`branch-btn-icon`}),O(`span`,B,p(c.gitStore.currentBranch),1),O(`span`,V,[l(m,null,{default:E(()=>[...t[7]||=[O(`svg`,{viewBox:`0 0 1024 1024`,xmlns:`http://www.w3.org/2000/svg`},[O(`path`,{fill:`currentColor`,d:`M831.872 340.864 512 652.672 192.128 340.864a30.592 30.592 0 0 0-42.752 0 29.12 29.12 0 0 0 0 41.6L489.664 714.24a32 32 0 0 0 44.672 0l340.288-331.776a29.12 29.12 0 0 0 0-41.6 30.592 30.592 0 0 0-42.752 0z`})],-1)]]),_:1})])])]),default:E(()=>[O(`div`,H,[i(` 搜索框 `),O(`div`,U,[l(C,{modelValue:c.branchFilter,"onUpdate:modelValue":t[0]||=e=>c.branchFilter=e,placeholder:c.$t(`@F13B4:搜索或签出分支`),size:`small`,clearable:``,autofocus:``},null,8,[`modelValue`,`placeholder`])]),i(` 分支列表 `),O(`div`,W,[(y(!0),r(k,null,b(c.filteredBranches,e=>(y(),r(`div`,{key:e,class:s([`branch-item`,{"is-active":e===c.gitStore.currentBranch}]),onClick:t=>c.selectBranch(e)},[e===c.gitStore.currentBranch?(y(),h(m,{key:0,class:`branch-item-check`},{default:E(()=>[l(c.Check)]),_:1})):(y(),r(`span`,K)),l(c.SvgIcon,{"icon-class":`git-branch`,"class-name":`branch-item-icon`}),O(`span`,q,p(e),1)],10,G))),128)),c.filteredBranches.length===0?(y(),r(`div`,J,p(c.$t(`@F13B4:没有匹配的分支`)),1)):i(`v-if`,!0)]),i(` 底部:创建新分支 `),O(`div`,Y,[O(`button`,{class:`branch-create-btn`,onClick:c.openCreateBranchDialog},[l(m,null,{default:E(()=>[l(c.Plus)]),_:1}),O(`span`,null,p(c.$t(`@F13B4:创建新分支`)),1)])])])]),_:1},8,[`visible`]),i(` 刷新按钮 `),l(c.IconButton,{tooltip:c.$t(`@CMDCON:刷新`),onClick:c.refreshCurrentBranch},{default:E(()=>[l(m,{class:s({"is-loading":c.isRefreshingBranch})},{default:E(()=>[l(c.Refresh)]),_:1},8,[`class`])]),_:1},8,[`tooltip`])]),i(` 创建分支对话框 `),l(c.CommonDialog,{modelValue:c.createBranchDialogVisible,"onUpdate:modelValue":t[6]||=e=>c.createBranchDialogVisible=e,title:c.$t(`@F13B4:创建新分支`),size:`small`,"destroy-on-close":!0,"append-to-body":!0,"custom-class":`create-branch-dialog`},{footer:E(()=>[O(`div`,$,[O(`div`,ee,[O(`button`,{type:`button`,class:`dialog-cancel-btn`,onClick:t[5]||=e=>c.createBranchDialogVisible=!1},p(c.$t(`@F13B4:取消`)),1),O(`button`,{type:`button`,class:`dialog-confirm-btn`,onClick:c.createNewBranch,disabled:c.gitStore.isCreatingBranch},[c.gitStore.isCreatingBranch?(y(),h(m,{key:1,class:`is-loading`},{default:E(()=>[...t[8]||=[O(`svg`,{viewBox:`0 0 1024 1024`,xmlns:`http://www.w3.org/2000/svg`},[O(`path`,{fill:`currentColor`,d:`M512 64a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V96a32 32 0 0 1 32-32zm0 640a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V736a32 32 0 0 1 32-32zm448-192a32 32 0 0 1-32 32H736a32 32 0 1 1 0-64h192a32 32 0 0 1 32 32zm-640 0a32 32 0 0 1-32 32H96a32 32 0 0 1 0-64h192a32 32 0 0 1 32 32z`})],-1)]]),_:1})):(y(),h(m,{key:0},{default:E(()=>[l(c.Check)]),_:1})),O(`span`,null,p(c.$t(`@F13B4:创建`)),1)],8,te)])])]),default:E(()=>[O(`div`,X,[l(j,{model:{newBranchName:c.newBranchName,selectedBaseBranch:c.selectedBaseBranch},"label-position":`top`},{default:E(()=>[l(T,null,{label:E(()=>[O(`div`,Z,[l(m,{class:`label-icon`},{default:E(()=>[l(c.Plus)]),_:1}),O(`span`,null,p(c.$t(`@F13B4:新分支名称`)),1)])]),default:E(()=>[l(C,{modelValue:c.newBranchName,"onUpdate:modelValue":t[3]||=e=>c.newBranchName=e,placeholder:c.$t(`@F13B4:请输入新分支名称`),class:`modern-input`,size:`large`,onKeyup:S(c.createNewBranch,[`enter`])},null,8,[`modelValue`,`placeholder`])]),_:1}),l(T,null,{label:E(()=>[O(`div`,Q,[l(m,{class:`label-icon`},{default:E(()=>[l(c.Menu)]),_:1}),O(`span`,null,p(c.$t(`@F13B4:基于分支`)),1)])]),default:E(()=>[l(A,{modelValue:c.selectedBaseBranch,"onUpdate:modelValue":t[4]||=e=>c.selectedBaseBranch=e,placeholder:c.$t(`@F13B4:选择基础分支`),class:`modern-select`,size:`large`,style:{width:`100%`}},{default:E(()=>[(y(!0),r(k,null,b(c.gitStore.allBranches,e=>(y(),h(D,{key:e,label:e,value:e},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`,`placeholder`])]),_:1})]),_:1},8,[`model`])])]),_:1},8,[`modelValue`,`title`])])):i(`v-if`,!0)}var re=j(I,[[`render`,ne],[`__scopeId`,`data-v-9548a76f`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/BranchSelector.vue`]]);export{re as default};