zen-gitsync 2.13.19 → 2.13.21

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 (43) hide show
  1. package/package.json +11 -6
  2. package/scripts/run-tests.cjs +56 -0
  3. package/src/gitCommit.js +0 -57
  4. package/src/ui/public/assets/{AppVersionBadge-Cxuony4u.js → AppVersionBadge-D9w7Usgz.js} +2 -2
  5. package/src/ui/public/assets/{BranchSelector-BZim6i5G.js → BranchSelector-BJpA20eU.js} +1 -1
  6. package/src/ui/public/assets/CommandConsole-60KxfUE3.css +1 -0
  7. package/src/ui/public/assets/{CommandConsole-D4tnVvzQ.js → CommandConsole-DUyDJSaq.js} +4 -4
  8. package/src/ui/public/assets/CommitForm-BCWCchcJ.js +6 -0
  9. package/src/ui/public/assets/{CommitForm-Cul_GlXI.css → CommitForm-CCBME4F0.css} +1 -1
  10. package/src/ui/public/assets/{CustomCommandManager-DvKPSaQP.js → CustomCommandManager-DRzAgnp3.js} +1 -1
  11. package/src/ui/public/assets/{EditorView-B0y0You_.js → EditorView-DuB3Btcp.js} +0 -0
  12. package/src/ui/public/assets/{FileDiffViewer-DF_7wLdm.js → FileDiffViewer-DldATw5k.js} +3 -3
  13. package/src/ui/public/assets/{FlowExecutionViewer-BpqYAHXA.js → FlowExecutionViewer-BNuIB5Bi.js} +1 -1
  14. package/src/ui/public/assets/FlowOrchestrationWorkspace-BcA7LT02.js +21 -0
  15. package/src/ui/public/assets/GitStatus-BFpSu8gV.js +6 -0
  16. package/src/ui/public/assets/{GitStatus-xdzfREd4.css → GitStatus-CGnFB5Iq.css} +1 -1
  17. package/src/ui/public/assets/{ImagePreview-BEYG8RMC.js → ImagePreview-C8eIs5yL.js} +1 -1
  18. package/src/ui/public/assets/{LogList-xw4BK-Go.js → LogList-C4mS0mZ4.js} +1 -1
  19. package/src/ui/public/assets/{ProjectStartupButton-8dj8XzM5.js → ProjectStartupButton-BBRjQvH3.js} +1 -1
  20. package/src/ui/public/assets/{RemoteRepoCard-DU4rD3Ek.js → RemoteRepoCard-OUVJTKSC.js} +1 -1
  21. package/src/ui/public/assets/ResetToRemoteButton-Bpqx8Rhc.js +1 -0
  22. package/src/ui/public/assets/{SourceMapView-Dtqqdhnw.js → SourceMapView-CDETiU3C.js} +1 -1
  23. package/src/ui/public/assets/{TemplateManager-CHFxc36Y.js → TemplateManager-idRwh__b.js} +1 -1
  24. package/src/ui/public/assets/{UserInputNode-CREMJaXU.js → UserInputNode-pnY8iicS.js} +1 -1
  25. package/src/ui/public/assets/WorkbenchView-B83HdnYr.js +12 -0
  26. package/src/ui/public/assets/WorkbenchView-DslIMLgz.css +1 -0
  27. package/src/ui/public/assets/{_plugin-vue_export-helper-B9V6d9og.js → _plugin-vue_export-helper-vLPduyLG.js} +2 -2
  28. package/src/ui/public/assets/index-Bi1D0fFa.js +7 -0
  29. package/src/ui/public/assets/index-DYjISu_4.css +1 -0
  30. package/src/ui/public/index.html +3 -3
  31. package/src/ui/server/routes/config.js +6 -5
  32. package/src/ui/server/routes/workbench.js +54 -6
  33. package/src/ui/server/utils/logger.js +77 -0
  34. package/src/ui/server/utils/logger.test.js +118 -0
  35. package/src/ui/public/assets/CommandConsole-C8gqasqx.css +0 -1
  36. package/src/ui/public/assets/CommitForm-DS_QT-f0.js +0 -6
  37. package/src/ui/public/assets/FlowOrchestrationWorkspace-BhFVwJIo.js +0 -21
  38. package/src/ui/public/assets/GitStatus-a1S3dLwU.js +0 -6
  39. package/src/ui/public/assets/ResetToRemoteButton-DSXFl5RR.js +0 -1
  40. package/src/ui/public/assets/WorkbenchView-CPEmAAf1.css +0 -1
  41. package/src/ui/public/assets/WorkbenchView-r3hIaLwR.js +0 -12
  42. package/src/ui/public/assets/index-B3sS0q3V.css +0 -1
  43. package/src/ui/public/assets/index-DkrC0Lp8.js +0 -7
@@ -17,6 +17,7 @@ import path from 'path';
17
17
  import os from 'os';
18
18
  import fs from 'fs/promises';
19
19
  import open from 'open';
20
+ import logger from '../utils/logger.js';
20
21
 
21
22
  // 跳过的产物/资源/lock 文件(用 stat 一行带过,不打 patch)
22
23
  const SKIP_FILE_PATTERNS = [
@@ -1136,10 +1137,9 @@ ${diffText || '(no staged content, please infer from the file list)'}`
1136
1137
 
1137
1138
  const prompt = userLocale.startsWith('en') ? promptEn : promptZh
1138
1139
 
1139
- console.log('[generate-commit] locale:', userLocale, '| prompt length:', prompt.length)
1140
- console.log('[generate-commit] ===== PROMPT START =====')
1141
- console.log(prompt)
1142
- console.log('[generate-commit] ===== PROMPT END =====')
1140
+ // AI prompt 默认不打印,只有 DEBUG=1 / DEBUG=logger 时才落地(防 Token 泄露)
1141
+ logger.debug('[generate-commit] locale:', userLocale, '| prompt length:', prompt.length)
1142
+ logger.debug('[generate-commit] prompt:\n' + prompt)
1143
1143
  const { default: fetch } = await import('node-fetch').catch(() => ({ default: globalThis.fetch }))
1144
1144
  const url = `${defaultModel.baseURL.replace(/\/$/, '')}/chat/completions`
1145
1145
  const headers = { 'Content-Type': 'application/json' }
@@ -1165,7 +1165,8 @@ ${diffText || '(no staged content, please infer from the file list)'}`
1165
1165
  return res.json({ success: false, error: msg })
1166
1166
  }
1167
1167
  const content = data?.choices?.[0]?.message?.content || ''
1168
- console.log('[generate-commit] raw content length:', content.length, JSON.stringify(content).slice(0, 600))
1168
+ // 响应内容只走 debug(默认关闭),前 600 字截断防 token 泄露
1169
+ logger.debug('[generate-commit] raw content length:', content.length, JSON.stringify(content).slice(0, 600))
1169
1170
 
1170
1171
  const codeBlockMatch = content.match(/```(?:json)?\s*(\{[^`]*?\})\s*```/)
1171
1172
  const jsonMatch = codeBlockMatch
@@ -82,6 +82,13 @@ const MAX_ATTACHMENTS_PER_SUBTASK = 9;
82
82
  // 中英两份都内置——用户保存到 ~/.zen-gitsync/ai-subtask-instruction.json 后覆盖。
83
83
  const DEFAULT_SUBTASK_INSTRUCTION_ZH = `你是一名任务拆分助手。
84
84
 
85
+ 【绝对禁止】
86
+ - 不要进入任何"plan 模式"、"plan 阶段"或"先写 plan 再执行"。
87
+ - 不要输出"我要进入 plan / 准备 / 探索 / 调研"之类的元叙述。
88
+ - 不要写"Plan 文件已写入 xxx"或"等用户批准后开始"这种"声明意图"的话。
89
+ - 你只做一件事:把用户给的任务拆成可独立执行的子任务清单,直接输出 JSON。中间任何"我要做什么"的描述都属于错误输出。
90
+ - 你的输出会被另一个程序读取,该程序只看最终 JSON,所有非 JSON 文字会被丢弃——所以不要把"执行步骤"写进 analysis 段,只写在 JSON 的 desc 字段里。
91
+
85
92
  【思考过程】
86
93
  在给出 JSON 之前,请先在内部仔细思考(如果模型支持,把思考放在 reasoning 中;否则可以先输出一段较长的仔细分析,再输出 JSON)。分析要覆盖足够维度,不要简短一两句话就过:
87
94
  - 任务的真实目标是什么?用户提供的描述/图片/上下文里有哪些关键信息和隐藏诉求?
@@ -111,6 +118,13 @@ JSON 要用 \`\`\`json ... \`\`\` 代码块包裹,前面可以有分析文字
111
118
 
112
119
  const DEFAULT_SUBTASK_INSTRUCTION_EN = `You are a task breakdown assistant.
113
120
 
121
+ [ABSOLUTE PROHIBITIONS]
122
+ - Do NOT enter any "plan mode" / "planning phase" / "I'll write a plan first, then execute".
123
+ - Do NOT output meta-narration like "I'm entering plan / preparing / exploring / researching".
124
+ - Do NOT write "Plan file written to xxx" or "waiting for user approval" style intent-declaration text.
125
+ - You only do one thing: split the user's task into an independently executable subtask list and output JSON directly. Any "what I'm going to do" description in the middle is an error.
126
+ - Your output is consumed by another program that only reads the final JSON. All non-JSON text is discarded — so put execution steps in the desc field of JSON, not in the analysis section.
127
+
114
128
  [Thinking process]
115
129
  Before producing JSON, think carefully (put your thoughts in reasoning if the model supports it; otherwise output a longer careful analysis first, then JSON). Cover enough dimensions — don't settle for a one-or-two-sentence summary:
116
130
  - What is the real goal? What key info and hidden needs are in the description / images / context?
@@ -1018,8 +1032,9 @@ function launchClaudeInNewWindow(cwd, promptText, resumeSessionId) {
1018
1032
  args.push('--resume', String(resumeSessionId));
1019
1033
  }
1020
1034
  args.push(
1021
- '-p', promptText,
1022
- '--input-format', 'text',
1035
+ // -p '-' 让 claude CLI 从 stdin 读取 prompt —— 避免 Windows 命令行 32K 长度上限
1036
+ // (spawn argv 会拼成 cmdline 给 CreateProcess,长 prompt 直接 ENAMETOOLONG)
1037
+ '-p', '-',
1023
1038
  '--output-format', 'stream-json',
1024
1039
  '--verbose',
1025
1040
  '--permission-mode', 'bypassPermissions',
@@ -1047,7 +1062,7 @@ function launchClaudeInNewWindow(cwd, promptText, resumeSessionId) {
1047
1062
  spawnedExe = claudeExe;
1048
1063
  child = spawn(claudeExe, args, {
1049
1064
  cwd,
1050
- stdio: ['ignore', 'pipe', 'pipe'],
1065
+ stdio: ['pipe', 'pipe', 'pipe'],
1051
1066
  windowsHide: false,
1052
1067
  env: { ...process.env, LANG: 'zh_CN.UTF-8' }
1053
1068
  });
@@ -1057,7 +1072,7 @@ function launchClaudeInNewWindow(cwd, promptText, resumeSessionId) {
1057
1072
  child = spawn('claude', args, {
1058
1073
  cwd,
1059
1074
  detached: true,
1060
- stdio: ['ignore', 'pipe', 'pipe'],
1075
+ stdio: ['pipe', 'pipe', 'pipe'],
1061
1076
  env: { ...process.env, LANG: 'zh_CN.UTF-8' }
1062
1077
  });
1063
1078
  }
@@ -1065,6 +1080,19 @@ function launchClaudeInNewWindow(cwd, promptText, resumeSessionId) {
1065
1080
  child.on('spawn', () => {
1066
1081
  // unref 让 claude 独立于父进程事件循环;返回 child 引用让调用方继续读 stdout。
1067
1082
  child.unref();
1083
+ // 长 prompt 通过 stdin 喂入(避开 Windows CreateProcess 32K 命令行上限)。
1084
+ // 必须在 spawn 事件回调里 write,而不是 resolve 前同步 write——因为 spawn
1085
+ // 返回时 child.stdin 句柄可能尚未绑定到真正的 pipe fd。
1086
+ // write 完成后必须 end(),否则 claude CLI 会一直阻塞在读 stdin 上 → hang。
1087
+ try {
1088
+ child.stdin.write(promptText, () => {
1089
+ try { child.stdin.end() } catch { /* 子进程已关闭,忽略 */ }
1090
+ });
1091
+ } catch (err) {
1092
+ // stdin 写入失败不要让 spawn 整体 reject —— 让 child 自然以错误状态收尾,
1093
+ // 后面的 stdout/stderr 监听会捕获到 LLM 端反馈。
1094
+ console.warn('[workbench] stdin write failed:', err && err.message || err);
1095
+ }
1068
1096
  resolve({ pid: child.pid, child });
1069
1097
  });
1070
1098
  });
@@ -1306,9 +1334,12 @@ ${prompt}`
1306
1334
  if (priorOutputs) priorOutputs.push({ title: sub.title, output: job.output || '' })
1307
1335
  }
1308
1336
  } catch (err) {
1309
- job.error = err && err.message ? err.message : String(err);
1337
+ const errMsg = err && err.message ? err.message : String(err);
1338
+ job.error = errMsg;
1310
1339
  job.status = 'error';
1311
1340
  sub.status = 'error';
1341
+ sub.error = errMsg;
1342
+ sub.errorAt = nowIso();
1312
1343
  } finally {
1313
1344
  // 移除 child 引用——避免后续被 SSE 序列化到前端
1314
1345
  delete job.child
@@ -1335,7 +1366,19 @@ async function persistTaskAfterRun(task) {
1335
1366
  const data = await readJson(TASKS_FILE, { tasks: [] });
1336
1367
  const t = data.tasks.find(x => x.id === task.id);
1337
1368
  if (t) {
1338
- t.subtasks = task.subtasks;
1369
+ // 仅同步 status 之外的 error/errorAt 字段,避免覆盖用户编辑过的 title/desc 等。
1370
+ // 历史 subtasks 持久化只写 status → 失败信息丢,hover "执行出错" 标签看不到原因。
1371
+ const newMap = new Map(task.subtasks.map(s => [s.id, s]));
1372
+ t.subtasks = (t.subtasks || []).map(old => {
1373
+ const fresh = newMap.get(old.id);
1374
+ if (!fresh) return old;
1375
+ return {
1376
+ ...old,
1377
+ status: fresh.status ?? old.status,
1378
+ error: fresh.error ?? old.error,
1379
+ errorAt: fresh.errorAt ?? old.errorAt,
1380
+ };
1381
+ });
1339
1382
  t.updatedAt = nowIso();
1340
1383
  await writeJson(TASKS_FILE, data);
1341
1384
  publish('task:update', t);
@@ -2257,6 +2300,9 @@ ${desc ? `描述:${desc}` : '描述:(无)'}${attachmentBlock}${templateB
2257
2300
  desc: s.desc || '',
2258
2301
  status: s.status || 'todo',
2259
2302
  promptOverride: s.promptOverride || '',
2303
+ // 保留失败信息:编辑已 error 的 sub 时不能丢 context,否则 hover popover 看不到原因
2304
+ error: typeof s.error === 'string' ? s.error : undefined,
2305
+ errorAt: typeof s.errorAt === 'string' ? s.errorAt : undefined,
2260
2306
  // 保留附件元数据(仅保留基础字段,丢弃客户端临时字段)
2261
2307
  attachments: Array.isArray(s.attachments) ? s.attachments.map(a => ({
2262
2308
  id: a.id,
@@ -2288,6 +2334,8 @@ ${desc ? `描述:${desc}` : '描述:(无)'}${attachmentBlock}${templateB
2288
2334
  desc: s.desc || '',
2289
2335
  status: s.status || 'todo',
2290
2336
  promptOverride: s.promptOverride || '',
2337
+ error: typeof s.error === 'string' ? s.error : undefined,
2338
+ errorAt: typeof s.errorAt === 'string' ? s.errorAt : undefined,
2291
2339
  attachments: Array.isArray(s.attachments) ? s.attachments : []
2292
2340
  })) : [],
2293
2341
  status: 'todo',
@@ -0,0 +1,77 @@
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
+ * 轻量 logger,带敏感字段自动打码,防止 AI prompt / API key / token 落地泄露。
17
+ *
18
+ * 用法:
19
+ * import logger from '../utils/logger.js'
20
+ * logger.info('hello', { user: 'a', apiKey: 'sk-xxx' })
21
+ * // -> hello { user: 'a', apiKey: '[REDACTED]' }
22
+ * logger.debug('prompt', bigPrompt) // 仅当 DEBUG=1 / DEBUG=logger 时打印
23
+ *
24
+ * 设计目标:
25
+ * - 零依赖,直接接管全后端 console.{log,info,warn,error}
26
+ * - 不改格式,console.* 调用 1:1 替换为 logger.*
27
+ * - 自动递归 redact 已知敏感字段(apiKey / token / prompt / Authorization 等)
28
+ * - debug 级别默认关闭,需 DEBUG 环境变量开启,避免误把整段 prompt 写到磁盘
29
+ */
30
+
31
+ // 命中这些 key(大小写不敏感)→ 值打印成 [REDACTED]
32
+ const SENSITIVE_KEYS = new Set([
33
+ 'apikey', 'api_key', 'token', 'authorization', 'prompt', 'password',
34
+ 'secret', 'access_token', 'refreshtoken', 'sessiontoken',
35
+ ])
36
+
37
+ const REDACTED = '[REDACTED]'
38
+ const MAX_STRING = 2000 // 单个字符串超过这个长度截断,防止 prompt 整段冲爆日志
39
+
40
+ function redact(value) {
41
+ if (value == null) return value
42
+ if (typeof value === 'string') {
43
+ return value.length > MAX_STRING ? value.slice(0, MAX_STRING) + '...[truncated]' : value
44
+ }
45
+ if (Array.isArray(value)) return value.map(redact)
46
+ if (typeof value === 'object') {
47
+ const out = {}
48
+ for (const [k, v] of Object.entries(value)) {
49
+ out[k] = SENSITIVE_KEYS.has(k.toLowerCase()) ? REDACTED : redact(v)
50
+ }
51
+ return out
52
+ }
53
+ return value
54
+ }
55
+
56
+ function fmt(args) {
57
+ return args.map(a => (typeof a === 'object' && a !== null ? redact(a) : a))
58
+ }
59
+
60
+ function debugEnabled() {
61
+ const flag = (process.env.DEBUG || '').toLowerCase()
62
+ if (!flag) return false
63
+ return flag === '1' || flag === 'true' || flag === '*' || flag.includes('logger')
64
+ }
65
+
66
+ const logger = {
67
+ /** debug 级,默认关闭,需 DEBUG=1 或 DEBUG=logger */
68
+ debug: (...args) => { if (debugEnabled()) console.log('[debug]', ...fmt(args)) },
69
+ info: (...args) => console.log(...fmt(args)),
70
+ warn: (...args) => console.warn(...fmt(args)),
71
+ error: (...args) => console.error(...fmt(args)),
72
+ redact,
73
+ SENSITIVE_KEYS,
74
+ }
75
+
76
+ export default logger
77
+ export { redact, SENSITIVE_KEYS }
@@ -0,0 +1,118 @@
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
+ import { test } from 'node:test'
16
+ import assert from 'node:assert/strict'
17
+ import logger, { redact, SENSITIVE_KEYS } from './logger.js'
18
+
19
+ test('redact: 命中已知敏感 key → 值变 [REDACTED]', () => {
20
+ assert.equal(redact({ apiKey: 'sk-12345' }).apiKey, '[REDACTED]')
21
+ assert.equal(redact({ token: 'tok-abc' }).token, '[REDACTED]')
22
+ assert.equal(redact({ Authorization: 'Bearer xyz' }).Authorization, '[REDACTED]')
23
+ assert.equal(redact({ password: 'pw' }).password, '[REDACTED]')
24
+ assert.equal(redact({ secret: 's' }).secret, '[REDACTED]')
25
+ })
26
+
27
+ test('redact: 大小写不敏感', () => {
28
+ assert.equal(redact({ APIKEY: 'x' }).APIKEY, '[REDACTED]')
29
+ assert.equal(redact({ Token: 'x' }).Token, '[REDACTED]')
30
+ assert.equal(redact({ AUTHORIZATION: 'x' }).AUTHORIZATION, '[REDACTED]')
31
+ })
32
+
33
+ test('redact: 安全字段保留', () => {
34
+ const out = redact({ user: 'alice', count: 3, file: 'a.ts' })
35
+ assert.equal(out.user, 'alice')
36
+ assert.equal(out.count, 3)
37
+ assert.equal(out.file, 'a.ts')
38
+ })
39
+
40
+ test('redact: 嵌套对象递归打码', () => {
41
+ const out = redact({
42
+ request: { prompt: 'long prompt', model: 'gpt-4' },
43
+ safe: 1,
44
+ })
45
+ assert.equal(out.request.prompt, '[REDACTED]')
46
+ assert.equal(out.request.model, 'gpt-4')
47
+ assert.equal(out.safe, 1)
48
+ })
49
+
50
+ test('redact: 数组递归', () => {
51
+ const out = redact([{ token: 'a' }, { token: 'b' }])
52
+ assert.equal(out[0].token, '[REDACTED]')
53
+ assert.equal(out[1].token, '[REDACTED]')
54
+ })
55
+
56
+ test('redact: 长字符串截断 2000 字符(非敏感字段才截断)', () => {
57
+ const big = 'x'.repeat(3000)
58
+ const out = redact({ fileContent: big })
59
+ assert.equal(out.fileContent.length, 2000 + '...[truncated]'.length)
60
+ assert.match(out.fileContent, /\.\.\.\[truncated\]$/)
61
+ })
62
+
63
+ test('redact: 敏感字段长字符串直接整体 redact,不截断(防 token 残留)', () => {
64
+ const big = 'x'.repeat(5000)
65
+ const out = redact({ prompt: big })
66
+ assert.equal(out.prompt, '[REDACTED]')
67
+ })
68
+
69
+ test('redact: null / undefined / 数字 / 布尔 透传', () => {
70
+ assert.equal(redact(null), null)
71
+ assert.equal(redact(undefined), undefined)
72
+ assert.equal(redact(42), 42)
73
+ assert.equal(redact(true), true)
74
+ })
75
+
76
+ test('logger.debug: 默认 DEBUG 未设 → 不打印', () => {
77
+ const orig = process.env.DEBUG
78
+ delete process.env.DEBUG
79
+ const captured = []
80
+ const origLog = console.log
81
+ console.log = (...args) => captured.push(args)
82
+ logger.debug('hidden')
83
+ console.log = origLog
84
+ if (orig != null) process.env.DEBUG = orig
85
+ assert.equal(captured.length, 0, '默认应静默')
86
+ })
87
+
88
+ test('logger.debug: DEBUG=1 → 打印并加 [debug] 前缀', () => {
89
+ const orig = process.env.DEBUG
90
+ process.env.DEBUG = '1'
91
+ const captured = []
92
+ const origLog = console.log
93
+ console.log = (...args) => captured.push(args)
94
+ logger.debug('visible')
95
+ console.log = origLog
96
+ if (orig != null) process.env.DEBUG = orig
97
+ assert.equal(captured.length, 1)
98
+ assert.equal(captured[0][0], '[debug]')
99
+ assert.equal(captured[0][1], 'visible')
100
+ })
101
+
102
+ test('logger.info: 自动 redact 对象中的敏感字段', () => {
103
+ const orig = process.env.DEBUG
104
+ delete process.env.DEBUG
105
+ const captured = []
106
+ const origLog = console.log
107
+ console.log = (...args) => captured.push(args)
108
+ logger.info('with secrets:', { apiKey: 'sk-12345', safe: 'ok' })
109
+ console.log = origLog
110
+ if (orig != null) process.env.DEBUG = orig
111
+ assert.equal(captured[0][1].apiKey, '[REDACTED]')
112
+ assert.equal(captured[0][1].safe, 'ok')
113
+ })
114
+
115
+ test('SENSITIVE_KEYS 导出且非空', () => {
116
+ assert.ok(SENSITIVE_KEYS instanceof Set)
117
+ assert.ok(SENSITIVE_KEYS.size > 0)
118
+ })
@@ -1 +0,0 @@
1
- .command-console[data-v-d0174eec]{background:var(--bg-console);box-shadow:var(--console-shadow);border-radius:10px;flex-direction:column;height:100%;padding:0;transition:all .3s;display:flex;overflow:hidden}.command-console[data-v-d0174eec]:hover{box-shadow:var(--console-shadow-hover);border-color:var(--border-console-hover)}.command-console .console-content[data-v-d0174eec]{flex:1;min-height:0;overflow:hidden}.command-console .termial-session[data-v-d0174eec]{background:var(--bg-console-output);height:100%;overflow:hidden}.command-console .console-content-main[data-v-d0174eec]{flex-direction:column;height:100%;display:flex;overflow:hidden}.command-console .console-content-main .orchestration-flow-panel[data-v-d0174eec],.command-console .console-content-main .orchestration-steps-panel[data-v-d0174eec],.command-console .console-content-main .console-input-row[data-v-d0174eec]{flex-shrink:0}.command-console .console-content-main .console-output[data-v-d0174eec]{flex:1;min-height:80px;max-height:none}.command-console.fullscreen[data-v-d0174eec]{z-index:9999;border-radius:0;flex-direction:column;max-height:100vh;margin:0;display:flex;position:fixed;inset:0}.command-console.fullscreen .console-content[data-v-d0174eec]{flex:1;display:flex;overflow:hidden}.command-console.fullscreen .console-output[data-v-d0174eec]{flex:1;max-height:none;overflow:auto}.console-header[data-v-d0174eec]{background:var(--bg-console-header);justify-content:space-between;align-items:center;padding:6px 12px;display:flex}.console-window-dots[data-v-d0174eec]{flex-shrink:0;align-items:center;gap:6px;margin-right:10px;display:flex}.console-window-dots .dot[data-v-d0174eec]{opacity:.85;border-radius:50%;width:12px;height:12px}.console-window-dots .dot-red[data-v-d0174eec]{background:#ff5f57}.console-window-dots .dot-yellow[data-v-d0174eec]{background:#ffbd2e}.console-window-dots .dot-green[data-v-d0174eec]{background:#28c840}.header-left[data-v-d0174eec]{align-items:center;gap:var(--spacing-base);display:flex}.console-title[data-v-d0174eec]{font-size:var(--font-size-sm);color:var(--text-console-secondary);letter-spacing:.3px;font-weight:500;font-family:var(--font-mono)}.terminal-sessions-panel[data-v-d0174eec]{background:var(--bg-console-output);border-bottom:none;flex-direction:column;height:100%;display:flex}.terminal-sessions-header[data-v-d0174eec]{background:var(--bg-console-cmd);justify-content:space-between;align-items:center;padding:8px 12px;display:flex}.terminal-sessions-title[data-v-d0174eec]{color:var(--text-console-secondary);align-items:baseline;gap:6px;font-weight:600;display:flex}.terminal-sessions-count[data-v-d0174eec]{color:var(--text-console-muted);font-weight:500}.terminal-sessions-actions[data-v-d0174eec]{align-items:center;gap:4px;display:flex}.terminal-sessions-body[data-v-d0174eec]{background:var(--bg-console-output);flex:1;padding:8px 12px 12px;overflow:auto}.terminal-sessions-empty[data-v-d0174eec]{color:var(--text-console-muted);padding:10px 0;font-size:13px}.terminal-sessions-list[data-v-d0174eec]{flex-direction:column;gap:8px;display:flex}.terminal-session-item[data-v-d0174eec]{background:var(--bg-console-subtle);border:1px solid var(--border-console);border-radius:8px;justify-content:space-between;align-items:center;gap:10px;padding:10px 12px;display:flex}.terminal-session-main[data-v-d0174eec]{flex:1;min-width:0}.terminal-session-command[data-v-d0174eec]{font-size:var(--font-size-md);color:var(--text-console);white-space:nowrap;text-overflow:ellipsis;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;overflow:hidden}.terminal-session-meta[data-v-d0174eec]{color:var(--text-console-muted);flex-direction:column;align-items:flex-start;gap:4px;margin-top:6px;font-size:12px;display:flex}.terminal-session-dir[data-v-d0174eec]{text-overflow:ellipsis;align-items:center;gap:4px;width:100%;font-size:12px;display:inline-flex;overflow:hidden}.terminal-session-pid[data-v-d0174eec]{white-space:nowrap;color:#bfdbfee6;vertical-align:middle;background:#3b82f62e;border:1px solid #3b82f64d;border-radius:999px;align-items:center;margin-left:6px;padding:1px 6px;font-size:11px;font-weight:600;line-height:1;display:inline-flex}.terminal-session-actions[data-v-d0174eec]{align-items:center;gap:4px;display:flex}.terminal-sessions-collapsed[data-v-d0174eec]{background:var(--bg-console-cmd);padding:8px 12px}[data-v-d0174eec] .el-splitter-panel{background:var(--bg-console-output)}[data-v-d0174eec] .el-splitter-bar{background:var(--border-console)}.header-actions[data-v-d0174eec]{align-items:center;gap:var(--spacing-md);display:flex}.header-actions[data-v-d0174eec] .icon-button,.header-actions[data-v-d0174eec] .el-button.is-text{color:var(--text-console-muted)}.header-actions[data-v-d0174eec] .icon-button:hover,.header-actions[data-v-d0174eec] .el-button.is-text:hover{color:var(--text-console)}.header-actions[data-v-d0174eec] .icon-button.is-active,.header-actions[data-v-d0174eec] .el-button.is-text.is-active{color:var(--color-primary-light)}.terminal-toggle-btn[data-v-d0174eec]{width:36px;height:36px;padding:var(--spacing-base);border-radius:var(--radius-md);transition:all .3s}.terminal-toggle-btn .el-icon[data-v-d0174eec]{color:var(--text-tertiary);transition:all .3s}.terminal-toggle-btn[data-v-d0174eec]:hover{background-color:#409eff1a}.terminal-toggle-btn:hover .el-icon[data-v-d0174eec]{color:var(--color-primary)}.terminal-toggle-btn.is-active[data-v-d0174eec]{background-color:#409eff26}.terminal-toggle-btn.is-active .el-icon[data-v-d0174eec]{color:var(--color-primary)}.terminal-toggle-btn.is-active[data-v-d0174eec]:hover{background-color:#409eff33}.execution-controls[data-v-d0174eec]{align-items:center;gap:var(--spacing-base);display:flex}.pause-btn[data-v-d0174eec],.stop-btn[data-v-d0174eec]{font-weight:500}.command-manager-btn[data-v-d0174eec]:hover{color:var(--color-success);background:#67c23a1a}.project-startup-btn[data-v-d0174eec]:hover{color:var(--color-primary);background:#409eff1a}.orchestrator-btn[data-v-d0174eec]:hover{color:var(--color-warning);background:#e6a23c1a}.orchestrator-manager-btn[data-v-d0174eec]:hover{color:var(--color-primary);background:#409eff1a}.toggle-console-btn[data-v-d0174eec]{padding:var(--spacing-sm) var(--spacing-base);font-size:var(--font-size-sm);color:var(--text-secondary);transition:all .3s}.toggle-console-btn[data-v-d0174eec]:hover{color:var(--color-primary);background:#409eff1a}.toggle-console-btn .el-icon[data-v-d0174eec]{font-size:var(--font-size-md);transition:transform .3s}.toggle-console-btn .rotate-icon[data-v-d0174eec]{transform:rotate(-90deg)}.console-content-slide-enter-active[data-v-d0174eec],.console-content-slide-leave-active[data-v-d0174eec]{transition:all .3s;overflow:hidden}.console-content-slide-enter-from[data-v-d0174eec],.console-content-slide-leave-to[data-v-d0174eec]{opacity:0;max-height:0}.console-content-slide-enter-to[data-v-d0174eec],.console-content-slide-leave-from[data-v-d0174eec]{opacity:1;max-height:500px}.console-input-row[data-v-d0174eec]{padding:var(--spacing-xs) var(--spacing-sm);background:var(--bg-console-input);border:1px solid var(--border-console-input);align-items:center;gap:8px;transition:all .3s;display:flex}.console-input-row[data-v-d0174eec]:focus-within{border-color:#4ade8066;box-shadow:0 0 0 2px #4ade801f}.prompt[data-v-d0174eec]{font-family:var(--font-mono);font-size:var(--font-size-sm);color:var(--color-success);border-radius:var(--radius-md);text-overflow:ellipsis;white-space:nowrap;cursor:help;max-width:45%;font-weight:500;transition:all .3s;overflow:hidden}.console-input[data-v-d0174eec]{flex:1}.console-input[data-v-d0174eec] .el-input__wrapper{padding:var(--spacing-sm) var(--spacing-base);font-family:var(--font-mono);font-size:var(--font-size-sm);background-color:#0000;border:none;box-shadow:none!important}.console-input[data-v-d0174eec] .el-input__inner{color:var(--text-console)}.console-input[data-v-d0174eec] .el-input__inner::placeholder{color:var(--text-console-faint);font-style:italic}.console-input-row .el-button[data-v-d0174eec]{padding:var(--spacing-base) var(--spacing-xl);border-radius:var(--radius-md);font-weight:500;transition:all .3s}.console-input-row .el-button[data-v-d0174eec]:hover{box-shadow:var(--shadow-md);transform:scale(1.02)}.console-input-row .el-button[data-v-d0174eec]:active{transform:scale(.98)}.console-input-row .el-button[data-v-d0174eec]:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.stdin-input-row[data-v-d0174eec]{align-items:center;gap:var(--spacing-base);padding:var(--spacing-base) var(--spacing-md);margin:var(--spacing-base) 0 0 0;border-radius:var(--radius-md);background:linear-gradient(135deg,#67c23a0d,#67c23a05);border:1px solid #67c23a4d;transition:all .3s;display:flex}.stdin-input-row[data-v-d0174eec]:focus-within{border-color:var(--color-success);background:linear-gradient(135deg,#67c23a14,#67c23a08);box-shadow:0 0 0 2px #67c23a1a}.stdin-icon[data-v-d0174eec]{color:var(--color-success);font-size:var(--font-size-md);flex-shrink:0}.stdin-input[data-v-d0174eec]{flex:1}.stdin-input[data-v-d0174eec] .el-input__wrapper{padding:var(--spacing-sm) var(--spacing-base);font-family:var(--font-mono);font-size:var(--font-size-sm);background-color:#0000;border:none;box-shadow:none!important}.stdin-input[data-v-d0174eec] .el-input__inner{color:var(--text-primary)}.stdin-input[data-v-d0174eec] .el-input__inner::placeholder{color:#67c23a80;font-style:italic}.console-output[data-v-d0174eec]{background:var(--bg-console-output);max-height:280px;overflow:auto}.console-output[data-v-d0174eec]::-webkit-scrollbar{width:8px;height:8px}.console-output[data-v-d0174eec]::-webkit-scrollbar-track{border-radius:var(--radius-base);background:0 0}.console-output[data-v-d0174eec]::-webkit-scrollbar-thumb{background:var(--console-scrollbar);border-radius:var(--radius-base);transition:background .3s}.console-output[data-v-d0174eec]::-webkit-scrollbar-thumb:hover{background:var(--console-scrollbar-hover)}.console-record[data-v-d0174eec]{border-bottom:1px solid var(--border-console-faint);transition:background .2s}.console-record[data-v-d0174eec]:hover{background:var(--bg-console-soft)}.console-record[data-v-d0174eec]:last-child{border-bottom:none}.cmd-header[data-v-d0174eec]{padding:10px var(--spacing-md);justify-content:space-between;align-items:center;gap:var(--spacing-base);background:var(--bg-console-cmd);display:flex}.cmd-actions[data-v-d0174eec]{align-items:center;gap:var(--spacing-sm);display:flex}.stop-btn[data-v-d0174eec]{padding:var(--spacing-sm) var(--spacing-base)}.stop-btn[data-v-d0174eec]:hover{background:#f56c6c1a}.cmd-line[data-v-d0174eec]{font-family:var(--font-mono);font-size:var(--font-size-sm);align-items:center;gap:var(--spacing-base);flex:1;min-width:0;font-weight:500;display:flex}.cmd-prefix[data-v-d0174eec]{color:var(--color-primary);flex-shrink:0;font-weight:600}.cmd-text[data-v-d0174eec]{color:var(--text-console);text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}.cmd-dir[data-v-d0174eec]{color:var(--text-console-muted);font-size:var(--font-size-sm);padding:0 var(--spacing-sm);text-overflow:ellipsis;white-space:nowrap;flex-shrink:0;max-width:420px;font-weight:400;overflow:hidden}.cmd-dir-icon[data-v-d0174eec]{vertical-align:-2px;margin-right:2px;font-size:14px}.running-icon[data-v-d0174eec]{color:var(--color-primary);margin-left:var(--spacing-sm);flex-shrink:0}.ts[data-v-d0174eec]{color:var(--text-console-very-faint);font-size:var(--font-size-sm);padding:0 var(--spacing-sm);flex-shrink:0;font-weight:400}.toggle-output-btn[data-v-d0174eec]{padding:var(--spacing-sm);min-width:auto;color:var(--text-secondary);flex-shrink:0;transition:all .3s}.toggle-output-btn[data-v-d0174eec]:hover{color:var(--color-primary);background:#409eff1a}.toggle-output-btn .el-icon[data-v-d0174eec]{transition:transform .3s}.toggle-output-btn .rotate-icon[data-v-d0174eec]{transform:rotate(-90deg)}.output-content[data-v-d0174eec]{padding:0 var(--spacing-md) 10px var(--spacing-md)}.output-slide-enter-active[data-v-d0174eec],.output-slide-leave-active[data-v-d0174eec]{transition:all .3s;overflow:hidden}.output-slide-enter-from[data-v-d0174eec],.output-slide-leave-to[data-v-d0174eec]{opacity:0;max-height:0}.output-slide-enter-to[data-v-d0174eec],.output-slide-leave-from[data-v-d0174eec]{opacity:1;max-height:500px}pre.stdout[data-v-d0174eec],pre.stderr[data-v-d0174eec]{padding:var(--spacing-base);font-family:var(--font-mono);font-size:var(--font-size-sm);white-space:pre-wrap;word-break:break-word;border-radius:var(--radius-base);color:var(--text-console);background:0 0;margin:0;line-height:1.5}pre.stderr[data-v-d0174eec]{background:#f56c6c14}.icon-btn[data-v-d0174eec]{width:18px;height:18px;color:var(--text-secondary)}.toggle-console-btn:hover .icon-btn[data-v-d0174eec]{color:var(--color-primary)}.orchestration-flow-panel[data-v-d0174eec]{margin-bottom:var(--spacing-md);background:var(--bg-panel);border:1px solid var(--border-card);border-radius:var(--radius-lg);position:relative}.flow-panel-header[data-v-d0174eec]{justify-content:space-between;align-items:center;gap:var(--spacing-md);padding:8px 10px;display:flex}.flow-panel-title[data-v-d0174eec]{min-width:0;font-size:var(--font-size-lg);color:var(--text-secondary);text-overflow:ellipsis;white-space:nowrap;flex:1;font-weight:600;overflow:hidden}.flow-panel-close-btn[data-v-d0174eec]{flex-shrink:0}.terminal-waiting-panel[data-v-d0174eec]{margin:var(--spacing-sm) var(--spacing-md);padding:var(--spacing-md) var(--spacing-lg);border:2px solid var(--color-primary);border-radius:var(--radius-md);align-items:center;gap:var(--spacing-lg);background:linear-gradient(135deg,#409eff14 0%,#409eff05 100%);animation:.3s ease-out slideDown-d0174eec;display:flex}.waiting-content[data-v-d0174eec]{align-items:center;gap:var(--spacing-md);flex:1;display:flex}.waiting-icon[data-v-d0174eec]{color:var(--color-primary);flex-shrink:0;font-size:24px}.waiting-text[data-v-d0174eec]{flex-direction:column;flex:1;gap:4px;display:flex}.waiting-title[data-v-d0174eec]{font-size:var(--font-size-base);color:var(--color-primary);font-weight:600;line-height:1.3}.waiting-desc[data-v-d0174eec]{font-size:var(--font-size-sm);color:var(--text-secondary);line-height:1.4}.waiting-desc strong[data-v-d0174eec]{color:var(--text-primary);font-weight:600}.waiting-actions[data-v-d0174eec]{gap:var(--spacing-sm);flex-shrink:0;display:flex}@keyframes slideDown-d0174eec{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.steps-header[data-v-d0174eec]{padding:var(--spacing-sm) var(--spacing-md);background:linear-gradient(135deg, var(--bg-container), var(--bg-panel))}.steps-title[data-v-d0174eec]{font-size:var(--font-size-sm);color:var(--text-secondary);letter-spacing:.5px;font-weight:600}.steps-list[data-v-d0174eec]{gap:var(--spacing-sm);padding:var(--spacing-sm) var(--spacing-md);scrollbar-width:thin;scrollbar-color:var(--border-card) transparent;display:flex;overflow-x:auto}.steps-list[data-v-d0174eec]::-webkit-scrollbar{height:5px}.steps-list[data-v-d0174eec]::-webkit-scrollbar-track{background:0 0}.steps-list[data-v-d0174eec]::-webkit-scrollbar-thumb{background:var(--border-card);border-radius:var(--radius-full)}.steps-list[data-v-d0174eec]::-webkit-scrollbar-thumb:hover{background:var(--border-component)}.step-item[data-v-d0174eec]{align-items:center;gap:var(--spacing-xs);background:var(--bg-container);border:1.5px solid var(--border-card);border-radius:var(--radius-md);cursor:default;flex-shrink:0;min-width:120px;max-width:200px;padding:8px 12px;transition:all .3s cubic-bezier(.4,0,.2,1);display:flex;position:relative;box-shadow:0 1px 2px #0000000a}.step-item.step-type-command[data-v-d0174eec]:not(.step-current):not(.step-completed){border-left:3px solid #409eff66}.step-item.step-type-wait[data-v-d0174eec]:not(.step-current):not(.step-completed){border-left:3px solid #e6a23c66}.step-item.step-type-version[data-v-d0174eec]:not(.step-current):not(.step-completed){border-left:3px solid #67c23a66}.step-item[data-v-d0174eec]:hover:not(.step-disabled){transform:scale(1.02);box-shadow:0 2px 6px #00000014}.step-item[data-v-d0174eec]:active:not(.step-disabled){transform:scale(.98)}.step-item[data-v-d0174eec]:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.step-item.step-current[data-v-d0174eec]{border-color:var(--color-primary);border-width:2px;box-shadow:0 2px 8px #409eff33,0 0 0 2px #409eff1f}.step-item.step-current.step-type-command[data-v-d0174eec]{background:linear-gradient(135deg,#409eff26 0%,#409eff0d 100%)}.step-item.step-current.step-type-wait[data-v-d0174eec]{border-color:var(--color-warning);background:linear-gradient(135deg,#e6a23c26 0%,#e6a23c0d 100%);box-shadow:0 2px 8px #e6a23c33,0 0 0 2px #e6a23c1f}.step-item.step-current.step-type-wait .step-indicator[data-v-d0174eec]{background:linear-gradient(135deg, var(--color-warning), #f0ad4e);animation:1.8s ease-in-out infinite pulse-ring-warning-d0174eec;box-shadow:0 0 6px #e6a23c59,0 0 0 2px #e6a23c26}.step-item.step-current.step-type-wait .step-name[data-v-d0174eec]{color:var(--color-warning)}.step-item.step-current.step-type-version[data-v-d0174eec]{border-color:var(--color-success);background:linear-gradient(135deg,#67c23a26 0%,#67c23a0d 100%);box-shadow:0 2px 8px #67c23a33,0 0 0 2px #67c23a1f}.step-item.step-current.step-type-version .step-indicator[data-v-d0174eec]{background:linear-gradient(135deg, var(--color-success), #5cb85c);animation:1.8s ease-in-out infinite pulse-ring-success-d0174eec;box-shadow:0 0 6px #67c23a59,0 0 0 2px #67c23a26}.step-item.step-current.step-type-version .step-name[data-v-d0174eec]{color:var(--color-success)}.step-item.step-current .step-indicator[data-v-d0174eec]{background:linear-gradient(135deg, var(--color-primary), #3a9eff);color:#fff;font-weight:700;animation:1.8s ease-in-out infinite pulse-ring-d0174eec;box-shadow:0 0 6px #409eff59,0 0 0 2px #409eff26}.step-item.step-current .step-indicator .step-type-icon[data-v-d0174eec]{color:#fff}.step-item.step-current .step-name[data-v-d0174eec]{color:var(--color-primary);font-weight:600}.step-item.step-completed[data-v-d0174eec]{opacity:.75;background:#67c23a0a;border-color:#67c23a4d}.step-item.step-completed .step-indicator[data-v-d0174eec]{background:linear-gradient(135deg, var(--color-success), #5cb85c);color:#fff;font-weight:600}.step-item.step-completed .step-name[data-v-d0174eec]{color:var(--text-tertiary);opacity:.8}.step-item.step-completed .step-type-tag[data-v-d0174eec]{opacity:.6}.step-item.step-pending[data-v-d0174eec]{opacity:.65;background:var(--bg-container)}.step-item.step-pending .step-indicator[data-v-d0174eec]{background:var(--bg-panel);border:2px solid var(--border-component);color:var(--text-tertiary);font-weight:500}.step-item.step-pending .step-name[data-v-d0174eec]{color:var(--text-secondary)}.step-item.step-pending .step-type-tag[data-v-d0174eec]{opacity:.7}.step-item.step-disabled[data-v-d0174eec]{opacity:.4;filter:grayscale(.5);cursor:not-allowed}.step-item.step-disabled .step-indicator[data-v-d0174eec]{background:var(--bg-panel);color:var(--text-disabled)}.step-item.step-disabled .step-name[data-v-d0174eec]{color:var(--text-disabled);text-decoration:line-through}.step-indicator[data-v-d0174eec]{background:var(--bg-panel);border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;width:26px;height:26px;transition:all .3s cubic-bezier(.4,0,.2,1);display:flex;position:relative}.step-indicator .step-type-icon[data-v-d0174eec]{color:var(--text-tertiary);font-size:14px}.step-indicator .step-icon-check[data-v-d0174eec]{color:#fff;font-size:14px}.step-number[data-v-d0174eec]{font-size:var(--font-size-xs);font-weight:600}.step-content[data-v-d0174eec]{flex-direction:column;flex:1;gap:3px;min-width:0;display:flex}.step-header[data-v-d0174eec]{align-items:center;gap:4px;display:flex}.step-type-tag[data-v-d0174eec]{border-radius:var(--radius-sm);text-transform:uppercase;letter-spacing:.3px;padding:2px 6px;font-size:10px;font-weight:600;line-height:1}.step-type-tag.type-command[data-v-d0174eec]{color:var(--color-primary);background:#409eff1f}.step-type-tag.type-wait[data-v-d0174eec]{color:var(--color-warning);background:#e6a23c1f}.step-type-tag.type-version[data-v-d0174eec]{color:var(--color-success);background:#67c23a1f}.step-terminal-tag[data-v-d0174eec]{color:#0ea5e9;background:#0ea5e91f;border:1px solid #0ea5e940;border-radius:5px;align-items:center;gap:4px;margin-left:6px;padding:1px 5px;font-size:9px;font-weight:600;line-height:1;display:inline-flex}.step-terminal-icon[data-v-d0174eec]{font-size:11px}.step-name[data-v-d0174eec]{color:var(--text-primary);white-space:nowrap;text-overflow:ellipsis;font-size:12.5px;line-height:1.3;transition:all .3s;overflow:hidden}.step-disabled-tag[data-v-d0174eec]{color:var(--text-disabled);background:var(--bg-panel);border-radius:var(--radius-sm);align-self:flex-start;padding:1px 4px;font-size:10px}.user-input-dialog-content[data-v-d0174eec]{padding:8px 2px}.user-input-empty[data-v-d0174eec]{color:var(--text-tertiary);padding:10px 0;font-size:13px}.user-input-form[data-v-d0174eec]{gap:var(--spacing-md);flex-direction:column;max-height:55vh;padding-right:6px;display:flex;overflow:auto}.user-input-row[data-v-d0174eec]{gap:var(--spacing-md);grid-template-columns:160px 1fr;align-items:center;display:grid}.user-input-label[data-v-d0174eec]{color:var(--color-text);word-break:break-all;font-size:13px;line-height:1.2}.user-input-label .required[data-v-d0174eec]{color:var(--color-danger);margin-right:4px}@keyframes pulse-ring-d0174eec{0%,to{box-shadow:0 0 6px #409eff59,0 0 0 2px #409eff40}50%{box-shadow:0 0 8px #409eff80,0 0 0 4px #409eff00}}@keyframes pulse-ring-warning-d0174eec{0%,to{box-shadow:0 0 6px #e6a23c59,0 0 0 2px #e6a23c40}50%{box-shadow:0 0 8px #e6a23c80,0 0 0 4px #e6a23c00}}@keyframes pulse-ring-success-d0174eec{0%,to{box-shadow:0 0 6px #67c23a59,0 0 0 2px #67c23a40}50%{box-shadow:0 0 8px #67c23a80,0 0 0 4px #67c23a00}}
@@ -1,6 +0,0 @@
1
- import"./rolldown-runtime-CMxvf4Kt.js";import{B as e,Bt as t,Cn as n,Ct as r,D as i,E as a,En as o,Et as s,Ft as c,G as l,H as u,Ht as d,In as f,J as p,K as m,L as h,Ln as g,Lt as _,N as v,P as y,Pt as b,Q as x,Qn as S,R as C,S as w,Vn as T,W as E,X as D,Y as O,Yn as k,Yt as A,Zn as j,_n as M,_r as N,a as P,at as ee,cn as te,cr as F,ct as I,dn as L,gn as R,hn as z,hr as B,ht as ne,i as V,kt as H,lt as re,mr as U,mt as ie,nn as ae,nt as oe,o as W,or as se,ot as ce,pn as le,q as ue,st as de,tt as fe,un as pe,v as me,vn as G,vr as K,wn as q,yn as J,z as he,zn as Y,zt as ge}from"./element-plus-CJjFCgLP.js";import{s as _e}from"./vendor-0YbzMuxw.js";import{n as X,t as Z}from"./_plugin-vue_export-helper-B9V6d9og.js";import{a as Q,c as ve,o as ye,r as be,s as xe}from"./index-DkrC0Lp8.js";import{t as Se}from"./TemplateManager-CHFxc36Y.js";import{a as Ce,i as we,n as Te,o as Ee,r as De,t as Oe}from"./ResetToRemoteButton-DSXFl5RR.js";var ke={key:0},Ae={key:1},je=Z(o({__name:`StageButton`,props:{from:{default:`form`}},emits:[`click`],setup(t,{emit:r}){let i=r,a=Q(),o=ye();function s(e){let t=e.replace(/\\/g,`/`);return o.lockedFiles.some(e=>t===e.replace(/\\/g,`/`))}function c(){return o.lockedFiles.length===0?!1:a.fileList.some(e=>[`modified`,`deleted`,`untracked`].includes(e.type)?s(e.path):!1)}let u=z(()=>a.fileList.filter(e=>[`modified`,`deleted`,`untracked`].includes(e.type)&&!s(e.path)).length),d=z(()=>a.fileList.some(e=>[`modified`,`deleted`,`untracked`].includes(e.type)&&!s(e.path))),f=z(()=>a.isSelectionMode&&a.hasSelectableFiles),p=z(()=>a.selectedUnstagedPaths.length),m=z(()=>a.isSelectionMode?p.value===0:!d.value),h=z(()=>f.value?`${X(`@29974:暂存所选 `)}${p.value}${X(`@29974: 个文件`)}`:d.value?c()?`${X(`@29974:暂存`)}${u.value}${X(`@29974:个未暂存文件(逐个添加)`)}`:`${X(`@29974:暂存所有更改(git add .)`)}`:X(`@29974:没有需要暂存的更改`));async function g(){i(`click`);try{if(f.value){await a.stageFiles(a.selectedUnstagedPaths);return}if(a.isSelectionMode)return;c()?await a.addToStage():await a.addAllToStage()}catch(e){console.error(`添加文件失败:`,e)}}return(r,i)=>{let o=e,s=l;return Y(),M(s,{content:h.value,placement:`top`},{default:j(()=>[q(o,{type:`primary`,icon:U(b),onClick:g,loading:U(a).isAddingFiles,disabled:m.value,class:B([`stage-button`,`from-${t.from}`,{"is-selective":f.value}])},{default:j(()=>[n(K(f.value?U(X)(`@29974:暂存所选`):U(X)(`@29974:暂存`))+` `,1),f.value?(Y(),J(`span`,ke,`(`+K(p.value)+`)`,1)):u.value>0?(Y(),J(`span`,Ae,`(`+K(u.value)+`)`,1)):G(``,!0)]),_:1},8,[`icon`,`loading`,`disabled`,`class`])]),_:1},8,[`content`])}}}),[[`__scopeId`,`data-v-22060f7f`]]),Me={key:0},Ne=Z(o({__name:`CommitButton`,props:{from:{default:`form`},hasUserCommitMessage:{type:Boolean,default:!1},finalCommitMessage:{default:``},skipHooks:{type:Boolean,default:!1}},emits:[`click`,`beforeCommit`,`afterCommit`],setup(t,{emit:r}){let i=t,a=r,o=Q(),c=ye();function u(e){let t=e.replace(/\\/g,`/`);return c.lockedFiles.some(e=>t===e.replace(/\\/g,`/`))}let d=z(()=>o.fileList.filter(e=>e.type===`added`&&!u(e.path)).length),f=z(()=>d.value>0),p=z(()=>o.hasConflictedFiles||o.isCommiting?!0:o.isMergeInProgress?!i.hasUserCommitMessage:!f.value||!i.hasUserCommitMessage),m=z(()=>o.isCommiting?X(`@76A11:正在提交中…`):o.hasConflictedFiles?X(`@76A11:存在冲突文件,请先解决冲突`):o.isMergeInProgress?i.hasUserCommitMessage?X(`@76A11:提交并完成合并`):X(`@76A11:请输入提交信息`):f.value?i.hasUserCommitMessage?`${X(`@76A11:提交`)}${d.value}${X(`@76A11:个已暂存文件`)}`:X(`@76A11:请输入提交信息`):X(`@76A11:没有已暂存的更改`)),h=z(()=>o.isCommiting?X(`@76A11:提交中…`):X(`@76A11:提交`));async function g(){if(i.finalCommitMessage.trim()){a(`beforeCommit`),a(`click`);try{a(`afterCommit`,await o.commitChanges(i.finalCommitMessage,i.skipHooks))}catch(e){console.error(`提交失败:`,e),a(`afterCommit`,!1)}}}return(r,i)=>{let a=e,c=l;return Y(),M(c,{content:m.value,placement:`top`,disabled:U(o).isCommiting},{default:j(()=>[q(a,{type:`primary`,onClick:g,icon:U(o).isCommiting?U(s):U(fe),loading:U(o).isCommiting,disabled:p.value,"aria-busy":U(o).isCommiting?`true`:void 0,"aria-label":U(o).isCommiting?U(X)(`@76A11:正在提交中…`):void 0,class:B([`commit-button`,`from-${t.from}`,{"is-committing":U(o).isCommiting}])},{default:j(()=>[n(K(h.value)+` `,1),d.value>0&&!U(o).isCommiting?(Y(),J(`span`,Me,`(`+K(d.value)+`)`,1)):G(``,!0)]),_:1},8,[`icon`,`loading`,`disabled`,`aria-busy`,`aria-label`,`class`])]),_:1},8,[`content`,`disabled`])}}}),[[`__scopeId`,`data-v-8b754849`]]),Pe={class:`push-progress-container`},Fe={key:0,class:`pulling-section`},Ie={class:`pulling-text-wrap`},Le={class:`pulling-title`},Re={class:`pulling-sub`},ze={class:`stage-header`},Be={class:`stage-icon`},Ve={class:`stage-info`},He={class:`stage-label`},Ue={key:0,class:`stage-percent`},We={key:0,class:`stage-progress`},Ge={key:2,class:`error-section`},Ke={class:`error-header`},qe={class:`error-title`},Je={class:`error-content`},Ye={key:0,class:`error-suggestion`},Xe={key:3,class:`messages-section`},Ze={class:`messages-title`},Qe=Z(o({__name:`PushProgressModal`,props:{modelValue:{type:Boolean}},emits:[`update:modelValue`,`complete`,`pull-requested`],setup(t,{expose:r,emit:a}){let{t:o}=_e(),c=t,l=a,u=ye(),d=Q(),f=F(`progress`),p=F([]),m=F(``),h=F(!1),g=z(()=>m.value.includes(`non-fast-forward`)||m.value.includes(`rejected`)&&m.value.includes(`fetch first`)),_=F(!1);async function v(){_.value=!0;try{(await d.gitPull()).success&&(S.value=!1,l(`pull-requested`))}finally{_.value=!1}}let y=se([{name:`counting`,label:o(`@PUSH:计数对象`),status:`wait`,percent:0},{name:`compressing`,label:o(`@PUSH:压缩对象`),status:`wait`,percent:0},{name:`writing`,label:o(`@PUSH:写入对象`),status:`wait`,percent:0},{name:`resolving`,label:o(`@PUSH:解析增量`),status:`wait`,percent:0}]),b=F(0),x=F(null),S=z({get:()=>c.modelValue,set:e=>l(`update:modelValue`,e)}),C=z(()=>{if(h.value)return o(`@PUSH:正在拉取远程更新`);switch(f.value){case`progress`:return o(`@PUSH:正在推送`);case`success`:return o(`@PUSH:推送成功`);case`error`:return o(`@PUSH:推送失败`);default:return``}});function w(e){switch(e.type){case`progress`:e.message&&(p.value.push(e.message),setTimeout(()=>{x.value&&(x.value.scrollTop=x.value.scrollHeight)},0));break;case`stage-progress`:if(e.stage&&typeof e.percent==`number`){let t=y.findIndex(t=>t.name===e.stage);t!==-1&&(y[t].percent=e.percent,y[t].status=e.percent===100?`finish`:`process`,b.value=t,e.percent===100&&t<y.length-1&&(y[t+1].status=`wait`))}break;case`complete`:e.success?(f.value=`success`,y.forEach(e=>{(e.status===`process`||e.status===`wait`)&&(e.status=`finish`,e.percent=100)}),b.value=-1,u.autoClosePushModal?setTimeout(()=>{S.value=!1,l(`complete`,!0)},2e3):l(`complete`,!0)):(f.value=`error`,m.value=e.error||`未知错误`,b.value<y.length&&(y[b.value].status=`error`),b.value=-1,l(`complete`,!1));break}}function E(){f.value=`progress`,p.value=[],m.value=``,b.value=0,h.value=!1,y.forEach(e=>{e.status=`wait`,e.percent=0})}function D(e){h.value=e}return r({handleProgress:w,reset:E,setPulling:D}),(t,r)=>{let a=e;return Y(),M(U(i),{modelValue:S.value,"onUpdate:modelValue":r[0]||=e=>S.value=e,title:C.value,width:`650px`,"close-on-click-modal":!1,"close-on-press-escape":!1,"show-close":f.value!==`progress`,"append-to-body":!0,"lock-scroll":!1,"destroy-on-close":``,class:B([`push-progress-dialog`,`status-${f.value}`])},{default:j(()=>[R(`div`,Pe,[h.value?(Y(),J(`div`,Fe,[r[1]||=R(`div`,{class:`pulling-icon-wrap`},[R(`svg`,{class:`pulling-spinner`,viewBox:`0 0 50 50`},[R(`circle`,{class:`pulling-spinner-track`,cx:`25`,cy:`25`,r:`20`,fill:`none`,"stroke-width":`4`}),R(`circle`,{class:`pulling-spinner-arc`,cx:`25`,cy:`25`,r:`20`,fill:`none`,"stroke-width":`4`})])],-1),R(`div`,Ie,[R(`div`,Le,K(U(o)(`@PUSH:正在拉取远程更新`)),1),R(`div`,Re,K(U(o)(`@PUSH:拉取完成后自动继续推送`)),1)])])):(Y(),J(`div`,{key:1,class:B([`stages-section`,{"is-loading":f.value===`progress`,"is-success":f.value===`success`}])},[(Y(!0),J(L,null,T(y,(e,t)=>(Y(),J(`div`,{key:e.name,class:B([`stage-item`,{active:b.value===t,finished:e.status===`finish`,error:e.status===`error`}])},[R(`div`,ze,[R(`div`,Be,[e.status===`finish`?(Y(),M(U(O),{key:0,class:`icon-finish`},{default:j(()=>[q(U(oe))]),_:1})):e.status===`error`?(Y(),M(U(O),{key:1,class:`icon-error`},{default:j(()=>[q(U(ce))]),_:1})):e.status===`process`?(Y(),M(U(O),{key:2,class:`icon-process rotating`},{default:j(()=>[q(U(s))]),_:1})):(Y(),M(U(O),{key:3,class:`icon-wait`},{default:j(()=>[q(U(s))]),_:1}))]),R(`div`,Ve,[R(`div`,He,K(e.label),1),e.status===`process`||e.status===`finish`?(Y(),J(`div`,Ue,K(e.percent)+`% `,1)):G(``,!0)])]),e.status===`process`||e.status===`finish`?(Y(),J(`div`,We,[q(U(me),{percentage:e.percent,"stroke-width":6,"show-text":!1,color:e.status===`finish`?`var(--color-success)`:`var(--color-primary)`},null,8,[`percentage`,`color`])])):G(``,!0)],2))),128))],2)),f.value===`error`&&m.value?(Y(),J(`div`,Ge,[R(`div`,Ke,[R(`div`,qe,K(U(o)(`@PUSH:错误详情`))+`:`,1),g.value?(Y(),M(a,{key:0,type:`primary`,size:`small`,loading:_.value,onClick:v,class:`pull-button`},{default:j(()=>[q(U(O),null,{default:j(()=>[q(U(ie))]),_:1}),n(` `+K(U(o)(`@PUSH:先拉取更新`)),1)]),_:1},8,[`loading`])):G(``,!0)]),R(`div`,Je,K(m.value),1),g.value?(Y(),J(`div`,Ye,K(U(o)(`@PUSH:检测到远程有新提交,请先拉取更新后再推送。`)),1)):G(``,!0)])):G(``,!0),p.value.length>0?(Y(),J(`div`,Xe,[R(`div`,Ze,K(U(o)(`@PUSH:详细信息`))+`:`,1),R(`div`,{ref_key:`messagesContainerRef`,ref:x,class:`progress-messages`},[(Y(!0),J(L,null,T(p.value,(e,t)=>(Y(),J(`div`,{key:t,class:`message-item`},K(e),1))),128))],512)])):G(``,!0)])]),_:1},8,[`modelValue`,`title`,`show-close`,`class`])}}}),[[`__scopeId`,`data-v-e8766d98`]]),$e={key:0},et=Z(o({__name:`PushButton`,props:{from:{default:`form`}},emits:[`click`,`beforePush`,`afterPush`],setup(t,{emit:r}){let i=r,a=Q(),o=F(!1),s=F(null),c=z(()=>a.branchAhead>0),u=z(()=>a.fileList.some(e=>e.type===`added`)),d=z(()=>a.hasConflictedFiles?!1:a.hasUpstream&&c.value&&!u.value),f=z(()=>!d.value),p=z(()=>a.hasConflictedFiles?X(`@F4137:存在冲突文件,请先解决冲突`):a.hasUpstream?c.value?u.value?X(`@F4137:有未提交的暂存更改,请先提交`):`${X(`@F4137:推送`)}${a.branchAhead}${X(`@F4137:个本地提交`)}`:X(`@F4137:没有需要推送的提交`):X(`@F4137:当前分支没有上游分支`)),m=z(()=>d.value?{backgroundColor:`var(--color-success)`,borderColor:`var(--color-success)`}:{});async function h(){i(`beforePush`),i(`click`);try{o.value=!0,s.value&&s.value.reset();let e=await a.pushToRemoteWithProgress(e=>{s.value&&s.value.handleProgress(e)});e&&await new Promise(e=>setTimeout(e,200)),i(`afterPush`,e)}catch(e){console.error(`推送失败:`,e),i(`afterPush`,!1)}}function g(e){}return(r,i)=>{let u=e,d=l;return Y(),J(`div`,null,[q(d,{content:p.value,placement:`top`},{default:j(()=>[q(u,{type:`primary`,icon:U(A),onClick:h,loading:U(a).isPushing,disabled:f.value,style:N(m.value),class:B([`push-button`,`from-${t.from}`])},{default:j(()=>[n(K(U(X)(`@F4137:推送`))+` `,1),c.value?(Y(),J(`span`,$e,`(`+K(U(a).branchAhead)+`)`,1)):G(``,!0)]),_:1},8,[`icon`,`loading`,`disabled`,`style`,`class`])]),_:1},8,[`content`]),q(Qe,{ref_key:`progressModalRef`,ref:s,modelValue:o.value,"onUpdate:modelValue":i[0]||=e=>o.value=e,onComplete:g},null,8,[`modelValue`])])}}}),[[`__scopeId`,`data-v-a0e22137`]]),tt={class:`one-push-content`},nt={class:`one-push-text`},rt={class:`one-push-title`},it={key:0,class:`one-push-desc`},at=Z(o({__name:`QuickPushButton`,props:{from:{default:`form`},hasUserCommitMessage:{type:Boolean,default:!1},finalCommitMessage:{default:``},skipHooks:{type:Boolean,default:!1}},emits:[`beforePush`,`pushStart`,`afterPush`,`clearFields`],setup(t,{expose:n,emit:r}){let i=Q(),a=ye(),o=F(!1),s=F(null),u=t,d=r;function f(e){let t=e.replace(/\\/g,`/`);return a.lockedFiles.some(e=>t===e.replace(/\\/g,`/`))}let p=z(()=>i.fileList.some(e=>!f(e.path))),m=z(()=>i.isSelectionMode&&i.selectedFiles.size>0&&i.selectedUnstagedPaths.length>0),h=z(()=>i.hasConflictedFiles?!0:i.isSelectionMode?!m.value||!u.hasUserCommitMessage||!i.hasUpstream:!p.value&&i.branchAhead===0||!u.hasUserCommitMessage||!i.hasUpstream),g=z(()=>i.isAddingFiles||i.isCommiting||i.isPushing),_=z(()=>{if(i.hasConflictedFiles)return X(`@2E184:存在冲突文件,请先解决冲突`);if(i.isSelectionMode)return i.selectedFiles.size===0?X(`@2E184:请先勾选要推送的文件`):i.selectedUnstagedPaths.length===0?X(`@2E184:所选文件无需暂存或被锁定`):u.hasUserCommitMessage?i.hasUpstream?X(`@2E184:一键完成:仅暂存所选文件 → 提交 → 推送到远程仓库`):X(`@2E184:当前分支没有上游分支`):X(`@2E184:请输入提交信息`);let e=i.branchAhead>0;return!p.value&&!e?X(`@2E184:没有需要提交或推送的更改`):u.hasUserCommitMessage?i.hasUpstream?p.value?X(`@2E184:一键完成:暂存所有更改 → 提交 → 推送到远程仓库`):X(`@2E184:本地已提交,一键推送到远程仓库`):X(`@2E184:当前分支没有上游分支`):X(`@2E184:请输入提交信息`)}),v=z(()=>i.isSelectionMode&&m.value?X(`@2E184:一键推送所选`):X(`@2E184:一键推送所有`)),y=z(()=>u.from===`form`?i.isSelectionMode&&m.value?X(`@2E184:暂存所选 + 提交 + 推送`):X(`@2E184:暂存 + 提交 + 推送`):``);async function b(){d(`beforePush`);try{let e=i.isSelectionMode&&m.value;if((e||p.value)&&!(e?await i.stageSelectedAndCommit(u.finalCommitMessage,u.skipHooks):await i.addAndCommit(u.finalCommitMessage,u.skipHooks))){d(`afterPush`,!1);return}if(d(`pushStart`),o.value=!0,a.pullBeforePush){s.value?.setPulling(!0);let e=await i.gitPull();if(s.value?.setPulling(!1),!e.success){P.error(X(`@2E184:拉取远程更新失败,已停止推送`)),o.value=!1,i.fetchStatus(),i.getBranchStatus(!0),d(`afterPush`,!1);return}}s.value&&s.value.reset();let t=await i.pushToRemoteWithProgress(e=>{s.value&&s.value.handleProgress(e)});if(t){try{window.dispatchEvent(new CustomEvent(`zen-gitsync:after-quick-push-success`))}catch{}d(`clearFields`)}d(`afterPush`,t)}catch(e){console.error(`一键推送失败:`,e),d(`afterPush`,!1)}}n({triggerQuickPush:b});function x(e){}return(n,r)=>{let i=O,a=e;return Y(),J(`div`,null,[q(U(l),{content:_.value,placement:`top`,"show-after":200},{default:j(()=>[q(a,{type:`primary`,onClick:b,loading:g.value,disabled:h.value,class:B([t.from,`one-push-button`])},{default:j(()=>[R(`div`,tt,[q(i,{class:`one-push-icon`},{default:j(()=>[q(U(c))]),_:1}),R(`div`,nt,[R(`span`,rt,K(v.value),1),t.from===`form`?(Y(),J(`span`,it,K(y.value),1)):G(``,!0)])])]),_:1},8,[`loading`,`disabled`,`class`])]),_:1},8,[`content`]),q(Qe,{ref_key:`progressModalRef`,ref:s,modelValue:o.value,"onUpdate:modelValue":r[0]||=e=>o.value=e,onComplete:x,onPullRequested:b},null,8,[`modelValue`])])}}}),[[`__scopeId`,`data-v-cd1a2b50`]]),ot={class:`create-tag-button`},st={class:`tag-dialog-content`},ct={class:`tag-info-card`},lt={class:`info-icon`},ut={class:`info-content`},dt={class:`form-tip`},ft={class:`form-tip`},pt={class:`form-tip`},mt=Z(o({__name:`CreateTagButton`,props:{variant:{default:`icon`}},setup(t){let i=t,a=Q(),o=F(!1),s=F(``),c=F(``),u=F(`lightweight`),f=F(``),p=F(!1);function h(){s.value=``,c.value=``,u.value=`lightweight`,f.value=``,o.value=!0}async function g(){if(!s.value.trim()){P.warning(X(`@TAG01:请输入标签名称`));return}if(!/^[a-zA-Z0-9._\/-]+$/.test(s.value)){P.warning(X(`@TAG01:标签名称只能包含字母、数字、点、下划线、斜杠和连字符`));return}try{p.value=!0;let e=await(await fetch(`/api/create-tag`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({tagName:s.value.trim(),message:c.value.trim(),type:u.value,commit:f.value.trim()})})).json();e.success?(P.success(X(`@TAG01:标签创建成功`)),o.value=!1):P.error(e.error||X(`@TAG01:创建标签失败`))}catch(e){console.error(`创建标签失败:`,e),P.error(X(`@TAG01:创建标签失败`))}finally{p.value=!1}}let _=z(()=>u.value===`lightweight`?X(`@TAG01:轻量标签是指向提交对象的引用,不包含额外信息`):X(`@TAG01:附注标签是完整的Git对象,包含标签信息、日期、标签者和可选的签名`));return(t,b)=>{let x=O,S=e,C=l,w=E,T=ue,D=v,k=y,A=m;return Y(),J(`div`,ot,[q(C,{content:U(X)(`@TAG01:为当前提交创建标签`),placement:`top`,"show-after":200,disabled:i.variant===`text`},{default:j(()=>[q(S,{type:`success`,onClick:h,disabled:!U(a).isGitRepo,circle:i.variant===`icon`,size:i.variant===`icon`?`small`:`default`,class:B(i.variant===`text`?`action-button`:``)},{default:j(()=>[i.variant===`icon`?(Y(),M(x,{key:0},{default:j(()=>[q(U(d))]),_:1})):(Y(),J(L,{key:1},[n(K(U(X)(`@TAG01:创建标签`)),1)],64))]),_:1},8,[`disabled`,`circle`,`size`,`class`])]),_:1},8,[`content`,`disabled`]),q(ve,{modelValue:o.value,"onUpdate:modelValue":b[4]||=e=>o.value=e,title:U(X)(`@TAG01:创建 Git 标签`),size:`medium`,"close-on-click-modal":!1,"show-footer":``,"confirm-text":U(X)(`@TAG01:创建`),"cancel-text":U(X)(`@TAG01:取消`),"confirm-loading":p.value,"custom-class":`tag-dialog`,onConfirm:g},{default:j(()=>[R(`div`,st,[R(`div`,ct,[R(`div`,lt,[q(x,null,{default:j(()=>[q(U(d))]),_:1})]),R(`div`,ut,[R(`h4`,null,K(U(X)(`@TAG01:Git 标签`)),1),R(`p`,null,K(U(X)(`@TAG01:标签用于标记项目的重要版本点,如发布版本 v1.0.0`)),1)])]),q(A,{"label-position":`top`,class:`tag-form`},{default:j(()=>[q(T,{label:U(X)(`@TAG01:标签名称`),required:``},{default:j(()=>[q(w,{modelValue:s.value,"onUpdate:modelValue":b[0]||=e=>s.value=e,placeholder:U(X)(`@TAG01:例如: v1.0.0 或 release-2024`),clearable:``,maxlength:`100`},{prefix:j(()=>[q(x,null,{default:j(()=>[q(U(d))]),_:1})]),_:1},8,[`modelValue`,`placeholder`]),R(`div`,dt,[q(x,null,{default:j(()=>[q(U(r))]),_:1}),R(`span`,null,K(U(X)(`@TAG01:建议使用语义化版本号,如 v1.0.0`)),1)])]),_:1},8,[`label`]),q(T,{label:U(X)(`@TAG01:标签类型`)},{default:j(()=>[q(k,{modelValue:u.value,"onUpdate:modelValue":b[1]||=e=>u.value=e,size:`default`},{default:j(()=>[q(D,{value:`lightweight`},{default:j(()=>[n(K(U(X)(`@TAG01:轻量标签`)),1)]),_:1}),q(D,{value:`annotated`},{default:j(()=>[n(K(U(X)(`@TAG01:附注标签`)),1)]),_:1})]),_:1},8,[`modelValue`]),R(`div`,ft,[q(x,null,{default:j(()=>[q(U(r))]),_:1}),R(`span`,null,K(_.value),1)])]),_:1},8,[`label`]),u.value===`annotated`?(Y(),M(T,{key:0,label:U(X)(`@TAG01:标签说明`),required:u.value===`annotated`},{default:j(()=>[q(w,{modelValue:c.value,"onUpdate:modelValue":b[2]||=e=>c.value=e,placeholder:U(X)(`@TAG01:为此标签添加说明信息`),clearable:``,rows:3,type:`textarea`,resize:`none`,maxlength:`500`,"show-word-limit":``},null,8,[`modelValue`,`placeholder`])]),_:1},8,[`label`,`required`])):G(``,!0),q(T,{label:U(X)(`@TAG01:目标提交(可选)`)},{default:j(()=>[q(w,{modelValue:f.value,"onUpdate:modelValue":b[3]||=e=>f.value=e,placeholder:U(X)(`@TAG01:留空则为当前HEAD,或输入commit SHA`),clearable:``,maxlength:`40`},{prefix:j(()=>[...b[5]||=[R(`span`,{class:`commit-prefix`},`commit:`,-1)]]),_:1},8,[`modelValue`,`placeholder`]),R(`div`,pt,[q(x,null,{default:j(()=>[q(U(r))]),_:1}),R(`span`,null,K(U(X)(`@TAG01:默认为当前HEAD提交,也可以指定历史提交`)),1)])]),_:1},8,[`label`])]),_:1})])]),_:1},8,[`modelValue`,`title`,`confirm-text`,`cancel-text`,`confirm-loading`])])}}}),[[`__scopeId`,`data-v-cbbcdcda`]]),ht={class:`tag-list-button`},gt={class:`tag-list-content`},_t={key:0,class:`tag-header`},vt={class:`tag-stats`},yt={class:`stat-item`},bt={class:`stat-number`},xt={class:`stat-label`},St={class:`tag-actions-header`},Ct={class:`tag-list-container`},wt={key:0,class:`empty-state`},Tt={class:`empty-text`},Et={class:`empty-hint`},Dt={key:1,class:`tag-cards`},Ot={class:`tag-card-content`},kt={class:`tag-info`},At={class:`tag-main-info`},jt={class:`tag-name-badge`},Mt={class:`tag-name-text`},Nt={class:`tag-meta`},Pt={class:`tag-commit`},Ft={class:`tag-date`},It={key:0,class:`tag-message`},Lt={class:`tag-card-actions`},Rt={key:0,class:`tag-detail-content`},zt={class:`detail-row`},Bt={class:`detail-label`},Vt={class:`detail-value`},Ht={class:`detail-row`},Ut={class:`detail-label`},Wt={class:`detail-value`},Gt={class:`detail-row`},Kt={class:`detail-label`},qt={class:`detail-value`},Jt={class:`detail-row`},Yt={class:`detail-label`},Xt={key:0,class:`detail-row detail-message`},Zt={class:`detail-label`},Qt={class:`message-content`},$t=Z(o({__name:`TagListButton`,props:{variant:{default:`icon`}},setup(t){let i=t,a=Q(),o=F(!1),s=F([]),c=F(!1),u=F(!1),f=F(!1),p=F(!1),m=F(null);async function h(){o.value=!0,await g()}async function g(){try{c.value=!0;let e=await(await fetch(`/api/list-tags`)).json();e.success?s.value=e.tags||[]:P.error(e.error||X(`@TAG01:获取标签列表失败`))}catch(e){console.error(`获取标签列表失败:`,e),P.error(X(`@TAG01:获取标签列表失败`))}finally{c.value=!1}}function v(e){m.value=e,p.value=!0}async function y(e){V.confirm(X(`@TAG01:确定要推送此标签到远程仓库吗?`),X(`@TAG01:推送标签`),{confirmButtonText:X(`@TAG01:推送`),cancelButtonText:X(`@TAG01:取消`),type:`info`}).then(async()=>{try{f.value=!0;let t=await(await fetch(`/api/push-tag`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({tagName:e})})).json();t.success?P.success(X(`@TAG01:标签推送成功`)):P.error(t.error||X(`@TAG01:推送标签失败`))}catch(e){console.error(`推送标签失败:`,e),P.error(X(`@TAG01:推送标签失败`))}finally{f.value=!1}}).catch(()=>{})}async function b(){V.confirm(X(`@TAG01:确定要推送所有标签到远程仓库吗?`),X(`@TAG01:推送所有标签`),{confirmButtonText:X(`@TAG01:推送`),cancelButtonText:X(`@TAG01:取消`),type:`info`}).then(async()=>{try{f.value=!0;let e=await(await fetch(`/api/push-all-tags`,{method:`POST`})).json();e.success?P.success(X(`@TAG01:所有标签推送成功`)):P.error(e.error||X(`@TAG01:推送标签失败`))}catch(e){console.error(`推送标签失败:`,e),P.error(X(`@TAG01:推送标签失败`))}finally{f.value=!1}}).catch(()=>{})}async function x(e){V.confirm(X(`@TAG01:确定要删除此标签吗?此操作不可恢复。`),X(`@TAG01:删除标签`),{confirmButtonText:X(`@TAG01:删除`),cancelButtonText:X(`@TAG01:取消`),type:`warning`}).then(async()=>{await C(e)}).catch(()=>{})}async function C(e){try{u.value=!0;let t=await(await fetch(`/api/delete-tag`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({tagName:e})})).json();t.success?(P.success(X(`@TAG01:标签删除成功`)),await g()):P.error(t.error||X(`@TAG01:删除标签失败`))}catch(e){console.error(`删除标签失败:`,e),P.error(X(`@TAG01:删除标签失败`))}finally{u.value=!1}}function E(e){if(!e)return`-`;try{return new Date(e).toLocaleString(`zh-CN`,{year:`numeric`,month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`})}catch{return e}}return(t,C)=>{let D=O,k=e,N=l,P=w,ee=he,te=W;return Y(),J(`div`,ht,[q(N,{content:U(X)(`@TAG01:查看和管理所有标签`),placement:`top`,"show-after":200,disabled:i.variant===`text`},{default:j(()=>[q(k,{type:`info`,onClick:h,disabled:!U(a).isGitRepo,circle:i.variant===`icon`,size:i.variant===`icon`?`small`:`default`,class:B(i.variant===`text`?`action-button`:``)},{default:j(()=>[i.variant===`icon`?(Y(),M(D,{key:0},{default:j(()=>[q(U(d))]),_:1})):(Y(),J(L,{key:1},[n(K(U(X)(`@TAG01:标签列表`)),1)],64))]),_:1},8,[`disabled`,`circle`,`size`,`class`])]),_:1},8,[`content`,`disabled`]),q(ve,{modelValue:o.value,"onUpdate:modelValue":C[0]||=e=>o.value=e,title:U(X)(`@TAG01:Git 标签列表`),size:`large`,"show-footer":!1,"custom-class":`tag-list-dialog`},{default:j(()=>[R(`div`,gt,[c.value?G(``,!0):(Y(),J(`div`,_t,[R(`div`,vt,[R(`div`,yt,[q(D,{class:`stat-icon`},{default:j(()=>[q(U(d))]),_:1}),R(`span`,bt,K(s.value.length),1),R(`span`,xt,K(U(X)(`@TAG01:个标签`)),1)])]),R(`div`,St,[q(k,{type:`primary`,size:`small`,icon:U(_),onClick:g,loading:c.value,class:`refresh-btn`},{default:j(()=>[n(K(U(X)(`@TAG01:刷新`)),1)]),_:1},8,[`icon`,`loading`]),s.value.length>0?(Y(),M(k,{key:0,type:`success`,size:`small`,icon:U(A),onClick:b,loading:f.value,class:`push-all-btn`},{default:j(()=>[n(K(U(X)(`@TAG01:推送所有标签`)),1)]),_:1},8,[`icon`,`loading`])):G(``,!0)])])),S((Y(),J(`div`,Ct,[s.value.length===0&&!c.value?(Y(),J(`div`,wt,[q(P,{description:U(X)(`@TAG01:暂无标签`),"image-size":120},{image:j(()=>[q(D,{class:`empty-icon`},{default:j(()=>[q(U(d))]),_:1})]),description:j(()=>[R(`p`,Tt,K(U(X)(`@TAG01:还没有创建任何标签`)),1),R(`p`,Et,K(U(X)(`@TAG01:使用创建标签功能为项目添加版本标记`)),1)]),_:1},8,[`description`])])):(Y(),J(`div`,Dt,[(Y(!0),J(L,null,T(s.value,e=>(Y(),J(`div`,{key:e.name,class:`tag-card`},[R(`div`,Ot,[R(`div`,kt,[R(`div`,At,[R(`div`,jt,[q(D,{class:`badge-icon`},{default:j(()=>[q(U(d))]),_:1}),R(`span`,Mt,K(e.name),1),q(ee,{size:`small`,type:e.type===`annotated`?`warning`:`info`,class:`type-tag`},{default:j(()=>[n(K(e.type===`annotated`?U(X)(`@TAG01:附注`):U(X)(`@TAG01:轻量`)),1)]),_:2},1032,[`type`])]),R(`div`,Nt,[R(`span`,Pt,[q(D,null,{default:j(()=>[q(U(r))]),_:1}),n(` `+K(e.commit.substring(0,8)),1)]),R(`span`,Ft,K(E(e.date)),1)]),e.message?(Y(),J(`div`,It,K(e.message),1)):G(``,!0)])]),R(`div`,Lt,[e.message?(Y(),M(k,{key:0,size:`small`,type:`info`,onClick:t=>v(e),class:`action-btn view-btn`},{default:j(()=>[n(K(U(X)(`@TAG01:查看`)),1)]),_:1},8,[`onClick`])):G(``,!0),q(k,{size:`small`,type:`success`,icon:U(A),onClick:t=>y(e.name),loading:f.value,class:`action-btn push-btn`},{default:j(()=>[n(K(U(X)(`@TAG01:推送`)),1)]),_:1},8,[`icon`,`onClick`,`loading`]),q(k,{size:`small`,type:`danger`,icon:U(re),onClick:t=>x(e.name),loading:u.value,class:`action-btn delete-btn`},{default:j(()=>[n(K(U(X)(`@TAG01:删除`)),1)]),_:1},8,[`icon`,`onClick`,`loading`])])])]))),128))]))])),[[te,c.value]])])]),_:1},8,[`modelValue`,`title`]),q(ve,{modelValue:p.value,"onUpdate:modelValue":C[1]||=e=>p.value=e,title:U(X)(`@TAG01:标签详情`),size:`medium`,"show-footer":!1,"custom-class":`tag-detail-dialog`},{default:j(()=>[m.value?(Y(),J(`div`,Rt,[R(`div`,zt,[R(`span`,Bt,K(U(X)(`@TAG01:标签名称:`)),1),R(`code`,Vt,K(m.value.name),1)]),R(`div`,Ht,[R(`span`,Ut,K(U(X)(`@TAG01:提交SHA:`)),1),R(`code`,Wt,K(m.value.commit),1)]),R(`div`,Gt,[R(`span`,Kt,K(U(X)(`@TAG01:创建时间:`)),1),R(`span`,qt,K(E(m.value.date)),1)]),R(`div`,Jt,[R(`span`,Yt,K(U(X)(`@TAG01:类型:`)),1),q(ee,{type:m.value.type===`annotated`?`warning`:`info`,size:`small`},{default:j(()=>[n(K(m.value.type===`annotated`?U(X)(`@TAG01:附注标签`):U(X)(`@TAG01:轻量标签`)),1)]),_:1},8,[`type`])]),m.value.message?(Y(),J(`div`,Xt,[R(`span`,Zt,K(U(X)(`@TAG01:标签说明:`)),1),R(`div`,Qt,K(m.value.message),1)])):G(``,!0)])):G(``,!0)]),_:1},8,[`modelValue`,`title`])])}}}),[[`__scopeId`,`data-v-fc8d7e86`]]),en={class:`git-operations-button`},tn={class:`actions-section`},nn={class:`action-groups`},rn={class:`action-group`},an={class:`group-title`},on={class:`group-buttons`},sn={key:0},cn={class:`action-group`},ln={class:`group-title`},un={class:`group-buttons`},dn={class:`action-group`},fn={class:`group-title`},pn={class:`group-buttons`},mn={key:0},hn={class:`action-group`},gn={class:`group-title`},_n={class:`group-buttons`},vn={class:`action-group`},yn={class:`group-title`},bn={class:`group-buttons`},xn={class:`action-group`},Sn={class:`group-title`},Cn={class:`group-buttons`},wn={class:`pull-error-content`},Tn={key:0},En={key:1},Dn={class:`pull-error-detail`},On={class:`pull-error-label`},kn={class:`pull-error-pre`},An=Z(o({__name:`GitOperationsButton`,props:{variant:{default:`icon`},hasUserCommitMessage:{type:Boolean,default:!1},finalCommitMessage:{default:``},skipHooks:{type:Boolean,default:!1}},emits:[`afterCommit`,`afterPush`,`beforePush`,`clearFields`],setup(t,{expose:i,emit:o}){let s=t,c=o,u=Q(),d=F(!1),f=F(!1),p=F({needsMerge:!1,error:``,fullError:``,pullOutput:``});function m(){d.value=!0}let h=z(()=>u.fileList.filter(e=>e.type===`added`).length),g=z(()=>u.branchBehind>0),_=z(()=>u.fileList.some(e=>[`modified`,`deleted`,`untracked`].includes(e.type)));async function v(){try{let e=await u.gitPull();e.success?(await u.fetchStatus(),await u.fetchLog(!1)):(p.value={needsMerge:e.needsMerge,error:e.error,fullError:e.fullError,pullOutput:e.pullOutput},f.value=!0)}catch(e){console.error(`拉取失败:`,e)}}async function y(){try{await u.gitFetchAll(),await u.fetchStatus(),await u.fetchLog(!1)}catch(e){console.error(`获取远程分支失败:`,e)}}async function b(){if(s.hasUserCommitMessage)try{await u.addAndCommit(s.finalCommitMessage,s.skipHooks),u.fetchStatus(),u.fetchLog(),c(`afterCommit`,!0),c(`clearFields`)}catch(e){console.error(`暂存并提交失败:`,e)}}function x(){c(`beforePush`)}function S(e){c(`afterPush`,e)}function C(){c(`clearFields`)}return i({openGitOperationsDrawer:m}),(i,o)=>{let w=O,T=e,E=l,D=a;return Y(),J(`div`,en,[s.variant===`icon`?(Y(),M(be,{key:0,tooltip:U(X)(`@F13B4:Git 操作`),size:`large`,"custom-class":`btn-rotate-on-hover`,onClick:m},{default:j(()=>[q(w,null,{default:j(()=>[q(U(H))]),_:1})]),_:1},8,[`tooltip`])):(Y(),M(T,{key:1,type:`primary`,class:`action-button`,onClick:m},{default:j(()=>[n(K(U(X)(`@F13B4:Git 操作`)),1)]),_:1})),q(D,{modelValue:d.value,"onUpdate:modelValue":o[2]||=e=>d.value=e,title:U(X)(`@76872:Git 操作`),direction:`rtl`,size:`362px`,"with-header":!0,"show-close":!0,"destroy-on-close":!1,"append-to-body":!0,class:`git-operations-drawer`},{default:j(()=>[R(`div`,tn,[R(`div`,nn,[R(`div`,rn,[R(`div`,an,K(U(X)(`@76872:基础操作`)),1),R(`div`,on,[q(je,{onClick:()=>{},from:`drawer`}),q(Ee,{onClick:()=>{},from:`drawer`}),q(Ne,{"has-user-commit-message":t.hasUserCommitMessage,"final-commit-message":t.finalCommitMessage,"skip-hooks":t.skipHooks,onBeforeCommit:()=>{},onAfterCommit:o[0]||=e=>c(`afterCommit`,e),onClick:()=>{},from:`drawer`},null,8,[`has-user-commit-message`,`final-commit-message`,`skip-hooks`]),q(et,{onBeforePush:()=>{},onAfterPush:o[1]||=e=>c(`afterPush`,e),onClick:()=>{},from:`drawer`}),q(E,{content:U(u).hasConflictedFiles?U(X)(`@76872:存在冲突文件,请先解决冲突`):g.value?`${U(X)(`@76872:拉取`)}${U(u).branchBehind}${U(X)(`@76872:个远程提交`)}`:`git pull`,placement:`top`},{default:j(()=>[q(T,{type:`primary`,icon:U(ie),onClick:v,loading:U(u).isGitPulling,disabled:!U(u).hasUpstream||U(u).hasConflictedFiles,class:`action-button`,style:N(U(u).hasUpstream&&!U(u).hasConflictedFiles?{color:`white`,backgroundColor:`#1e90ff`,borderColor:`#1e90ff`}:{})},{default:j(()=>[n(K(U(X)(`@76872:拉取`))+` `,1),g.value?(Y(),J(`span`,sn,`(`+K(U(u).branchBehind)+`)`,1)):G(``,!0)]),_:1},8,[`icon`,`loading`,`disabled`,`style`])]),_:1},8,[`content`]),q(E,{content:`git fetch --all`,placement:`top`},{default:j(()=>[q(T,{type:`info`,icon:U(de),onClick:y,loading:U(u).isGitFetching,class:`action-button`,style:{color:`white`,"background-color":`#1e90ff`,"border-color":`#1e90ff`}},{default:j(()=>[n(K(U(X)(`@76872:获取所有远程分支`)),1)]),_:1},8,[`icon`,`loading`])]),_:1})])]),R(`div`,cn,[R(`div`,ln,K(U(X)(`@76872:组合操作`)),1),R(`div`,un,[q(E,{content:U(u).hasConflictedFiles?U(X)(`@76872:存在冲突文件,请先解决冲突`):`git add + git commit`,placement:`top`},{default:j(()=>[q(T,{type:`primary`,icon:U(ne),onClick:b,loading:U(u).isAddingFiles||U(u).isCommiting,disabled:!_.value||!t.hasUserCommitMessage||U(u).hasConflictedFiles,class:`action-button`},{default:j(()=>[n(K(U(X)(`@76872:暂存并提交`)),1)]),_:1},8,[`icon`,`loading`,`disabled`])]),_:1},8,[`content`]),q(at,{from:`drawer`,"has-user-commit-message":t.hasUserCommitMessage,"final-commit-message":t.finalCommitMessage,"skip-hooks":t.skipHooks,onBeforePush:x,onAfterPush:S,onClearFields:C},null,8,[`has-user-commit-message`,`final-commit-message`,`skip-hooks`])])]),R(`div`,dn,[R(`div`,fn,K(U(X)(`@76872:重置操作`)),1),R(`div`,pn,[q(E,{content:h.value>0?`${U(X)(`@76872:撤销`)}${h.value}${U(X)(`@76872:个已暂存文件`)}`:`git reset HEAD`,placement:`top`},{default:j(()=>[q(T,{type:`warning`,icon:U(ge),onClick:U(u).resetHead,loading:U(u).isResetting,disabled:h.value===0||U(u).hasConflictedFiles,class:`action-button reset-button`},{default:j(()=>[n(K(U(X)(`@76872:重置暂存区`))+` `,1),h.value>0?(Y(),J(`span`,mn,`(`+K(h.value)+`)`,1)):G(``,!0)]),_:1},8,[`icon`,`onClick`,`loading`,`disabled`])]),_:1},8,[`content`]),q(Oe,{variant:`text`})])]),R(`div`,hn,[R(`div`,gn,K(U(X)(`@76872:分支操作`)),1),R(`div`,_n,[q(we,{variant:`text`})])]),R(`div`,vn,[R(`div`,yn,K(U(X)(`@76872:储藏操作`)),1),R(`div`,bn,[q(De,{variant:`text`}),q(Te,{variant:`text`})])]),R(`div`,xn,[R(`div`,Sn,K(U(X)(`@TAG01:标签操作`)),1),R(`div`,Cn,[q(mt,{variant:`text`}),q($t,{variant:`text`})])])])])]),_:1},8,[`modelValue`,`title`]),q(ve,{modelValue:f.value,"onUpdate:modelValue":o[3]||=e=>f.value=e,title:p.value.needsMerge?U(X)(`@76872:需要合并更改`):U(X)(`@76872:拉取失败`),size:`medium`,"show-footer":!0,"show-cancel":!1,"confirm-text":U(X)(`@76872:我知道了`),"append-to-body":!0,onConfirm:o[4]||=e=>f.value=!1},{default:j(()=>[R(`div`,wn,[R(`div`,{class:B([`pull-error-type`,p.value.needsMerge?`is-warning`:`is-error`])},[q(w,{class:`pull-error-icon`},{default:j(()=>[q(U(r))]),_:1}),p.value.needsMerge?(Y(),J(`span`,Tn,K(U(X)(`@76872:本地存在未提交的更改,与远程内容冲突,请先处理本地更改后再拉取。`)),1)):(Y(),J(`span`,En,K(U(X)(`@76872:执行 git pull 时发生错误,请查看详细信息。`)),1))],2),R(`div`,Dn,[R(`div`,On,K(U(X)(`@76872:错误详情`))+`:`,1),R(`pre`,kn,K(p.value.fullError||p.value.error),1)])])]),_:1},8,[`modelValue`,`title`,`confirm-text`])])}}}),[[`__scopeId`,`data-v-58350746`]]),jn={class:`loading-container`},Mn={class:`loading-text`},Nn={key:0,class:`loading-progress`},Pn=Z(o({__name:`GlobalLoading`,props:{visible:{type:Boolean,default:!1},text:{default:X(`@2AEBA:加载中...`)},showProgress:{type:Boolean,default:!1},progress:{default:0},mock:{type:Boolean,default:!1}},setup(e){return(t,n)=>(Y(),M(le,{to:`body`},[q(ae,{name:`loading-fade`},{default:j(()=>[e.visible||e.mock?(Y(),J(`div`,{key:0,class:`global-loading-overlay`,onClick:n[0]||=pe(()=>{},[`stop`])},[R(`div`,jn,[n[1]||=R(`div`,{class:`loading-spinner`},[R(`div`,{class:`spinner-ring`}),R(`div`,{class:`spinner-ring`}),R(`div`,{class:`spinner-ring`})],-1),R(`div`,Mn,K(e.text),1),e.showProgress||e.mock?(Y(),J(`div`,Nn,[R(`div`,{class:B([`progress-bar`,{"is-mock":e.mock&&!e.showProgress}]),style:N(e.showProgress?{width:e.progress+`%`}:void 0)},null,6)])):G(``,!0)])])):G(``,!0)]),_:1})]))}}),[[`__scopeId`,`data-v-6d13a220`]]),Fn={class:`success-container`},In={class:`success-text`},Ln={key:0,class:`success-description`},Rn=Z(o({__name:`SuccessModal`,props:{visible:{type:Boolean,default:!1},text:{default:X(`@71545:操作成功!`)},description:{default:``}},setup(e){return(t,n)=>(Y(),M(le,{to:`body`},[q(ae,{name:`success-fade`},{default:j(()=>[e.visible?(Y(),J(`div`,{key:0,class:`success-overlay`,onClick:n[0]||=pe(()=>{},[`stop`])},[R(`div`,Fn,[n[1]||=R(`div`,{class:`success-icon`},[R(`svg`,{viewBox:`0 0 52 52`,class:`success-svg`},[R(`circle`,{class:`success-circle`,cx:`26`,cy:`26`,r:`25`,fill:`none`}),R(`path`,{class:`success-check`,fill:`none`,d:`m14.1 27.2l7.1 7.2 16.7-16.8`})])],-1),R(`div`,In,K(e.text),1),e.description?(Y(),J(`div`,Ln,K(e.description),1)):G(``,!0)])])):G(``,!0)]),_:1})]))}}),[[`__scopeId`,`data-v-c10f43b3`]]),$=se({visible:!1,text:X(`@F2A3A:加载中...`),showProgress:!1,progress:0});function zn(){return{loadingState:$,show:e=>{$.visible=!0,$.text=e?.text||X(`@F2A3A:加载中...`),$.showProgress=e?.showProgress||!1,$.progress=e?.progress||0},hide:()=>{$.visible=!1},updateProgress:e=>{$.progress=Math.max(0,Math.min(100,e))},updateText:e=>{$.text=e},setText:e=>{$.visible&&($.text=e)}}}var Bn=se({visible:!1,text:X(`@B8591:操作成功!`),description:``});function Vn(){let e=e=>{Bn.visible=!0,Bn.text=e?.text||X(`@B8591:操作成功!`),Bn.description=e?.description||``;let n=e?.duration||2e3;setTimeout(()=>{t()},n)},t=()=>{Bn.visible=!1};return{successState:Bn,show:e,hide:t}}var Hn={class:`one-commit-content`},Un={class:`one-commit-text`},Wn={class:`one-commit-title`},Gn={key:0,class:`one-commit-desc`},Kn=Z(o({__name:`QuickCommitButton`,props:{from:{default:`form`},hasUserCommitMessage:{type:Boolean,default:!1},finalCommitMessage:{default:``},skipHooks:{type:Boolean,default:!1}},emits:[`beforeCommit`,`afterCommit`,`clearFields`],setup(t,{expose:n,emit:r}){let i=Q(),a=ye(),o=t,s=r;function c(e){let t=e.replace(/\\/g,`/`);return a.lockedFiles.some(e=>t===e.replace(/\\/g,`/`))}let u=z(()=>i.fileList.some(e=>!c(e.path))),d=z(()=>i.isSelectionMode&&i.selectedFiles.size>0&&i.selectedUnstagedPaths.length>0),f=z(()=>i.hasConflictedFiles?!0:i.isSelectionMode?!d.value||!o.hasUserCommitMessage:!u.value||!o.hasUserCommitMessage),p=z(()=>i.isAddingFiles||i.isCommiting),m=z(()=>i.hasConflictedFiles?X(`@2E184:存在冲突文件,请先解决冲突`):i.isSelectionMode?i.selectedFiles.size===0?X(`@2E184:请先勾选要提交的文件`):i.selectedUnstagedPaths.length===0?X(`@2E184:所选文件无需暂存或被锁定`):o.hasUserCommitMessage?X(`@2E184:一键完成:仅暂存所选文件 → 提交`):X(`@2E184:请输入提交信息`):u.value?o.hasUserCommitMessage?X(`@2E184:一键完成:暂存所有更改 → 提交`):X(`@2E184:请输入提交信息`):X(`@2E184:没有需要提交的更改`)),h=z(()=>i.isSelectionMode&&d.value?X(`@2E184:一键提交所选`):X(`@2E184:一键提交`)),g=z(()=>o.from===`form`?i.isSelectionMode&&d.value?X(`@2E184:暂存所选 + 提交`):X(`@2E184:暂存 + 提交`):``);async function _(){s(`beforeCommit`);try{let e=await i.stageSelectedAndCommit(o.finalCommitMessage,o.skipHooks);e&&s(`clearFields`),s(`afterCommit`,e)}catch(e){console.error(`一键提交失败:`,e),s(`afterCommit`,!1)}}return n({triggerQuickCommit:_}),(n,r)=>{let i=O,a=e;return Y(),J(`div`,null,[q(U(l),{content:m.value,placement:`top`,"show-after":200},{default:j(()=>[q(a,{type:`primary`,onClick:_,loading:p.value,disabled:f.value,class:B([t.from,`one-commit-button`])},{default:j(()=>[R(`div`,Hn,[q(i,{class:`one-commit-icon`},{default:j(()=>[q(U(ne))]),_:1}),R(`div`,Un,[R(`span`,Wn,K(h.value),1),t.from===`form`?(Y(),J(`span`,Gn,K(g.value),1)):G(``,!0)])])]),_:1},8,[`loading`,`disabled`,`class`])]),_:1},8,[`content`])])}}}),[[`__scopeId`,`data-v-620d61d7`]]),qn={class:`form-bottom-actions`},Jn={class:`actions-flex-container`},Yn={class:`left-actions`},Xn={class:`button-grid`},Zn={class:`right-actions`},Qn=Z(o({__name:`GitActionButtons`,props:{hasUserCommitMessage:{type:Boolean,default:!1},finalCommitMessage:{default:``},skipHooks:{type:Boolean,default:!1},from:{default:`form`}},emits:[`afterCommit`,`afterPush`,`beforePush`,`pushStart`,`clearFields`],setup(e,{expose:t,emit:n}){let r=n,i=F(null);function a(e){r(`afterCommit`,e)}function o(e){r(`afterPush`,e)}function s(){r(`beforePush`)}function c(){r(`pushStart`)}function l(){r(`clearFields`)}async function u(){return i.value?.triggerQuickPush()}return t({triggerQuickPush:u}),(t,n)=>(Y(),J(`div`,qn,[R(`div`,Jn,[R(`div`,Yn,[R(`div`,Xn,[q(je,{onClick:()=>{},from:e.from},null,8,[`from`]),q(Ne,{"has-user-commit-message":e.hasUserCommitMessage,"final-commit-message":e.finalCommitMessage,"skip-hooks":e.skipHooks,onBeforeCommit:()=>{},onAfterCommit:a,onClick:()=>{},from:e.from},null,8,[`has-user-commit-message`,`final-commit-message`,`skip-hooks`,`from`]),q(et,{onBeforePush:()=>{},onAfterPush:o,onClick:()=>{},from:e.from},null,8,[`from`])])]),R(`div`,Zn,[q(Kn,{from:e.from,"has-user-commit-message":e.hasUserCommitMessage,"final-commit-message":e.finalCommitMessage,"skip-hooks":e.skipHooks,onAfterCommit:a,onClearFields:l},null,8,[`from`,`has-user-commit-message`,`final-commit-message`,`skip-hooks`]),q(at,{ref_key:`quickPushRef`,ref:i,from:e.from,"has-user-commit-message":e.hasUserCommitMessage,"final-commit-message":e.finalCommitMessage,"skip-hooks":e.skipHooks,onBeforePush:s,onPushStart:c,onAfterPush:o,onClearFields:l},null,8,[`from`,`has-user-commit-message`,`final-commit-message`,`skip-hooks`])])])]))}}),[[`__scopeId`,`data-v-2f7ac0a2`]]),$n={class:`dialog-toolbar`},er={class:`filter-controls`},tr={class:`toolbar-actions`},nr=[`disabled`],rr={class:`btn-text`},ir=[`disabled`],ar={class:`btn-text`},or=[`disabled`],sr={class:`btn-text`},cr={class:`history-scroll`},lr={key:0,class:`loading-state`},ur={class:`loading-text`},dr={key:3,class:`history-list`},fr=[`onClick`],pr={class:`command-info`},mr={class:`command-text`},hr={class:`command-meta`},gr={class:`timestamp`},_r={class:`duration`},vr={class:`item-actions`},yr={key:0,class:`item-details`},br={key:0,class:`output-section`},xr={class:`output-header`},Sr=[`onClick`],Cr={class:`output-content`},wr={key:0,class:`truncation-notice`},Tr={class:`output-header`},Er={class:`output-content`},Dr={key:0,class:`truncation-notice`},Or={key:2,class:`output-section error`},kr={class:`output-header`},Ar={class:`output-content`},jr=Z(o({__name:`CommandHistory`,setup(e){let r=Q(),i=F([]),a=F(!1),o=F(!1),c=F(!1),u=F(!1),d=F(new Set),m=F(!1),_=F(!1),v=F(`all`),y=F(`all`),b=F(``),S=z(()=>{let e=i.value;if(v.value!==`all`&&(e=e.filter(e=>v.value===`success`?e.success:!e.success)),y.value!==`all`&&(e=e.filter(e=>{let t=e.command.trim().startsWith(`git `);return y.value===`git`?t:!t})),b.value.trim()){let t=b.value.toLowerCase();e=e.filter(e=>e.command.toLowerCase().includes(t)||e.stdout&&e.stdout.toLowerCase().includes(t)||e.stderr&&e.stderr.toLowerCase().includes(t)||e.error&&e.error.toLowerCase().includes(t))}return e}),k=z(()=>i.value.filter(e=>e.success).length),A=z(()=>i.value.filter(e=>!e.success).length),N=z(()=>i.value.filter(e=>e.command.trim().startsWith(`git `)).length),te=z(()=>i.value.filter(e=>!e.command.trim().startsWith(`git `)).length);function ne(){_.value=!0,i.value.length===0&&H()}async function H(){try{if(a.value=!0,r.socket&&r.socket.connected)r.socket.emit(`request_full_history`);else{let e=await(await fetch(`/api/command-history`)).json();e.success?i.value=e.history:P.error(`${X(`@81F0F:加载命令历史失败: `)}${e.error}`)}}catch(e){P.error(`${X(`@81F0F:加载命令历史失败: `)}${e.message}`)}finally{a.value=!1}}async function ie(){if(S.value.length===0){P.warning(X(`@81F0F:没有可复制的命令历史`));return}try{c.value=!0;let e=S.value.map(e=>{let t=`# ${W(e.timestamp)}${X(`@81F0F: (耗时: `)}${se(e.executionTime)}) - ${e.success?X(`@81F0F:成功`):X(`@81F0F:失败`)}\n`;if(t+=`${e.command}\n`,e.stdout&&(t+=`\n# 输出:\n${e.stdout}\n`),e.stderr){let n=fe(e.command)?X(`@81F0F:输出信息`):X(`@81F0F:错误输出`);t+=`\n# ${n}:\n${e.stderr}\n`}return e.error&&(t+=`\n# 错误信息:\n${e.error}\n`),t}).join(`
2
- ---
3
-
4
- `);await navigator.clipboard.writeText(e),P({message:X(`@81F0F:命令历史已复制到剪贴板`),type:`success`,zIndex:1e5})}catch(e){P.error(`${X(`@81F0F:复制失败: `)}${e.message}`)}finally{c.value=!1}}async function ae(){if(S.value.length===0){P.warning(X(`@81F0F:没有可复制的命令`));return}try{m.value=!0;let e=S.value.map(e=>e.command).join(`
5
- `);await navigator.clipboard.writeText(e),P({message:X(`@81F0F:命令列表已复制到剪贴板`),type:`success`,zIndex:1e5})}catch(e){P.error(`${X(`@81F0F:复制失败: `)}${e.message}`)}finally{m.value=!1}}async function oe(){try{if(await V.confirm(X(`@81F0F:确定要清空所有命令历史记录吗?此操作不可恢复。`),X(`@81F0F:清空命令历史`),{confirmButtonText:X(`@81F0F:确定`),cancelButtonText:X(`@81F0F:取消`),type:`warning`}),o.value=!0,r.socket&&r.socket.connected)r.socket.emit(`clear_command_history`);else{let e=await(await fetch(`/api/clear-command-history`,{method:`POST`,headers:{"Content-Type":`application/json`}})).json();e.success?(i.value=[],P.success(X(`@81F0F:命令历史已清空`))):P.error(`${X(`@81F0F:清空命令历史失败: `)}${e.error}`)}}catch(e){e!==`cancel`&&e.toString()!==`Error: cancel`&&P.error(`${X(`@81F0F:清空命令历史失败: `)}${e.message}`)}finally{o.value=!1}}function W(e){return new Date(e).toLocaleString()}function se(e){return e<1e3?`${e}ms`:`${(e/1e3).toFixed(2)}s`}function ce(e){d.value.has(e)?d.value.delete(e):d.value.add(e)}function le(e){return d.value.has(e)}async function ue(e){try{await navigator.clipboard.writeText(e),P({message:X(`@81F0F:命令已复制到剪贴板`),type:`success`,zIndex:1e5})}catch(e){P.error(`${X(`@81F0F:复制失败: `)}${e.message}`)}}function de(e){return e.includes(`git push`)||e.includes(`git-push`)}function fe(e){return!!de(e)}async function me(e){try{let t=``;if(e.stdout&&(t+=`标准输出:\n${e.stdout}\n\n`),e.stderr){let n=fe(e.command)?X(`@81F0F:输出信息`):X(`@81F0F:错误输出`);t+=`${n}:\n${e.stderr}\n\n`}e.error&&(t+=`错误信息:\n${e.error}`),await navigator.clipboard.writeText(t.trim()),P({message:X(`@81F0F:输出已复制到剪贴板`),type:`success`,zIndex:1e5})}catch(e){P.error(`${X(`@81F0F:复制失败: `)}${e.message}`)}}function ge(){if(!r.socket){console.error(X(`@81F0F:Socket实例不可用`));return}r.socket.on(`initial_command_history`,e=>{i.value=e.history,u.value=!0}),r.socket.on(`command_history_update`,e=>{i.value.unshift(e.newCommand),i.value.length>100&&i.value.pop(),u.value=!0}),r.socket.on(`full_command_history`,e=>{i.value=e.history,a.value=!1,u.value=!0}),r.socket.on(`command_history_cleared`,e=>{e.success&&(i.value=[],P.success(X(`@81F0F:命令历史已清空`))),o.value=!1}),r.socket.on(`connect`,()=>{u.value=!0,P.success(X(`@81F0F:已连接到实时命令历史`))}),r.socket.on(`disconnect`,()=>{u.value=!1,P.warning(X(`@81F0F:实时命令历史连接已断开`))})}function _e(){r.socket&&(r.socket.off(`initial_command_history`),r.socket.off(`command_history_update`),r.socket.off(`full_command_history`),r.socket.off(`command_history_cleared`))}return f(()=>{ge(),r.socket||(console.log(X(`@81F0F:尝试初始化Socket连接`)),r.initSocketConnection())}),g(()=>{_e()}),(e,r)=>{let d=O,f=he,g=h,P=C,F=E,z=l,V=w,H=p;return Y(),J(L,null,[q(be,{tooltip:U(X)(`@81F0F:查看Git命令历史`),size:`large`,onClick:ne},{default:j(()=>[q(d,null,{default:j(()=>[q(U(ee))]),_:1})]),_:1},8,[`tooltip`]),q(ve,{modelValue:_.value,"onUpdate:modelValue":r[3]||=e=>_.value=e,title:U(X)(`@81F0F:Git 命令历史`),"destroy-on-close":``,"custom-class":`command-history-dialog`,"append-to-body":!0},{default:j(()=>[R(`div`,$n,[q(f,{type:u.value?`success`:`danger`,size:`small`,effect:`dark`,class:`socket-status`},{default:j(()=>[n(K(u.value?U(X)(`@81F0F:实时更新`):U(X)(`@81F0F:未连接`)),1)]),_:1},8,[`type`]),R(`div`,er,[q(P,{modelValue:v.value,"onUpdate:modelValue":r[0]||=e=>v.value=e,size:`small`,class:`filter-select`},{default:j(()=>[q(g,{label:`全部状态`,value:`all`}),q(g,{label:`成功 (${k.value})`,value:`success`},null,8,[`label`]),q(g,{label:`失败 (${A.value})`,value:`error`},null,8,[`label`])]),_:1},8,[`modelValue`]),q(P,{modelValue:y.value,"onUpdate:modelValue":r[1]||=e=>y.value=e,size:`small`,class:`filter-select`},{default:j(()=>[q(g,{label:`全部命令`,value:`all`}),q(g,{label:`Git 命令 (${N.value})`,value:`git`},null,8,[`label`]),q(g,{label:`其他命令 (${te.value})`,value:`other`},null,8,[`label`])]),_:1},8,[`modelValue`]),q(F,{modelValue:b.value,"onUpdate:modelValue":r[2]||=e=>b.value=e,size:`small`,placeholder:`搜索命令或输出...`,clearable:``,class:`search-input`},{prefix:j(()=>[q(d,null,{default:j(()=>[q(U(t))]),_:1})]),_:1},8,[`modelValue`])]),R(`div`,tr,[q(z,{content:U(X)(`@81F0F:只复制命令列表(不含输出)`),placement:`bottom`,effect:`dark`,"show-after":200},{default:j(()=>[R(`button`,{class:`modern-btn copy-commands-button enhanced-btn`,onClick:ae,disabled:S.value.length===0||m.value},[m.value?(Y(),M(d,{key:1,class:`btn-icon is-loading`},{default:j(()=>[q(U(s))]),_:1})):(Y(),M(d,{key:0,class:`btn-icon`},{default:j(()=>[q(U(I))]),_:1})),R(`span`,rr,K(U(X)(`@81F0F:命令`)),1)],8,nr)]),_:1},8,[`content`]),q(z,{content:U(X)(`@81F0F:复制完整命令历史(含输出)`),placement:`bottom`,effect:`dark`,"show-after":200},{default:j(()=>[R(`button`,{class:`modern-btn copy-all-button enhanced-btn`,onClick:ie,disabled:S.value.length===0||c.value},[c.value?(Y(),M(d,{key:1,class:`btn-icon is-loading`},{default:j(()=>[q(U(s))]),_:1})):(Y(),M(d,{key:0,class:`btn-icon`},{default:j(()=>[q(U(I))]),_:1})),R(`span`,ar,K(U(X)(`@81F0F:全部`)),1)],8,ir)]),_:1},8,[`content`]),q(z,{content:U(X)(`@81F0F:清空命令历史`),placement:`bottom`,effect:`dark`,"show-after":200},{default:j(()=>[R(`button`,{class:`modern-btn clear-button enhanced-btn danger-btn`,onClick:oe,disabled:i.value.length===0||o.value},[o.value?(Y(),M(d,{key:1,class:`btn-icon is-loading`},{default:j(()=>[q(U(s))]),_:1})):(Y(),M(d,{key:0,class:`btn-icon`},{default:j(()=>[q(U(re))]),_:1})),R(`span`,sr,K(U(X)(`@81F0F:清空`)),1)],8,or)]),_:1},8,[`content`])])]),R(`div`,cr,[a.value&&i.value.length===0?(Y(),J(`div`,lr,[q(d,{class:`loading-icon is-loading`},{default:j(()=>[q(U(s))]),_:1}),R(`div`,ur,K(U(X)(`@81F0F:加载命令历史...`)),1)])):i.value.length===0?(Y(),M(V,{key:1,description:U(X)(`@81F0F:暂无命令历史`)},null,8,[`description`])):S.value.length===0?(Y(),M(V,{key:2,description:U(X)(`@81F0F:没有匹配的命令`)},null,8,[`description`])):(Y(),J(`div`,dr,[(Y(!0),J(L,null,T(S.value,(e,t)=>(Y(),J(`div`,{key:t,class:B([`history-item`,{"is-error":!e.success}])},[R(`div`,{class:`item-header`,onClick:e=>ce(t)},[R(`div`,pr,[R(`div`,mr,[q(f,{size:`small`,type:e.success?`success`:`danger`,effect:`dark`,class:`status-tag`},{default:j(()=>[n(K(e.success?U(X)(`@81F0F:成功`):U(X)(`@81F0F:失败`)),1)]),_:2},1032,[`type`]),R(`code`,null,K(e.command),1)]),R(`div`,hr,[R(`span`,gr,K(W(e.timestamp)),1),R(`span`,_r,K(U(X)(`@81F0F:耗时: `))+K(se(e.executionTime)),1)])]),R(`div`,vr,[q(be,{tooltip:U(X)(`@81F0F:复制命令`),"custom-class":`item-copy-button`,onClick:pe(t=>ue(e.command),[`stop`])},{default:j(()=>[q(d,null,{default:j(()=>[q(U(I))]),_:1})]),_:1},8,[`tooltip`,`onClick`]),R(`div`,{class:B([`expand-button`,{"is-expanded":le(t)}])},[q(d,{class:`btn-icon`},{default:j(()=>[le(t)?(Y(),M(U(x),{key:0})):(Y(),M(U(D),{key:1}))]),_:2},1024)],2)])],8,fr),le(t)?(Y(),J(`div`,yr,[e.stdout?(Y(),J(`div`,br,[R(`div`,xr,[R(`h4`,null,K(U(X)(`@81F0F:标准输出`)),1),q(z,{content:U(X)(`@81F0F:复制输出`),placement:`bottom`,effect:`dark`,"show-after":200},{default:j(()=>[R(`button`,{class:`modern-btn output-copy-button enhanced-btn`,onClick:t=>me(e)},[q(d,{class:`btn-icon`},{default:j(()=>[q(U(I))]),_:1})],8,Sr)]),_:2},1032,[`content`])]),R(`pre`,Cr,K(e.stdout),1),e.isStdoutTruncated?(Y(),J(`div`,wr,[q(H,{type:`info`,closable:!1,"show-icon":``},{default:j(()=>[n(K(U(X)(`@81F0F:输出内容过长已被截断,请直接执行命令查看完整输出`)),1)]),_:1})])):G(``,!0)])):G(``,!0),e.stderr?(Y(),J(`div`,{key:1,class:B([`output-section`,fe(e.command)?``:`error`])},[R(`div`,Tr,[R(`h4`,null,K(fe(e.command)?U(X)(`@81F0F:输出信息`):U(X)(`@81F0F:错误输出`)),1)]),R(`pre`,Er,K(e.stderr),1),e.isStderrTruncated?(Y(),J(`div`,Dr,[q(H,{type:`info`,closable:!1,"show-icon":``},{default:j(()=>[n(K(fe(e.command)?U(X)(`@81F0F:输出信息`):U(X)(`@81F0F:错误输出`))+K(U(X)(`@81F0F:内容过长已被截断,请直接执行命令查看完整输出`)),1)]),_:2},1024)])):G(``,!0)],2)):G(``,!0),e.error?(Y(),J(`div`,Or,[R(`div`,kr,[R(`h4`,null,K(U(X)(`@81F0F:错误信息`)),1)]),R(`pre`,Ar,K(e.error),1)])):G(``,!0)])):G(``,!0)],2))),128))]))])]),_:1},8,[`modelValue`,`title`])],64)}}}),[[`__scopeId`,`data-v-75b80e1e`]]),Mr={class:`card-header app-card-header`},Nr={class:`header-left`},Pr={class:`header-right`},Fr={class:`card-content app-card-content`},Ir={class:`layout-container`},Lr={key:0,class:`git-config-warning`},Rr={key:0,class:`merge-in-progress-banner`},zr={class:`commit-section`},Br={key:0,class:`commit-form`},Vr={class:`description-container`},Hr={key:1,class:`standard-commit-form`},Ur={class:`standard-commit-header`},Wr={class:`type-scope-container`},Gr={class:`scope-wrapper`},Kr={class:`description-container description-inline`},qr={class:`advanced-fields`},Jr={key:0,class:`status-updating-indicator`},Yr={key:0,class:`status-updating-indicator`},Xr=Z(o({__name:`CommitForm`,setup(e){let t=F(!1);async function n(){if(!t.value){t.value=!0;try{let e=r.isSelectionMode&&r.selectedFiles.size>0?[...r.selectedFiles]:[],t=xe(),n=await(await fetch(`/api/config/generate-commit-message`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({selectedPaths:e,locale:t.currentLocale})})).json();if(!n.success){P.error(n.error||X(`@76872:AI生成失败`));return}let i=[`feat`,`fix`,`docs`,`style`,`refactor`,`test`,`chore`];if(y.value)n.type&&i.includes(n.type)&&(b.value=n.type),n.scope!==void 0&&(x.value=n.scope),n.description&&(w.value=n.description);else{let e=n.type&&n.description?n.scope?`${n.type}(${n.scope}): ${n.description}`:`${n.type}: ${n.description}`:n.description||``;e&&(a.value=e)}P.success(X(`@76872:AI已生成提交信息`))}catch(e){P.error(`${X(`@76872:AI生成失败`)}: ${e.message}`)}finally{t.value=!1}}}let r=Q(),i=ye(),a=F(``),{loadingState:o,show:c,hide:l,setText:d}=zn(),{successState:m}=Vn(),g=F(!1),_=F(`输入提交信息...`),v=F(``),y=z({get:()=>i.isStandardCommit,set:e=>{i.isStandardCommit=e}}),b=F(`feat`),x=F(``),w=F(``),A=F(``),N=F(``),ee=F([]),I=F(!1),ne=F([]),V=F(!1),H=F(!1),re=z({get:()=>i.skipHooks,set:e=>{i.skipHooks=e}}),ie=z({get:()=>i.autoQuickPushOnEnter,set:e=>{i.autoQuickPushOnEnter=e}}),oe=F(null),W=F(!1),se=z(()=>[{value:`feat`,label:`feat: ${X(`@76872:新功能`)}`},{value:`fix`,label:`fix: ${X(`@76872:修复bug`)}`},{value:`docs`,label:`docs: ${X(`@76872:文档修改`)}`},{value:`style`,label:`style: ${X(`@76872:样式修改`)}`},{value:`refactor`,label:`refactor: ${X(`@76872:代码重构`)}`},{value:`test`,label:`test: ${X(`@76872:测试代码`)}`},{value:`chore`,label:`chore: ${X(`@76872:构建/工具修改`)}`}]),ce=F([]),le=z(()=>{if(!y.value)return a.value||v.value;let e=`${b.value||``}`;return x.value&&(e+=`(${x.value})`),e+=`: ${w.value}`,A.value&&(e+=`\n\n${A.value}`),N.value&&(e+=`\n\n${N.value}`),e}),ue=z(()=>y.value?(r.isMergeInProgress||(b.value||``).trim()!==``)&&(w.value||``).trim()!==``:a.value.trim()!==``),de=z(()=>r.hasConflictedFiles?!0:r.isMergeInProgress?!ue.value:!r.fileList.some(e=>!Oe(e.path))||!ue.value),fe=z(()=>{let e=`${X(`@76872:输入提交信息 (默认: `)}${v.value})`;return ie.value?`${e}${X(`@76872:(按回车一键推送)`)}`:e}),pe=z(()=>{let e=X(`@76872:简短描述(必填)`);return ie.value?X(`@76872:简短描述(必填,按回车一键推送)`):e}),me=z(()=>{let e=`git commit -m "${le.value}"`;return re.value&&(e+=` --no-verify`),e});function he(){let e=i.config;e&&(_.value=`${X(`@76872:输入提交信息 (默认: `)}${e.defaultCommitMessage})`,v.value=e.defaultCommitMessage||``,e.descriptionTemplates&&Array.isArray(e.descriptionTemplates)&&(ee.value=e.descriptionTemplates),e.scopeTemplates&&Array.isArray(e.scopeTemplates)&&(ne.value=e.scopeTemplates),e.messageTemplates&&Array.isArray(e.messageTemplates)&&(ce.value=e.messageTemplates))}function ge(e){w.value=e,I.value=!1}function _e(e){x.value=e,V.value=!1}function Z(){I.value=!0}function ve(){V.value=!0}function we(){a.value=``,w.value=``,A.value=``,N.value=``,b.value=`feat`,i.autoSetDefaultMessage&&i.defaultCommitMessage&&(y.value?w.value=i.defaultCommitMessage:a.value=i.defaultCommitMessage)}function Te(){c({text:X(`@76872:正在暂存文件...`),showProgress:!1})}function Ee(){l()}function De(e){if(l(),e){g.value=!0;try{setTimeout(async()=>{try{console.log(X(`@76872:推送成功,状态已更新`))}catch(e){console.error(`一键推送后处理失败:`,e)}finally{g.value=!1}},1e3)}catch(e){console.error(`一键推送后处理失败:`,e),g.value=!1}}}function Oe(e){let t=e.replace(/\\/g,`/`);return i.lockedFiles.some(e=>t===e.replace(/\\/g,`/`))}function ke(e){a.value=e,H.value=!1}async function Ae(e){if(!ie.value||!ue.value)return;let t=r.fileList.some(e=>!Oe(e.path)),n=r.hasConflictedFiles;if(!(!t||!ue.value||!r.hasUpstream||n)&&e.key===`Enter`&&!e.shiftKey){e.preventDefault();try{await oe.value?.triggerQuickPush()}catch(e){console.error(`回车自动一键提交失败:`,e)}}}async function je(e){try{await i.saveDefaultMessage(e)&&P.success(X(`@76872:默认提交信息设置成功`))}catch(e){P.error(`${X(`@76872:设置默认提交信息失败: `)}${e.message}`)}}k(()=>r.pendingMergeMessage,e=>{e&&(y.value?(b.value=``,w.value=e):a.value=e,r.pendingMergeMessage=``,P.info(X(`@76872:已自动填充合并提交信息`)))}),k(()=>r.isAddingFiles,e=>{e&&o.visible&&d(X(`@76872:正在暂存文件...`))}),k(()=>r.isCommiting,e=>{e&&o.visible&&d(X(`@76872:正在提交更改...`))}),k(()=>r.isPushing,e=>{e&&o.visible&&l()}),f(async()=>{k(()=>i.config,he,{immediate:!0}),i.config||await i.loadConfig(),i.autoSetDefaultMessage&&i.defaultCommitMessage&&(y.value?w.value||=i.defaultCommitMessage:a.value||=i.defaultCommitMessage),r.pendingMergeMessage&&(y.value?(b.value=``,w.value=r.pendingMergeMessage):a.value=r.pendingMergeMessage,r.pendingMergeMessage=``,P.info(X(`@76872:已自动填充合并提交信息`)))});function Me(e,t){t([...e?ee.value.filter(t=>t.toLowerCase().includes(e.toLowerCase())).map(e=>({value:e})):ee.value.map(e=>({value:e})),{value:`⚙️ 管理模板...`,isSettings:!0}])}function Ne(e,t){t([...e?ne.value.filter(t=>t.toLowerCase().includes(e.toLowerCase())).map(e=>({value:e})):ne.value.map(e=>({value:e})),{value:`⚙️ 管理模板...`,isSettings:!0}])}function Pe(e){e.isSettings?(Z(),w.value=``):w.value=e.value}function Fe(e){e.isSettings?(ve(),x.value=``):x.value=e.value}function Ie(e,t){t([...e?ce.value.filter(t=>t.toLowerCase().includes(e.toLowerCase())).map(e=>({value:e})):ce.value.map(e=>({value:e})),{value:`⚙️ 管理模板...`,isSettings:!0}])}function Le(e){e.isSettings?(H.value=!0,a.value=``):a.value=e.value}return(e,i)=>{let c=O,l=An,d=p,f=u,_=h,v=C,k=E;return Y(),J(L,null,[R(`div`,{class:B([`card app-card`,{"is-pushing":U(r).isPushing}])},[R(`div`,Mr,[R(`div`,Nr,[U(r).userName!==``&&U(r).userEmail!==``?(Y(),M(Qn,{key:0,ref_key:`gitActionButtonsRef`,ref:oe,"has-user-commit-message":ue.value,"final-commit-message":le.value,"skip-hooks":re.value,onAfterCommit:i[0]||=e=>{e&&we()},onAfterPush:De,onBeforePush:Te,onPushStart:Ee,onClearFields:we},null,8,[`has-user-commit-message`,`final-commit-message`,`skip-hooks`])):G(``,!0)]),R(`div`,Pr,[q(be,{tooltip:U(X)(`@76872:AI生成提交信息`),"icon-class":t.value?``:`ai-commit`,size:`medium`,disabled:t.value,onClick:n},{default:j(()=>[t.value?(Y(),M(c,{key:0,class:`is-loading`},{default:j(()=>[q(U(s))]),_:1})):G(``,!0)]),_:1},8,[`tooltip`,`icon-class`,`disabled`]),q(jr),q(l,{class:`ml-auto`,variant:`icon`})])]),R(`div`,Fr,[R(`div`,Ir,[U(r).userName===``||U(r).userEmail===``?(Y(),J(`div`,Lr,[q(d,{title:U(X)(`@76872:Git用户信息未配置`),type:`warning`,closable:!1,"show-icon":``},{default:j(()=>[R(`p`,null,K(U(X)(`@76872:您需要配置Git用户名和邮箱才能提交代码。请使用以下命令配置:`)),1),i[11]||=R(`pre`,{class:`config-command`},`git config --global user.name "Your Name"
6
- git config --global user.email "your.email@example.com"`,-1)]),_:1},8,[`title`])])):(Y(),J(L,{key:1},[U(r).isMergeInProgress?(Y(),J(`div`,Rr,[q(d,{title:U(X)(`@76872:合并进行中`),type:`warning`,closable:!1,"show-icon":``},{default:j(()=>[R(`span`,null,K(U(X)(`@76872:分支合并尚未完成,请输入提交信息后点击「提交」按钮完成合并。`)),1)]),_:1},8,[`title`])])):G(``,!0),R(`div`,zr,[y.value?(Y(),J(`div`,Hr,[R(`div`,Ur,[R(`div`,Wr,[q(v,{modelValue:b.value,"onUpdate:modelValue":i[2]||=e=>b.value=e,placeholder:U(X)(`@76872:提交类型`),class:`type-select`,clearable:``},{default:j(()=>[(Y(!0),J(L,null,T(se.value,e=>(Y(),M(_,{key:e.value,label:e.label,value:e.value},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`,`placeholder`]),R(`div`,Gr,[q(f,{modelValue:x.value,"onUpdate:modelValue":i[3]||=e=>x.value=e,"fetch-suggestions":Ne,placeholder:U(X)(`@76872:作用域(可选)`),class:`scope-input`,clearable:``,onSelect:Fe},null,8,[`modelValue`,`placeholder`])]),R(`div`,Kr,[q(f,{modelValue:w.value,"onUpdate:modelValue":i[4]||=e=>w.value=e,"fetch-suggestions":Me,placeholder:pe.value,class:`description-input`,clearable:``,onSelect:Pe,onKeydown:Ae},null,8,[`modelValue`,`placeholder`])])])]),R(`div`,{class:`advanced-options-toggle`,onClick:i[5]||=e=>W.value=!W.value},[R(`span`,null,K(W.value?U(X)(`@76872:收起`):U(X)(`@76872:正文及页脚`)),1),q(c,{class:B([`toggle-icon`,{"is-active":W.value}])},{default:j(()=>[q(U(D))]),_:1},8,[`class`])]),S(R(`div`,qr,[q(k,{modelValue:A.value,"onUpdate:modelValue":i[6]||=e=>A.value=e,type:`textarea`,rows:4,placeholder:U(X)(`@76872:正文(可选):详细描述本次提交的内容和原因`),class:`body-input`,clearable:``},null,8,[`modelValue`,`placeholder`]),q(k,{modelValue:N.value,"onUpdate:modelValue":i[7]||=e=>N.value=e,placeholder:U(X)(`@76872:页脚(可选):如 Closes #123`),class:`footer-input`,clearable:``},null,8,[`modelValue`,`placeholder`])],512),[[te,W.value]])])):(Y(),J(`div`,Br,[R(`div`,Vr,[q(f,{modelValue:a.value,"onUpdate:modelValue":i[1]||=e=>a.value=e,"fetch-suggestions":Ie,placeholder:fe.value,type:`textarea`,rows:3,resize:`none`,class:`commit-message-input`,onSelect:Le,onKeydown:Ae},null,8,[`modelValue`,`placeholder`])])])),de.value?G(``,!0):(Y(),M(Ce,{key:2,command:me.value,title:U(X)(`@76872:提交命令预览:`),placeholder:`git commit -m "<提交信息>"`},null,8,[`command`,`title`]))])],64))])])],2),q(Se,{visible:I.value,"onUpdate:visible":i[8]||=e=>I.value=e,type:`description`,title:U(X)(`@76872:简短描述模板设置`),placeholder:U(X)(`@76872:输入新模板内容`),"edit-placeholder":U(X)(`@76872:编辑模板内容`),"empty-description":U(X)(`@76872:暂无保存的模板`),onUseTemplate:ge},null,8,[`visible`,`title`,`placeholder`,`edit-placeholder`,`empty-description`]),q(Se,{visible:V.value,"onUpdate:visible":i[9]||=e=>V.value=e,type:`scope`,title:U(X)(`@76872:作用域模板设置`),placeholder:U(X)(`@76872:输入新作用域模板`),"edit-placeholder":U(X)(`@76872:编辑作用域模板内容`),"empty-description":U(X)(`@76872:暂无保存的作用域`),onUseTemplate:_e},null,8,[`visible`,`title`,`placeholder`,`edit-placeholder`,`empty-description`]),q(Se,{visible:H.value,"onUpdate:visible":i[10]||=e=>H.value=e,type:`message`,title:U(X)(`@76872:默认提交信息设置`),placeholder:U(X)(`@76872:输入新模板内容`),"edit-placeholder":U(X)(`@76872:编辑模板内容`),"empty-description":U(X)(`@76872:暂无保存的模板`),"show-default-section":!0,"show-help-text":!0,onUseTemplate:ke,onSetDefault:je},null,8,[`visible`,`title`,`placeholder`,`edit-placeholder`,`empty-description`]),q(ae,{name:`el-fade-in-linear`},{default:j(()=>[g.value?(Y(),J(`div`,Jr,[q(c,{class:`is-loading`},{default:j(()=>[q(U(s))]),_:1}),R(`span`,null,K(U(X)(`@76872:更新状态中...`)),1)])):G(``,!0)]),_:1}),q(Pn,{visible:U(o).visible,text:U(o).text,"show-progress":U(o).showProgress,progress:U(o).progress},null,8,[`visible`,`text`,`show-progress`,`progress`]),q(Rn,{visible:U(m).visible,text:U(m).text,description:U(m).description},null,8,[`visible`,`text`,`description`]),q(ae,{name:`el-fade-in-linear`},{default:j(()=>[g.value?(Y(),J(`div`,Yr,[q(c,{class:`is-loading`},{default:j(()=>[q(U(s))]),_:1}),R(`span`,null,K(U(X)(`@76872:更新状态中...`)),1)])):G(``,!0)]),_:1})],64)}}}),[[`__scopeId`,`data-v-a5b34a76`]]);export{Xr as default};