zen-gitsync 2.17.21 → 2.17.23

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 (60) hide show
  1. package/README.md +20 -12
  2. package/package.json +10 -1
  3. package/scripts/release.js +214 -82
  4. package/src/ui/public/assets/{AgentEngineSelector-D_8VedA0.js → AgentEngineSelector-DLJ8He83.js} +1 -1
  5. package/src/ui/public/assets/{AgentView-CpKIfQLq.js → AgentView-CQ18nw02.js} +1 -1
  6. package/src/ui/public/assets/{AppVersionBadge-kyk4Mmvf.js → AppVersionBadge-1pyUzRer.js} +2 -2
  7. package/src/ui/public/assets/{BranchSelector-BUPiKcdW.js → BranchSelector-DrsrZiWJ.js} +1 -1
  8. package/src/ui/public/assets/{CommitForm-CMe1gjY-.js → CommitForm-B5p-7P7m.js} +1 -1
  9. package/src/ui/public/assets/{CommonDialog-DMWtstZq.js → CommonDialog-BEm2cK1X.js} +1 -1
  10. package/src/ui/public/assets/{EditorView-mUmFBb7H.css → EditorView-C6HFYeEM.css} +1 -1
  11. package/src/ui/public/assets/EditorView-fuMrS9P7.js +1 -0
  12. package/src/ui/public/assets/{FileDiffViewer-CvN5b1ZC.js → FileDiffViewer-CYxcLw10.js} +1 -1
  13. package/src/ui/public/assets/{FlowExecutionViewer-Ynr4q8qE.js → FlowExecutionViewer-DTmlBLXQ.js} +1 -1
  14. package/src/ui/public/assets/{FlowOrchestrationWorkspace-DPDZc9uf.js → FlowOrchestrationWorkspace-Da_UmTRT.js} +1 -1
  15. package/src/ui/public/assets/{IconButton-CFJkDLVG.js → IconButton-BShiC2AP.js} +1 -1
  16. package/src/ui/public/assets/{LogList-CbfsCVsy.js → LogList-5M5JBhlB.js} +1 -1
  17. package/src/ui/public/assets/{MindmapView-D8A1V-Fd.js → MindmapView-BUV_w14M.js} +1 -1
  18. package/src/ui/public/assets/{MonitorView-Bm_vUP8Y.js → MonitorView-D9N4QH5Y.js} +1 -1
  19. package/src/ui/public/assets/{ProjectStartupButton-BBND5XcZ.js → ProjectStartupButton-DYYQ-O7P.js} +1 -1
  20. package/src/ui/public/assets/RecentDirectoriesChat-BtWa_HMY.js +1 -0
  21. package/src/ui/public/assets/RecentDirectoriesChat-vHT8jMxW.css +1 -0
  22. package/src/ui/public/assets/{RemoteManagerDialog-BVQeIr8U.js → RemoteManagerDialog-C4QIJK_F.js} +1 -1
  23. package/src/ui/public/assets/{RemoteRepoCard-vuCu_cpA.js → RemoteRepoCard-BmDh538v.js} +1 -1
  24. package/src/ui/public/assets/{SourceMapView-BZjgxQM8.js → SourceMapView-Ceamya-N.js} +1 -1
  25. package/src/ui/public/assets/{SvgIcon-D0hK-p1U.js → SvgIcon-xtz4vvc9.js} +1 -1
  26. package/src/ui/public/assets/{TemplateManager-XoPZv_i6.js → TemplateManager-DhKTZ4EM.js} +1 -1
  27. package/src/ui/public/assets/{UserInputNode-CZarmsrv.js → UserInputNode-DfeCGlEO.js} +1 -1
  28. package/src/ui/public/assets/WorkbenchView-D9l3i4Qj.css +1 -0
  29. package/src/ui/public/assets/WorkbenchView-DX2epPD9.js +6 -0
  30. package/src/ui/public/assets/{_plugin-vue_export-helper-N8Vc5eEs.js → _plugin-vue_export-helper-C_bQVzeb.js} +4 -4
  31. package/src/ui/public/assets/{agentConversations-Da7zLPfP.js → agentConversations-BUPj8vzH.js} +1 -1
  32. package/src/ui/public/assets/configStore-DJH7OlB_.js +1 -0
  33. package/src/ui/public/assets/{gitStore-grKwgyHH.js → gitStore-ByP9lpuT.js} +1 -1
  34. package/src/ui/public/assets/index-CFX8sK4w.js +29 -0
  35. package/src/ui/public/assets/{previewSandbox-D4455rKO.js → previewSandbox-DSzZ_Rky.js} +1 -1
  36. package/src/ui/public/index.html +10 -10
  37. package/src/ui/public/sounds/CREDITS.txt +32 -0
  38. package/src/ui/public/sounds/task-done.wav +0 -0
  39. package/src/ui/public/sounds/task-error.wav +0 -0
  40. package/src/ui/server/routes/config.js +4 -1
  41. package/src/ui/server/routes/workbench/index.js +15 -6
  42. package/src/ui/server/routes/workbench/jobActivity.js +274 -0
  43. package/src/ui/server/routes/workbench/jobActivity.test.js +295 -0
  44. package/src/ui/server/routes/workbench/liveJobs.js +3 -0
  45. package/src/ui/server/routes/workbench/orchestratorStore.js +53 -2
  46. package/src/ui/server/routes/workbench/orchestratorStore.progressReport.test.js +177 -0
  47. package/src/ui/server/routes/workbench/progressReport.js +54 -47
  48. package/src/ui/server/routes/workbench/progressReport.test.js +73 -42
  49. package/src/ui/server/routes/workbench/projectRegistry.js +36 -2
  50. package/src/ui/server/routes/workbench/projectRegistry.test.js +98 -0
  51. package/src/ui/server/routes/workbench/taskRunner.js +9 -0
  52. package/src/utils/selfUpdatePolicy.js +123 -0
  53. package/src/utils/selfUpdatePolicy.test.js +204 -0
  54. package/src/ui/public/assets/EditorView-C6msf9YP.js +0 -1
  55. package/src/ui/public/assets/RecentDirectoriesChat-BQbncY1L.css +0 -1
  56. package/src/ui/public/assets/RecentDirectoriesChat-D9fMFh8r.js +0 -1
  57. package/src/ui/public/assets/WorkbenchView-BLyXsdYw.css +0 -1
  58. package/src/ui/public/assets/WorkbenchView-CPur8WEj.js +0 -6
  59. package/src/ui/public/assets/configStore-BFb0I8eP.js +0 -1
  60. package/src/ui/public/assets/index-BHYAwndE.js +0 -29
@@ -0,0 +1,123 @@
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
+ // 发布后自更新「这一轮要不要真调 npm install」的判定 —— 纯函数,不碰网络/IO,便于单测。
16
+ //
17
+ // 为什么要把这个判定单独抽出来(2026-09-29 v2.17.21 事故):
18
+ // 原来的写法是 `if (probe.ok) { 真装 }` —— 探针(直接 GET 一次 tarball URL)是**硬闸门**。
19
+ // 那次探针连着 35 轮全报 `HTTP 404`,于是 600s 里 `npm install` **一次都没被执行**,
20
+ // 唯一发生的事就是每 15s 打印一行"还取不到";而发布脚本放弃后,用户手动
21
+ // `npm install -g zen-gitsync@2.17.21` 16s 就装上了。
22
+ //
23
+ // 结论:探针只是"省一次注定失败的调用"的**优化**,不是事实。真正的判据只有 npm 自己。
24
+ // 所以判定改为「两个就绪信号任一为真就真试 + 探针不可信时按节奏强制真试」,
25
+ // 超时前还会补最后一次真试(见 scripts/release.js: selfUpdateGlobal)。
26
+ //
27
+ // 两个就绪信号各自对应一条能绕开对方缓存的安装路径(这就是为什么两条都要看):
28
+ // - packument 里已有这个版本 → `npm install -g <pkg>@<ver>` 能解析;
29
+ // - tarball 可取 → `npm install -g <tarball URL>` 直连能装(不经过 packument 缓存)。
30
+
31
+ // 探针一直说"取不到"时,每隔几轮强制真试一次。
32
+ // 4 轮 × 前段 15s ≈ 每 1 分钟一次真试;窗口有 30 分钟,能拿到二十几次真装机会,
33
+ // 而不是 0 次;单次失败(npm 报 404/ETARGET)只花几秒,不心疼。
34
+ export const FORCE_INSTALL_EVERY = 4
35
+
36
+ /**
37
+ * 判定这一轮是否真的调用 npm 安装。
38
+ *
39
+ * @param {object} input
40
+ * @param {number} input.attempt - 从 1 开始的轮次
41
+ * @param {{ok: boolean, status?: number, error?: string, unknown?: boolean}} input.probe
42
+ * isTarballFetchable() 的结果:`ok=true/status=0(网络错)/status=404` 三种形态
43
+ * @param {boolean} input.packumentHasVersion - `npm view <pkg>@<ver> version` 是否拿得到
44
+ * @param {number} [input.forceEvery] - 强制真试的间隔轮数,0/负数 = 不强制
45
+ * @returns {{attempt: boolean, reason: string}}
46
+ * reason: packument-ready | tarball-ready | probe-failed | forced | probe-says-missing
47
+ */
48
+ export function shouldAttemptInstall({ attempt, probe, packumentHasVersion, forceEvery = FORCE_INSTALL_EVERY }) {
49
+ // ① 任何一条路已被证实可用 → 立刻真装,不浪费窗口
50
+ if (packumentHasVersion) return { attempt: true, reason: 'packument-ready' }
51
+ if (probe?.ok) return { attempt: true, reason: 'tarball-ready' }
52
+
53
+ // ② 探针"没结论"(网络抖动 / 拿不到 fetch / 超时返回 status=0)→ 当成可用,由 npm 自己去判。
54
+ // 探针失败 ≠ tarball 不存在;把它当"取不到"会平白削掉一整轮机会。
55
+ if (!probe || probe.status === 0 || probe.error) return { attempt: true, reason: 'probe-failed' }
56
+
57
+ // ③ 探针明确说"这个路径 404":这是唯一允许跳过的情形,但必须按期强制真试 ——
58
+ // 404 可能来自边缘节点的负缓存 / 透明代理,而不是 registry 真的没有这个对象。
59
+ if (Number.isFinite(forceEvery) && forceEvery > 0 && attempt % forceEvery === 0) {
60
+ return { attempt: true, reason: 'forced' }
61
+ }
62
+
63
+ return { attempt: false, reason: 'probe-says-missing' }
64
+ }
65
+
66
+ /**
67
+ * 轮询窗口用尽时,还要不要补最后一次真试。
68
+ *
69
+ * 只在这一整轮"从头到尾没真装过"时才补:那种情况下窗口的内容是纯等待,
70
+ * 一次事实判据都没取到(探针误报时就是这个形态,等于白等 600s)。
71
+ * 若最后一轮刚试过(只差几秒),再试一次没意义。
72
+ *
73
+ * @param {{installAttempts: number, lastRoundAttempted: boolean}} input
74
+ * @returns {boolean}
75
+ */
76
+ export function shouldFinalAttempt({ installAttempts, lastRoundAttempted }) {
77
+ if (lastRoundAttempted) return false
78
+ // installAttempts === 0 是主目标(整轮零真试);> 0 但最后一轮在跳过,也顺手补一次。
79
+ return true
80
+ }
81
+
82
+ /**
83
+ * 这一轮的轮询间隔:前段密集、后段退避。
84
+ *
85
+ * 为什么窗口加长后必须退避(v2.17.21 之后):registry 元数据/对象就绪最长见过
86
+ * 十几分钟(比原来 600s 的上限还长),所以上限提到 30 分钟。但 30 分钟里仍按 15s
87
+ * 一跳 = 一百多轮,既是上百次 `npm view` + 上百次探针,也把日志刷成噪声。
88
+ * 前段(默认 600s,原来就是"整段窗口")保持 15s 的灵敏度,之后退到 60s 慢炖。
89
+ *
90
+ * @param {object} input
91
+ * @param {number} input.elapsedMs - 从轮询开始到现在
92
+ * @param {number} input.fastWindowMs - 前段长度,超过它就开始退避
93
+ * @param {number} input.fastIntervalMs - 前段间隔
94
+ * @param {number} input.slowIntervalMs - 后段间隔
95
+ * @returns {number} 毫秒
96
+ */
97
+ export function nextPollIntervalMs({ elapsedMs, fastWindowMs, fastIntervalMs, slowIntervalMs }) {
98
+ return elapsedMs < fastWindowMs ? fastIntervalMs : slowIntervalMs
99
+ }
100
+
101
+ /**
102
+ * 把 npm 的失败输出归成一个短码,用来在放弃时汇总"到底卡在哪"。
103
+ *
104
+ * 为什么需要:原先只打最后一次的失败原文,于是"E404(对象/元数据还没就绪)"
105
+ * 与"EPERM(文件被占)"分不清 —— 两者的处理方式完全相反(一个只能等,一个要杀实例)。
106
+ * 汇总成 `E404 ×8 / ETARGET ×2` 这样一行,下一次事故就不用再靠猜。
107
+ *
108
+ * @param {string} output - npm install 的 stdout+stderr
109
+ * @returns {string} E404 | ETARGET | EPERM | EBUSY | ENOTFOUND | ETIMEDOUT | ENETUNREACH | '其他'
110
+ */
111
+ export function classifyInstallError(output) {
112
+ const s = String(output || '')
113
+ if (!s) return '其他'
114
+ // 顺序有讲究:E404 / ETARGET 是"registry 还没就绪",EPERM / EBUSY 是"文件被占",
115
+ // 两类混在一起时优先报前者(它是自更新这一段的主题),但两者都会各自计数。
116
+ if (/EPERM|EBUSY|operation not permitted|Failed to remove/i.test(s)) return 'EPERM'
117
+ if (/\bETARGET\b/.test(s)) return 'ETARGET'
118
+ if (/\bE404\b|404 Not Found/i.test(s)) return 'E404'
119
+ if (/\bENOTFOUND\b/.test(s)) return 'ENOTFOUND'
120
+ if (/\bETIMEDOUT\b|timed out/i.test(s)) return 'ETIMEDOUT'
121
+ if (/\bENETUNREACH\b|ECONNRESET|ECONNREFUSED/i.test(s)) return 'ENETUNREACH'
122
+ return '其他'
123
+ }
@@ -0,0 +1,204 @@
1
+ // Copyright 2026 xz333221
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ //
15
+ // src/utils/selfUpdatePolicy.js 纯函数单元测试(node:test 内置)。
16
+ //
17
+ // 回归的核心一条:v2.17.21 那次 release 里 35 轮探针全报 404,结果是
18
+ // "npm install 一次都没真跑过"。这里用同样的输入序列断言"必须拿到真装机会"。
19
+ import { test } from 'node:test'
20
+ import assert from 'node:assert/strict'
21
+ import {
22
+ shouldAttemptInstall,
23
+ shouldFinalAttempt,
24
+ nextPollIntervalMs,
25
+ classifyInstallError,
26
+ FORCE_INSTALL_EVERY,
27
+ } from './selfUpdatePolicy.js'
28
+
29
+ const MISSING = { ok: false, status: 404 }
30
+ const NET_ERROR = { ok: false, status: 0, error: 'fetch failed' }
31
+ const OK = { ok: true, status: 206 }
32
+
33
+ // ========== 两个就绪信号 ==========
34
+
35
+ test('shouldAttemptInstall: packument 已有该版本 → 真装(即使探针说 404)', () => {
36
+ const plan = shouldAttemptInstall({ attempt: 1, probe: MISSING, packumentHasVersion: true })
37
+ assert.deepEqual(plan, { attempt: true, reason: 'packument-ready' })
38
+ })
39
+
40
+ test('shouldAttemptInstall: tarball 已可取 → 真装', () => {
41
+ const plan = shouldAttemptInstall({ attempt: 1, probe: OK, packumentHasVersion: false })
42
+ assert.deepEqual(plan, { attempt: true, reason: 'tarball-ready' })
43
+ })
44
+
45
+ test('shouldAttemptInstall: packument 优先于 tarball(两条路都在时按前者排 spec)', () => {
46
+ const plan = shouldAttemptInstall({ attempt: 1, probe: OK, packumentHasVersion: true })
47
+ assert.equal(plan.reason, 'packument-ready')
48
+ })
49
+
50
+ // ========== 探针"没结论"不许当结果 ==========
51
+
52
+ test('shouldAttemptInstall: 探针网络失败(status=0)→ 真装,不跳过', () => {
53
+ const plan = shouldAttemptInstall({ attempt: 1, probe: NET_ERROR, packumentHasVersion: false })
54
+ assert.deepEqual(plan, { attempt: true, reason: 'probe-failed' })
55
+ })
56
+
57
+ test('shouldAttemptInstall: 探针带 error 字段 → 真装,不跳过', () => {
58
+ const plan = shouldAttemptInstall({
59
+ attempt: 2,
60
+ probe: { ok: false, status: 0, error: 'ECONNRESET' },
61
+ packumentHasVersion: false,
62
+ })
63
+ assert.equal(plan.attempt, true)
64
+ assert.equal(plan.reason, 'probe-failed')
65
+ })
66
+
67
+ test('shouldAttemptInstall: 拿不到探针结果(undefined/null)→ 真装,不跳过', () => {
68
+ for (const probe of [undefined, null]) {
69
+ const plan = shouldAttemptInstall({ attempt: 1, probe, packumentHasVersion: false })
70
+ assert.equal(plan.attempt, true, `probe=${probe} 时必须真装`)
71
+ assert.equal(plan.reason, 'probe-failed')
72
+ }
73
+ })
74
+
75
+ test('shouldAttemptInstall: 老 Node 拿不到 fetch 时的 unknown 形态 → 真装', () => {
76
+ const plan = shouldAttemptInstall({
77
+ attempt: 1,
78
+ probe: { ok: true, unknown: true },
79
+ packumentHasVersion: false,
80
+ })
81
+ assert.deepEqual(plan, { attempt: true, reason: 'tarball-ready' })
82
+ })
83
+
84
+ // ========== 明确 404:可以跳过,但必须按期强制真试 ==========
85
+
86
+ test('shouldAttemptInstall: 探针 404 且未到强制轮 → 跳过', () => {
87
+ for (const attempt of [1, 2, 3]) {
88
+ const plan = shouldAttemptInstall({ attempt, probe: MISSING, packumentHasVersion: false })
89
+ assert.equal(plan.attempt, false, `第 ${attempt} 轮不该跳过以外的行为`)
90
+ assert.equal(plan.reason, 'probe-says-missing')
91
+ }
92
+ })
93
+
94
+ test('shouldAttemptInstall: 探针 404,第 4/8 轮强制真试', () => {
95
+ for (const attempt of [4, 8, 12]) {
96
+ const plan = shouldAttemptInstall({ attempt, probe: MISSING, packumentHasVersion: false })
97
+ assert.deepEqual(plan, { attempt: true, reason: 'forced' }, `第 ${attempt} 轮应强制`)
98
+ }
99
+ })
100
+
101
+ test('shouldAttemptInstall: 探针回 403/500 等非 404 状态 → 同样按强制节奏,不当成"可取"', () => {
102
+ const early = shouldAttemptInstall({ attempt: 1, probe: { ok: false, status: 500 }, packumentHasVersion: false })
103
+ assert.equal(early.attempt, false)
104
+ const forced = shouldAttemptInstall({ attempt: 4, probe: { ok: false, status: 500 }, packumentHasVersion: false })
105
+ assert.equal(forced.reason, 'forced')
106
+ })
107
+
108
+ test('shouldAttemptInstall: forceEvery=0 关闭强制 → 404 一直跳过(只有探针/超时兜底)', () => {
109
+ for (const attempt of [1, 4, 8, 40]) {
110
+ const plan = shouldAttemptInstall({
111
+ attempt,
112
+ probe: MISSING,
113
+ packumentHasVersion: false,
114
+ forceEvery: 0,
115
+ })
116
+ assert.equal(plan.attempt, false)
117
+ }
118
+ })
119
+
120
+ test('shouldAttemptInstall: forceEvery 可覆盖(测试/调参用)', () => {
121
+ const plan = shouldAttemptInstall({
122
+ attempt: 2,
123
+ probe: MISSING,
124
+ packumentHasVersion: false,
125
+ forceEvery: 2,
126
+ })
127
+ assert.equal(plan.reason, 'forced')
128
+ })
129
+
130
+ // ========== 事故回归:35 轮全 404,不许零真试 ==========
131
+
132
+ test('回归 v2.17.21:探针连续 35 轮 404 时,真试次数必须 ≥ 8 且第 4 轮就开始', () => {
133
+ const attempts = []
134
+ for (let attempt = 1; attempt <= 35; attempt += 1) {
135
+ const plan = shouldAttemptInstall({ attempt, probe: MISSING, packumentHasVersion: false })
136
+ if (plan.attempt) attempts.push(attempt)
137
+ }
138
+ // 旧实现:attempts 为空(probe.ok 恒 false → 一次 npm 都没调)
139
+ assert.ok(attempts.length > 0, '不允许出现"整轮零真试"')
140
+ assert.equal(attempts[0], FORCE_INSTALL_EVERY, '第 4 轮就必须开始真试,而不是等满 600s')
141
+ assert.ok(attempts.length >= 8, `600s(35 轮)里至少 8 次真装机会,实际 ${attempts.length}`)
142
+ })
143
+
144
+ // ========== 超时前的最后一次真试 ==========
145
+
146
+ test('shouldFinalAttempt: 整轮没真装过 → 补最后一次', () => {
147
+ assert.equal(shouldFinalAttempt({ installAttempts: 0, lastRoundAttempted: false }), true)
148
+ })
149
+
150
+ test('shouldFinalAttempt: 最后一轮刚试过 → 不补(几秒前才失败,再试无意义)', () => {
151
+ assert.equal(shouldFinalAttempt({ installAttempts: 9, lastRoundAttempted: true }), false)
152
+ })
153
+
154
+ test('shouldFinalAttempt: 试过但最后一轮在跳过 → 仍补一次', () => {
155
+ assert.equal(shouldFinalAttempt({ installAttempts: 8, lastRoundAttempted: false }), true)
156
+ })
157
+
158
+ // ========== 轮询间隔退避(窗口从 600s 提到 30 分钟后必须有) ==========
159
+
160
+ const INTERVAL_CFG = { fastWindowMs: 600_000, fastIntervalMs: 15_000, slowIntervalMs: 60_000 }
161
+
162
+ test('nextPollIntervalMs: 前段(600s 内)保持密集 15s', () => {
163
+ for (const elapsedMs of [0, 1_000, 599_999]) {
164
+ assert.equal(nextPollIntervalMs({ ...INTERVAL_CFG, elapsedMs }), 15_000, `elapsed=${elapsedMs}`)
165
+ }
166
+ })
167
+
168
+ test('nextPollIntervalMs: 到点即切到慢炖 60s(边界取后段)', () => {
169
+ assert.equal(nextPollIntervalMs({ ...INTERVAL_CFG, elapsedMs: 600_000 }), 60_000)
170
+ assert.equal(nextPollIntervalMs({ ...INTERVAL_CFG, elapsedMs: 1_500_000 }), 60_000)
171
+ })
172
+
173
+ test('nextPollIntervalMs: 30 分钟窗口的总轮数可控(不是"15s 跳 120 轮")', () => {
174
+ // 前 600s / 15s = 40 轮;剩下 1200s / 60s = 20 轮 → 60 轮封顶
175
+ const total = 600_000 / 15_000 + (1_800_000 - 600_000) / 60_000
176
+ assert.equal(total, 60)
177
+ assert.ok(total <= 60, '长窗口不许把日志刷成上百轮')
178
+ })
179
+
180
+ // ========== 失败归类(放弃时汇总"卡在哪") ==========
181
+
182
+ test('classifyInstallError: E404 / ETARGET → registry 还没就绪', () => {
183
+ assert.equal(classifyInstallError('npm error code E404\nnpm error 404 Not Found - GET https://...'), 'E404')
184
+ assert.equal(classifyInstallError('npm error code ETARGET\nnpm error No matching version found'), 'ETARGET')
185
+ })
186
+
187
+ test('classifyInstallError: EPERM / EBUSY → 文件被占(和"还没就绪"完全不同的处置)', () => {
188
+ assert.equal(classifyInstallError('npm warn cleanup Failed to remove some directories: EPERM'), 'EPERM')
189
+ assert.equal(classifyInstallError('npm error EBUSY: resource busy or locked'), 'EPERM')
190
+ })
191
+
192
+ test('classifyInstallError: 网络类与空输入不炸,各有短码', () => {
193
+ assert.equal(classifyInstallError('npm error code ENOTFOUND registry.npmjs.org'), 'ENOTFOUND')
194
+ assert.equal(classifyInstallError('npm error code ETIMEDOUT'), 'ETIMEDOUT')
195
+ assert.equal(classifyInstallError('npm error ECONNRESET'), 'ENETUNREACH')
196
+ assert.equal(classifyInstallError(''), '其他')
197
+ assert.equal(classifyInstallError(undefined), '其他')
198
+ assert.equal(classifyInstallError('some unknown failure'), '其他')
199
+ })
200
+
201
+ test('classifyInstallError: 两类同时出现时优先报文件占用(它是唯一要"动手"的那类)', () => {
202
+ const mixed = 'npm error code E404\nnpm error EPERM: operation not permitted'
203
+ assert.equal(classifyInstallError(mixed), 'EPERM')
204
+ })
@@ -1 +0,0 @@
1
- import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Cn as t,Dn as n,En as r,Er as i,H as a,Jn as o,Kn as s,Mn as c,Pn as ee,Pr as l,Qn as te,Qr as u,Rn as d,Tn as f,Un as p,Xn as m,Yr as h,_n as ne,a as g,br as _,cr as re,gn as ie,hn as v,jn as y,ln as b,lr as x,or as S,pr as C,qr as w,vn as T,wn as E,xn as ae,xr as oe,yn as D}from"./element-plus-Bx3j6vzG.js";import{o as se,r as O,t as ce}from"./vendor-CyWsJd6S.js";import{n as k,t as A}from"./_plugin-vue_export-helper-N8Vc5eEs.js";import{t as le}from"./SvgIcon-D0hK-p1U.js";import{t as ue}from"./configStore-BFb0I8eP.js";import{n as de,t as fe}from"./fileIcon-B5p5pGN9.js";import{a as pe,i as me,n as he,r as ge,s as _e,t as ve}from"./previewSandbox-D4455rKO.js";import{a as ye,c as be,l as xe,n as Se,o as Ce,r as we,s as Te}from"./monaco-DkJuNcCr.js";import{t as Ee}from"./useThemeObserver-DYxFoHh1.js";import{r as De,t as j}from"./flow-mindmap-OPE_D4da.js";import{r as Oe}from"./index-BHYAwndE.js";import{a as ke,i as Ae,n as je,o as Me,r as Ne,s as Pe,t as Fe}from"./agentConversations-Da7zLPfP.js";import{n as Ie,t as M}from"./AgentEngineSelector-D_8VedA0.js";function Le(e){return{ts:`typescript`,tsx:`typescript`,js:`javascript`,mjs:`javascript`,cjs:`javascript`,jsx:`javascript`,vue:`html`,html:`html`,htm:`html`,css:`css`,scss:`scss`,less:`less`,json:`json`,jsonc:`json`,md:`markdown`,markdown:`markdown`,yaml:`yaml`,yml:`yaml`,toml:`ini`,xml:`xml`,svg:`xml`,sh:`shell`,bash:`shell`,zsh:`shell`,fish:`shell`,ps1:`powershell`,py:`python`,go:`go`,rs:`rust`,java:`java`,kt:`kotlin`,rb:`ruby`,php:`php`,c:`c`,cpp:`cpp`,h:`cpp`,cs:`csharp`,sql:`sql`,graphql:`graphql`,gql:`graphql`,txt:`plaintext`,log:`plaintext`,ini:`ini`,env:`ini`,gitignore:`ini`,dockerfile:`dockerfile`}[e.toLowerCase()]??`plaintext`}d(),C();var N={class:`mindmap-preview`},P={class:`mindmap-preview-canvas`},F=A(ee({__name:`MindmapPreview`,props:{content:{}},setup(e){let r=e,a=t(()=>j(r.content||``,`未命名文档`));return(e,t)=>(m(),n(`div`,N,[t[0]||=E(`div`,{class:`mindmap-preview-header`},[E(`span`,{class:`mindmap-preview-title`},`整篇导图`),E(`span`,{class:`mindmap-preview-hint`},`基于整篇 Markdown 自动生成 · 阅读模式`)],-1),E(`div`,P,[c(i(De),{data:a.value,"preview-mode":``},null,8,[`data`])])]))}}),[[`__scopeId`,`data-v-d2fe328b`]]);d(),C(),l(),b();var Re={class:`agent-panel-header`},ze=[`title`,`aria-label`],Be={class:`agent-panel-title`},Ve={key:1,class:`agent-panel-title`},He=[`title`,`aria-label`],I=[`title`],Ue={class:`agent-panel-convs`},We=[`data-theme`],L=[`title`],R={class:`agent-context-att-name`},z=[`title`,`aria-label`],Ge=A(ee({__name:`EditorAgentPanel`,props:{activeFilePath:{},activeFileName:{},active:{type:Boolean}},emits:[`close`],setup(a,{emit:ee}){let l=a,te=ee,{theme:d}=Ee(),h=t(()=>d.value===`dark`?`dark`:`light`),{sessions:ne,sessionsLoading:g,currentSessionId:re,messages:v,isStreaming:y,pendingQuestion:b,answeringQuestion:C,isSessionGenerating:T,currentEngine:oe,pendingEngine:A,isEngineLocked:le,pickEngine:ue,loadSessions:de,loadSession:fe,deleteSession:pe,renameSession:me,newSession:he,sendMessage:ge,answerQuestion:_e,stop:ve}=Pe(),ye=t(()=>le.value?oe.value:A.value);function be(e){le.value||ue(e)}let xe=t(()=>ke(ne.value,T)),Se=Ne(),Ce=Ae(),we=_(null),Te=_(null),De=_(null),j=_(null),Oe=_(null),{width:Le,narrow:N}=Ie(Oe),P=_(`chat`),F=_(null),Ge=_(!1),B=null,Ke=t(()=>!!l.activeFileName&&!Ge.value);function qe(e){return Array.from(e.children).find(e=>e.classList?.contains(`acu-input-attachments`))??null}function Je(){let e=Te.value?.$el;if(!e)return;let t=e.querySelector(`.agent-context-slot`);if(!Ke.value){if(!t)return;F.value=null,p(()=>t.remove());return}let n=F.value&&e.contains(F.value)?F.value:t;n||(n=document.createElement(`div`),n.className=`agent-context-slot`);let r=qe(e),i=r??e;n.parentElement!==i&&i.insertBefore(n,r?r.firstChild:e.firstChild),F.value=n}function Ye(e=!0){we.value?.scrollToBottom(e)}async function Xe(e){let t=Ge.value?void 0:l.activeFilePath||void 0;await ge(e.text,e.files,{openFilePath:t}),await p(),Ye()}function Ze(e){fe(e),P.value=`chat`}function Qe(){he(),P.value=`chat`}S(()=>v.value.length,()=>{p(()=>Ye(!1))});function $e(){let e=j.value;e&&typeof MutationObserver<`u`&&(B?.disconnect(),B=new MutationObserver(()=>Je()),B.observe(e,{childList:!0,subtree:!0}))}return S(()=>l.active,e=>{e&&(P.value=`chat`,de().catch(()=>{}),p(()=>{Je(),Ye(!1)}))}),S(N,e=>{e||(P.value=`chat`)}),S(()=>l.activeFilePath,()=>{Ge.value=!1}),S(Ke,e=>{e&&p(Je)}),o(()=>{de().catch(()=>{}),p(()=>{Je(),$e()})}),s(()=>{B?.disconnect(),B=null,F.value=null}),(t,o)=>(m(),n(`div`,{ref_key:`rootRef`,ref:Oe,class:`editor-agent-panel`},[E(`div`,Re,[i(N)&&P.value===`list`?(m(),n(D,{key:0},[E(`button`,{class:`agent-panel-icon-btn agent-panel-back-btn`,title:i(k)(`@EDITOR:返回对话`),"aria-label":i(k)(`@EDITOR:返回对话`),onClick:o[0]||=e=>P.value=`chat`},[...o[4]||=[E(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[E(`line`,{x1:`19`,y1:`12`,x2:`5`,y2:`12`}),E(`polyline`,{points:`12 19 5 12 12 5`})],-1)]],8,ze),E(`span`,Be,u(i(k)(`@EDITOR:会话列表`)),1)],64)):(m(),n(`span`,Ve,u(i(k)(`@EDITOR:g ai 对话`)),1)),o[7]||=E(`div`,{class:`agent-panel-spacer`},null,-1),!i(N)||P.value===`chat`?(m(),f(M,{key:2,class:`agent-panel-engine`,engine:ye.value,locked:i(le),onSelect:be},null,8,[`engine`,`locked`])):r(``,!0),i(N)&&P.value===`chat`?(m(),n(`button`,{key:3,class:`agent-panel-icon-btn agent-panel-list-btn`,title:i(k)(`@EDITOR:会话列表`),"aria-label":i(k)(`@EDITOR:会话列表`),onClick:o[1]||=e=>P.value=`list`},[...o[5]||=[e(`<svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" data-v-d910c906><line x1="8" y1="6" x2="21" y2="6" data-v-d910c906></line><line x1="8" y1="12" x2="21" y2="12" data-v-d910c906></line><line x1="8" y1="18" x2="21" y2="18" data-v-d910c906></line><line x1="3" y1="6" x2="3.01" y2="6" data-v-d910c906></line><line x1="3" y1="12" x2="3.01" y2="12" data-v-d910c906></line><line x1="3" y1="18" x2="3.01" y2="18" data-v-d910c906></line></svg>`,1)]],8,He)):r(``,!0),E(`button`,{class:`agent-panel-icon-btn`,title:i(k)(`@EDITOR:关闭对话`),onClick:o[2]||=e=>te(`close`)},[...o[6]||=[E(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"stroke-linecap":`round`},[E(`line`,{x1:`18`,y1:`6`,x2:`6`,y2:`18`}),E(`line`,{x1:`6`,y1:`6`,x2:`18`,y2:`18`})],-1)]],8,I)]),E(`div`,{class:w([`agent-panel-body`,{"is-wide":!i(N)}])},[x(E(`div`,Ue,[c(i(O),{"show-search":!0,items:xe.value,"active-id":i(re),loading:i(g),labels:i(Se),onSelect:Ze,onNew:Qe,onRename:i(me),onDelete:i(pe)},null,8,[`items`,`active-id`,`loading`,`labels`,`onRename`,`onDelete`])],512),[[ie,!i(N)||P.value===`list`]]),x(E(`div`,{ref_key:`chatHostRef`,ref:De,class:`agent-panel-chat`},[c(i(ce),{ref_key:`chatRef`,ref:we,"show-input":!1,messages:i(v),"assistant-name":i(je),"assistant-avatar":i(Fe),theme:h.value,question:i(b),"question-submitting":i(C),"question-labels":i(Ce),onAnswer:i(_e)},null,8,[`messages`,`assistant-name`,`assistant-avatar`,`theme`,`question`,`question-submitting`,`question-labels`,`onAnswer`])],512),[[ie,!i(N)||P.value===`chat`]]),i(Le)>0?(m(),n(`div`,{key:0,ref_key:`composerRef`,ref:j,class:`agent-panel-composer acu-root`,"data-theme":h.value},[c(i(se),{ref_key:`inputRef`,ref:Te,disabled:i(y),generating:i(y),placeholder:i(y)?i(k)(`@AGENT:正在生成中...`):i(k)(`@AGENT:输入消息,Enter 发送`),"upload-config":{accept:i(Me)},onSend:Xe,onStop:i(ve)},null,8,[`disabled`,`generating`,`placeholder`,`upload-config`,`onStop`]),F.value?(m(),f(ae,{key:0,to:F.value},[Ke.value?(m(),n(`div`,{key:0,class:`agent-context-att`,title:a.activeFilePath||``},[o[9]||=E(`svg`,{class:`agent-context-att-icon`,viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.7`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[E(`path`,{d:`M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z`}),E(`polyline`,{points:`14 3 14 8 19 8`})],-1),E(`span`,R,u(a.activeFileName),1),E(`button`,{type:`button`,class:`agent-context-att-remove`,title:i(k)(`@EDITOR:不引用当前文档`),"aria-label":i(k)(`@EDITOR:不引用当前文档`),onClick:o[3]||=e=>Ge.value=!0},[...o[8]||=[E(`svg`,{viewBox:`0 0 24 24`,width:`10`,height:`10`,fill:`none`,stroke:`currentColor`,"stroke-width":`3`,"stroke-linecap":`round`,"aria-hidden":`true`},[E(`line`,{x1:`18`,y1:`6`,x2:`6`,y2:`18`}),E(`line`,{x1:`6`,y1:`6`,x2:`18`,y2:`18`})],-1)]],8,z)],8,L)):r(``,!0)],8,[`to`])):r(``,!0)],8,We)):r(``,!0)],2)],512))}}),[[`__scopeId`,`data-v-d910c906`]]);d(),C(),l(),b();var B={class:`sidebar-header`},Ke={class:`sidebar-title`},qe={class:`sidebar-actions`},Je={class:`sidebar-search`},Ye=[`placeholder`,`title`],Xe=[`title`,`aria-label`],Ze={key:0,class:`sidebar-tree`},Qe={key:1,class:`tree-arrow-spacer`},$e={class:`tree-icon mit-icon`,"aria-hidden":`true`},et=[`xlink:href`],tt=[`onClick`,`onContextmenu`],nt={key:1,class:`tree-arrow-spacer`},rt={key:2,class:`tree-icon mit-icon`,"aria-hidden":`true`},it=[`xlink:href`],at={key:3,class:`tree-icon mit-icon`,"aria-hidden":`true`},ot=[`xlink:href`],st=[`title`],ct={key:0,class:`tree-name-hit`},lt={key:4,class:`tree-loading`},ut={key:0,viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,style:{"flex-shrink":`0`,color:`var(--color-warning)`}},dt={key:1,viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,style:{"flex-shrink":`0`,color:`var(--text-tertiary)`}},ft=[`placeholder`],pt={key:0,class:`tree-node tree-inline-input-row`,style:{paddingLeft:`12px`}},mt={key:0,viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,style:{"flex-shrink":`0`,color:`var(--color-warning)`}},ht={key:1,viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,style:{"flex-shrink":`0`,color:`var(--text-tertiary)`}},gt=[`placeholder`],_t={key:1,class:`tree-empty`},vt={key:1,class:`sidebar-loading`},yt={class:`editor-main`},bt={key:0,class:`editor-tabs`},xt=[`onClick`,`title`],St={class:`tab-name`},Ct={key:0,class:`tab-dirty-dot`},wt=[`onClick`],Tt=[`title`],Et=[`disabled`,`title`],Dt=[`title`],Ot={key:1,class:`editor-empty`},kt={viewBox:`0 0 24 24`,width:`48`,height:`48`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,style:{opacity:`.3`}},At={class:`editor-empty-hint`},jt={class:`editor-body`},Mt={key:0,class:`image-tab-placeholder`},Nt={viewBox:`0 0 24 24`,width:`56`,height:`56`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,style:{opacity:`.35`}},Pt={class:`image-tab-placeholder-title`},Ft={class:`image-tab-placeholder-hint`},It={class:`preview-header`},Lt={class:`preview-title`},Rt={class:`preview-ext-badge`},zt=[`title`],Bt={class:`preview-body`},Vt=[`sandbox`,`srcdoc`],Ht=6e4,Ut=A(ee({__name:`EditorView`,props:{pendingFilePath:{}},setup(ee){self.MonacoEnvironment={getWorker(e,t){return t===`json`?new be:t===`css`||t===`scss`||t===`less`?new Te:t===`html`||t===`handlebars`||t===`razor`?new Ce:t===`typescript`||t===`javascript`?new ye:new xe}};let l=ee,d=ue(),b=Oe(),C=_([]),se=_(!1),O=_(``),ce=_(``),A=null;function De(){O.value=``,ce.value=``,A&&=(clearTimeout(A),null)}S(O,e=>{A&&clearTimeout(A),A=setTimeout(()=>{ce.value=e,A=null},180)}),s(()=>{A&&clearTimeout(A),Ae()});let j=null;function ke(){Ae(),d.ui.fileTreeAutoRefresh&&(j=setInterval(()=>{document.hidden||d.currentDirectory&&(O.value.trim()||M())},Ht))}function Ae(){j&&=(clearInterval(j),null)}S(()=>d.currentDirectory,()=>{ke()}),S(()=>d.ui.fileTreeAutoRefresh,()=>{ke()});async function je(e,t=0){let n=await(await fetch(`/api/browse_directory?path=${encodeURIComponent(e)}`)).json();return n.success?n.items.map(e=>({...e,depth:t,expanded:!1,loading:!1,children:(e.type,void 0)})):[]}async function Me(){let e=d.currentDirectory;if(e){se.value=!0;try{C.value=await je(e,0)}finally{se.value=!1}}}function Ne(e,t=new Set){for(let n of e)n.type===`directory`&&n.expanded&&(t.add(n.path),n.children&&Ne(n.children,t));return t}function Pe(e,t=0){return(e||[]).map(e=>{let n={name:e.name,path:e.path,type:e.type,depth:t,expanded:!1,loading:!1};return n.type===`directory`&&Array.isArray(e.children)&&(n.children=Pe(e.children,t+1),n.expanded=!0),n})}async function Fe(e){let t=d.currentDirectory;if(!t)return null;try{let n=await(await fetch(`/api/browse_directory_tree`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({path:t,expand:e})})).json().catch(()=>null);return!n?.success||!Array.isArray(n.items)?null:Pe(n.items,0)}catch{return null}}function Ie(e,t){let n=new Map(e.map(e=>[e.path,e])),r=e.length!==t.length;if(!r){for(let n=0;n<t.length;n++)if(e[n].path!==t[n].path){r=!0;break}}for(let e=0;e<t.length;e++){let i=t[e],a=n.get(i.path);a&&(t[e]=a,a.name!==i.name&&(a.name=i.name,r=!0),a.type===`directory`&&a.expanded&&Array.isArray(i.children)&&(Array.isArray(a.children)?Ie(a.children,i.children)&&(a.children=i.children,r=!0):(a.children=i.children,r=!0)))}return r}async function M(e={}){if(!d.currentDirectory)return;let t=await Fe([...Ne(C.value)]);if(!t){e.notifyOnError&&g.error(k(`@EDITOR:刷新失败`));return}if(C.value.length===0){C.value=t;return}Ie(C.value,t)&&(C.value=t)}async function N(e){if(e.type===`directory`){if(e.expanded)e.expanded=!1;else{if(!e.children){e.loading=!0;try{e.children=await je(e.path,e.depth+1)}finally{e.loading=!1}}e.expanded=!0}}}function P(e){let t=[];for(let n of e)t.push(n),n.type===`directory`&&n.expanded&&n.children&&t.push(...P(n.children));return t}let Re=t(()=>ce.value.trim().toLowerCase());function ze(e,t){if(!t)return e;let n=[];for(let r of e){let e=r.children?ze(r.children,t):[],i=r.name.toLowerCase().includes(t);r.type===`directory`?(i||e.length>0)&&(r.expanded=!0,r.children!==void 0&&(r.children=e),n.push(r)):i&&n.push(r)}return n}let Be=t(()=>ze(C.value,Re.value)),Ve=t(()=>Re.value.length>0&&Be.value.length===0);function He(e){let t=ce.value.trim();if(!t)return[{text:e,hit:!1}];let n=e.toLowerCase(),r=t.toLowerCase(),i=[],a=0,o=n.indexOf(r,a);for(;o!==-1;)o>a&&i.push({text:e.slice(a,o),hit:!1}),i.push({text:e.slice(o,o+r.length),hit:!0}),a=o+r.length,o=n.indexOf(r,a);return a<e.length&&i.push({text:e.slice(a),hit:!1}),i}let I=_(null);function Ue(){let e=I.value;e&&(e.focus(),e.select())}function We(){O.value?(De(),I.value?.focus()):(I.value?.blur(),V.value?.focus())}let L=_([]),R=_(null),z=_(null);async function Ut(e){if(z.value=e,e.type!==`file`){N(e);return}let t=L.value.find(t=>t.path===e.path);if(console.log(`[debug-open-in-editor] EditorView openFile existing tab check:`,{path:e.path,found:!!t,tabsCount:L.value.length}),t){R.value=e.path,p(()=>Xt());return}let n=e.name.split(`.`).pop()||``;if(Fn.has(n.toLowerCase())){let t={path:e.path,name:e.name,content:``,originalContent:``,isDirty:!1,language:`plaintext`};L.value.push(t),R.value=e.path,J.value=!0;return}if(_e(e.name)){let t={path:e.path,name:e.name,content:``,originalContent:``,isDirty:!1,language:`office`};L.value.push(t),R.value=e.path,Y.value=!1,J.value=!0;return}try{let t=await fetch(`/api/editor/file?path=${encodeURIComponent(e.path)}`),r=await t.json();if(console.log(`[debug-open-in-editor] EditorView fetch /api/editor/file response:`,{path:e.path,status:t.status,data:r}),!r.success){g.error(`${k(`@EDITOR:打开文件失败: `)}${r.error}`);return}let i=Le(n),a={path:e.path,name:e.name,content:r.content,originalContent:r.content,isDirty:!1,language:i};console.log(`[debug-open-in-editor] EditorView pushing tab:`,{path:a.path,name:a.name,contentLen:a.content.length,lang:a.language}),L.value.push(a),R.value=e.path,console.log(`[debug-open-in-editor] EditorView tabs after push:`,L.value.length,`activeTabPath=`,R.value)}catch(e){console.log(`[debug-open-in-editor] EditorView fetch threw:`,e),g.error(`${k(`@EDITOR:打开文件失败: `)}${e.message}`)}}S(()=>l.pendingFilePath,async e=>{if(console.log(`[debug-open-in-editor] EditorView watcher fired, filePath=`,e),!e)return;await p();let t=e.split(/[\\/]/).pop()||e;console.log(`[debug-open-in-editor] EditorView calling openFile, name=`,t,`path=`,e),await Ut({name:t,path:e,type:`file`,depth:0}),console.log(`[debug-open-in-editor] EditorView openFile returned`)},{immediate:!0});function Wt(e,t){t.stopPropagation();let n=L.value.findIndex(t=>t.path===e);n!==-1&&(!L.value[n].isDirty||confirm(k(`@EDITOR:文件未保存,确认关闭?`)))&&(L.value.splice(n,1),R.value===e&&(R.value=L.value[Math.min(n,L.value.length-1)]?.path??null))}let Gt=()=>L.value.find(e=>e.path===R.value)??null,Kt=_(null),V=oe(null),qt=new Map;function Jt(e){let t=qt.get(e.path);return(!t||t.isDisposed())&&(t=we.createModel(e.content,e.language,Se.file(e.path)),qt.set(e.path,t)),t}function Yt(){if(!Kt.value)return;let e=document.documentElement.getAttribute(`data-theme`)===`dark`;V.value=we.create(Kt.value,{theme:e?`vs-dark`:`vs`,fontSize:13,lineHeight:20,fontFamily:`'JetBrains Mono', 'Fira Code', 'Cascadia Code', Consolas, monospace`,minimap:{enabled:!0},scrollBeyondLastLine:!1,renderWhitespace:`selection`,automaticLayout:!0,tabSize:2,wordWrap:`off`,smoothScrolling:!0,cursorBlinking:`smooth`,padding:{top:8,bottom:8},editContext:!1}),V.value.onDidChangeModelContent(()=>{let e=Gt();if(!e)return;let t=V.value.getValue();e.content=t,e.isDirty=t!==e.originalContent}),V.value.onDidBlurEditorText(()=>{d.ui.editorAutoSave&&Gt()?.isDirty&&$t(!1),requestAnimationFrame(()=>{if(!H.value||H.value.offsetParent===null)return;let e=document.activeElement;e&&(e.tagName===`INPUT`||e.tagName===`TEXTAREA`||e.isContentEditable||e.classList?.contains(`native-edit-context`)||e.classList?.contains(`monaco-editor`))||Xt()})})}S(R,e=>{if(!V.value||!e)return;let t=L.value.find(t=>t.path===e);if(!t)return;let n=Jt(t);V.value.setModel(n),p(()=>Xt())});function Xt(){if(!V.value)return;V.value.focus();let e=document.querySelector(`.monaco-editor .native-edit-context`);e&&document.activeElement!==e&&requestAnimationFrame(()=>e.focus?.())}S(()=>L.value.filter(e=>e.isDirty).length,e=>{b.setDirtyCount(e)},{immediate:!0}),s(()=>b.setDirtyCount(0)),Ee(()=>{let e=document.documentElement.getAttribute(`data-theme`)===`dark`;we.setTheme(e?`vs-dark`:`vs`)});let Zt=null;function Qt(){if(Zt||!H.value)return;let e=[H.value],t=H.value.parentElement;for(;t;){if(t.classList.contains(`view-pane`)||t.classList.contains(`editor-pane`)){e.push(t);break}t=t.parentElement}Zt=new MutationObserver(()=>{H.value&&H.value.offsetParent!==null&&R.value&&V.value&&requestAnimationFrame(()=>{let e=document.activeElement;e&&(e.tagName===`INPUT`||e.tagName===`TEXTAREA`||e.isContentEditable||e.classList?.contains(`native-edit-context`)||e.classList?.contains(`monaco-editor`))||Xt()})});let n=Zt;e.forEach(e=>n.observe(e,{attributes:!0,attributeFilter:[`style`,`class`,`hidden`]}))}o(async()=>{Yt(),await Me(),Qt(),ke(),R.value&&p(()=>Xt())}),s(()=>{Zt?.disconnect(),Zt=null,V.value?.dispose(),qt.forEach(e=>e.dispose()),qt.clear()});async function $t(e=!1){let t=Gt();if(t)try{let n=await(await fetch(`/api/editor/file`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({path:t.path,content:t.content})})).json();if(!n.success){g.error(`${k(`@EDITOR:保存失败: `)}${n.error}`);return}t.originalContent=t.content,t.isDirty=!1,e||g.success(k(`@EDITOR:已保存`))}catch(e){g.error(`${k(`@EDITOR:保存失败: `)}${e.message}`)}}function en(e){let t=e.ctrlKey||e.metaKey;if(t&&e.key.toLowerCase()===`f`){e.preventDefault(),Ue();return}t&&e.key===`s`&&(e.preventDefault(),$t())}o(()=>window.addEventListener(`keydown`,en)),s(()=>window.removeEventListener(`keydown`,en));let H=_(null),tn=_(220),nn=!1,rn=0,an=0;function on(e){nn=!0,rn=e.clientX,an=tn.value,document.addEventListener(`mousemove`,sn),document.addEventListener(`mouseup`,cn),e.preventDefault()}function sn(e){if(!nn)return;let t=e.clientX-rn;tn.value=Math.max(140,Math.min(400,an+t))}function cn(){nn=!1,document.removeEventListener(`mousemove`,sn),document.removeEventListener(`mouseup`,cn)}function ln(e){return e.type===`directory`?de(e.name):fe(e.name)}let U=_(null),W=_(null),G=_(null),un=_(null);function dn(){let e=z.value;return e?e.type===`directory`?{parentPath:e.path,afterNode:e,depth:e.depth+1}:{parentPath:e.path.includes(`/`)||e.path.includes(`\\`)?e.path.replace(/[\\/][^\\/]+$/,``):d.currentDirectory??``,afterNode:e,depth:e.depth}:{parentPath:d.currentDirectory??``,afterNode:null,depth:0}}async function fn(){let e=dn();z.value?.type===`directory`&&!z.value.expanded&&await N(z.value),U.value={...e,kind:`file`,value:``},await p(),G.value?.focus()}async function pn(){let e=dn();z.value?.type===`directory`&&!z.value.expanded&&await N(z.value),U.value={...e,kind:`directory`,value:``},await p(),G.value?.focus()}function mn(){U.value=null}async function hn(){let e=U.value;if(!e||!e.value.trim()){U.value=null;return}let t=e.value.trim(),n=e.parentPath.replace(/[/\\]$/,``)+`/`+t;if(e.kind===`file`){let e=await(await fetch(`/api/editor/file`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({path:n})})).json();if(!e.success){g.error(e.error);return}g.success(k(`@EDITOR:创建成功`))}else{let e=await(await fetch(`/api/editor/directory`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({path:n})})).json();if(!e.success){g.error(e.error);return}g.success(k(`@EDITOR:创建成功`))}U.value=null,await M()}function gn(e){e.key===`Enter`&&(e.preventDefault(),hn()),e.key===`Escape`&&(e.preventDefault(),mn())}let K=_(null),_n=_(null);function vn(e,t){e.preventDefault(),K.value={x:e.clientX,y:e.clientY,node:t}}function q(){K.value=null}async function yn(){let e=K.value?.node;q(),e&&(z.value=e),e?.type===`directory`&&!e.expanded&&await N(e);let t=dn();U.value={...t,kind:`file`,value:``},await p(),G.value?.focus()}async function bn(){let e=K.value?.node;q(),e&&(z.value=e),e?.type===`directory`&&!e.expanded&&await N(e);let t=dn();U.value={...t,kind:`directory`,value:``},await p(),G.value?.focus()}async function xn(){let e=K.value?.node;q(),e&&(W.value={node:e,value:e.name},await p(),un.value?.focus(),un.value?.select())}async function Sn(){let e=W.value;if(!e||!e.value.trim()||e.value.trim()===e.node.name){W.value=null;return}let t=e.value.trim(),n=e.node.path.replace(/[\\/][^\\/]+$/,``).replace(/[/\\]$/,``)+`/`+t,r=await(await fetch(`/api/editor/rename`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({oldPath:e.node.path,newPath:n})})).json();if(!r.success){g.error(r.error);return}let i=L.value.find(t=>t.path===e.node.path);i&&(i.path=n,i.name=t,R.value===e.node.path&&(R.value=n)),W.value=null,await M()}function Cn(e){e.key===`Enter`&&(e.preventDefault(),Sn()),e.key===`Escape`&&(e.preventDefault(),W.value=null)}async function wn(){let e=K.value?.node;if(q(),!e)return;let t=e.type===`directory`?k(`@EDITOR:文件夹`):k(`@EDITOR:文件`);if(!confirm(`${k(`@EDITOR:确认删除`)} ${t} "${e.name}"?`))return;let n=await(await fetch(`/api/editor/entry?path=${encodeURIComponent(e.path)}`,{method:`DELETE`})).json();if(!n.success){g.error(n.error);return}let r=L.value.findIndex(t=>t.path===e.path);r!==-1&&(L.value.splice(r,1),R.value===e.path&&(R.value=L.value[Math.max(0,r-1)]?.path??null)),g.success(k(`@EDITOR:已删除`)),await M()}async function Tn(){let e=K.value?.node;if(q(),e)try{let t=await(await fetch(`/api/editor/reveal`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({path:e.path})})).json();t.success||g.error(t.error)}catch(e){g.error(e?.message||String(e))}}function En(e){let t=d.currentDirectory;if(!t)return e;let n=e=>e.replace(/\\/g,`/`).replace(/\/+$/,``),r=n(t),i=n(e);return i===r?`.`:i.startsWith(r+`/`)?i.slice(r.length+1):i}async function Dn(e){try{if(navigator.clipboard&&window.isSecureContext)return await navigator.clipboard.writeText(e),!0}catch{}try{let t=document.createElement(`textarea`);t.value=e,t.style.position=`fixed`,t.style.left=`-9999px`,document.body.appendChild(t),t.select();let n=document.execCommand(`copy`);return document.body.removeChild(t),n}catch{return!1}}async function On(){let e=K.value?.node;q(),e&&(await Dn(e.path)?g.success(k(`@EDITOR:已复制到剪贴板`)):g.error(k(`@EDITOR:复制失败`)))}async function kn(){let e=K.value?.node;q(),e&&(await Dn(En(e.path))?g.success(k(`@EDITOR:已复制到剪贴板`)):g.error(k(`@EDITOR:复制失败`)))}async function An(){let e=K.value?.node;if(q(),e)try{let t=await(await fetch(`/api/editor/open-in-vscode`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({path:e.path})})).json();t.success||g.error(t.error||k(`@EDITOR:VSCode 未安装`))}catch(e){g.error(e?.message||String(e))}}let jn=new Set([`html`,`htm`]),Mn=t(()=>{let e=K.value?.node;if(!e||e.type!==`file`)return!1;let t=e.name.slice(e.name.lastIndexOf(`.`)+1).toLowerCase();return jn.has(t)});async function Nn(){let e=K.value?.node;if(q(),e)try{let t=await(await fetch(`/api/editor/open-in-browser`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({path:e.path})})).json();t.success||g.error(t.error||k(`@EDITOR:浏览器打开失败`))}catch(e){g.error(e?.message||String(e))}}o(()=>document.addEventListener(`click`,q)),s(()=>document.removeEventListener(`click`,q));let Pn=new Set([`md`,`html`,`htm`,`svg`]),Fn=new Set([`png`,`jpg`,`jpeg`,`gif`,`webp`,`ico`,`bmp`]),J=_(!1),Y=_(!1),X=_(!1),In=_(!1),Ln=_(0),Z=t(()=>L.value.find(e=>e.path===R.value)??null),Rn=t(()=>Z.value?.language===`plaintext`&&Z.value?.content===``),zn=t(()=>Z.value?.language===`office`),Q=t(()=>(Z.value?.name??``).split(`.`).pop()?.toLowerCase()??``),Bn=t(()=>Pn.has(Q.value)||Fn.has(Q.value)||_e(Q.value)),Vn=t(()=>((Z.value?.content??``).match(/^#{1,6}\s+/gm)||[]).length),$=t(()=>Q.value===`md`&&Vn.value>0);S(R,()=>{J.value&&!Bn.value&&(J.value=!1),Y.value&&!$.value&&(Y.value=!1)});function Hn(){Bn.value&&(J.value||(Y.value=!1,X.value=!1),J.value=!J.value)}function Un(){$.value&&(Y.value||(J.value=!1,X.value=!1),Y.value=!Y.value)}function Wn(){X.value||(J.value=!1,Y.value=!1),X.value=!X.value,In.value=!0}let Gn=t(()=>{let e=Z.value;if(!e)return``;let t=Q.value,n=document.documentElement.getAttribute(`data-theme`)===`light`?`#ffffff`:`#0d1117`;return t===`html`||t===`htm`?he(e.content):t===`svg`?`<!DOCTYPE html><html><head><meta charset="utf-8"><style>html,body{margin:0;padding:0;background:${n};display:flex;align-items:center;justify-content:center;min-height:100vh;}svg{max-width:100%;max-height:90vh;}</style></head><body>${e.content}</body></html>`:``}),Kn=!1,qn=0,Jn=0;function Yn(e){Kn=!0,qn=e.clientX,Jn=Ln.value,document.addEventListener(`mousemove`,Xn),document.addEventListener(`mouseup`,Zn),e.preventDefault()}function Xn(e){if(!Kn)return;let t=e.clientX-qn;Ln.value=Math.max(200,Math.min(900,Jn+t))}function Zn(){Kn=!1,document.removeEventListener(`mousemove`,Xn),document.removeEventListener(`mouseup`,Zn)}return(t,o)=>(m(),n(D,null,[E(`div`,{class:`editor-view`,ref_key:`containerRef`,ref:H},[E(`div`,{class:`editor-sidebar`,style:h({width:tn.value+`px`})},[E(`div`,B,[E(`span`,Ke,u(i(k)(`@EDITOR:资源管理器`)),1),E(`div`,qe,[c(i(a),{content:i(k)(`@EDITOR:新建文件`),placement:`bottom`,"show-after":300},{default:re(()=>[E(`button`,{class:`sidebar-action-btn`,onClick:fn},[...o[11]||=[E(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[E(`path`,{d:`M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z`}),E(`polyline`,{points:`14 2 14 8 20 8`}),E(`line`,{x1:`12`,y1:`13`,x2:`12`,y2:`19`}),E(`line`,{x1:`9`,y1:`16`,x2:`15`,y2:`16`})],-1)]])]),_:1},8,[`content`]),c(i(a),{content:i(k)(`@EDITOR:新建文件夹`),placement:`bottom`,"show-after":300},{default:re(()=>[E(`button`,{class:`sidebar-action-btn`,onClick:pn},[...o[12]||=[E(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[E(`path`,{d:`M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z`}),E(`line`,{x1:`12`,y1:`11`,x2:`12`,y2:`17`}),E(`line`,{x1:`9`,y1:`14`,x2:`15`,y2:`14`})],-1)]])]),_:1},8,[`content`]),c(i(a),{content:i(k)(`@EDITOR:刷新`),placement:`bottom`,"show-after":300},{default:re(()=>[E(`button`,{class:`sidebar-action-btn`,onClick:o[0]||=e=>M({notifyOnError:!0})},[...o[13]||=[E(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[E(`polyline`,{points:`1 4 1 10 7 10`}),E(`polyline`,{points:`23 20 23 14 17 14`}),E(`path`,{d:`M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15`})],-1)]])]),_:1},8,[`content`])])]),E(`div`,Je,[o[15]||=E(`svg`,{class:`sidebar-search-icon`,viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[E(`circle`,{cx:`11`,cy:`11`,r:`7`}),E(`line`,{x1:`21`,y1:`21`,x2:`16.65`,y2:`16.65`})],-1),x(E(`input`,{ref_key:`searchInputRef`,ref:I,"onUpdate:modelValue":o[1]||=e=>O.value=e,type:`text`,class:`sidebar-search-input`,placeholder:i(k)(`@EDITOR:搜索文件...`),title:i(k)(`@EDITOR:搜索文件...`),spellcheck:`false`,autocomplete:`off`,onKeydown:ne(We,[`escape`])},null,40,Ye),[[v,O.value]]),O.value?(m(),n(`button`,{key:0,class:`sidebar-search-clear`,title:i(k)(`@EDITOR:清除搜索`),"aria-label":i(k)(`@EDITOR:清除搜索`),onClick:De},[...o[14]||=[E(`svg`,{viewBox:`0 0 24 24`,width:`12`,height:`12`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[E(`line`,{x1:`18`,y1:`6`,x2:`6`,y2:`18`}),E(`line`,{x1:`6`,y1:`6`,x2:`18`,y2:`18`})],-1)]],8,Xe)):r(``,!0)]),se.value?(m(),n(`div`,vt,[...o[24]||=[E(`span`,{class:`spin-icon`},null,-1)]])):(m(),n(`div`,Ze,[(m(!0),n(D,null,te(P(Be.value),e=>(m(),n(D,{key:e.path},[W.value&&W.value.node.path===e.path?(m(),n(`div`,{key:0,class:`tree-node tree-inline-input-row`,style:h({paddingLeft:12+e.depth*14+`px`})},[e.type===`directory`?(m(),n(`span`,{key:0,class:w([`tree-arrow`,{expanded:e.expanded}])},[...o[16]||=[E(`svg`,{viewBox:`0 0 24 24`,width:`10`,height:`10`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[E(`polyline`,{points:`9 18 15 12 9 6`})],-1)]],2)):(m(),n(`span`,Qe)),(m(),n(`svg`,$e,[E(`use`,{"xlink:href":`#${ln(e)}`},null,8,et)])),x(E(`input`,{ref_for:!0,ref_key:`renameInputRef`,ref:un,"onUpdate:modelValue":o[2]||=e=>W.value.value=e,onKeydown:Cn,onBlur:Sn,onClick:o[3]||=T(()=>{},[`stop`])},null,544),[[v,W.value.value]])],4)):(m(),n(`div`,{key:1,class:w([`tree-node`,{"tree-node--dir":e.type===`directory`,"tree-node--file":e.type===`file`,"tree-node--active":R.value===e.path,"tree-node--selected":z.value?.path===e.path&&R.value!==e.path}]),style:h({paddingLeft:12+e.depth*14+`px`}),onClick:t=>Ut(e),onContextmenu:t=>vn(t,e)},[e.type===`directory`?(m(),n(`span`,{key:0,class:w([`tree-arrow`,{expanded:e.expanded}])},[...o[17]||=[E(`svg`,{viewBox:`0 0 24 24`,width:`10`,height:`10`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[E(`polyline`,{points:`9 18 15 12 9 6`})],-1)]],2)):(m(),n(`span`,nt)),e.type===`directory`?(m(),n(`svg`,rt,[E(`use`,{"xlink:href":`#${ln(e)}`},null,8,it)])):(m(),n(`svg`,at,[E(`use`,{"xlink:href":`#${ln(e)}`},null,8,ot)])),E(`span`,{class:`tree-name`,title:e.path},[(m(!0),n(D,null,te(He(e.name),(e,t)=>(m(),n(D,{key:t},[e.hit?(m(),n(`span`,ct,u(e.text),1)):(m(),n(D,{key:1},[y(u(e.text),1)],64))],64))),128))],8,st),e.loading?(m(),n(`span`,lt)):r(``,!0)],46,tt)),U.value&&U.value.afterNode?.path===e.path?(m(),n(`div`,{key:2,class:`tree-node tree-inline-input-row`,style:h({paddingLeft:12+U.value.depth*14+`px`})},[o[20]||=E(`span`,{class:`tree-arrow-spacer`},null,-1),U.value.kind===`directory`?(m(),n(`svg`,ut,[...o[18]||=[E(`path`,{d:`M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z`},null,-1)]])):(m(),n(`svg`,dt,[...o[19]||=[E(`path`,{d:`M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z`},null,-1),E(`polyline`,{points:`14 2 14 8 20 8`},null,-1)]])),x(E(`input`,{ref_for:!0,ref_key:`inlineInputRef`,ref:G,class:`tree-inline-input`,"onUpdate:modelValue":o[4]||=e=>U.value.value=e,placeholder:U.value.kind===`file`?i(k)(`@EDITOR:输入文件名`):i(k)(`@EDITOR:输入文件夹名`),onKeydown:gn,onBlur:mn,onClick:o[5]||=T(()=>{},[`stop`])},null,40,ft),[[v,U.value.value]])],4)):r(``,!0)],64))),128)),U.value&&U.value.afterNode===null?(m(),n(`div`,pt,[o[23]||=E(`span`,{class:`tree-arrow-spacer`},null,-1),U.value.kind===`directory`?(m(),n(`svg`,mt,[...o[21]||=[E(`path`,{d:`M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z`},null,-1)]])):(m(),n(`svg`,ht,[...o[22]||=[E(`path`,{d:`M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z`},null,-1),E(`polyline`,{points:`14 2 14 8 20 8`},null,-1)]])),x(E(`input`,{ref_key:`inlineInputRef`,ref:G,class:`tree-inline-input`,"onUpdate:modelValue":o[6]||=e=>U.value.value=e,placeholder:U.value.kind===`file`?i(k)(`@EDITOR:输入文件名`):i(k)(`@EDITOR:输入文件夹名`),onKeydown:gn,onBlur:mn,onClick:o[7]||=T(()=>{},[`stop`])},null,40,gt),[[v,U.value.value]])])):r(``,!0),!U.value&&(Ve.value||C.value.length===0)?(m(),n(`div`,_t,u(Ve.value?i(k)(`@EDITOR:未找到匹配文件`):i(k)(`@EDITOR:暂无文件`)),1)):r(``,!0)]))],4),E(`div`,{class:`editor-resizer`,onMousedown:on},null,32),E(`div`,yt,[L.value.length>0?(m(),n(`div`,bt,[(m(!0),n(D,null,te(L.value,e=>(m(),n(`div`,{key:e.path,class:w([`editor-tab`,{active:R.value===e.path,dirty:e.isDirty}]),onClick:t=>R.value=e.path,title:e.path},[E(`span`,St,u(e.name),1),e.isDirty?(m(),n(`span`,Ct)):r(``,!0),E(`button`,{class:`tab-close`,onClick:t=>Wt(e.path,t)},[...o[25]||=[E(`svg`,{viewBox:`0 0 24 24`,width:`12`,height:`12`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"stroke-linecap":`round`},[E(`line`,{x1:`18`,y1:`6`,x2:`6`,y2:`18`}),E(`line`,{x1:`6`,y1:`6`,x2:`18`,y2:`18`})],-1)]],8,wt)],10,xt))),128)),o[29]||=E(`div`,{class:`editor-tabs-spacer`},null,-1),Bn.value?(m(),n(`button`,{key:0,class:w([`preview-toggle-btn`,{active:J.value}]),title:J.value?i(k)(`@EDITOR:关闭预览`):i(k)(`@EDITOR:打开预览`),onClick:Hn},[o[26]||=E(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[E(`path`,{d:`M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z`}),E(`circle`,{cx:`12`,cy:`12`,r:`3`})],-1),E(`span`,null,u(i(k)(`@EDITOR:预览`)),1)],10,Tt)):r(``,!0),$.value?(m(),n(`button`,{key:1,class:w([`preview-toggle-btn mindmap-toggle-btn`,{active:Y.value,disabled:!$.value}]),disabled:!$.value,title:$.value?Y.value?i(k)(`@EDITOR:关闭思维导图`):i(k)(`@EDITOR:打开思维导图`):i(k)(`@EDITOR:需要至少一个 # 标题`),onClick:Un},[o[27]||=e(`<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" data-v-4ce372fa><circle cx="12" cy="12" r="2" data-v-4ce372fa></circle><circle cx="5" cy="6" r="1.6" data-v-4ce372fa></circle><circle cx="19" cy="6" r="1.6" data-v-4ce372fa></circle><circle cx="5" cy="18" r="1.6" data-v-4ce372fa></circle><circle cx="19" cy="18" r="1.6" data-v-4ce372fa></circle><line x1="11" y1="11" x2="6.4" y2="7" data-v-4ce372fa></line><line x1="13" y1="11" x2="17.6" y2="7" data-v-4ce372fa></line><line x1="11" y1="13" x2="6.4" y2="17" data-v-4ce372fa></line><line x1="13" y1="13" x2="17.6" y2="17" data-v-4ce372fa></line></svg>`,1),E(`span`,null,u(i(k)(`@EDITOR:思维导图`)),1)],10,Et)):r(``,!0),E(`button`,{class:w([`preview-toggle-btn agent-toggle-btn`,{active:X.value}]),title:X.value?i(k)(`@EDITOR:关闭 g ai 对话`):i(k)(`@EDITOR:打开 g ai 对话`),onClick:Wn},[o[28]||=E(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[E(`path`,{d:`M12 3l1.9 4.6L18.5 9.5l-4.6 1.9L12 16l-1.9-4.6L5.5 9.5l4.6-1.9z`}),E(`path`,{d:`M18 16.5l.9 2.1 2.1.9-2.1.9-.9 2.1-.9-2.1-2.1-.9 2.1-.9z`})],-1),E(`span`,null,u(i(k)(`@EDITOR:g ai 对话`)),1)],10,Dt)])):r(``,!0),L.value.length===0?(m(),n(`div`,Ot,[(m(),n(`svg`,kt,[...o[30]||=[E(`path`,{d:`M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z`},null,-1),E(`polyline`,{points:`14 2 14 8 20 8`},null,-1)]])),E(`p`,null,u(i(k)(`@EDITOR:从左侧选择文件打开`)),1),E(`p`,At,u(i(k)(`@EDITOR:Ctrl+S 保存`)),1)])):r(``,!0),E(`div`,jt,[E(`div`,{class:w([`monaco-container`,{hidden:L.value.length===0||Rn.value||zn.value}]),ref_key:`editorContainerRef`,ref:Kt},null,2),Rn.value&&L.value.length>0&&!J.value&&!Y.value?(m(),n(`div`,Mt,[(m(),n(`svg`,Nt,[...o[31]||=[E(`rect`,{x:`3`,y:`3`,width:`18`,height:`18`,rx:`2`},null,-1),E(`circle`,{cx:`9`,cy:`9`,r:`2`},null,-1),E(`path`,{d:`m21 15-5-5L5 21`},null,-1)]])),E(`p`,Pt,u(Z.value?.name),1),E(`p`,Ft,u(i(k)(`@EDITOR:这是图片文件,已在右侧预览面板中打开`)),1)])):r(``,!0),(J.value||Y.value||X.value)&&L.value.length>0?(m(),n(`div`,{key:1,class:`preview-resizer`,onMousedown:Yn},null,32)):r(``,!0),In.value?x((m(),f(Ge,{key:2,active:X.value&&L.value.length>0,"active-file-path":R.value,"active-file-name":Z.value?.name??``,style:h({flexBasis:Ln.value+`px`}),onClose:o[8]||=e=>X.value=!1},null,8,[`active`,`active-file-path`,`active-file-name`,`style`])),[[ie,X.value&&L.value.length>0]]):r(``,!0),(J.value||Y.value)&&L.value.length>0?(m(),n(`div`,{key:3,class:`preview-panel`,style:h({flexBasis:Ln.value+`px`})},[E(`div`,It,[E(`span`,Lt,u(Y.value?i(k)(`@EDITOR:思维导图`):i(k)(`@EDITOR:预览`)),1),E(`span`,Rt,u(Q.value.toUpperCase()),1),o[33]||=E(`div`,{class:`preview-header-spacer`},null,-1),E(`button`,{class:`preview-close-btn`,title:Y.value?i(k)(`@EDITOR:关闭思维导图`):i(k)(`@EDITOR:关闭预览`),onClick:o[9]||=e=>Y.value?Y.value=!1:J.value=!1},[...o[32]||=[E(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"stroke-linecap":`round`},[E(`line`,{x1:`18`,y1:`6`,x2:`6`,y2:`18`}),E(`line`,{x1:`6`,y1:`6`,x2:`18`,y2:`18`})],-1)]],8,zt)]),E(`div`,Bt,[Y.value&&Q.value===`md`&&Z.value?(m(),f(F,{key:0,content:Z.value.content,class:`preview-mindmap`},null,8,[`content`])):J.value&&Q.value===`md`&&Z.value?(m(),f(me,{key:1,content:Z.value.content,class:`preview-markdown`},null,8,[`content`])):J.value&&[`html`,`htm`,`svg`].includes(Q.value)?(m(),n(`iframe`,{key:2,class:`preview-iframe`,sandbox:i(ve),srcdoc:Gn.value},null,8,Vt)):J.value&&i(Fn).has(Q.value)&&Z.value?(m(),f(pe,{key:3,"file-path":Z.value.path,"file-name":Z.value.name},null,8,[`file-path`,`file-name`])):J.value&&zn.value&&Z.value?(m(),f(ge,{key:4,"file-path":Z.value.path},null,8,[`file-path`])):r(``,!0)])],4)):r(``,!0)])])],512),(m(),f(ae,{to:`body`},[K.value?(m(),n(`div`,{key:0,ref_key:`ctxMenuRef`,ref:_n,class:`ctx-menu`,style:h({left:K.value.x+`px`,top:K.value.y+`px`}),onClick:o[10]||=T(()=>{},[`stop`])},[E(`button`,{class:`ctx-menu-item`,onClick:yn},[o[34]||=E(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[E(`path`,{d:`M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z`}),E(`polyline`,{points:`14 2 14 8 20 8`}),E(`line`,{x1:`12`,y1:`13`,x2:`12`,y2:`19`}),E(`line`,{x1:`9`,y1:`16`,x2:`15`,y2:`16`})],-1),y(` `+u(i(k)(`@EDITOR:新建文件`)),1)]),E(`button`,{class:`ctx-menu-item`,onClick:bn},[o[35]||=E(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[E(`path`,{d:`M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z`}),E(`line`,{x1:`12`,y1:`11`,x2:`12`,y2:`17`}),E(`line`,{x1:`9`,y1:`14`,x2:`15`,y2:`14`})],-1),y(` `+u(i(k)(`@EDITOR:新建文件夹`)),1)]),o[42]||=E(`div`,{class:`ctx-menu-sep`},null,-1),E(`button`,{class:`ctx-menu-item`,onClick:On},[o[36]||=E(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[E(`rect`,{x:`9`,y:`9`,width:`13`,height:`13`,rx:`2`,ry:`2`}),E(`path`,{d:`M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1`})],-1),y(` `+u(i(k)(`@EDITOR:复制绝对路径`)),1)]),E(`button`,{class:`ctx-menu-item`,onClick:kn},[o[37]||=E(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[E(`path`,{d:`M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71`}),E(`path`,{d:`M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71`})],-1),y(` `+u(i(k)(`@EDITOR:复制相对路径`)),1)]),o[43]||=E(`div`,{class:`ctx-menu-sep`},null,-1),Mn.value?(m(),n(`button`,{key:0,class:`ctx-menu-item`,onClick:Nn},[o[38]||=E(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[E(`circle`,{cx:`12`,cy:`12`,r:`9`}),E(`line`,{x1:`3`,y1:`12`,x2:`21`,y2:`12`}),E(`path`,{d:`M12 3a13 13 0 0 1 3.5 9 13 13 0 0 1-3.5 9 13 13 0 0 1-3.5-9A13 13 0 0 1 12 3z`})],-1),y(` `+u(i(k)(`@EDITOR:在浏览器中打开`)),1)])):r(``,!0),E(`button`,{class:`ctx-menu-item`,onClick:Tn},[o[39]||=E(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[E(`path`,{d:`M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z`}),E(`path`,{d:`M3 7v10a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2`})],-1),y(` `+u(i(k)(`@EDITOR:在资源管理器中打开`)),1)]),E(`button`,{class:`ctx-menu-item`,onClick:An},[c(le,{"icon-class":`vscode`,"class-name":`ctx-menu-icon`}),y(` `+u(i(k)(`@EDITOR:在 VSCode 中打开`)),1)]),E(`button`,{class:`ctx-menu-item`,onClick:xn},[o[40]||=E(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[E(`path`,{d:`M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7`}),E(`path`,{d:`M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z`})],-1),y(` `+u(i(k)(`@EDITOR:重命名`)),1)]),E(`button`,{class:`ctx-menu-item ctx-menu-item--danger`,onClick:wn},[o[41]||=E(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[E(`polyline`,{points:`3 6 5 6 21 6`}),E(`path`,{d:`M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6`}),E(`path`,{d:`M10 11v6`}),E(`path`,{d:`M14 11v6`}),E(`path`,{d:`M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2`})],-1),y(` `+u(i(k)(`@EDITOR:删除`)),1)])],4)):r(``,!0)]))],64))}}),[[`__scopeId`,`data-v-4ce372fa`]]);export{Ut as default};
@@ -1 +0,0 @@
1
- .dir-chat[data-v-96ce7584]{height:min(420px,42vh);min-height:200px;margin-top:var(--spacing-sm);border-top:1px solid var(--border-color-light);padding-top:var(--spacing-sm);display:flex}.dir-chat[data-v-96ce7584]>.acu-chat{flex:1;min-width:0}.dir-chat--fill[data-v-96ce7584]{flex:auto;height:auto;min-height:0}.dir-chat[data-v-96ce7584] .acu-welcome{padding:var(--spacing-base);align-items:flex-start;overflow-y:auto}.dir-chat[data-v-96ce7584] .acu-welcome-inner{margin-block:auto}.dir-chat[data-v-96ce7584] .acu-welcome-logo{display:none}.dir-chat[data-v-96ce7584] .acu-welcome-title{font-size:var(--font-size-lg);margin-bottom:var(--spacing-xs)}.dir-chat[data-v-96ce7584] .acu-welcome-desc{font-size:var(--font-size-sm);margin-bottom:var(--spacing-base)}.dir-chat[data-v-96ce7584] .acu-welcome-grid{gap:var(--spacing-sm)}
@@ -1 +0,0 @@
1
- import{Cn as e,Dn as t,Er as n,Kn as r,Mn as i,Pn as a,Pr as o,Rn as s,Xn as c,pr as l,qr as u}from"./element-plus-Bx3j6vzG.js";import{t as d}from"./vendor-CyWsJd6S.js";import{n as f,t as p}from"./_plugin-vue_export-helper-N8Vc5eEs.js";import{t as m}from"./useThemeObserver-DYxFoHh1.js";import{i as h,n as g,s as _}from"./agentConversations-Da7zLPfP.js";s(),l(),o();var v=p(a({__name:`RecentDirectoriesChat`,props:{dirStatus:{},summary:{},fill:{type:Boolean}},setup(a){let o=a,{theme:s}=m(),l=e(()=>s.value===`dark`?`dark`:`light`),{messages:p,isStreaming:v,pendingQuestion:y,answeringQuestion:b,sendMessage:x,answerQuestion:S,stop:C}=_(),w=h(),T=e(()=>[{id:`priority`,label:f(`@13D1C:这些项目该先处理哪个?`),prompt:f(`@13D1C:这些项目里该先处理哪个?按优先级给我一个处理顺序,并说明每一项该做什么。`)},{id:`behind`,label:f(`@13D1C:哪些项目落后远端?`),prompt:f(`@13D1C:哪些项目落后远端?分别落后多少个提交?`)},{id:`pull-behind`,label:f(`@13D1C:落后远端的都帮我 pull 下代码`),prompt:f(`@13D1C:落后远端的项目都帮我 pull 下代码,逐个执行并汇报结果。`)},{id:`uncommitted`,label:f(`@13D1C:看一下各项目未提交的都改了什么`),prompt:f(`@13D1C:看一下各项目未提交的改动都改了什么,按项目列出来。`)}]);async function E(e){await x(e.text,e.files,{engine:`gai`,dirStatus:o.dirStatus,dirSummary:o.summary})}async function D(e){await E({text:e.prompt,files:[]})}return r(()=>{C()}),(e,r)=>(c(),t(`div`,{class:u([`dir-chat`,{"dir-chat--fill":a.fill}])},[i(n(d),{messages:n(p),"assistant-name":n(g),theme:l.value,disabled:n(v),generating:n(v),"show-avatar":!1,"upload-config":{enabled:!1},placeholder:n(v)?n(f)(`@13D1C:g ai 正在回答...`):n(f)(`@13D1C:追问 g ai:这批项目该怎么处理?`),"welcome-title":n(f)(`@13D1C:可以接着问 g ai`),"welcome-description":n(f)(`@13D1C:它已经拿到了这批目录的 Git 状态,可以直接问该先处理哪个、某个项目落后了什么。`),"preset-questions":T.value,question:n(y),"question-submitting":n(b),"question-labels":n(w),onSend:E,onSelect:D,onStop:n(C),onAnswer:n(S)},null,8,[`messages`,`assistant-name`,`theme`,`disabled`,`generating`,`placeholder`,`welcome-title`,`welcome-description`,`preset-questions`,`question`,`question-submitting`,`question-labels`,`onStop`,`onAnswer`])],2))}}),[[`__scopeId`,`data-v-96ce7584`]]);export{v as default};