zen-gitsync 2.17.34 → 2.17.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -3
- package/package.json +4 -1
- package/src/cli/ai/agent.js +34 -2
- package/src/cli/ai/cli.integration.test.js +30 -0
- package/src/cli/ai/paste.js +372 -0
- package/src/cli/ai/paste.test.js +276 -0
- package/src/cli/ai/termui.js +44 -6
- package/src/cli/ai/termui.test.js +39 -3
- package/src/ui/public/assets/{AgentEngineSelector-DVuUEDHz.js → AgentEngineSelector-DVs4LGHZ.js} +1 -1
- package/src/ui/public/assets/{AgentView-xdFrDybl.js → AgentView-Blp40VRr.js} +1 -1
- package/src/ui/public/assets/{AppVersionBadge-CCqQiZPO.js → AppVersionBadge-BEnoFzwh.js} +2 -2
- package/src/ui/public/assets/{BranchSelector-GD8NqzJj.js → BranchSelector-C7eXeFif.js} +1 -1
- package/src/ui/public/assets/{CommitForm-DNuJSePt.js → CommitForm-CK9jLJOC.js} +1 -1
- package/src/ui/public/assets/{CommonDialog-Cg3qSsFG.js → CommonDialog-BTeIpgGT.js} +1 -1
- package/src/ui/public/assets/{EditorView-ivXCi959.js → EditorView-D00zvntf.js} +1 -1
- package/src/ui/public/assets/{FileDiffViewer-DS1-m59W.js → FileDiffViewer-zqgG9ok3.js} +1 -1
- package/src/ui/public/assets/{FlowExecutionViewer-DXhO7HwA.js → FlowExecutionViewer-VFnxkbIs.js} +1 -1
- package/src/ui/public/assets/{FlowOrchestrationWorkspace-DIJboi94.js → FlowOrchestrationWorkspace-CIIdKK3v.js} +1 -1
- package/src/ui/public/assets/{IconButton-BVgngz_Y.js → IconButton-Cgc5v9vb.js} +1 -1
- package/src/ui/public/assets/{LogList-DGRGqcb_.js → LogList-DyQv-Yec.js} +1 -1
- package/src/ui/public/assets/{MindmapView-CRtCsbfO.js → MindmapView-EC2Wk_Qi.js} +1 -1
- package/src/ui/public/assets/{MonitorView-Ml1e4m41.js → MonitorView-Z5ZbGtaU.js} +1 -1
- package/src/ui/public/assets/{ProjectStartupButton-BDoX_Equ.js → ProjectStartupButton-Ci19q1bL.js} +1 -1
- package/src/ui/public/assets/{RecentDirectoriesChat-CwPIeHuv.js → RecentDirectoriesChat-DT0sguEG.js} +1 -1
- package/src/ui/public/assets/{RemoteManagerDialog-B9JvGgsK.js → RemoteManagerDialog-BRQpjMSK.js} +1 -1
- package/src/ui/public/assets/{RemoteRepoCard-BvZJtHNN.js → RemoteRepoCard-yK90_VfS.js} +1 -1
- package/src/ui/public/assets/{SourceMapView-CxTHZDOP.js → SourceMapView-C55ixUwz.js} +1 -1
- package/src/ui/public/assets/{SvgIcon-dJcILWS2.js → SvgIcon-ub85vovN.js} +1 -1
- package/src/ui/public/assets/{TemplateManager-BqrwTyxG.js → TemplateManager-uDno_64z.js} +1 -1
- package/src/ui/public/assets/{UserInputNode-D28zKp0v.js → UserInputNode-Ce55MMEZ.js} +1 -1
- package/src/ui/public/assets/WorkbenchView-CtJD3pz-.js +228 -0
- package/src/ui/public/assets/WorkbenchView-D1Pf6Etd.css +1 -0
- package/src/ui/public/assets/{_plugin-vue_export-helper-Be8qXN0e.js → _plugin-vue_export-helper-VuE2vqnn.js} +2 -2
- package/src/ui/public/assets/{agentConversations-BAvoMaCc.js → agentConversations-DcW54Tlt.js} +1 -1
- package/src/ui/public/assets/{configStore-Bj7SEMRL.js → configStore-De_8eQuS.js} +1 -1
- package/src/ui/public/assets/{gitStore-BaBKqLlD.js → gitStore-BP6TATf7.js} +1 -1
- package/src/ui/public/assets/{index-B0MdMohu.js → index-Bq_-TrTP.js} +5 -5
- package/src/ui/public/assets/{previewSandbox-DKUIjkxY.js → previewSandbox-DcVlFmag.js} +1 -1
- package/src/ui/public/assets/{toolsStore-MahCZx-D.js → toolsStore-CQclze0T.js} +1 -1
- package/src/ui/public/index.html +11 -11
- package/src/ui/server/routes/workbench/hiddenProjects.js +87 -0
- package/src/ui/server/routes/workbench/hiddenProjects.test.js +60 -0
- package/src/ui/server/routes/workbench/index.js +69 -1
- package/src/ui/server/routes/workbench/shared.js +8 -0
- package/src/ui/public/assets/WorkbenchView-BhWKWSFS.js +0 -220
- package/src/ui/public/assets/WorkbenchView-Bx5r6sZ5.css +0 -1
|
@@ -0,0 +1,276 @@
|
|
|
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
|
+
// src/cli/ai/paste.js 单元测试:
|
|
16
|
+
// - 仓库/过滤器/归一化都是纯逻辑,直接断言字符串
|
|
17
|
+
// - 最后一组用真 readline + PassThrough 跑端到端(terminal: true 在非 TTY stream 上可用),
|
|
18
|
+
// 验证"一次粘贴 = 一个 line 事件"和 rl.question 的还原 —— 这两条是本次改动的立身之本,
|
|
19
|
+
// 光测过滤器测不出 readline 那层的真实行为
|
|
20
|
+
import { test } from 'node:test'
|
|
21
|
+
import assert from 'node:assert/strict'
|
|
22
|
+
import readline from 'node:readline'
|
|
23
|
+
import { PassThrough } from 'node:stream'
|
|
24
|
+
import {
|
|
25
|
+
PASTE_START, PASTE_END,
|
|
26
|
+
normalizePasteText, createPasteStore, createPasteFilter, installPasteCapture,
|
|
27
|
+
enableBracketedPaste, disableBracketedPaste,
|
|
28
|
+
} from './paste.js'
|
|
29
|
+
|
|
30
|
+
// ── 归一化 ──────────────────────────────────────────────
|
|
31
|
+
|
|
32
|
+
test('normalizePasteText: CRLF/CR 归一为 LF,并去掉复制带上的行尾换行', () => {
|
|
33
|
+
assert.equal(normalizePasteText('a\r\nb\r\n'), 'a\nb')
|
|
34
|
+
assert.equal(normalizePasteText('a\rb'), 'a\nb')
|
|
35
|
+
assert.equal(normalizePasteText('a\nb\n'), 'a\nb')
|
|
36
|
+
assert.equal(normalizePasteText('a\n\n'), 'a\n') // 只去一个,用户主动留的空行不吞
|
|
37
|
+
assert.equal(normalizePasteText(''), '')
|
|
38
|
+
assert.equal(normalizePasteText(null), '')
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
// ── 仓库 ────────────────────────────────────────────────
|
|
42
|
+
|
|
43
|
+
test('store: 占位符可自定义,原文按行数/字符数生成,能原样还原', () => {
|
|
44
|
+
const store = createPasteStore({
|
|
45
|
+
formatToken: ({ index, lines }) => `[粘贴 #${index} · ${lines} 行]`,
|
|
46
|
+
})
|
|
47
|
+
const token = store.add('RADAR_REVIEW_API_KEY=sk-1\nRADAR_REVIEW_MODEL=deepseek\n')
|
|
48
|
+
assert.equal(token, '[粘贴 #1 · 2 行]')
|
|
49
|
+
|
|
50
|
+
const expanded = store.expand(`加上 .env ${token}`)
|
|
51
|
+
assert.equal(expanded.text, '加上 .env RADAR_REVIEW_API_KEY=sk-1\nRADAR_REVIEW_MODEL=deepseek')
|
|
52
|
+
assert.equal(expanded.used, 1)
|
|
53
|
+
assert.deepEqual(expanded.stale, [])
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
test('store: 空内容不占位(只粘了一个换行不该塞个空占位符)', () => {
|
|
57
|
+
const store = createPasteStore()
|
|
58
|
+
assert.equal(store.add('\n'), '')
|
|
59
|
+
assert.equal(store.add(''), '')
|
|
60
|
+
assert.equal(store.size, 0)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('store: 普通方括号文本不会被误还原', () => {
|
|
64
|
+
const store = createPasteStore()
|
|
65
|
+
store.add('x\ny')
|
|
66
|
+
const out = store.expand('数组 [1] 和 [粘贴 stuff] 都该原样保留')
|
|
67
|
+
assert.equal(out.text, '数组 [1] 和 [粘贴 stuff] 都该原样保留')
|
|
68
|
+
assert.equal(out.used, 0)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
test('store: 多段粘贴各自还原,互不串门', () => {
|
|
72
|
+
const store = createPasteStore({ formatToken: ({ index }) => `<p${index}>` })
|
|
73
|
+
const a = store.add('A1\nA2')
|
|
74
|
+
const b = store.add('B1\nB2')
|
|
75
|
+
assert.equal(store.expand(`${a} 与 ${b}`).text, 'A1\nA2 与 B1\nB2')
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
test('store: 超容量淘汰最旧的,命中旧占位符时报 stale 而不是静默出错', () => {
|
|
79
|
+
const store = createPasteStore({ maxEntries: 2, formatToken: ({ index }) => `<p${index}>` })
|
|
80
|
+
store.add('one')
|
|
81
|
+
store.add('two')
|
|
82
|
+
store.add('three') // 挤掉 <p1>
|
|
83
|
+
const out = store.expand('<p1> 和 <p2>')
|
|
84
|
+
assert.equal(out.text, '<p1> 和 two') // 活的照常还原
|
|
85
|
+
assert.deepEqual(out.stale, ['<p1>']) // 死的明确点名
|
|
86
|
+
assert.equal(out.used, 1)
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
// ── 过滤器 ──────────────────────────────────────────────
|
|
90
|
+
|
|
91
|
+
test('filter: 整段粘贴替换为一个占位符,后面的回车照常透传', () => {
|
|
92
|
+
const store = createPasteStore({ formatToken: ({ index, lines }) => `<p${index}:${lines}>` })
|
|
93
|
+
const filter = createPasteFilter({ store })
|
|
94
|
+
const out = filter.push(`${PASTE_START}a\nb\nc${PASTE_END}\r`)
|
|
95
|
+
assert.equal(out, '<p1:3>\r')
|
|
96
|
+
assert.equal(store.expand('<p1:3>').text, 'a\nb\nc')
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
test('filter: 标记被切在两个 chunk 里也能识别', () => {
|
|
100
|
+
const store = createPasteStore({ formatToken: () => '<P>' })
|
|
101
|
+
const filter = createPasteFilter({ store })
|
|
102
|
+
// 起止标记各切一刀,内容再切一刀 —— 模拟大粘贴被 TCP/终端分片
|
|
103
|
+
assert.equal(filter.push(`\x1b[20`), '')
|
|
104
|
+
assert.equal(filter.push(`0~first\n`), '')
|
|
105
|
+
assert.equal(filter.push(`second\x1b[20`), '')
|
|
106
|
+
assert.equal(filter.push(`1~\r`), '<P>\r')
|
|
107
|
+
assert.equal(store.expand('<P>').text, 'first\nsecond')
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
test('filter: 不含粘贴标记的普通数据原样输出(含跨块拼接)', () => {
|
|
111
|
+
const store = createPasteStore()
|
|
112
|
+
const filter = createPasteFilter({ store })
|
|
113
|
+
assert.equal(filter.push('hello'), 'hello')
|
|
114
|
+
assert.equal(filter.push(' world'), ' world')
|
|
115
|
+
assert.equal(filter.push(Buffer.from('中文\n', 'utf8')), '中文\n')
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
test('filter: needsRewrite 对普通打字走快路径,只有疑似粘贴标记才改写', () => {
|
|
119
|
+
const filter = createPasteFilter({ store: createPasteStore() })
|
|
120
|
+
assert.equal(filter.needsRewrite('abc'), false)
|
|
121
|
+
assert.equal(filter.needsRewrite(Buffer.from('abc')), false)
|
|
122
|
+
// 方向键这类 ESC 序列不含 `\x1b[20`,照样走快路径(Buffer 都不转字符串)
|
|
123
|
+
assert.equal(filter.needsRewrite('\x1b[A'), false)
|
|
124
|
+
assert.equal(filter.push('\x1b[A'), '\x1b[A')
|
|
125
|
+
// 疑似标记(可能被切块)→ 走改写;解析器找不到完整标记时原样返回
|
|
126
|
+
assert.equal(filter.needsRewrite('\x1b[20'), true)
|
|
127
|
+
assert.equal(filter.push('\x1b[20'), '')
|
|
128
|
+
assert.equal(filter.push('04h'), '\x1b[2004h') // 拼回原样,没被吃掉
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
test('filter: 结束标记一直不来时兜底关闭,不吞后续输入', async () => {
|
|
132
|
+
const store = createPasteStore({ formatToken: () => '<P>' })
|
|
133
|
+
const flushed = []
|
|
134
|
+
const filter = createPasteFilter({ store, flushDelayMs: 20, onFlush: (t) => flushed.push(t) })
|
|
135
|
+
assert.equal(filter.push(`${PASTE_START}orphan\ncontent`), '')
|
|
136
|
+
assert.equal(filter.inPaste, true)
|
|
137
|
+
await new Promise((r) => setTimeout(r, 60))
|
|
138
|
+
assert.deepEqual(flushed, ['<P>'])
|
|
139
|
+
assert.equal(filter.inPaste, false)
|
|
140
|
+
assert.equal(store.expand('<P>').text, 'orphan\ncontent')
|
|
141
|
+
filter.dispose()
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
test('filter: 未开 bracketed paste 的终端不会被改坏(没有标记 = 没有行为)', () => {
|
|
145
|
+
const store = createPasteStore()
|
|
146
|
+
const filter = createPasteFilter({ store })
|
|
147
|
+
// 终端不支持时,多行粘贴就是一串带 \n 的普通字节 —— 过滤器照原样放行
|
|
148
|
+
assert.equal(filter.push('line1\nline2\n'), 'line1\nline2\n')
|
|
149
|
+
assert.equal(store.size, 0)
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
// ── 终端开关 ────────────────────────────────────────────
|
|
153
|
+
|
|
154
|
+
test('bracketed paste 开关: 只在 TTY 且未禁用时写 DECSET 2004', () => {
|
|
155
|
+
const tty = { isTTY: true }
|
|
156
|
+
const out = []
|
|
157
|
+
assert.equal(enableBracketedPaste(s => out.push(s), { env: {}, stream: tty }), true)
|
|
158
|
+
assert.equal(disableBracketedPaste(s => out.push(s), { env: {}, stream: tty }), true)
|
|
159
|
+
assert.deepEqual(out, ['\x1b[?2004h', '\x1b[?2004l'])
|
|
160
|
+
|
|
161
|
+
// 管道 / CI / TERM=dumb / 逃生开关:一个字节都不该写出去
|
|
162
|
+
const silent = []
|
|
163
|
+
const write = s => silent.push(s)
|
|
164
|
+
assert.equal(enableBracketedPaste(write, { env: {}, stream: { isTTY: false } }), false)
|
|
165
|
+
assert.equal(enableBracketedPaste(write, { env: {}, stream: undefined }), false)
|
|
166
|
+
assert.equal(enableBracketedPaste(write, { env: { TERM: 'dumb' }, stream: tty }), false)
|
|
167
|
+
assert.equal(enableBracketedPaste(write, { env: { ZEN_AI_NO_BRACKETED_PASTE: '1' }, stream: tty }), false)
|
|
168
|
+
assert.equal(disableBracketedPaste(write, { env: { ZEN_AI_NO_BRACKETED_PASTE: '1' }, stream: tty }), false)
|
|
169
|
+
assert.deepEqual(silent, [])
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
// ── 端到端:真 readline ─────────────────────────────────
|
|
173
|
+
|
|
174
|
+
/** 造一个跑在内存流上的 readline(terminal: true,与线上 TTY 分支同一套键位解析) */
|
|
175
|
+
function makeRepl() {
|
|
176
|
+
const input = new PassThrough()
|
|
177
|
+
const output = new PassThrough()
|
|
178
|
+
output.resume()
|
|
179
|
+
const rl = readline.createInterface({ input, output, terminal: true, prompt: '> ' })
|
|
180
|
+
const lines = []
|
|
181
|
+
rl.on('line', (line) => lines.push(line))
|
|
182
|
+
return { input, output, rl, lines }
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function nextLine(lines, timeoutMs = 500) {
|
|
186
|
+
return new Promise((resolve, reject) => {
|
|
187
|
+
const started = Date.now()
|
|
188
|
+
const tick = () => {
|
|
189
|
+
if (lines.length) return resolve(lines[0])
|
|
190
|
+
if (Date.now() - started > timeoutMs) return reject(new Error('no line event'))
|
|
191
|
+
setTimeout(tick, 5)
|
|
192
|
+
}
|
|
193
|
+
tick()
|
|
194
|
+
})
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
test('端到端: 多行粘贴只产生一个 line 事件,展开后就是原文', async () => {
|
|
198
|
+
const { input, rl, lines } = makeRepl()
|
|
199
|
+
const capture = installPasteCapture(rl, {
|
|
200
|
+
formatToken: ({ index, lines: n }) => `[粘贴 #${index} · ${n} 行]`,
|
|
201
|
+
})
|
|
202
|
+
assert.ok(capture)
|
|
203
|
+
|
|
204
|
+
input.write(`${PASTE_START}加上 .env\nRADAR_REVIEW_API_KEY=sk-x2Gt\nRADAR_REVIEW_MODEL=deepseek\x1b[201~\r`)
|
|
205
|
+
const line = await nextLine(lines)
|
|
206
|
+
|
|
207
|
+
// 修复前:这里会是 3 个 line 事件,且只有第一个能发出去
|
|
208
|
+
assert.equal(lines.length, 1)
|
|
209
|
+
assert.equal(line, '[粘贴 #1 · 3 行]')
|
|
210
|
+
assert.equal(
|
|
211
|
+
capture.expand(line).text,
|
|
212
|
+
'加上 .env\nRADAR_REVIEW_API_KEY=sk-x2Gt\nRADAR_REVIEW_MODEL=deepseek'
|
|
213
|
+
)
|
|
214
|
+
rl.close()
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
test('端到端: 占位符里含中文/中点也不破坏 readline 的按键解析', async () => {
|
|
218
|
+
const { input, rl, lines } = makeRepl()
|
|
219
|
+
const capture = installPasteCapture(rl, { formatToken: ({ index, lines: n }) => `[粘贴 #${index} · ${n} 行]` })
|
|
220
|
+
|
|
221
|
+
input.write(`${PASTE_START}甲乙丙\n丁戊己${PASTE_END}\r`)
|
|
222
|
+
const line = await nextLine(lines)
|
|
223
|
+
// 真值:中文占位符原样进输入行(说明 string chunk 没被 readline 的 StringDecoder 啃坏)
|
|
224
|
+
assert.equal(line, '[粘贴 #1 · 2 行]')
|
|
225
|
+
assert.equal(capture.expand(line).text, '甲乙丙\n丁戊己')
|
|
226
|
+
rl.close()
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
test('端到端: 粘贴后继续手打再回车,拼接顺序正确', async () => {
|
|
230
|
+
const { input, rl, lines } = makeRepl()
|
|
231
|
+
const capture = installPasteCapture(rl, { formatToken: () => '<P>' })
|
|
232
|
+
|
|
233
|
+
input.write(`${PASTE_START}KEY=1\nSECRET=2${PASTE_END}`)
|
|
234
|
+
input.write(' 请写进 .env')
|
|
235
|
+
input.write('\r')
|
|
236
|
+
const line = await nextLine(lines)
|
|
237
|
+
assert.equal(capture.expand(line.trim()).text, 'KEY=1\nSECRET=2 请写进 .env')
|
|
238
|
+
rl.close()
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
test('端到端: rl.question 的回调拿到的是还原后的答案(不经过 line 事件)', async () => {
|
|
242
|
+
const { input, rl, lines } = makeRepl()
|
|
243
|
+
const capture = installPasteCapture(rl, { formatToken: () => '<P>' })
|
|
244
|
+
|
|
245
|
+
const answer = await new Promise((resolve) => {
|
|
246
|
+
rl.question('path: ', (a) => resolve(a))
|
|
247
|
+
input.write(`${PASTE_START}/var/www/a\n/var/www/b${PASTE_END}\r`)
|
|
248
|
+
})
|
|
249
|
+
assert.equal(answer, '/var/www/a\n/var/www/b')
|
|
250
|
+
assert.equal(lines.length, 0) // question 期间不触发 line 事件 —— 所以必须单独包 question
|
|
251
|
+
rl.close()
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
test('installPasteCapture: 输入流不可改写时给空实现,调用方无需判空', () => {
|
|
255
|
+
const capture = installPasteCapture({ /* 没有 input */ })
|
|
256
|
+
assert.equal(capture.expand('原文').text, '原文')
|
|
257
|
+
assert.equal(capture.expand('原文').used, 0)
|
|
258
|
+
capture.dispose() // 不应抛
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
test('端到端: dispose 后恢复原样,不再拦数据(也不会把终端留在 bracketed paste 里)', async () => {
|
|
262
|
+
const { input, rl, lines } = makeRepl()
|
|
263
|
+
const capture = installPasteCapture(rl, { formatToken: () => '<P>' })
|
|
264
|
+
// 补丁是给 input 加的自有属性(原型上的 emit 没被动过)→ 卸载后应当连属性都不剩
|
|
265
|
+
assert.equal(Object.prototype.hasOwnProperty.call(input, 'emit'), true)
|
|
266
|
+
capture.dispose()
|
|
267
|
+
assert.equal(Object.prototype.hasOwnProperty.call(input, 'emit'), false)
|
|
268
|
+
assert.equal(typeof rl.question, 'function')
|
|
269
|
+
|
|
270
|
+
// 卸载后:多行粘贴回到"每个 \n 一次提交"的 readline 原生行为(不再吞内容)
|
|
271
|
+
input.write('a\nb\n')
|
|
272
|
+
await nextLine(lines)
|
|
273
|
+
await new Promise((r) => setTimeout(r, 30))
|
|
274
|
+
assert.deepEqual(lines, ['a', 'b'])
|
|
275
|
+
rl.close()
|
|
276
|
+
})
|
package/src/cli/ai/termui.js
CHANGED
|
@@ -491,23 +491,27 @@ export function createAssistantWriter({
|
|
|
491
491
|
}
|
|
492
492
|
|
|
493
493
|
const emitContentLine = (raw, withNewline = true) => {
|
|
494
|
-
//
|
|
494
|
+
// 围栏标记行:切换状态,用一个淡淡的拐角代替裸 ```
|
|
495
|
+
// 这里刻意不画边框线:命令行是给用户复制去终端里跑的,任何行内前缀都会被
|
|
496
|
+
// 一起复制进剪贴板 —— 早期版本给每行加 `│ ` 槽线,复制出来就是带竖线的残废命令。
|
|
495
497
|
if (/^\s*```/.test(raw)) {
|
|
496
498
|
inFence = !inFence
|
|
497
499
|
const bullet = contentLines === 0 ? BULLET_FIRST : BULLET_REST
|
|
498
500
|
contentLines++
|
|
499
501
|
lastBlank = false
|
|
500
|
-
const language = raw.trim().slice(3).trim()
|
|
501
|
-
writeContentRows(bullet, chalk.gray(inFence ? '
|
|
502
|
+
const language = raw.trim().slice(3).trim()
|
|
503
|
+
writeContentRows(bullet, chalk.gray(inFence ? '┌ ' + (language || 'code') : '└'), withNewline)
|
|
502
504
|
return
|
|
503
505
|
}
|
|
504
|
-
//
|
|
506
|
+
// 围栏内:原文顶格输出 —— 不加前缀、不按终端宽度折行。
|
|
507
|
+
// 折行在这里是**硬折行**(真的写 \n 字节),一条长命令会被拦腰截成几行,
|
|
508
|
+
// 复制粘回 shell 就成了几条互不相干的命令。宁可让终端自己软折:
|
|
509
|
+
// 软折只是显示层的,终端复制时给出的仍是模型写的那一行。
|
|
505
510
|
if (inFence) {
|
|
506
|
-
const bullet = contentLines === 0 ? BULLET_FIRST : BULLET_REST
|
|
507
511
|
contentLines++
|
|
508
512
|
lastBlank = false
|
|
509
513
|
showAnswerHeader()
|
|
510
|
-
write(
|
|
514
|
+
write(chalk.hex('#cbd5e1')(normalizeTerminalNewlines(raw)) + (withNewline ? '\n' : ''))
|
|
511
515
|
return
|
|
512
516
|
}
|
|
513
517
|
// 空白行:首个正文行之前不输出;连续空行合并为一行
|
|
@@ -654,6 +658,39 @@ export function printTurnSummary(stats, options, write = s => process.stdout.wri
|
|
|
654
658
|
write(renderTurnSummary(stats, options))
|
|
655
659
|
}
|
|
656
660
|
|
|
661
|
+
// ──────────────────────────────────────────────
|
|
662
|
+
// 粘贴内容回显
|
|
663
|
+
// ──────────────────────────────────────────────
|
|
664
|
+
//
|
|
665
|
+
// 开了多行粘贴之后,输入行里只剩一个占位符(`[粘贴 #1 · 4 行]`),原文在内存里。
|
|
666
|
+
// 提交时要把"实际发出去的内容"亮一遍 —— 否则回看终端记录只有一行占位符,
|
|
667
|
+
// 等于把用户粘的东西藏起来了。
|
|
668
|
+
//
|
|
669
|
+
// 用与工具结果同款的 ` │ ` 槽线(缩进一致、看着整齐),但槽线走青色 ——
|
|
670
|
+
// 这条是用户自己的消息,不该和工具输出一个色系。超长时掐中间:头几行 + "还有 N 行" + 末行,
|
|
671
|
+
// 因为粘贴内容的尾部(配置项的最后一个键、日志的最后一行)通常最需要确认。
|
|
672
|
+
|
|
673
|
+
export function renderPasteEcho(text, {
|
|
674
|
+
locale = 'zh-CN',
|
|
675
|
+
width = Math.min(100, termWidth() - 6),
|
|
676
|
+
maxRows = 16,
|
|
677
|
+
} = {}) {
|
|
678
|
+
const zh = !String(locale || '').startsWith('en')
|
|
679
|
+
const rows = wrapTerminalText(normalizeTerminalNewlines(text), Math.max(8, width))
|
|
680
|
+
let body = rows
|
|
681
|
+
if (rows.length > maxRows) {
|
|
682
|
+
const omitted = rows.length - maxRows + 1
|
|
683
|
+
body = [
|
|
684
|
+
...rows.slice(0, maxRows - 2),
|
|
685
|
+
zh ? `… 还有 ${omitted} 行` : `… ${omitted} more lines`,
|
|
686
|
+
rows[rows.length - 1],
|
|
687
|
+
]
|
|
688
|
+
}
|
|
689
|
+
return body
|
|
690
|
+
.map(row => chalk.cyan(' │ ') + chalk.hex('#cbd5e1')(row))
|
|
691
|
+
.join('\n') + '\n'
|
|
692
|
+
}
|
|
693
|
+
|
|
657
694
|
// ──────────────────────────────────────────────
|
|
658
695
|
// 工具调用块(Claude Code 风格)
|
|
659
696
|
// ──────────────────────────────────────────────
|
|
@@ -842,6 +879,7 @@ export default {
|
|
|
842
879
|
afterTool,
|
|
843
880
|
printTurnSummary,
|
|
844
881
|
renderTurnSummary,
|
|
882
|
+
renderPasteEcho,
|
|
845
883
|
wrapTerminalText,
|
|
846
884
|
printOk,
|
|
847
885
|
printWarn,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
stripAnsi, truncateDisplay, summarizeToolArgs,
|
|
25
25
|
createAssistantWriter, printToolHeader, printToolResult, startSpinner,
|
|
26
26
|
renderPlan, afterTool,
|
|
27
|
-
formatDuration, wrapTerminalText, renderTurnSummary,
|
|
27
|
+
formatDuration, wrapTerminalText, renderTurnSummary, renderPasteEcho,
|
|
28
28
|
filterSlashCommands, renderSlashHintBody, parseKeyForSlashHint, SLASH_COMMANDS,
|
|
29
29
|
renderSelectableListBody, parseKeyForSelectableList,
|
|
30
30
|
} from './termui.js'
|
|
@@ -227,17 +227,32 @@ test('writer: 标题与列表渲染', () => {
|
|
|
227
227
|
assert.ok(text.includes('- 列表项'))
|
|
228
228
|
})
|
|
229
229
|
|
|
230
|
-
test('writer:
|
|
230
|
+
test('writer: 代码围栏内容顶格输出,不带任何行内前缀(复制即原文)', () => {
|
|
231
231
|
const c = collect()
|
|
232
232
|
const w = createAssistantWriter({ write: c.write })
|
|
233
233
|
w.writeContent('```js\nconst x = 1\n```\n围栏外\n')
|
|
234
234
|
w.finish()
|
|
235
235
|
const lines = c.lines()
|
|
236
|
-
|
|
236
|
+
// 顶格 = 行首没有空格/槽线,从行首选中复制出来就是能直接跑的原文
|
|
237
|
+
assert.ok(lines.includes('const x = 1'), `代码行应顶格原样输出,实际: ${JSON.stringify(lines)}`)
|
|
238
|
+
assert.ok(!lines.some(l => l.includes('│')), '不应再出现 │ 槽线(会被一起复制走)')
|
|
237
239
|
assert.ok(!lines.some(l => l.trim() === '```js' || l.trim() === '```'), '裸围栏标记不应出现')
|
|
238
240
|
assert.ok(lines.some(l => l.includes('围栏外')))
|
|
239
241
|
})
|
|
240
242
|
|
|
243
|
+
test('writer: 代码块内不折行 —— 长命令复制出来仍是一整行', () => {
|
|
244
|
+
const c = collect()
|
|
245
|
+
const w = createAssistantWriter({ width: 40, write: c.write })
|
|
246
|
+
const cmd = 'sudo cp /etc/nginx/conf.d/xz_server.conf /etc/nginx/conf.d/xz_server.conf.bak-$(date +%Y%m%d-%H%M%S) && sudo systemctl reload nginx'
|
|
247
|
+
w.writeContent('```bash\n' + cmd + '\n```\n')
|
|
248
|
+
w.finish()
|
|
249
|
+
const lines = c.lines()
|
|
250
|
+
// 硬折行会把一条命令截成几行,粘回 shell 就成了几条互不相干的命令
|
|
251
|
+
assert.ok(lines.includes(cmd), '超宽命令必须原样一整行,交给终端软折')
|
|
252
|
+
const fragments = lines.filter(l => l.trim() && l.trim() !== cmd && cmd.includes(l.trim()))
|
|
253
|
+
assert.deepEqual(fragments, [], '不应出现被拦腰折断的命令碎片行')
|
|
254
|
+
})
|
|
255
|
+
|
|
241
256
|
test('writer: ** 标记跨 chunk 也能正确渲染(行缓冲)', () => {
|
|
242
257
|
const c = collect()
|
|
243
258
|
const w = createAssistantWriter({ write: c.write })
|
|
@@ -459,6 +474,27 @@ test('turn summaries distinguish missing and partial usage, and show cancellatio
|
|
|
459
474
|
assert.match(text, /输入含缓存 80/)
|
|
460
475
|
})
|
|
461
476
|
|
|
477
|
+
test('renderPasteEcho: 多行粘贴内容逐行回显,带独立槽线', () => {
|
|
478
|
+
const rows = stripAnsi(renderPasteEcho('第一行\n第二行\n第三行', { width: 60 })).split('\n')
|
|
479
|
+
assert.deepEqual(rows.slice(0, 3), [' │ 第一行', ' │ 第二行', ' │ 第三行'])
|
|
480
|
+
})
|
|
481
|
+
|
|
482
|
+
test('renderPasteEcho: 超长内容掐中间,保留末行(尾部常是最后一个配置项/最后一行日志)', () => {
|
|
483
|
+
const text = Array.from({ length: 30 }, (_, i) => `line${i + 1}`).join('\n')
|
|
484
|
+
const rows = stripAnsi(renderPasteEcho(text, { width: 60, maxRows: 8 })).split('\n').filter(Boolean)
|
|
485
|
+
assert.equal(rows.length, 8)
|
|
486
|
+
assert.equal(rows[0], ' │ line1')
|
|
487
|
+
assert.equal(rows[6], ' │ … 还有 23 行')
|
|
488
|
+
assert.equal(rows[7], ' │ line30')
|
|
489
|
+
})
|
|
490
|
+
|
|
491
|
+
test('renderPasteEcho: en locale 的省略提示,且 CRLF 归一成换行', () => {
|
|
492
|
+
const text = Array.from({ length: 30 }, (_, i) => `l${i}`).join('\r\n')
|
|
493
|
+
const rows = stripAnsi(renderPasteEcho(text, { width: 60, maxRows: 8, locale: 'en-US' })).split('\n').filter(Boolean)
|
|
494
|
+
assert.equal(rows.length, 8)
|
|
495
|
+
assert.equal(rows[6], ' │ … 23 more lines')
|
|
496
|
+
})
|
|
497
|
+
|
|
462
498
|
test('filterSlashCommands: 单个 / 返回全部命令', () => {
|
|
463
499
|
const got = filterSlashCommands('/', 'zh').map(m => m.cmd)
|
|
464
500
|
assert.deepEqual(got, SLASH_COMMANDS.map(c => c.cmd))
|
package/src/ui/public/assets/{AgentEngineSelector-DVuUEDHz.js → AgentEngineSelector-DVs4LGHZ.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"./rolldown-runtime-C0FnF6B9.js";import{$n as e,Bn as t,C as n,Dn as r,En as i,Fr as a,In as o,J as s,Jr as c,On as l,Pn as u,S as d,Tn as f,Wn as p,Y as m,Yn as h,Zn as g,br as _,cr as v,ei as y,kn as b,pr as x,qn as S,tt as C,w,xn as T}from"./element-plus-Buzx8xRf.js";import{n as E,t as D}from"./_plugin-vue_export-helper-
|
|
1
|
+
import"./rolldown-runtime-C0FnF6B9.js";import{$n as e,Bn as t,C as n,Dn as r,En as i,Fr as a,In as o,J as s,Jr as c,On as l,Pn as u,S as d,Tn as f,Wn as p,Y as m,Yn as h,Zn as g,br as _,cr as v,ei as y,kn as b,pr as x,qn as S,tt as C,w,xn as T}from"./element-plus-Buzx8xRf.js";import{n as E,t as D}from"./_plugin-vue_export-helper-VuE2vqnn.js";import{t as O}from"./SvgIcon-ub85vovN.js";import{t as k}from"./toolsStore-CQclze0T.js";import{s as A,v as j}from"./index-Bq_-TrTP.js";import{c as M,d as N,l as P,u as F}from"./agentConversations-DcW54Tlt.js";t(),x();function I(e,t=680){let n=_(0),r=null;function i(){let t=e.value;return t?(n.value=t.clientWidth,typeof ResizeObserver>`u`||(r=new ResizeObserver(e=>{let t=e[0]?.contentRect?.width;typeof t==`number`&&(n.value=t)}),r.observe(t),!0)):!1}return h(()=>{i()||p(()=>i())}),S(()=>{r?.disconnect(),r=null}),{width:n,narrow:f(()=>n.value>0&&n.value<t)}}t(),x();var L=o({__name:`AgentEngineSelector`,props:{engine:{type:String,required:!0},locked:{type:Boolean,required:!1}},emits:[`select`],setup(e,{expose:t,emit:r}){t();let i=e,a=r,o=k(),c=f(()=>F(i.engine)),l=f(()=>({gai:!0,claude:o.claudeAvailable,opencode:o.opencodeAvailable,codex:o.codexAvailable})),u=_(!1),p=_(null);function h(e){if(!i.locked){if(!l.value[e]){if(!N(e))return;p.value=e,u.value=!0;return}a(`select`,e)}}let g={props:i,emit:a,toolsStore:o,engineName:c,engineAvailability:l,installDialogVisible:u,installTool:p,onCommand:h,get $t(){return E},get ElIcon(){return s},get ElDropdown(){return d},get ElDropdownMenu(){return w},get ElDropdownItem(){return n},get ArrowDown(){return m},get Check(){return C},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}});t(),a();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(t,n,a,o,s,d){return g(),b(T,null,[l(` 单根包一层:父级传下来的 class(Tab 行的 margin-left:auto、面板的 flex:none)
|
|
2
2
|
才能可靠落到这里 —— 多根组件会丢掉 fallthrough class。 `),i(`div`,R,[u(o.ElDropdown,{trigger:`click`,onCommand:o.onCommand},{dropdown:v(()=>[u(o.ElDropdownMenu,null,{default:v(()=>[(g(!0),b(T,null,e(o.AGENT_ENGINE_OPTIONS,e=>(g(),r(o.ElDropdownItem,{key:e.id,command:e.id},{default:v(()=>[i(`span`,V,[o.isExternalAgentEngine(e.id)?(g(),r(o.TaskExecutorIcon,{key:0,executor:e.id,class:`agent-engine__item-icon`},null,8,[`executor`])):(g(),r(o.SvgIcon,{key:1,"icon-class":o.BUILTIN_ENGINE_ICON,class:`agent-engine__item-icon`},null,8,[`icon-class`])),i(`span`,H,y(e.name),1),a.engine===e.id?(g(),r(o.ElIcon,{key:2,class:`agent-engine__item-check`},{default:v(()=>[u(o.Check)]),_:1})):o.engineAvailability[e.id]?l(`v-if`,!0):(g(),b(`span`,U,y(o.$t(`@42BB9:未安装`)),1))])]),_:2},1032,[`command`]))),128))]),_:1})]),default:v(()=>[i(`button`,{type:`button`,class:c([`agent-engine__btn`,{"is-locked":a.locked}]),disabled:a.locked,title:a.locked?o.$t(`@AGENT:本会话的引擎已锁定;要换引擎请新建会话`):o.$t(`@AGENT:新建会话使用的引擎`),"aria-label":o.$t(`@AGENT:智能体引擎`)},[o.isExternalAgentEngine(a.engine)?(g(),r(o.TaskExecutorIcon,{key:0,executor:a.engine,class:`agent-engine__icon`},null,8,[`executor`])):(g(),r(o.SvgIcon,{key:1,"icon-class":o.BUILTIN_ENGINE_ICON,class:`agent-engine__icon`},null,8,[`icon-class`])),i(`span`,B,y(o.engineName),1),u(o.ElIcon,{class:`agent-engine__caret`},{default:v(()=>[u(o.ArrowDown)]),_:1})],10,z)]),_:1}),u(o.ToolInstallDialog,{modelValue:o.installDialogVisible,"onUpdate:modelValue":n[0]||=e=>o.installDialogVisible=e,tool:o.installTool},null,8,[`modelValue`,`tool`])])],2112)}var G=D(L,[[`render`,W],[`__scopeId`,`data-v-c67a4d14`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/components/AgentEngineSelector.vue`]]);export{I as n,G as t};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import"./rolldown-runtime-C0FnF6B9.js";import{$n as e,At as t,Bn as n,Ct as r,Dn as i,En as a,Fr as o,Gt as s,Ht as ee,In as c,J as l,Jr as u,M as d,Nn as f,On as p,Pn as m,Tn as h,Tt as g,W as _,Wn as v,Xr as y,Yt as b,Zn as x,_n as S,a as C,an as w,br as T,cr as E,dn as D,ei as O,et as k,i as A,j,kn as M,kt as N,lr as P,lt as F,mt as I,nr as L,o as R,or as z,pr as B,st as V,tt as H,vr as U,xn as W}from"./element-plus-Buzx8xRf.js";import{a as G,t as K}from"./vendor-wERX2bc3.js";import{n as q,t as J}from"./_plugin-vue_export-helper-Be8qXN0e.js";import{t as te}from"./configStore-Bj7SEMRL.js";import{t as ne}from"./CommonDialog-Cg3qSsFG.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-BAvoMaCc.js";import{n as ue,t as de}from"./AgentEngineSelector-DVuUEDHz.js";n(),B();var fe=c({__name:`MarketplacePanel`,props:{type:{type:String,required:!0}},setup(e,{expose:t}){t();let n=e,i=te(),a=T([]),o=T([]),c=T(!1),l=T(``),u=T(``),d=T([]),f=T(`project`),p=T(new Set),m=T(new Set),g=T(new Set),_=h(()=>i.currentDirectory||``),v=null;async function y(){if(!c.value){c.value=!0;try{let e=new URLSearchParams({type:n.type,cwd:_.value});u.value&&e.set(`q`,u.value),d.value.length&&e.set(`sources`,d.value.join(`,`));let t=await(await fetch(`/api/agent/marketplace/catalog?${e}`)).json();t?.success?(a.value=t.groups||[],o.value=t.installed||[]):C.error(t?.error||q(`@MKT:加载失败`))}catch{C.error(q(`@MKT:加载失败`))}finally{c.value=!1}}}z(l,e=>{v&&clearTimeout(v),v=setTimeout(()=>{u.value=e.trim(),y()},400)}),z(d,()=>y()),z(()=>n.type,()=>{d.value=[],u.value=``,l.value=``,y()}),z(_,()=>y()),y();let x=h(()=>{let e=_.value?_.value.split(/[\\/]/).filter(Boolean).pop():``;return f.value===`project`?e||q(`@MKT:当前项目`):q(`@MKT:g ai 智能体`)});function S(e){return e.stars?`${E(e.stars)} ★`:e.downloads?`${E(e.downloads)} ${q(`@MKT:周下载`)}`:e.uses?`${E(e.uses)} ${q(`@MKT:次使用`)}`:``}function E(e){return e>=1e3?`${(e/1e3).toFixed(e>=1e4?0:1)}k`:String(e)}function D(e){return`${e.id}`}function O(e){return p.value.has(D(e))}let k=h(()=>{let e={project:[],global:[]};for(let t of o.value)(e[t.target]||=[]).push(t);return e}),j=U({visible:!1,item:null,env:{},args:``});function M(e){return n.type===`mcp`&&(!!e.envKeys?.length||!!e.args?.length)}function P(e){j.item=e,j.env=Object.fromEntries((e.envKeys||[]).map(e=>[e,``])),j.args=(e.args||[]).join(` `),j.visible=!0}function L(){let e=j.item;if(j.visible=!1,!e)return;let t=Object.fromEntries(Object.entries(j.env).filter(([,e])=>e.trim()!==``)),n=j.args.trim()?j.args.trim().match(/(?:[^\s"]+|"[^"]*")+/g)?.map(e=>e.replace(/^"|"$/g,``))??void 0:void 0;B(e,{env:t,...n?{args:n}:{}})}async function R(e){if(!e.installed||await V(e)){if(M(e)){P(e);return}await B(e,{})}}async function B(e,t){let r=D(e);p.value.add(r);try{let r=await fetch(`/api/agent/marketplace/install`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({type:n.type,target:f.value,cwd:_.value,item:{...e,...t}})}),i=await r.json().catch(()=>null);if(!r.ok||!i?.success){C.error(i?.error||q(`@MKT:安装失败`));return}i.item?.warning&&C.warning(i.item.warning),i.item?.envKeys?.length?C.warning(`${q(`@MKT:还缺环境变量`)}: ${i.item.envKeys.join(`, `)}`):C.success(q(`@MKT:安装成功`)),await y()}catch{C.error(q(`@MKT:安装失败`))}finally{p.value.delete(r)}}async function V(e){try{return await A.confirm(`${e.name} ${q(`@MKT:已安装,要重新安装吗?`)}`,q(`@MKT:重新安装`),{confirmButtonText:q(`@MKT:重装`),cancelButtonText:q(`@MKT:取消`),type:`warning`}),!0}catch{return!1}}async function W(e){let t=`${e.target}:${e.id}`;g.value.add(t);try{let t=await fetch(`/api/agent/marketplace/reveal`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({type:n.type,target:e.target,cwd:_.value,id:e.id})}),r=await t.json().catch(()=>null);(!t.ok||!r?.success)&&C.error(r?.error||q(`@MKT:打开失败`))}catch{C.error(q(`@MKT:打开失败`))}finally{g.value.delete(t)}}async function G(e){try{await A.confirm(`${q(`@MKT:确定卸载`)} ${e.name}?`,q(`@MKT:卸载`),{confirmButtonText:q(`@MKT:卸载`),cancelButtonText:q(`@MKT:取消`),type:`warning`})}catch{return}let t=`${e.target}:${e.id}`;m.value.add(t);try{let t=new URLSearchParams({target:e.target,cwd:_.value}),r=await fetch(`/api/agent/marketplace/item/${n.type}/${encodeURIComponent(e.id)}?${t}`,{method:`DELETE`}),i=await r.json().catch(()=>null);if(!r.ok||!i?.success){C.error(i?.error||q(`@MKT:卸载失败`));return}C.success(q(`@MKT:已卸载`)),await y()}catch{C.error(q(`@MKT:卸载失败`))}finally{m.value.delete(t)}}let K={props:n,configStore:i,groups:a,installed:o,loading:c,searchInput:l,query:u,selectedSources:d,installTarget:f,installing:p,removing:m,revealing:g,cwd:_,get searchTimer(){return v},set searchTimer(e){v=e},loadCatalog:y,targetLabel:x,metricText:S,formatCount:E,cardKey:D,isBusy:O,installedByTarget:k,configDialog:j,needsConfig:M,openConfigDialog:P,confirmConfig:L,onInstall:R,doInstall:B,confirmReinstall:V,onReveal:W,onRemove:G,get $t(){return q},get Search(){return s},get Refresh(){return ee},get Delete(){return F},get Link(){return N},get Check(){return H},get Star(){return b},get Download(){return I},get Warning(){return w},get FolderOpened(){return r},CommonDialog:ne};return Object.defineProperty(K,"__isScriptSetup",{enumerable:!1,value:!0}),K}});n(),D(),o();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(t,n,r,o,s,ee){let c=l,h=j,g=d,v=_,y=R;return x(),M(`div`,pe,[p(` ── 工具栏 ───────────────────────────────── `),a(`div`,Y,[a(`div`,X,[m(c,{class:`mp-search-icon`},{default:E(()=>[m(o.Search)]),_:1}),P(a(`input`,{"onUpdate:modelValue":n[0]||=e=>o.searchInput=e,class:`mp-search-input`,type:`text`,placeholder:r.type===`skill`?o.$t(`@MKT:搜索 Skill...`):o.$t(`@MKT:搜索 MCP 服务...`)},null,8,me),[[S,o.searchInput]])]),m(g,{modelValue:o.installTarget,"onUpdate:modelValue":n[1]||=e=>o.installTarget=e,size:`small`,class:`mp-target`},{default:E(()=>[m(h,{value:`project`},{default:E(()=>[f(O(o.$t(`@MKT:当前项目`)),1)]),_:1}),m(h,{value:`global`},{default:E(()=>[f(O(o.$t(`@MKT:g ai 智能体`)),1)]),_:1})]),_:1},8,[`modelValue`]),m(v,{content:o.$t(`@MKT:刷新`),placement:`top`,"show-after":300},{default:E(()=>[a(`button`,{class:u([`mp-refresh`,{spinning:o.loading}]),onClick:o.loadCatalog},[m(c,null,{default:E(()=>[m(o.Refresh)]),_:1})],2)]),_:1},8,[`content`])]),a(`div`,he,[a(`span`,Z,[f(O(o.$t(`@MKT:安装到`))+` `,1),a(`b`,null,O(o.targetLabel),1)]),a(`div`,Q,[(x(!0),M(W,null,e(o.groups,e=>(x(),M(`button`,{key:e.id,class:u([`mp-chip`,{active:o.selectedSources.includes(e.id)}]),onClick:()=>{let t=o.selectedSources.indexOf(e.id);t>=0?o.selectedSources.splice(t,1):o.selectedSources.push(e.id)}},O(e.label),11,ge))),128)),o.selectedSources.length?(x(),M(`button`,{key:0,class:`mp-chip clear`,onClick:n[2]||=e=>o.selectedSources=[]},O(o.$t(`@MKT:全部来源`)),1)):p(`v-if`,!0)])]),p(` ── 内容 ─────────────────────────────────── `),P((x(),M(`div`,$,[(x(!0),M(W,null,e(o.groups,t=>(x(),M(`section`,{key:t.id,class:`mp-group`},[a(`header`,_e,[a(`h3`,ve,O(t.label),1),t.status===`ok`?(x(),M(`span`,ye,O(t.items.length),1)):(x(),M(`span`,be,[m(c,null,{default:E(()=>[m(o.Warning)]),_:1}),f(` `+O(t.error||o.$t(`@MKT:来源不可用`)),1)])),t.homepage?(x(),M(`a`,{key:2,class:`mp-group-link`,href:t.homepage,target:`_blank`,rel:`noopener noreferrer`,title:t.homepage},[m(c,null,{default:E(()=>[m(o.Link)]),_:1})],8,xe)):p(`v-if`,!0)]),t.status===`ok`&&t.items.length?(x(),M(`div`,Se,[(x(!0),M(W,null,e(t.items,t=>(x(),M(`article`,{key:o.cardKey(t),class:`mp-card`},[a(`div`,Ce,[a(`span`,{class:`mp-card-name`,title:t.name},O(t.name),9,we),o.metricText(t)?(x(),M(`span`,Te,[m(c,null,{default:E(()=>[t.stars?(x(),i(o.Star,{key:0})):(x(),i(o.Download,{key:1}))]),_:2},1024),f(` `+O(o.metricText(t)),1)])):p(`v-if`,!0)]),a(`p`,{class:`mp-card-desc`,title:t.description},O(t.description||o.$t(`@MKT:暂无描述`)),9,Ee),a(`div`,De,[t.package?(x(),M(`code`,{key:0,class:`mp-meta-pkg`,title:t.package},O(t.package),9,Oe)):t.repository?(x(),M(`span`,{key:1,class:`mp-meta-repo`,title:t.repository+(t.subpath?` · `+t.subpath:``)},[f(O(t.repository),1),t.subpath?(x(),M(W,{key:0},[f(` · `+O(t.subpath),1)],64)):p(`v-if`,!0)],8,ke)):p(`v-if`,!0),t.transport===`remote`?(x(),M(`span`,Ae,O(o.$t(`@MKT:远程服务`)),1)):p(`v-if`,!0),(x(!0),M(W,null,e((t.tags||[]).slice(0,2),e=>(x(),M(`span`,{key:e,class:`mp-tag`},O(e),1))),128))]),a(`div`,je,[t.upstream?(x(),M(`a`,{key:0,class:`mp-card-link`,href:t.upstream,target:`_blank`,rel:`noopener noreferrer`},O(o.$t(`@MKT:查看来源`)),9,Me)):p(`v-if`,!0),n[6]||=a(`span`,{class:`mp-foot-spacer`},null,-1),t.installed?(x(),M(`span`,Ne,[m(c,null,{default:E(()=>[m(o.Check)]),_:1}),f(O(o.$t(`@MKT:已安装`)),1)])):t.installable===!1?(x(),M(`span`,Fe,O(o.$t(`@MKT:暂不支持一键安装`)),1)):(x(),M(`button`,{key:2,class:`mp-install-btn`,disabled:o.isBusy(t),onClick:e=>o.onInstall(t)},O(o.isBusy(t)?o.$t(`@MKT:安装中...`):o.$t(`@MKT:安装`)),9,Pe))])]))),128))])):t.status===`ok`?(x(),M(`div`,Ie,O(o.$t(`@MKT:该来源暂无结果`)),1)):p(`v-if`,!0)]))),128)),p(` ── 已安装 ─────────────────────────────── `),o.installed.length?(x(),M(`section`,Le,[a(`header`,Re,[a(`h3`,ze,O(o.$t(`@MKT:已安装`)),1),a(`span`,Be,O(o.installed.length),1)]),(x(),M(W,null,e([`project`,`global`],t=>a(`div`,{key:t},[o.installedByTarget[t]?.length?(x(),M(`div`,Ve,[a(`div`,He,O(t===`project`?o.$t(`@MKT:当前项目`):o.$t(`@MKT:g ai 智能体`)),1),a(`div`,Ue,[(x(!0),M(W,null,e(o.installedByTarget[t],e=>(x(),M(`div`,{key:t+e.id,class:`mp-installed-row`},[a(`span`,{class:`mp-installed-name`,title:e.name},O(e.name),9,We),p(` 实际落盘的标识:SKILL.md 里的 name 常与仓库名不同(如仓库 taste-skill
|
|
1
|
+
import"./rolldown-runtime-C0FnF6B9.js";import{$n as e,At as t,Bn as n,Ct as r,Dn as i,En as a,Fr as o,Gt as s,Ht as ee,In as c,J as l,Jr as u,M as d,Nn as f,On as p,Pn as m,Tn as h,Tt as g,W as _,Wn as v,Xr as y,Yt as b,Zn as x,_n as S,a as C,an as w,br as T,cr as E,dn as D,ei as O,et as k,i as A,j,kn as M,kt as N,lr as P,lt as F,mt as I,nr as L,o as R,or as z,pr as B,st as V,tt as H,vr as U,xn as W}from"./element-plus-Buzx8xRf.js";import{a as G,t as K}from"./vendor-wERX2bc3.js";import{n as q,t as J}from"./_plugin-vue_export-helper-VuE2vqnn.js";import{t as te}from"./configStore-De_8eQuS.js";import{t as ne}from"./CommonDialog-BTeIpgGT.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-DcW54Tlt.js";import{n as ue,t as de}from"./AgentEngineSelector-DVs4LGHZ.js";n(),B();var fe=c({__name:`MarketplacePanel`,props:{type:{type:String,required:!0}},setup(e,{expose:t}){t();let n=e,i=te(),a=T([]),o=T([]),c=T(!1),l=T(``),u=T(``),d=T([]),f=T(`project`),p=T(new Set),m=T(new Set),g=T(new Set),_=h(()=>i.currentDirectory||``),v=null;async function y(){if(!c.value){c.value=!0;try{let e=new URLSearchParams({type:n.type,cwd:_.value});u.value&&e.set(`q`,u.value),d.value.length&&e.set(`sources`,d.value.join(`,`));let t=await(await fetch(`/api/agent/marketplace/catalog?${e}`)).json();t?.success?(a.value=t.groups||[],o.value=t.installed||[]):C.error(t?.error||q(`@MKT:加载失败`))}catch{C.error(q(`@MKT:加载失败`))}finally{c.value=!1}}}z(l,e=>{v&&clearTimeout(v),v=setTimeout(()=>{u.value=e.trim(),y()},400)}),z(d,()=>y()),z(()=>n.type,()=>{d.value=[],u.value=``,l.value=``,y()}),z(_,()=>y()),y();let x=h(()=>{let e=_.value?_.value.split(/[\\/]/).filter(Boolean).pop():``;return f.value===`project`?e||q(`@MKT:当前项目`):q(`@MKT:g ai 智能体`)});function S(e){return e.stars?`${E(e.stars)} ★`:e.downloads?`${E(e.downloads)} ${q(`@MKT:周下载`)}`:e.uses?`${E(e.uses)} ${q(`@MKT:次使用`)}`:``}function E(e){return e>=1e3?`${(e/1e3).toFixed(e>=1e4?0:1)}k`:String(e)}function D(e){return`${e.id}`}function O(e){return p.value.has(D(e))}let k=h(()=>{let e={project:[],global:[]};for(let t of o.value)(e[t.target]||=[]).push(t);return e}),j=U({visible:!1,item:null,env:{},args:``});function M(e){return n.type===`mcp`&&(!!e.envKeys?.length||!!e.args?.length)}function P(e){j.item=e,j.env=Object.fromEntries((e.envKeys||[]).map(e=>[e,``])),j.args=(e.args||[]).join(` `),j.visible=!0}function L(){let e=j.item;if(j.visible=!1,!e)return;let t=Object.fromEntries(Object.entries(j.env).filter(([,e])=>e.trim()!==``)),n=j.args.trim()?j.args.trim().match(/(?:[^\s"]+|"[^"]*")+/g)?.map(e=>e.replace(/^"|"$/g,``))??void 0:void 0;B(e,{env:t,...n?{args:n}:{}})}async function R(e){if(!e.installed||await V(e)){if(M(e)){P(e);return}await B(e,{})}}async function B(e,t){let r=D(e);p.value.add(r);try{let r=await fetch(`/api/agent/marketplace/install`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({type:n.type,target:f.value,cwd:_.value,item:{...e,...t}})}),i=await r.json().catch(()=>null);if(!r.ok||!i?.success){C.error(i?.error||q(`@MKT:安装失败`));return}i.item?.warning&&C.warning(i.item.warning),i.item?.envKeys?.length?C.warning(`${q(`@MKT:还缺环境变量`)}: ${i.item.envKeys.join(`, `)}`):C.success(q(`@MKT:安装成功`)),await y()}catch{C.error(q(`@MKT:安装失败`))}finally{p.value.delete(r)}}async function V(e){try{return await A.confirm(`${e.name} ${q(`@MKT:已安装,要重新安装吗?`)}`,q(`@MKT:重新安装`),{confirmButtonText:q(`@MKT:重装`),cancelButtonText:q(`@MKT:取消`),type:`warning`}),!0}catch{return!1}}async function W(e){let t=`${e.target}:${e.id}`;g.value.add(t);try{let t=await fetch(`/api/agent/marketplace/reveal`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({type:n.type,target:e.target,cwd:_.value,id:e.id})}),r=await t.json().catch(()=>null);(!t.ok||!r?.success)&&C.error(r?.error||q(`@MKT:打开失败`))}catch{C.error(q(`@MKT:打开失败`))}finally{g.value.delete(t)}}async function G(e){try{await A.confirm(`${q(`@MKT:确定卸载`)} ${e.name}?`,q(`@MKT:卸载`),{confirmButtonText:q(`@MKT:卸载`),cancelButtonText:q(`@MKT:取消`),type:`warning`})}catch{return}let t=`${e.target}:${e.id}`;m.value.add(t);try{let t=new URLSearchParams({target:e.target,cwd:_.value}),r=await fetch(`/api/agent/marketplace/item/${n.type}/${encodeURIComponent(e.id)}?${t}`,{method:`DELETE`}),i=await r.json().catch(()=>null);if(!r.ok||!i?.success){C.error(i?.error||q(`@MKT:卸载失败`));return}C.success(q(`@MKT:已卸载`)),await y()}catch{C.error(q(`@MKT:卸载失败`))}finally{m.value.delete(t)}}let K={props:n,configStore:i,groups:a,installed:o,loading:c,searchInput:l,query:u,selectedSources:d,installTarget:f,installing:p,removing:m,revealing:g,cwd:_,get searchTimer(){return v},set searchTimer(e){v=e},loadCatalog:y,targetLabel:x,metricText:S,formatCount:E,cardKey:D,isBusy:O,installedByTarget:k,configDialog:j,needsConfig:M,openConfigDialog:P,confirmConfig:L,onInstall:R,doInstall:B,confirmReinstall:V,onReveal:W,onRemove:G,get $t(){return q},get Search(){return s},get Refresh(){return ee},get Delete(){return F},get Link(){return N},get Check(){return H},get Star(){return b},get Download(){return I},get Warning(){return w},get FolderOpened(){return r},CommonDialog:ne};return Object.defineProperty(K,"__isScriptSetup",{enumerable:!1,value:!0}),K}});n(),D(),o();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(t,n,r,o,s,ee){let c=l,h=j,g=d,v=_,y=R;return x(),M(`div`,pe,[p(` ── 工具栏 ───────────────────────────────── `),a(`div`,Y,[a(`div`,X,[m(c,{class:`mp-search-icon`},{default:E(()=>[m(o.Search)]),_:1}),P(a(`input`,{"onUpdate:modelValue":n[0]||=e=>o.searchInput=e,class:`mp-search-input`,type:`text`,placeholder:r.type===`skill`?o.$t(`@MKT:搜索 Skill...`):o.$t(`@MKT:搜索 MCP 服务...`)},null,8,me),[[S,o.searchInput]])]),m(g,{modelValue:o.installTarget,"onUpdate:modelValue":n[1]||=e=>o.installTarget=e,size:`small`,class:`mp-target`},{default:E(()=>[m(h,{value:`project`},{default:E(()=>[f(O(o.$t(`@MKT:当前项目`)),1)]),_:1}),m(h,{value:`global`},{default:E(()=>[f(O(o.$t(`@MKT:g ai 智能体`)),1)]),_:1})]),_:1},8,[`modelValue`]),m(v,{content:o.$t(`@MKT:刷新`),placement:`top`,"show-after":300},{default:E(()=>[a(`button`,{class:u([`mp-refresh`,{spinning:o.loading}]),onClick:o.loadCatalog},[m(c,null,{default:E(()=>[m(o.Refresh)]),_:1})],2)]),_:1},8,[`content`])]),a(`div`,he,[a(`span`,Z,[f(O(o.$t(`@MKT:安装到`))+` `,1),a(`b`,null,O(o.targetLabel),1)]),a(`div`,Q,[(x(!0),M(W,null,e(o.groups,e=>(x(),M(`button`,{key:e.id,class:u([`mp-chip`,{active:o.selectedSources.includes(e.id)}]),onClick:()=>{let t=o.selectedSources.indexOf(e.id);t>=0?o.selectedSources.splice(t,1):o.selectedSources.push(e.id)}},O(e.label),11,ge))),128)),o.selectedSources.length?(x(),M(`button`,{key:0,class:`mp-chip clear`,onClick:n[2]||=e=>o.selectedSources=[]},O(o.$t(`@MKT:全部来源`)),1)):p(`v-if`,!0)])]),p(` ── 内容 ─────────────────────────────────── `),P((x(),M(`div`,$,[(x(!0),M(W,null,e(o.groups,t=>(x(),M(`section`,{key:t.id,class:`mp-group`},[a(`header`,_e,[a(`h3`,ve,O(t.label),1),t.status===`ok`?(x(),M(`span`,ye,O(t.items.length),1)):(x(),M(`span`,be,[m(c,null,{default:E(()=>[m(o.Warning)]),_:1}),f(` `+O(t.error||o.$t(`@MKT:来源不可用`)),1)])),t.homepage?(x(),M(`a`,{key:2,class:`mp-group-link`,href:t.homepage,target:`_blank`,rel:`noopener noreferrer`,title:t.homepage},[m(c,null,{default:E(()=>[m(o.Link)]),_:1})],8,xe)):p(`v-if`,!0)]),t.status===`ok`&&t.items.length?(x(),M(`div`,Se,[(x(!0),M(W,null,e(t.items,t=>(x(),M(`article`,{key:o.cardKey(t),class:`mp-card`},[a(`div`,Ce,[a(`span`,{class:`mp-card-name`,title:t.name},O(t.name),9,we),o.metricText(t)?(x(),M(`span`,Te,[m(c,null,{default:E(()=>[t.stars?(x(),i(o.Star,{key:0})):(x(),i(o.Download,{key:1}))]),_:2},1024),f(` `+O(o.metricText(t)),1)])):p(`v-if`,!0)]),a(`p`,{class:`mp-card-desc`,title:t.description},O(t.description||o.$t(`@MKT:暂无描述`)),9,Ee),a(`div`,De,[t.package?(x(),M(`code`,{key:0,class:`mp-meta-pkg`,title:t.package},O(t.package),9,Oe)):t.repository?(x(),M(`span`,{key:1,class:`mp-meta-repo`,title:t.repository+(t.subpath?` · `+t.subpath:``)},[f(O(t.repository),1),t.subpath?(x(),M(W,{key:0},[f(` · `+O(t.subpath),1)],64)):p(`v-if`,!0)],8,ke)):p(`v-if`,!0),t.transport===`remote`?(x(),M(`span`,Ae,O(o.$t(`@MKT:远程服务`)),1)):p(`v-if`,!0),(x(!0),M(W,null,e((t.tags||[]).slice(0,2),e=>(x(),M(`span`,{key:e,class:`mp-tag`},O(e),1))),128))]),a(`div`,je,[t.upstream?(x(),M(`a`,{key:0,class:`mp-card-link`,href:t.upstream,target:`_blank`,rel:`noopener noreferrer`},O(o.$t(`@MKT:查看来源`)),9,Me)):p(`v-if`,!0),n[6]||=a(`span`,{class:`mp-foot-spacer`},null,-1),t.installed?(x(),M(`span`,Ne,[m(c,null,{default:E(()=>[m(o.Check)]),_:1}),f(O(o.$t(`@MKT:已安装`)),1)])):t.installable===!1?(x(),M(`span`,Fe,O(o.$t(`@MKT:暂不支持一键安装`)),1)):(x(),M(`button`,{key:2,class:`mp-install-btn`,disabled:o.isBusy(t),onClick:e=>o.onInstall(t)},O(o.isBusy(t)?o.$t(`@MKT:安装中...`):o.$t(`@MKT:安装`)),9,Pe))])]))),128))])):t.status===`ok`?(x(),M(`div`,Ie,O(o.$t(`@MKT:该来源暂无结果`)),1)):p(`v-if`,!0)]))),128)),p(` ── 已安装 ─────────────────────────────── `),o.installed.length?(x(),M(`section`,Le,[a(`header`,Re,[a(`h3`,ze,O(o.$t(`@MKT:已安装`)),1),a(`span`,Be,O(o.installed.length),1)]),(x(),M(W,null,e([`project`,`global`],t=>a(`div`,{key:t},[o.installedByTarget[t]?.length?(x(),M(`div`,Ve,[a(`div`,He,O(t===`project`?o.$t(`@MKT:当前项目`):o.$t(`@MKT:g ai 智能体`)),1),a(`div`,Ue,[(x(!0),M(W,null,e(o.installedByTarget[t],e=>(x(),M(`div`,{key:t+e.id,class:`mp-installed-row`},[a(`span`,{class:`mp-installed-name`,title:e.name},O(e.name),9,We),p(` 实际落盘的标识:SKILL.md 里的 name 常与仓库名不同(如仓库 taste-skill
|
|
2
2
|
里的 skill 自称 brandkit),不显示这个用户就对不上广场卡片上的名字 `),e.id&&e.id!==e.name?(x(),M(`code`,{key:0,class:`mp-installed-id`,title:e.dir||e.file||e.id},O(e.id),9,Ge)):p(`v-if`,!0),e.package?(x(),M(`code`,Ke,O(e.package),1)):p(`v-if`,!0),e.requiredEnv?.length?(x(),M(`span`,qe,O(o.$t(`@MKT:待配置`))+`: `+O(e.requiredEnv.join(`, `)),1)):p(`v-if`,!0),n[7]||=a(`span`,{class:`mp-foot-spacer`},null,-1),a(`button`,{class:`mp-reveal-btn`,disabled:o.revealing.has(t+e.id),title:e.dir||e.file||``,onClick:t=>o.onReveal(e)},[m(c,null,{default:E(()=>[m(o.FolderOpened)]),_:1}),f(` `+O(o.$t(`@MKT:打开文件夹`)),1)],8,Je),a(`button`,{class:`mp-remove-btn`,disabled:o.removing.has(t+e.id),onClick:t=>o.onRemove(e)},[m(c,null,{default:E(()=>[m(o.Delete)]),_:1}),f(` `+O(o.removing.has(t+e.id)?o.$t(`@MKT:卸载中...`):o.$t(`@MKT:卸载`)),1)],8,Ye)]))),128))])])):p(`v-if`,!0)])),64))])):p(`v-if`,!0),!o.loading&&!o.groups.length?(x(),M(`div`,Xe,O(o.$t(`@MKT:加载失败`)),1)):p(`v-if`,!0)])),[[y,o.loading]]),p(` ── MCP 安装前配置 ───────────────────────── `),m(o.CommonDialog,{modelValue:o.configDialog.visible,"onUpdate:modelValue":n[5]||=e=>o.configDialog.visible=e,title:o.$t(`@MKT:配置 MCP`),width:`460px`,type:`flex`,"close-on-click-modal":!1,"append-to-body":``},{footer:E(()=>[a(`button`,{class:`mkt-cancel`,onClick:n[4]||=e=>o.configDialog.visible=!1},O(o.$t(`@MKT:取消`)),1),a(`button`,{class:`mkt-confirm`,onClick:o.confirmConfig},O(o.$t(`@MKT:安装`)),1)]),default:E(()=>[o.configDialog.item?(x(),M(`div`,Ze,[a(`p`,Qe,O(o.configDialog.item.name),1),(x(!0),M(W,null,e(Object.keys(o.configDialog.env),e=>(x(),M(`div`,{key:e,class:`mkt-field`},[a(`label`,null,O(e),1),P(a(`input`,{"onUpdate:modelValue":t=>o.configDialog.env[e]=t,type:`text`,autocomplete:`off`,placeholder:o.$t(`@MKT:环境变量值`),spellcheck:`false`},null,8,$e),[[S,o.configDialog.env[e]]])]))),128)),o.configDialog.item.args?.length?(x(),M(`div`,et,[a(`label`,null,O(o.$t(`@MKT:启动参数`)),1),P(a(`input`,{"onUpdate:modelValue":n[3]||=e=>o.configDialog.args=e,type:`text`,autocomplete:`off`,spellcheck:`false`},null,512),[[S,o.configDialog.args]]),a(`p`,tt,O(o.$t(`@MKT:参数提示`)),1)])):p(`v-if`,!0)])):p(`v-if`,!0)]),_:1},8,[`modelValue`,`title`])])}var rt=J(fe,[[`render`,nt],[`__scopeId`,`data-v-e9f9e851`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/components/MarketplacePanel.vue`]]);n(),B();var it=c({__name:`AgentView`,setup(e,{expose:n}){n();let r=te(),i=T(null),{narrow:a}=ue(i),o=T(`chat`),s=T(`chat`),ee=h(()=>s.value===`mcp`?`mcp`:`skill`),c=h(()=>[{id:`chat`,label:q(`@AGENT:对话`),icon:k},{id:`skill`,label:q(`@AGENT:Skill 广场`),icon:g},{id:`mcp`,label:q(`@AGENT:MCP 广场`),icon:V}]),{sessions:u,sessionsLoading:d,currentSessionId:f,messages:p,isStreaming:m,sessionLoading:_,loadSessions:y,loadSession:b,deleteSession:x,renameSession:S,newSession:C,sendMessage:w,pendingQuestion:E,answeringQuestion:D,answerQuestion:O,isSessionGenerating:A,currentEngine:j,pendingEngine:M,isEngineLocked:N,pickEngine:P,stop:F}=ce(),I=h(()=>N.value?j.value:M.value);function L(e){N.value||P(e)}let R=h(()=>{let e=r.theme;return e===`dark`||e===`auto`&&window.matchMedia(`(prefers-color-scheme: dark)`).matches?`dark`:`light`}),B=h(()=>re(u.value,A)),H=se(),U=h(()=>B.value.find(e=>e.id===f.value)?.title||q(`@AGENT:对话`)),W={"--welcome-avatar":`url("${le}")`},J=h(()=>[{id:`p1`,label:q(`@AGENT:查看项目结构`),prompt:q(`@AGENT:prompt_p1`)},{id:`p2`,label:q(`@AGENT:分析代码质量`),prompt:q(`@AGENT:prompt_p2`)},{id:`p3`,label:q(`@AGENT:帮我写测试`),prompt:q(`@AGENT:prompt_p3`)},{id:`p4`,label:q(`@AGENT:Git 状态检查`),prompt:q(`@AGENT:prompt_p4`)},{id:`p5`,label:q(`@AGENT:帮我启动项目`),prompt:q(`@AGENT:prompt_p5`)}]);async function ne(e){await w(e.text,e.files),await v(),X()}async function fe(e){await w(e.prompt),await v(),X()}let pe=ie(),Y=T(null);function X(e=!0){Y.value?.scrollToBottom(e)}z(()=>p.value.length,()=>{v(()=>X(!1))});function me(e){b(e),o.value=`chat`}function he(){C(),o.value=`chat`}let Z=T(280),Q=T(!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)}z(a,e=>{e||(o.value=`chat`)}),z(()=>[r.currentDirectory,m.value],async([e,t],n)=>{let r=!n||e!==n[0],i=!!n&&n[1]===!0&&!t;(r||i)&&await y(),f.value&&!m.value&&!u.value.some(e=>e.sessionId===f.value)&&C()},{immediate:!0});let $={configStore:r,rootRef:i,narrow:a,chatPage:o,activeTab:s,marketplaceType:ee,tabs:c,sessions:u,sessionsLoading:d,currentSessionId:f,messages:p,isStreaming:m,sessionLoading:_,loadSessions:y,loadSession:b,deleteSession:x,renameSession:S,newSession:C,sendMessage:w,pendingQuestion:E,answeringQuestion:D,answerQuestion:O,isSessionGenerating:A,currentEngine:j,pendingEngine:M,isEngineLocked:N,pickEngine:P,stop:F,displayEngine:I,handleEngineSelect:L,chatTheme:R,conversationItems:B,conversationLabels:H,currentSessionTitle:U,welcomeAvatarStyle:W,presetQuestions:J,onSend:ne,onSelectPreset:fe,questionLabels:pe,chatContainerRef:Y,scrollToBottom:X,selectSession:me,handleNewSession:he,sidebarWidth:Z,isResizing:Q,startResize:ge,get $t(){return q},get ElIcon(){return l},get Loading(){return t},get ChatContainer(){return G},get ConversationList(){return K},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}),$}});n(),o();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(t,n,r,o,s,ee){return x(),M(`div`,at,[p(` ═══ 宽屏:左侧会话列表(只在「对话」Tab 显示)═══
|
|
3
3
|
窄屏时这一整块不渲染,会话列表改成 body 里的一个整页(见 .agent-list-page) `),o.activeTab===`chat`&&!o.narrow?(x(),M(W,{key:0},[a(`aside`,{class:`agent-sidebar`,style:y({width:o.sidebarWidth+`px`})},[p(` 会话列表:UI 与交互都在组件库的 ConversationList 里 `),m(o.ConversationList,{class:`agent-conversations`,items:o.conversationItems,"active-id":o.currentSessionId,loading:o.sessionsLoading,labels:o.conversationLabels,onSelect:o.selectSession,onNew:o.handleNewSession,onRename:o.renameSession,onDelete:o.deleteSession},null,8,[`items`,`active-id`,`loading`,`labels`,`onRename`,`onDelete`])],4),p(` 拖拽分隔条 `),a(`div`,{class:u([`sidebar-resizer`,{active:o.isResizing}]),onMousedown:o.startResize},null,34)],64)):p(`v-if`,!0),p(` ═══ 右侧:Tab 栏 + 内容区 ═══ `),a(`main`,ot,[a(`nav`,st,[(x(!0),M(W,null,e(o.tabs,e=>(x(),M(`button`,{key:e.id,type:`button`,class:u([`agent-tab`,{active:o.activeTab===e.id}]),role:`tab`,"aria-selected":o.activeTab===e.id,onClick:t=>o.activeTab=e.id},[m(o.ElIcon,null,{default:E(()=>[(x(),i(L(e.icon)))]),_:2},1024),a(`span`,null,O(e.label),1)],10,ct))),128)),p(` ═══ 引擎选择器 ═══
|
|
4
4
|
与工作台执行器下拉同一套交互(点击展开、未安装标出来、点了直接开安装弹窗)。
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"./rolldown-runtime-C0FnF6B9.js";import{At as e,Bn as t,Dn as n,En as r,Fr as i,In as a,J as o,Jr as s,Nn as c,On as l,Pn as u,Tn as d,W as f,Wn as p,Yn as m,Zn as h,a as g,br as _,cr as v,ei as y,i as b,kn as x,nt as S,or as C,pr as w,qn as T,rt as E,z as D}from"./element-plus-Buzx8xRf.js";import{n as O,t as k}from"./_plugin-vue_export-helper-
|
|
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 ee(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 N(){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(()=>{})})}t(),w();var P=`npm install -g zen-gitsync --registry https://registry.npmjs.org/`,F=a({__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(t,{expose:n,emit:r}){n();let i=t,a=r,o=_(null);C(()=>i.logs,async()=>{await p(),o.value&&(o.value.scrollTop=o.value.scrollHeight)});function s(){i.status!==`running`&&(i.status===`success`&&i.countdown>0&&a(`cancel`),a(`update:modelValue`,!1))}function c(){a(`retry`)}function l(){a(`restart`)}function u(){a(`cancel`),a(`update:modelValue`,!1)}async function d(){try{await navigator.clipboard.writeText(P),g.success(O(`@F13B4:已复制升级命令`))}catch{g.warning(O(`@F13B4:复制失败,请手动复制`))}}let f={MANUAL_COMMAND:P,props:i,emit:a,logEl:o,close:s,onRetry:c,onRestart:l,onLater:u,onCopyCommand:d,get Loading(){return e},get CircleCheck(){return S},get CircleClose(){return E},get $t(){return O},CommonDialog:A};return Object.defineProperty(f,"__isScriptSetup",{enumerable:!1,value:!0}),f}});t(),i();var I={key:3},L={key:4},R={key:5},z={key:0,class:`upgrade-hint`},B={key:0,class:`upgrade-countdown`},V={key:1,class:`upgrade-manual`},H={class:`upgrade-manual__label`};function U(e,t,i,a,d,f){let p=o,m=D;return h(),n(a.CommonDialog,{"model-value":i.modelValue,"onUpdate:modelValue":t[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:v(()=>[i.status===`failed`?(h(),n(m,{key:0,type:`primary`,onClick:a.onRetry},{default:v(()=>[c(y(a.$t(`@F13B4:重试`)),1)]),_:1})):l(`v-if`,!0),i.status===`failed`?(h(),n(m,{key:1,onClick:a.onCopyCommand},{default:v(()=>[c(y(a.$t(`@F13B4:复制升级命令`)),1)]),_:1})):l(`v-if`,!0),i.status===`success`?(h(),n(m,{key:2,type:`primary`,onClick:a.onRestart},{default:v(()=>[c(y(a.$t(`@F13B4:立即重启并刷新`)),1)]),_:1})):l(`v-if`,!0),i.status===`success`?(h(),n(m,{key:3,onClick:a.onLater},{default:v(()=>[c(y(a.$t(`@F13B4:稍后手动重启`)),1)]),_:1})):l(`v-if`,!0),i.status===`running`?(h(),n(m,{key:4,disabled:``},{default:v(()=>[c(y(a.$t(`@F13B4:升级中`))+`... `,1)]),_:1})):l(`v-if`,!0)]),default:v(()=>[r(`div`,{class:s([`upgrade-status`,`is-${i.status}`])},[i.status===`running`?(h(),n(p,{key:0,class:`is-loading`},{default:v(()=>[u(a.Loading)]),_:1})):i.status===`success`?(h(),n(p,{key:1,color:`var(--color-success)`},{default:v(()=>[u(a.CircleCheck)]),_:1})):(h(),n(p,{key:2,color:`var(--color-danger)`},{default:v(()=>[u(a.CircleClose)]),_:1})),i.status===`running`?(h(),x(`span`,I,y(a.$t(`@F13B4:升级中`)),1)):i.status===`success`?(h(),x(`span`,L,y(a.$t(`@F13B4:升级完成`)),1)):(h(),x(`span`,R,y(a.$t(`@F13B4:升级失败`)),1))],2),i.status===`success`?(h(),x(`p`,z,[c(y(a.$t(`@F13B4:新版本已全局安装,需要重启服务才能生效`))+` `,1),i.countdown>0?(h(),x(`span`,B,y(a.$t(`@F13B4:{seconds} 秒后自动刷新`,{seconds:i.countdown})),1)):l(`v-if`,!0)])):l(`v-if`,!0),i.status===`failed`?(h(),x(`p`,V,[r(`span`,H,y(a.$t(`@F13B4:手动升级命令`)),1),r(`code`,{class:`upgrade-manual__cmd`},y(a.MANUAL_COMMAND))])):l(`v-if`,!0),r(`pre`,{ref:`logEl`,class:`upgrade-log`},y(i.logs||a.$t(`@F13B4:等待日志输出`)),513)]),_:1},8,[`model-value`,`title`,`show-close`])}var W=k(F,[[`render`,U],[`__scopeId`,`data-v-bc566bba`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/components/UpgradeDialog.vue`]]);t(),w();var G=`https://github.com/xz333221/zen-gitsync/releases`,K=5,q=`app-version-check`,J=36e5,Y=a({__name:`AppVersionBadge`,setup(e,{expose:t}){t();let n=`2.17.34`,r=_(n),i=d(()=>r.value||n),a=_(null),o=_(!1),s=_(``),c=_(`running`),l=_(0),u=null,f=_(!1);function p(){try{let e=sessionStorage.getItem(q);if(!e)return null;let{at:t,data:n}=JSON.parse(e);return Date.now()-t>J?null:n}catch{return null}}function h(e){try{sessionStorage.setItem(q,JSON.stringify({at:Date.now(),data:e}))}catch{}}async function v(e=!1){let t=p();t&&(a.value=t);try{let t=await M();a.value=t,h(t),t.current&&(r.value=t.current),!e&&t.success&&t.hasUpdate&&g({type:`success`,message:O(`@F13B4:发现新版本 {version}`,{version:t.latest??``}),duration:4e3})}catch(t){e||g({type:`warning`,message:O(`@F13B4:检查更新失败 {error}`,{error:t?.message||``})})}}async function y(){if(a.value?.hasUpdate){try{await b.confirm(O(`@F13B4:确定要从 {current} 升级到 {latest} 吗?`,{current:a.value.current,latest:a.value.latest}),O(`@F13B4:升级`),{confirmButtonText:O(`@F13B4:确定升级`),cancelButtonText:O(`@F13B4:取消`),type:`info`})}catch{return}s.value=``,c.value=`running`,o.value=!0,await ee(e=>{if(e.type===`done`){if(c.value=e.code===0?`success`:`failed`,e.code===0){try{sessionStorage.removeItem(q)}catch{}a.value?.latest&&(r.value=a.value.latest),x()}}else e.message&&(s.value+=e.message)})}}function x(){S(),l.value=K,u=setInterval(()=>{--l.value,l.value<=0&&(u&&=(clearInterval(u),null),w())},1e3)}function S(){u&&=(clearInterval(u),null),l.value=0}function C(){S()}async function w(){if(S(),!f.value){f.value=!0;try{let e=await N(),{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];g({type:`warning`,message:n?O(n):O(`@F13B4:重启失败 {error}`,{error:t})}),f.value=!1}}}T(()=>{S()}),m(()=>{v(!0)});let E={buildVersion:n,releasesUrl:G,runtimeVersion:r,displayVersion:i,latestInfo:a,upgradeDialogVisible:o,upgradeLogs:s,upgradeStatus:c,AUTO_REFRESH_SECONDS:K,countdown:l,get countdownTimer(){return u},set countdownTimer(e){u=e},restartInFlight:f,CACHE_KEY:q,CACHE_TTL_MS:J,readCache:p,writeCache:h,checkUpdate:v,handleUpgrade:y,startAutoRefreshCountdown:x,cancelAutoRefreshCountdown:S,handleCancelAutoRefresh:C,handleRestart:w,get $t(){return O},UpgradeDialog:W};return Object.defineProperty(E,"__isScriptSetup",{enumerable:!1,value:!0}),E}});t(),i();var X={class:`app-version-badge`},Z=[`aria-label`],Q=[`aria-label`],$=[`title`,`aria-label`],te={class:`upgrade-btn__label`},ne={class:`upgrade-btn__version`};function re(e,t,n,i,a,o){let s=f;return h(),x(`div`,X,[l(` GitHub 链接 `),u(s,{content:i.$t(`@F13B4:在 GitHub 上查看源码`),placement:`top`,effect:`dark`,"show-after":300},{default:v(()=>[r(`a`,{href:`https://github.com/xz333221/zen-gitsync`,target:`_blank`,rel:`noopener noreferrer`,class:`badge-icon-link`,"aria-label":i.$t(`@F13B4:在 GitHub 上查看源码`)},[...t[1]||=[r(`svg`,{viewBox:`0 0 24 24`,width:`15`,height:`15`,"aria-hidden":`true`,fill:`currentColor`,xmlns:`http://www.w3.org/2000/svg`},[r(`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,Z)]),_:1},8,[`content`]),l(` NPM 链接 `),u(s,{content:i.$t(`@F13B4:在 npm 上查看包`),placement:`top`,effect:`dark`,"show-after":300},{default:v(()=>[r(`a`,{href:`https://www.npmjs.com/package/zen-gitsync`,target:`_blank`,rel:`noopener noreferrer`,class:`badge-icon-link badge-icon-link--npm`,"aria-label":i.$t(`@F13B4:在 npm 上查看包`)},[...t[2]||=[r(`svg`,{viewBox:`0 0 24 24`,width:`15`,height:`15`,"aria-hidden":`true`,fill:`currentColor`,xmlns:`http://www.w3.org/2000/svg`},[r(`path`,{d:`M2 2v20h20V2H2zm17.167 17.167H12.5v-10h-3.333v10H4.833V4.833h14.334v14.334z`})],-1)]],8,Q)]),_:1},8,[`content`]),l(` 版本号 `),u(s,{content:i.$t(`@F13B4:查看更新`),placement:`top`,effect:`dark`,"show-after":300},{default:v(()=>[r(`a`,{href:i.releasesUrl,target:`_blank`,rel:`noopener noreferrer`,class:`version-link`},`v`+y(i.displayVersion),1)]),_:1},8,[`content`]),i.latestInfo?.hasUpdate?(h(),x(`button`,{key:0,type:`button`,class:`upgrade-btn`,title:i.$t(`@F13B4:发现新版本 {version},点击升级`,{version:i.latestInfo.latest??``}),"aria-label":i.$t(`@F13B4:发现新版本 {version},点击升级`,{version:i.latestInfo.latest??``}),onClick:i.handleUpgrade},[t[3]||=r(`span`,{class:`upgrade-btn__dot`,"aria-hidden":`true`},null,-1),r(`span`,te,y(i.$t(`@F13B4:升级`)),1),r(`span`,ne,`v`+y(i.latestInfo.latest),1)],8,$)):l(`v-if`,!0),u(i.UpgradeDialog,{modelValue:i.upgradeDialogVisible,"onUpdate:modelValue":t[0]||=e=>i.upgradeDialogVisible=e,logs:i.upgradeLogs,status:i.upgradeStatus,countdown:i.countdown,onRetry:i.handleUpgrade,onRestart:i.handleRestart,onCancel:i.handleCancelAutoRefresh},null,8,[`modelValue`,`logs`,`status`,`countdown`])])}var ie=k(Y,[[`render`,re],[`__scopeId`,`data-v-7e0300ec`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/components/AppVersionBadge.vue`]]);export{ie as default};
|
|
1
|
+
import"./rolldown-runtime-C0FnF6B9.js";import{At as e,Bn as t,Dn as n,En as r,Fr as i,In as a,J as o,Jr as s,Nn as c,On as l,Pn as u,Tn as d,W as f,Wn as p,Yn as m,Zn as h,a as g,br as _,cr as v,ei as y,i as b,kn as x,nt as S,or as C,pr as w,qn as T,rt as E,z as D}from"./element-plus-Buzx8xRf.js";import{n as O,t as k}from"./_plugin-vue_export-helper-VuE2vqnn.js";import{t as A}from"./CommonDialog-BTeIpgGT.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 ee(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 N(){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(()=>{})})}t(),w();var P=`npm install -g zen-gitsync --registry https://registry.npmjs.org/`,F=a({__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(t,{expose:n,emit:r}){n();let i=t,a=r,o=_(null);C(()=>i.logs,async()=>{await p(),o.value&&(o.value.scrollTop=o.value.scrollHeight)});function s(){i.status!==`running`&&(i.status===`success`&&i.countdown>0&&a(`cancel`),a(`update:modelValue`,!1))}function c(){a(`retry`)}function l(){a(`restart`)}function u(){a(`cancel`),a(`update:modelValue`,!1)}async function d(){try{await navigator.clipboard.writeText(P),g.success(O(`@F13B4:已复制升级命令`))}catch{g.warning(O(`@F13B4:复制失败,请手动复制`))}}let f={MANUAL_COMMAND:P,props:i,emit:a,logEl:o,close:s,onRetry:c,onRestart:l,onLater:u,onCopyCommand:d,get Loading(){return e},get CircleCheck(){return S},get CircleClose(){return E},get $t(){return O},CommonDialog:A};return Object.defineProperty(f,"__isScriptSetup",{enumerable:!1,value:!0}),f}});t(),i();var I={key:3},L={key:4},R={key:5},z={key:0,class:`upgrade-hint`},B={key:0,class:`upgrade-countdown`},V={key:1,class:`upgrade-manual`},H={class:`upgrade-manual__label`};function U(e,t,i,a,d,f){let p=o,m=D;return h(),n(a.CommonDialog,{"model-value":i.modelValue,"onUpdate:modelValue":t[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:v(()=>[i.status===`failed`?(h(),n(m,{key:0,type:`primary`,onClick:a.onRetry},{default:v(()=>[c(y(a.$t(`@F13B4:重试`)),1)]),_:1})):l(`v-if`,!0),i.status===`failed`?(h(),n(m,{key:1,onClick:a.onCopyCommand},{default:v(()=>[c(y(a.$t(`@F13B4:复制升级命令`)),1)]),_:1})):l(`v-if`,!0),i.status===`success`?(h(),n(m,{key:2,type:`primary`,onClick:a.onRestart},{default:v(()=>[c(y(a.$t(`@F13B4:立即重启并刷新`)),1)]),_:1})):l(`v-if`,!0),i.status===`success`?(h(),n(m,{key:3,onClick:a.onLater},{default:v(()=>[c(y(a.$t(`@F13B4:稍后手动重启`)),1)]),_:1})):l(`v-if`,!0),i.status===`running`?(h(),n(m,{key:4,disabled:``},{default:v(()=>[c(y(a.$t(`@F13B4:升级中`))+`... `,1)]),_:1})):l(`v-if`,!0)]),default:v(()=>[r(`div`,{class:s([`upgrade-status`,`is-${i.status}`])},[i.status===`running`?(h(),n(p,{key:0,class:`is-loading`},{default:v(()=>[u(a.Loading)]),_:1})):i.status===`success`?(h(),n(p,{key:1,color:`var(--color-success)`},{default:v(()=>[u(a.CircleCheck)]),_:1})):(h(),n(p,{key:2,color:`var(--color-danger)`},{default:v(()=>[u(a.CircleClose)]),_:1})),i.status===`running`?(h(),x(`span`,I,y(a.$t(`@F13B4:升级中`)),1)):i.status===`success`?(h(),x(`span`,L,y(a.$t(`@F13B4:升级完成`)),1)):(h(),x(`span`,R,y(a.$t(`@F13B4:升级失败`)),1))],2),i.status===`success`?(h(),x(`p`,z,[c(y(a.$t(`@F13B4:新版本已全局安装,需要重启服务才能生效`))+` `,1),i.countdown>0?(h(),x(`span`,B,y(a.$t(`@F13B4:{seconds} 秒后自动刷新`,{seconds:i.countdown})),1)):l(`v-if`,!0)])):l(`v-if`,!0),i.status===`failed`?(h(),x(`p`,V,[r(`span`,H,y(a.$t(`@F13B4:手动升级命令`)),1),r(`code`,{class:`upgrade-manual__cmd`},y(a.MANUAL_COMMAND))])):l(`v-if`,!0),r(`pre`,{ref:`logEl`,class:`upgrade-log`},y(i.logs||a.$t(`@F13B4:等待日志输出`)),513)]),_:1},8,[`model-value`,`title`,`show-close`])}var W=k(F,[[`render`,U],[`__scopeId`,`data-v-bc566bba`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/components/UpgradeDialog.vue`]]);t(),w();var G=`https://github.com/xz333221/zen-gitsync/releases`,K=5,q=`app-version-check`,J=36e5,Y=a({__name:`AppVersionBadge`,setup(e,{expose:t}){t();let n=`2.17.36`,r=_(n),i=d(()=>r.value||n),a=_(null),o=_(!1),s=_(``),c=_(`running`),l=_(0),u=null,f=_(!1);function p(){try{let e=sessionStorage.getItem(q);if(!e)return null;let{at:t,data:n}=JSON.parse(e);return Date.now()-t>J?null:n}catch{return null}}function h(e){try{sessionStorage.setItem(q,JSON.stringify({at:Date.now(),data:e}))}catch{}}async function v(e=!1){let t=p();t&&(a.value=t);try{let t=await M();a.value=t,h(t),t.current&&(r.value=t.current),!e&&t.success&&t.hasUpdate&&g({type:`success`,message:O(`@F13B4:发现新版本 {version}`,{version:t.latest??``}),duration:4e3})}catch(t){e||g({type:`warning`,message:O(`@F13B4:检查更新失败 {error}`,{error:t?.message||``})})}}async function y(){if(a.value?.hasUpdate){try{await b.confirm(O(`@F13B4:确定要从 {current} 升级到 {latest} 吗?`,{current:a.value.current,latest:a.value.latest}),O(`@F13B4:升级`),{confirmButtonText:O(`@F13B4:确定升级`),cancelButtonText:O(`@F13B4:取消`),type:`info`})}catch{return}s.value=``,c.value=`running`,o.value=!0,await ee(e=>{if(e.type===`done`){if(c.value=e.code===0?`success`:`failed`,e.code===0){try{sessionStorage.removeItem(q)}catch{}a.value?.latest&&(r.value=a.value.latest),x()}}else e.message&&(s.value+=e.message)})}}function x(){S(),l.value=K,u=setInterval(()=>{--l.value,l.value<=0&&(u&&=(clearInterval(u),null),w())},1e3)}function S(){u&&=(clearInterval(u),null),l.value=0}function C(){S()}async function w(){if(S(),!f.value){f.value=!0;try{let e=await N(),{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];g({type:`warning`,message:n?O(n):O(`@F13B4:重启失败 {error}`,{error:t})}),f.value=!1}}}T(()=>{S()}),m(()=>{v(!0)});let E={buildVersion:n,releasesUrl:G,runtimeVersion:r,displayVersion:i,latestInfo:a,upgradeDialogVisible:o,upgradeLogs:s,upgradeStatus:c,AUTO_REFRESH_SECONDS:K,countdown:l,get countdownTimer(){return u},set countdownTimer(e){u=e},restartInFlight:f,CACHE_KEY:q,CACHE_TTL_MS:J,readCache:p,writeCache:h,checkUpdate:v,handleUpgrade:y,startAutoRefreshCountdown:x,cancelAutoRefreshCountdown:S,handleCancelAutoRefresh:C,handleRestart:w,get $t(){return O},UpgradeDialog:W};return Object.defineProperty(E,"__isScriptSetup",{enumerable:!1,value:!0}),E}});t(),i();var X={class:`app-version-badge`},Z=[`aria-label`],Q=[`aria-label`],$=[`title`,`aria-label`],te={class:`upgrade-btn__label`},ne={class:`upgrade-btn__version`};function re(e,t,n,i,a,o){let s=f;return h(),x(`div`,X,[l(` GitHub 链接 `),u(s,{content:i.$t(`@F13B4:在 GitHub 上查看源码`),placement:`top`,effect:`dark`,"show-after":300},{default:v(()=>[r(`a`,{href:`https://github.com/xz333221/zen-gitsync`,target:`_blank`,rel:`noopener noreferrer`,class:`badge-icon-link`,"aria-label":i.$t(`@F13B4:在 GitHub 上查看源码`)},[...t[1]||=[r(`svg`,{viewBox:`0 0 24 24`,width:`15`,height:`15`,"aria-hidden":`true`,fill:`currentColor`,xmlns:`http://www.w3.org/2000/svg`},[r(`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,Z)]),_:1},8,[`content`]),l(` NPM 链接 `),u(s,{content:i.$t(`@F13B4:在 npm 上查看包`),placement:`top`,effect:`dark`,"show-after":300},{default:v(()=>[r(`a`,{href:`https://www.npmjs.com/package/zen-gitsync`,target:`_blank`,rel:`noopener noreferrer`,class:`badge-icon-link badge-icon-link--npm`,"aria-label":i.$t(`@F13B4:在 npm 上查看包`)},[...t[2]||=[r(`svg`,{viewBox:`0 0 24 24`,width:`15`,height:`15`,"aria-hidden":`true`,fill:`currentColor`,xmlns:`http://www.w3.org/2000/svg`},[r(`path`,{d:`M2 2v20h20V2H2zm17.167 17.167H12.5v-10h-3.333v10H4.833V4.833h14.334v14.334z`})],-1)]],8,Q)]),_:1},8,[`content`]),l(` 版本号 `),u(s,{content:i.$t(`@F13B4:查看更新`),placement:`top`,effect:`dark`,"show-after":300},{default:v(()=>[r(`a`,{href:i.releasesUrl,target:`_blank`,rel:`noopener noreferrer`,class:`version-link`},`v`+y(i.displayVersion),1)]),_:1},8,[`content`]),i.latestInfo?.hasUpdate?(h(),x(`button`,{key:0,type:`button`,class:`upgrade-btn`,title:i.$t(`@F13B4:发现新版本 {version},点击升级`,{version:i.latestInfo.latest??``}),"aria-label":i.$t(`@F13B4:发现新版本 {version},点击升级`,{version:i.latestInfo.latest??``}),onClick:i.handleUpgrade},[t[3]||=r(`span`,{class:`upgrade-btn__dot`,"aria-hidden":`true`},null,-1),r(`span`,te,y(i.$t(`@F13B4:升级`)),1),r(`span`,ne,`v`+y(i.latestInfo.latest),1)],8,$)):l(`v-if`,!0),u(i.UpgradeDialog,{modelValue:i.upgradeDialogVisible,"onUpdate:modelValue":t[0]||=e=>i.upgradeDialogVisible=e,logs:i.upgradeLogs,status:i.upgradeStatus,countdown:i.countdown,onRetry:i.handleUpgrade,onRestart:i.handleRestart,onCancel:i.handleCancelAutoRefresh},null,8,[`modelValue`,`logs`,`status`,`countdown`])])}var ie=k(Y,[[`render`,re],[`__scopeId`,`data-v-7e0300ec`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/components/AppVersionBadge.vue`]]);export{ie as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./rolldown-runtime-C0FnF6B9.js";import{$n as e,Bn as t,Dn as n,En as r,F as i,Fr as a,G as o,Ht as s,I as c,In as l,J as u,Jr as d,K as f,Nt as p,On as m,Pn as h,Tn as g,U as _,Zn as v,br as y,cr as b,dn as x,ei as S,kn as C,pr as w,r as T,tt as E,xn as D,yn as O,zt as k}from"./element-plus-Buzx8xRf.js";import{n as A,t as j}from"./_plugin-vue_export-helper-
|
|
1
|
+
import"./rolldown-runtime-C0FnF6B9.js";import{$n as e,Bn as t,Dn as n,En as r,F as i,Fr as a,G as o,Ht as s,I as c,In as l,J as u,Jr as d,K as f,Nt as p,On as m,Pn as h,Tn as g,U as _,Zn as v,br as y,cr as b,dn as x,ei as S,kn as C,pr as w,r as T,tt as E,xn as D,yn as O,zt as k}from"./element-plus-Buzx8xRf.js";import{n as A,t as j}from"./_plugin-vue_export-helper-VuE2vqnn.js";import{t as M}from"./SvgIcon-ub85vovN.js";import{t as N}from"./IconButton-Cgc5v9vb.js";import{r as P}from"./gitStore-BP6TATf7.js";import{t as F}from"./CommonDialog-BTeIpgGT.js";t(),w();var I=l({__name:`BranchSelector`,emits:[`branchChanged`],setup(e,{expose:t,emit:n}){t();let r=P(),i=n,a=y(!1),o=y(``),c=g(()=>{let e=o.value.trim().toLowerCase();return e?r.allBranches.filter(t=>t.toLowerCase().includes(e)):r.allBranches});async function l(e){if(e===r.currentBranch){a.value=!1;return}a.value=!1,await r.changeBranch(e)&&(i(`branchChanged`),r.refreshLog())}let u=y(!1),d=y(``),f=y(``);function m(){a.value=!1,f.value=r.currentBranch,u.value=!0}async function h(){await r.createBranch(d.value,f.value)&&(u.value=!1,d.value=``,i(`branchChanged`))}let _=y(!1);async function v(){if(!_.value){_.value=!0;try{await Promise.all([r.getCurrentBranch(!0),r.getBranchStatus(!0),r.getAllBranches()]),i(`branchChanged`),r.refreshLog()}finally{_.value=!1}}}let b={gitStore:r,emit:i,branchPopoverVisible:a,branchFilter:o,filteredBranches:c,selectBranch:l,createBranchDialogVisible:u,newBranchName:d,selectedBaseBranch:f,openCreateBranchDialog:m,createNewBranch:h,isRefreshingBranch:_,refreshCurrentBranch:v,get $t(){return A},get Plus(){return k},get Menu(){return p},get Check(){return E},get Refresh(){return s},CommonDialog:F,IconButton:N,SvgIcon:M};return Object.defineProperty(b,"__isScriptSetup",{enumerable:!1,value:!0}),b}});t(),a(),x();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(t,a,s,l,p,g){let y=u,x=_,w=T,E=f,k=i,A=c,j=o;return l.gitStore.currentBranch?(v(),C(`div`,L,[r(`div`,R,[m(` VSCode 风格分支按钮 + 弹出列表 `),h(w,{visible:l.branchPopoverVisible,"onUpdate:visible":a[1]||=e=>l.branchPopoverVisible=e,placement:`top-start`,width:260,trigger:`click`,"popper-class":`branch-popover`,"show-arrow":!1,onShow:a[2]||=e=>l.branchFilter=``},{reference:b(()=>[r(`button`,z,[h(l.SvgIcon,{"icon-class":`git-branch`,"class-name":`branch-btn-icon`}),r(`span`,B,S(l.gitStore.currentBranch),1),r(`span`,V,[h(y,null,{default:b(()=>[...a[7]||=[r(`svg`,{viewBox:`0 0 1024 1024`,xmlns:`http://www.w3.org/2000/svg`},[r(`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:b(()=>[r(`div`,H,[m(` 搜索框 `),r(`div`,U,[h(x,{modelValue:l.branchFilter,"onUpdate:modelValue":a[0]||=e=>l.branchFilter=e,placeholder:l.$t(`@F13B4:搜索或签出分支`),size:`small`,clearable:``,autofocus:``},null,8,[`modelValue`,`placeholder`])]),m(` 分支列表 `),r(`div`,W,[(v(!0),C(D,null,e(l.filteredBranches,e=>(v(),C(`div`,{key:e,class:d([`branch-item`,{"is-active":e===l.gitStore.currentBranch}]),onClick:t=>l.selectBranch(e)},[e===l.gitStore.currentBranch?(v(),n(y,{key:0,class:`branch-item-check`},{default:b(()=>[h(l.Check)]),_:1})):(v(),C(`span`,K)),h(l.SvgIcon,{"icon-class":`git-branch`,"class-name":`branch-item-icon`}),r(`span`,q,S(e),1)],10,G))),128)),l.filteredBranches.length===0?(v(),C(`div`,J,S(l.$t(`@F13B4:没有匹配的分支`)),1)):m(`v-if`,!0)]),m(` 底部:创建新分支 `),r(`div`,Y,[r(`button`,{class:`branch-create-btn`,onClick:l.openCreateBranchDialog},[h(y,null,{default:b(()=>[h(l.Plus)]),_:1}),r(`span`,null,S(l.$t(`@F13B4:创建新分支`)),1)])])])]),_:1},8,[`visible`]),m(` 刷新按钮 `),h(l.IconButton,{tooltip:l.$t(`@CMDCON:刷新`),onClick:l.refreshCurrentBranch},{default:b(()=>[h(y,{class:d({"is-loading":l.isRefreshingBranch})},{default:b(()=>[h(l.Refresh)]),_:1},8,[`class`])]),_:1},8,[`tooltip`])]),m(` 创建分支对话框 `),h(l.CommonDialog,{modelValue:l.createBranchDialogVisible,"onUpdate:modelValue":a[6]||=e=>l.createBranchDialogVisible=e,title:l.$t(`@F13B4:创建新分支`),size:`small`,"destroy-on-close":!0,"append-to-body":!0,"custom-class":`create-branch-dialog`},{footer:b(()=>[r(`div`,$,[r(`div`,ee,[r(`button`,{type:`button`,class:`dialog-cancel-btn`,onClick:a[5]||=e=>l.createBranchDialogVisible=!1},S(l.$t(`@F13B4:取消`)),1),r(`button`,{type:`button`,class:`dialog-confirm-btn`,onClick:l.createNewBranch,disabled:l.gitStore.isCreatingBranch},[l.gitStore.isCreatingBranch?(v(),n(y,{key:1,class:`is-loading`},{default:b(()=>[...a[8]||=[r(`svg`,{viewBox:`0 0 1024 1024`,xmlns:`http://www.w3.org/2000/svg`},[r(`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})):(v(),n(y,{key:0},{default:b(()=>[h(l.Check)]),_:1})),r(`span`,null,S(l.$t(`@F13B4:创建`)),1)],8,te)])])]),default:b(()=>[r(`div`,X,[h(j,{model:{newBranchName:l.newBranchName,selectedBaseBranch:l.selectedBaseBranch},"label-position":`top`},{default:b(()=>[h(E,null,{label:b(()=>[r(`div`,Z,[h(y,{class:`label-icon`},{default:b(()=>[h(l.Plus)]),_:1}),r(`span`,null,S(l.$t(`@F13B4:新分支名称`)),1)])]),default:b(()=>[h(x,{modelValue:l.newBranchName,"onUpdate:modelValue":a[3]||=e=>l.newBranchName=e,placeholder:l.$t(`@F13B4:请输入新分支名称`),class:`modern-input`,size:`large`,onKeyup:O(l.createNewBranch,[`enter`])},null,8,[`modelValue`,`placeholder`])]),_:1}),h(E,null,{label:b(()=>[r(`div`,Q,[h(y,{class:`label-icon`},{default:b(()=>[h(l.Menu)]),_:1}),r(`span`,null,S(l.$t(`@F13B4:基于分支`)),1)])]),default:b(()=>[h(A,{modelValue:l.selectedBaseBranch,"onUpdate:modelValue":a[4]||=e=>l.selectedBaseBranch=e,placeholder:l.$t(`@F13B4:选择基础分支`),class:`modern-select`,size:`large`,style:{width:`100%`}},{default:b(()=>[(v(!0),C(D,null,e(l.gitStore.allBranches,e=>(v(),n(k,{key:e,label:e,value:e},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`,`placeholder`])]),_:1})]),_:1},8,[`model`])])]),_:1},8,[`modelValue`,`title`])])):m(`v-if`,!0)}var re=j(I,[[`render`,ne],[`__scopeId`,`data-v-9548a76f`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/components/BranchSelector.vue`]]);export{re as default};
|