zen-gitsync 2.17.47 → 2.17.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -2
- package/package.json +2 -1
- package/src/cli/ai/mcp.js +323 -27
- package/src/cli/ai/mcp.test.js +202 -2
- package/src/ui/public/assets/{AgentEngineSelector-CKiVaqrY.js → AgentEngineSelector-Bm_wrfGT.js} +1 -1
- package/src/ui/public/assets/AgentView-BwqOHAs3.js +1 -0
- package/src/ui/public/assets/{AgentView-CRqQYAzh.css → AgentView-uHf-KMCH.css} +1 -1
- package/src/ui/public/assets/{AppVersionBadge-IWS9XBUV.js → AppVersionBadge-DyhIkbbF.js} +2 -2
- package/src/ui/public/assets/{BranchSelector-C_mK2mkS.js → BranchSelector-CDQZlH-y.js} +1 -1
- package/src/ui/public/assets/{CommitForm-C6I9rQXn.js → CommitForm-DpIXE8z1.js} +1 -1
- package/src/ui/public/assets/{CommonDialog-2zVHBuqT.js → CommonDialog-NqZURH2F.js} +1 -1
- package/src/ui/public/assets/EditorView-0T5LR5Hz.css +1 -0
- package/src/ui/public/assets/EditorView-BC6V8V5_.js +1 -0
- package/src/ui/public/assets/{FlowExecutionViewer-0Xw0oDen.js → FlowExecutionViewer-DxDKzmaP.js} +1 -1
- package/src/ui/public/assets/{FlowOrchestrationWorkspace-BKUspY-s.js → FlowOrchestrationWorkspace-BHASB5iW.js} +1 -1
- package/src/ui/public/assets/{LogList-pbwn5n2S.js → LogList-CdtFyrLd.js} +1 -1
- package/src/ui/public/assets/{MindmapView-DYh6nuuF.js → MindmapView-2tt7W7A3.js} +1 -1
- package/src/ui/public/assets/{MonitorView-CsJyUL9v.js → MonitorView--IW5ll8A.js} +1 -1
- package/src/ui/public/assets/{ProjectStartupButton-BhFQfAX1.js → ProjectStartupButton-CWKSZVGw.js} +1 -1
- package/src/ui/public/assets/RecentDirectoriesChat-DINPN4ju.js +1 -0
- package/src/ui/public/assets/RecentDirectoriesChat-THkqWEtO.css +1 -0
- package/src/ui/public/assets/{RemoteManagerDialog-CIZagKkC.js → RemoteManagerDialog-BVwpcCAu.js} +1 -1
- package/src/ui/public/assets/{RemoteRepoCard-Dj-B-6WU.js → RemoteRepoCard-Dy3AF_XZ.js} +1 -1
- package/src/ui/public/assets/{SourceMapView-pIlmQzYw.js → SourceMapView-BnHeu5wE.js} +1 -1
- package/src/ui/public/assets/{SvgIcon-CaefOO1F.js → SvgIcon-DcVasCdo.js} +1 -1
- package/src/ui/public/assets/{UserInputNode-1--I25vm.js → UserInputNode-B313MadX.js} +1 -1
- package/src/ui/public/assets/WorkbenchView-0cY9WHPM.js +20 -0
- package/src/ui/public/assets/WorkbenchView-rscs76HF.css +1 -0
- package/src/ui/public/assets/{_plugin-vue_export-helper-UTW98kcD.js → _plugin-vue_export-helper-Bsx6Zj3t.js} +5 -5
- package/src/ui/public/assets/agentConversations-BnG4a1oH.js +8 -0
- package/src/ui/public/assets/{configStore-H-n3ukZ_.js → configStore-DQSKV2_Y.js} +1 -1
- package/src/ui/public/assets/{dagre-Br4Eexe7.js → dagre-BmYeUlEa.js} +3 -3
- package/src/ui/public/assets/{element-plus-CZdvD4lq.js → element-plus-DTtm3XCd.js} +1 -1
- package/src/ui/public/assets/{flow-mindmap-4kZ-2J2Y.js → flow-mindmap-JxOspgwx.js} +1 -1
- package/src/ui/public/assets/{index-CD7otmb_.js → index-BApctCNq.js} +7 -7
- package/src/ui/public/assets/{monaco-CoYCcK3Q.js → monaco-D3R9OM26.js} +1 -1
- package/src/ui/public/assets/{office-docx-DndLP6GO.js → office-docx-CO7mIaWO.js} +1 -1
- package/src/ui/public/assets/{office-excel-Jt5zzo6D.js → office-excel-gA4KEkK4.js} +1 -1
- package/src/ui/public/assets/{office-pptx-J8tzRTjU.js → office-pptx-CQK4l_1Q.js} +1 -1
- package/src/ui/public/assets/{vendor-BD09UDuP.js → vendor-O17eRefg.js} +497 -497
- package/src/ui/public/assets/vendor-U3ZXMgeO.css +1 -0
- package/src/ui/public/assets/{vue-flow-CkM05TWt.js → vue-flow-BG6ZF1It.js} +1 -1
- package/src/ui/public/index.html +12 -12
- package/src/ui/server/routes/workbench/agentMarketplace.js +65 -30
- package/src/ui/server/routes/workbench/agentMarketplace.test.js +28 -4
- package/src/ui/server/routes/workbench/liveJobs.js +4 -0
- package/src/ui/server/routes/workbench/liveJobs.test.js +11 -0
- package/src/ui/server/routes/workbench/taskRunner.js +44 -7
- package/src/ui/server/routes/workbench/taskRunner.thinking.test.js +115 -0
- package/src/ui/public/assets/AgentView-c1frCBc3.js +0 -1
- package/src/ui/public/assets/EditorView-DUJrWJgh.js +0 -1
- package/src/ui/public/assets/EditorView-DqagGedH.css +0 -1
- package/src/ui/public/assets/RecentDirectoriesChat-BxbpKrXc.css +0 -1
- package/src/ui/public/assets/RecentDirectoriesChat-DM6sRO9L.js +0 -1
- package/src/ui/public/assets/WorkbenchView-BLzcZqy0.css +0 -1
- package/src/ui/public/assets/WorkbenchView-bpzL6m84.js +0 -20
- package/src/ui/public/assets/agentConversations-B9LNft3v.js +0 -8
- package/src/ui/public/assets/vendor-DNiTBOIX.css +0 -1
|
@@ -704,7 +704,8 @@ async function installedMcpsIn(file, target) {
|
|
|
704
704
|
name: clampText(server?.name || id, 80),
|
|
705
705
|
description: clampText(server?.description || '', 400),
|
|
706
706
|
package: server?.package || '',
|
|
707
|
-
|
|
707
|
+
// 手写的 url 型(http 传输)没有 command,退回显示 url —— 否则列表里这一项看起来是空的
|
|
708
|
+
command: server?.command || server?.url || '',
|
|
708
709
|
args: Array.isArray(server?.args) ? server.args : [],
|
|
709
710
|
envKeys: Object.keys(server?.env || {}),
|
|
710
711
|
file,
|
|
@@ -878,11 +879,10 @@ async function installSkill({ item, target, cwd }) {
|
|
|
878
879
|
async function installMcp({ item, target, cwd }) {
|
|
879
880
|
const packageName = String(item.package || '').trim();
|
|
880
881
|
const isStdio = !!packageName;
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
const bridge = !isStdio && item.remoteUrl ? 'mcp-remote' : '';
|
|
882
|
+
const remoteUrl = String(item.remoteUrl || '').trim();
|
|
883
|
+
const isRemote = !isStdio && /^https?:\/\//i.test(remoteUrl);
|
|
884
884
|
|
|
885
|
-
if (!isStdio && !
|
|
885
|
+
if (!isStdio && !isRemote) {
|
|
886
886
|
throw new HttpError(422, '该 MCP 服务没有提供 npm 包或远程端点,暂时无法一键安装');
|
|
887
887
|
}
|
|
888
888
|
if (isStdio && !SAFE_PACKAGE.test(packageName)) throw new HttpError(400, 'MCP npm 包名不合法');
|
|
@@ -896,6 +896,54 @@ async function installMcp({ item, target, cwd }) {
|
|
|
896
896
|
throw new HttpError(409, `该 MCP 服务已安装在${paths.label}`);
|
|
897
897
|
}
|
|
898
898
|
|
|
899
|
+
// 安装时顺手收集的键值(弹窗里用户填的)。只收合法的标识符键,
|
|
900
|
+
// 值为空的键跳过 —— 留给用户以后手改配置文件,而不是写一个空值进去让 server 起不来。
|
|
901
|
+
const filled = {};
|
|
902
|
+
if (item.env && typeof item.env === 'object') {
|
|
903
|
+
for (const [key, value] of Object.entries(item.env)) {
|
|
904
|
+
if (!/^[A-Za-z_][A-Za-z0-9_-]*$/.test(String(key))) continue;
|
|
905
|
+
const text = String(value ?? '').trim();
|
|
906
|
+
if (text) filled[key] = clampText(text, 2000);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
// 还缺哪些必填键,记下来给 UI 提示"装好了但还差配置"
|
|
910
|
+
const missingKeys = (Array.isArray(item.envKeys) ? item.envKeys : []).filter(key => !filled[key]);
|
|
911
|
+
const name = item.name || id;
|
|
912
|
+
const description = clampText(item.description || '', 400);
|
|
913
|
+
|
|
914
|
+
// ── 远程端点:直接写 http 配置,g ai 自己的 Streamable HTTP 客户端直连 ──
|
|
915
|
+
//
|
|
916
|
+
// 早先这里是桥成 stdio(npx -y mcp-remote <url>)。桥本身没错,但**鉴权传不进去**:
|
|
917
|
+
// mcp-remote 认的是它自己的 --header 约定,不是我们收集的那组键值 ——
|
|
918
|
+
// 表现就是"装好了但用不了"。g ai 现已原生支持 Streamable HTTP,直接落 url + headers
|
|
919
|
+
// 更短、更可控,也少一层随包升级漂移的中间件。
|
|
920
|
+
if (isRemote) {
|
|
921
|
+
const headers = {};
|
|
922
|
+
if (item.headers && typeof item.headers === 'object') {
|
|
923
|
+
for (const [key, value] of Object.entries(item.headers)) {
|
|
924
|
+
if (!key || value === undefined || value === null) continue;
|
|
925
|
+
headers[String(key)] = clampText(String(value), 2000);
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
// 弹窗收集的键值对远程服务来说就是请求头(没有子进程,env 无处可落)
|
|
929
|
+
Object.assign(headers, filled);
|
|
930
|
+
|
|
931
|
+
config.mcpServers[id] = {
|
|
932
|
+
name,
|
|
933
|
+
description,
|
|
934
|
+
type: 'http',
|
|
935
|
+
url: remoteUrl,
|
|
936
|
+
headers,
|
|
937
|
+
transport: 'remote',
|
|
938
|
+
requiredEnv: missingKeys,
|
|
939
|
+
};
|
|
940
|
+
await fs.mkdir(path.dirname(paths.file), { recursive: true });
|
|
941
|
+
await fs.writeFile(paths.file, `${JSON.stringify(config, null, 2)}\n`, 'utf8');
|
|
942
|
+
return { id, type: 'mcp', name, target, file: paths.file, envKeys: missingKeys, warning: '' };
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
// ── npm 包:stdio ──
|
|
946
|
+
//
|
|
899
947
|
// 项目级顺手 npm install 一次:把版本钉进 package.json,启动也更快。
|
|
900
948
|
// 失败不阻断 —— npx 运行时仍会按需下载,只是慢一点。
|
|
901
949
|
//
|
|
@@ -903,49 +951,36 @@ async function installMcp({ item, target, cwd }) {
|
|
|
903
951
|
// 装到 ~/.zen-gitsync/ai/node_modules 里 npx 根本解析不到,等于白装一份;
|
|
904
952
|
// npx 自己的缓存本来就是按用户全局共享的,首次启动下载一次即可。
|
|
905
953
|
let installWarning = '';
|
|
906
|
-
const primary = isStdio ? packageName : bridge;
|
|
907
954
|
if (target === 'project') {
|
|
908
955
|
try {
|
|
909
|
-
await execFileAsync(npmBinary(), ['install', '--save-dev',
|
|
956
|
+
await execFileAsync(npmBinary(), ['install', '--save-dev', packageName], { cwd, timeout: NPM_TIMEOUT_MS, windowsHide: true });
|
|
910
957
|
} catch (err) {
|
|
911
958
|
installWarning = `npm install 未成功(${clampText(err.message, 200)}),已写入配置,首次启动时会由 npx 按需下载`;
|
|
912
959
|
}
|
|
913
960
|
}
|
|
914
961
|
|
|
915
|
-
const args =
|
|
916
|
-
? (Array.isArray(item.args) && item.args.length ? item.args : ['-y', packageName])
|
|
917
|
-
: ['-y', bridge, String(item.remoteUrl)];
|
|
962
|
+
const args = Array.isArray(item.args) && item.args.length ? item.args : ['-y', packageName];
|
|
918
963
|
const replaceProject = value => String(value).replaceAll('${project}', cwd || process.cwd());
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
if (item.env && typeof item.env === 'object') {
|
|
924
|
-
for (const [key, value] of Object.entries(item.env)) {
|
|
925
|
-
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(String(key))) continue;
|
|
926
|
-
const text = String(value ?? '').trim();
|
|
927
|
-
if (text) env[key] = clampText(text, 2000);
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
// 还缺哪些必填环境变量,记下来给 UI 提示"装好了但还差配置"
|
|
931
|
-
const missingEnv = (Array.isArray(item.envKeys) ? item.envKeys : []).filter(key => !env[key]);
|
|
964
|
+
// 环境变量名比请求头名严(不接受连字符),stdio 这条路再筛一遍
|
|
965
|
+
const stdioEnv = Object.fromEntries(
|
|
966
|
+
Object.entries(filled).filter(([key]) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(key)),
|
|
967
|
+
);
|
|
932
968
|
|
|
933
969
|
config.mcpServers[id] = {
|
|
934
|
-
name
|
|
935
|
-
description
|
|
970
|
+
name,
|
|
971
|
+
description,
|
|
936
972
|
command: 'npx',
|
|
937
973
|
args: args.map(replaceProject),
|
|
938
|
-
env,
|
|
974
|
+
env: stdioEnv,
|
|
939
975
|
// 记下来给 UI 提示"这个 server 需要哪些环境变量",也便于卸载时回溯
|
|
940
|
-
requiredEnv:
|
|
941
|
-
package:
|
|
942
|
-
...(item.transport === 'remote' ? { transport: 'remote', remoteUrl: item.remoteUrl } : {}),
|
|
976
|
+
requiredEnv: missingKeys,
|
|
977
|
+
package: packageName,
|
|
943
978
|
};
|
|
944
979
|
|
|
945
980
|
await fs.mkdir(path.dirname(paths.file), { recursive: true });
|
|
946
981
|
await fs.writeFile(paths.file, `${JSON.stringify(config, null, 2)}\n`, 'utf8');
|
|
947
982
|
|
|
948
|
-
return { id, type: 'mcp', name
|
|
983
|
+
return { id, type: 'mcp', name, target, file: paths.file, envKeys: missingKeys, warning: installWarning };
|
|
949
984
|
}
|
|
950
985
|
|
|
951
986
|
/**
|
|
@@ -249,24 +249,48 @@ test('install mcp: 非法包名被拒绝,且不写出配置文件', async () =>
|
|
|
249
249
|
if (!before) assert.equal(await exists(PROJECT_MCP), false);
|
|
250
250
|
});
|
|
251
251
|
|
|
252
|
-
test('install mcp:
|
|
252
|
+
test('install mcp: 只有远程端点时直接写 http 配置(url + headers),不再绕 mcp-remote', async () => {
|
|
253
253
|
const { call } = harness();
|
|
254
254
|
const { status } = await call('POST /api/agent/marketplace/install', {
|
|
255
255
|
body: {
|
|
256
256
|
type: 'mcp',
|
|
257
257
|
target: 'global',
|
|
258
258
|
cwd: sandboxProject,
|
|
259
|
-
item: {
|
|
259
|
+
item: {
|
|
260
|
+
id: 'remote-only',
|
|
261
|
+
name: 'Remote',
|
|
262
|
+
remoteUrl: 'https://example.com/mcp',
|
|
263
|
+
transport: 'remote',
|
|
264
|
+
env: { Authorization: 'Bearer t0ken' },
|
|
265
|
+
},
|
|
260
266
|
},
|
|
261
267
|
});
|
|
262
268
|
assert.equal(status, 200);
|
|
263
269
|
const config = JSON.parse(await fs.readFile(AI_MCP_FILE, 'utf8'));
|
|
264
270
|
const server = config.mcpServers['remote-only'];
|
|
265
|
-
assert.equal(server.
|
|
266
|
-
assert.
|
|
271
|
+
assert.equal(server.type, 'http');
|
|
272
|
+
assert.equal(server.url, 'https://example.com/mcp');
|
|
273
|
+
// 弹窗里填的键值对远程服务就是请求头(g ai 的 http 客户端只认 headers)
|
|
274
|
+
assert.equal(server.headers.Authorization, 'Bearer t0ken');
|
|
275
|
+
assert.equal(server.command, undefined, 'http 型不该再落 command,否则会被当成 stdio 去 spawn');
|
|
267
276
|
assert.equal(server.transport, 'remote');
|
|
268
277
|
});
|
|
269
278
|
|
|
279
|
+
test('install mcp: 远程端点不是 http(s) 时拒绝,不写出半成品配置', async () => {
|
|
280
|
+
const { call } = harness();
|
|
281
|
+
const before = await exists(AI_MCP_FILE);
|
|
282
|
+
const { status } = await call('POST /api/agent/marketplace/install', {
|
|
283
|
+
body: {
|
|
284
|
+
type: 'mcp',
|
|
285
|
+
target: 'global',
|
|
286
|
+
cwd: sandboxProject,
|
|
287
|
+
item: { id: 'bad-remote', name: 'Bad', remoteUrl: 'ftp://example.com/mcp', transport: 'remote' },
|
|
288
|
+
},
|
|
289
|
+
});
|
|
290
|
+
assert.equal(status, 422);
|
|
291
|
+
if (!before) assert.equal(await exists(AI_MCP_FILE), false);
|
|
292
|
+
});
|
|
293
|
+
|
|
270
294
|
test('install mcp: 既没有包也没有远程端点时拒绝', async () => {
|
|
271
295
|
const { call } = harness();
|
|
272
296
|
const { status } = await call('POST /api/agent/marketplace/install', {
|
|
@@ -91,6 +91,10 @@ export function projectJob(j) {
|
|
|
91
91
|
// 最后一次产出的时刻。别的实例跑的任务,进度报告只能从这份文件上读它 ——
|
|
92
92
|
// 不过白名单就会变成"本实例的报告说得出静默多久,跨实例的报告永远说不出来"。
|
|
93
93
|
lastActivityAt: j.lastActivityAt || null,
|
|
94
|
+
// 思考段计时(第一个思考分片 → 最后一个分片)。前端折叠态显示「想了多久」靠它,
|
|
95
|
+
// 运行中的任务也要能看到 —— 不过白名单就变成"本实例看得见耗时、别的实例看不见"。
|
|
96
|
+
thinkingStartedAt: j.thinkingStartedAt || null,
|
|
97
|
+
thinkingEndedAt: j.thinkingEndedAt || null,
|
|
94
98
|
endedAt: j.endedAt || null,
|
|
95
99
|
exitCode: typeof j.exitCode === 'number' ? j.exitCode : null,
|
|
96
100
|
error: j.error || null,
|
|
@@ -87,6 +87,8 @@ const runningJob = (id, extra = {}) => ({
|
|
|
87
87
|
prompt: 'p',
|
|
88
88
|
output: 'out',
|
|
89
89
|
thinking: 'think',
|
|
90
|
+
thinkingStartedAt: '2026-09-28T14:56:52.000Z',
|
|
91
|
+
thinkingEndedAt: '2026-09-28T14:56:58.500Z',
|
|
90
92
|
toolCalls: [],
|
|
91
93
|
claudeSessionId: null,
|
|
92
94
|
// 不该被广播出去的内部字段(白名单投影必须剥掉)
|
|
@@ -112,11 +114,20 @@ test('projectJob:白名单投影剥掉 child 等不可序列化字段,保留前
|
|
|
112
114
|
assert.equal(rec.agent, 'claude');
|
|
113
115
|
assert.equal(rec.claudeSessionId, null);
|
|
114
116
|
assert.deepEqual(rec.toolCalls, []);
|
|
117
|
+
// 思考段计时必须过白名单:漏了它 = 本实例看得见「想了多久」、别的实例永远看不见
|
|
118
|
+
assert.equal(rec.thinkingStartedAt, '2026-09-28T14:56:52.000Z');
|
|
119
|
+
assert.equal(rec.thinkingEndedAt, '2026-09-28T14:56:58.500Z');
|
|
115
120
|
assert.ok(!('child' in rec), 'child 必须先剥掉,否则 JSON.stringify 直接抛');
|
|
116
121
|
// 投影结果要能真的序列化
|
|
117
122
|
assert.doesNotThrow(() => JSON.stringify(rec));
|
|
118
123
|
});
|
|
119
124
|
|
|
125
|
+
test('projectJob:老 job 没有计时字段时归成 null(不是 undefined,前端不用判两种空)', () => {
|
|
126
|
+
const rec = projectJob(runningJob('j-old', { thinkingStartedAt: undefined, thinkingEndedAt: undefined }));
|
|
127
|
+
assert.equal(rec.thinkingStartedAt, null);
|
|
128
|
+
assert.equal(rec.thinkingEndedAt, null);
|
|
129
|
+
});
|
|
130
|
+
|
|
120
131
|
test('toLiveRecord:正文/思考截尾,工具流水只留最近若干条', () => {
|
|
121
132
|
const toolCalls = Array.from({ length: LIVE_TOOL_CALL_LIMIT + 5 }, (_, i) => ({
|
|
122
133
|
id: `c${i}`,
|
|
@@ -577,6 +577,40 @@ export function createToolCallTracker(job, onUpdates) {
|
|
|
577
577
|
return { record, flush, seal };
|
|
578
578
|
}
|
|
579
579
|
|
|
580
|
+
/**
|
|
581
|
+
* 思考文本的保底上限(尾部截断:模型偶尔会长时间闷头思考,尾巴才是最新的)。
|
|
582
|
+
* 与工具流水的截断同一口径,只是这里量级更大。
|
|
583
|
+
*/
|
|
584
|
+
export const MAX_THINKING = 100 * 1024 * 1024;
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* 追加一段思考文本:截尾 + 记「思考段计时」。
|
|
588
|
+
*
|
|
589
|
+
* 计时口径与 zen-ai-chat-ui 的 ThinkingBlock 一致:**第一个分片记起点、之后每个
|
|
590
|
+
* 分片把终点往前推**(不是"思考状态转 done 为止"——那样会把"想完了但正文还没开始"
|
|
591
|
+
* 的空档也算进去)。这两个时间戳随 job 落盘(jobs.json)、随 live-jobs 跨实例可见,
|
|
592
|
+
* 前端折叠着也能显示「想了多久」;只在内存里算的话,刷新页面就没了。
|
|
593
|
+
*
|
|
594
|
+
* 导出仅为回归测试可见(taskRunner.thinking.test.js):跑整条 runSingleSubtask
|
|
595
|
+
* 去断言这两个字段,代价是起一个假 CLI 进程,不划算。
|
|
596
|
+
*
|
|
597
|
+
* @param {object} job 执行记录(thinking / lastActivityAt 与两个计时字段都记在它身上)
|
|
598
|
+
* @param {string} text 本批新增的思考文本
|
|
599
|
+
* @param {string} [at] 时间戳(ISO);默认取当前时刻,测试可注入
|
|
600
|
+
* @returns {string} 本次真正追加进 job.thinking 的增量(供批量推送用)
|
|
601
|
+
*/
|
|
602
|
+
export function appendThinkingToJob(job, text, at = nowIso()) {
|
|
603
|
+
if (!text) return '';
|
|
604
|
+
job.lastActivityAt = at;
|
|
605
|
+
if (!job.thinkingStartedAt) job.thinkingStartedAt = at;
|
|
606
|
+
job.thinkingEndedAt = at;
|
|
607
|
+
const prev = job.thinking || '';
|
|
608
|
+
job.thinking = (prev + text).slice(-MAX_THINKING);
|
|
609
|
+
// 顶到上限之后这里返回 ''(增量不再往前端推)—— 100MB 的思考文本没有真实场景,
|
|
610
|
+
// 真到那一步终态快照仍带全文尾巴,不值得为它把增量算法复杂化。
|
|
611
|
+
return job.thinking.slice(prev.length);
|
|
612
|
+
}
|
|
613
|
+
|
|
580
614
|
/**
|
|
581
615
|
* claude stream-json 事件处理器。
|
|
582
616
|
* system/init → session_id(--resume 续接用)
|
|
@@ -961,7 +995,12 @@ export async function runSingleSubtask(task, sub, repoPath, branch, options) {
|
|
|
961
995
|
claudeSessionId: resumeSessionId,
|
|
962
996
|
// 工具调用流水({id,name,argsPreview,arguments,result,status,error}[])。
|
|
963
997
|
// 先给个空数组,前端拿到的 job:update 就有了稳定形态,不用到处判 undefined。
|
|
964
|
-
toolCalls: []
|
|
998
|
+
toolCalls: [],
|
|
999
|
+
// 思考段计时(第一个思考分片 → 最后一个分片,ISO 字符串)。
|
|
1000
|
+
// 显式给 null 而不是不写:快照 / 落盘 / 跨实例的口径要一致,前端也不用判 undefined。
|
|
1001
|
+
// 记法与语义见 appendThinkingToJob。
|
|
1002
|
+
thinkingStartedAt: null,
|
|
1003
|
+
thinkingEndedAt: null
|
|
965
1004
|
};
|
|
966
1005
|
jobs.set(jobId, job);
|
|
967
1006
|
publish('job:update', job);
|
|
@@ -998,7 +1037,7 @@ export async function runSingleSubtask(task, sub, repoPath, branch, options) {
|
|
|
998
1037
|
// 工具调用 → job.toolCalls(前端工具块 + 落盘归档)
|
|
999
1038
|
// 其他事件 → 忽略,避免噪声
|
|
1000
1039
|
const MAX_OUTPUT = 100 * 1024 * 1024;
|
|
1001
|
-
|
|
1040
|
+
// 思考的截断上限是模块级的 MAX_THINKING(appendThinkingToJob 要用)
|
|
1002
1041
|
job.output = '';
|
|
1003
1042
|
job.thinking = '';
|
|
1004
1043
|
const lineBuf = { stdout: '', stderr: '' };
|
|
@@ -1022,11 +1061,9 @@ export async function runSingleSubtask(task, sub, repoPath, branch, options) {
|
|
|
1022
1061
|
}
|
|
1023
1062
|
};
|
|
1024
1063
|
const appendThinking = (text) => {
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
job.thinking = (job.thinking + text).slice(-MAX_THINKING);
|
|
1029
|
-
thinkingBatch += job.thinking.slice(prevLen);
|
|
1064
|
+
// 追加 / 截断 / 思考段计时都在 appendThinkingToJob 里(导出给回归测试的那份),
|
|
1065
|
+
// 这里只负责批量推送:一批 NDJSON 处理完统一 flush 一次
|
|
1066
|
+
thinkingBatch += appendThinkingToJob(job, text);
|
|
1030
1067
|
};
|
|
1031
1068
|
|
|
1032
1069
|
// 工具调用:写进 job.toolCalls(随 job 落盘),并按批推 job:toolcalls 给前端。
|
|
@@ -0,0 +1,115 @@
|
|
|
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
|
+
// 思考段计时的回归测试(2026-10-08)。
|
|
16
|
+
//
|
|
17
|
+
// 背景:任务执行弹窗里的思考块以前只有「思考」两个字,折叠着看不出它想了多久。
|
|
18
|
+
// zen-ai-chat-ui 的 ThinkingBlock 支持在标题右侧显示「第一个思考分片 → 最后一个
|
|
19
|
+
// 分片」的耗时(折叠也看得见),但时间戳得由宿主喂 —— 也就是这里测的
|
|
20
|
+
// appendThinkingToJob。口径拧了「单测全绿而数字是错的」(比如把起点记成 job 开始、
|
|
21
|
+
// 或每次追加都重置起点),所以把口径钉死在单测里。
|
|
22
|
+
//
|
|
23
|
+
// 钉住的口径:
|
|
24
|
+
// 1. 第一个分片记起点,之后每个分片把终点往前推(**不是**"到第一个正文为止")
|
|
25
|
+
// 2. 起点一旦记下就不再移动(中途隔着工具调用再想一段,预览窗口跟着往后推)
|
|
26
|
+
// 3. 空分片不产生任何副作用(连 lastActivityAt 都不碰)
|
|
27
|
+
// 4. 老 job(没有这两个字段)第一次追加也补得上
|
|
28
|
+
// 5. 返回值 = 本次真正追加的增量(批量推送 job:thinking-delta 用它)
|
|
29
|
+
//
|
|
30
|
+
// 隔离策略同 taskRunner.toolcalls.test.js:import taskRunner.js 之前把
|
|
31
|
+
// USERPROFILE/HOME 指向 mkdtemp 沙箱(taskRunner → jobStore import 时就会 hydrate)。
|
|
32
|
+
|
|
33
|
+
import { test } from 'node:test';
|
|
34
|
+
import assert from 'node:assert/strict';
|
|
35
|
+
import path from 'node:path';
|
|
36
|
+
import os from 'node:os';
|
|
37
|
+
import { mkdtempSync } from 'node:fs';
|
|
38
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
39
|
+
|
|
40
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
41
|
+
const projectRoot = path.resolve(__dirname, '../../../../..');
|
|
42
|
+
|
|
43
|
+
// ---- 环境隔离:必须在 import taskRunner.js 之前完成 ----
|
|
44
|
+
const sandbox = mkdtempSync(path.join(os.tmpdir(), 'zen-thinking-test-'));
|
|
45
|
+
process.env.USERPROFILE = sandbox;
|
|
46
|
+
process.env.HOME = sandbox;
|
|
47
|
+
delete process.env.HOMEDRIVE;
|
|
48
|
+
delete process.env.HOMEPATH;
|
|
49
|
+
|
|
50
|
+
const { appendThinkingToJob } = await import(
|
|
51
|
+
pathToFileURL(path.join(projectRoot, 'src/ui/server/routes/workbench/taskRunner.js')).href
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
/** 一个刚创建、还没产出任何思考的 job(字段形状照 runSingleSubtask 里那个字面量) */
|
|
55
|
+
const makeJob = (extra = {}) => ({
|
|
56
|
+
id: 'j1',
|
|
57
|
+
thinking: '',
|
|
58
|
+
lastActivityAt: null,
|
|
59
|
+
thinkingStartedAt: null,
|
|
60
|
+
thinkingEndedAt: null,
|
|
61
|
+
...extra,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('第一个分片记起点,之后每个分片把终点往前推', () => {
|
|
65
|
+
const job = makeJob();
|
|
66
|
+
const t1 = '2026-10-08T01:00:00.000Z';
|
|
67
|
+
const t2 = '2026-10-08T01:00:03.000Z';
|
|
68
|
+
const t3 = '2026-10-08T01:00:09.000Z';
|
|
69
|
+
|
|
70
|
+
appendThinkingToJob(job, '先看看目录', t1);
|
|
71
|
+
assert.equal(job.thinkingStartedAt, t1, '第一个分片就是起点');
|
|
72
|
+
assert.equal(job.thinkingEndedAt, t1, '只有一个分片时终点与起点相同');
|
|
73
|
+
|
|
74
|
+
appendThinkingToJob(job, ',再读文件', t2);
|
|
75
|
+
assert.equal(job.thinkingStartedAt, t1, '起点不随后续分片移动');
|
|
76
|
+
assert.equal(job.thinkingEndedAt, t2, '每来一个分片,终点往前推');
|
|
77
|
+
|
|
78
|
+
// 中间隔着工具调用再想一段 —— 窗口跟着推到最后一段(与 ThinkingBlock 的
|
|
79
|
+
// 「第一个思考分片 → 最后一个分片」同口径,不把中间干活的时间算进去)
|
|
80
|
+
appendThinkingToJob(job, ',最后收个尾', t3);
|
|
81
|
+
assert.equal(job.thinkingStartedAt, t1);
|
|
82
|
+
assert.equal(job.thinkingEndedAt, t3);
|
|
83
|
+
assert.equal(job.thinking, '先看看目录,再读文件,最后收个尾');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test('每次追加都把 lastActivityAt 记到同一时刻(静默看门狗的记账口径)', () => {
|
|
87
|
+
const job = makeJob();
|
|
88
|
+
appendThinkingToJob(job, '想', '2026-10-08T02:00:00.000Z');
|
|
89
|
+
assert.equal(job.lastActivityAt, '2026-10-08T02:00:00.000Z');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('返回值 = 本次真正追加的增量(供批量推送 job:thinking-delta)', () => {
|
|
93
|
+
const job = makeJob();
|
|
94
|
+
assert.equal(appendThinkingToJob(job, '第一段', '2026-10-08T02:10:00.000Z'), '第一段');
|
|
95
|
+
assert.equal(appendThinkingToJob(job, '第二段', '2026-10-08T02:10:01.000Z'), '第二段');
|
|
96
|
+
assert.equal(job.thinking, '第一段第二段');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test('空分片:整条记录一个字都不动(连 lastActivityAt 都不碰)', () => {
|
|
100
|
+
const job = makeJob({ lastActivityAt: '2026-10-08T03:00:00.000Z' });
|
|
101
|
+
assert.equal(appendThinkingToJob(job, ''), '');
|
|
102
|
+
assert.equal(appendThinkingToJob(job, undefined), '');
|
|
103
|
+
assert.equal(job.thinking, '');
|
|
104
|
+
assert.equal(job.thinkingStartedAt, null, '空分片不该开出计时窗口');
|
|
105
|
+
assert.equal(job.thinkingEndedAt, null);
|
|
106
|
+
assert.equal(job.lastActivityAt, '2026-10-08T03:00:00.000Z', 'lastActivityAt 保持原值');
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('老 job(字段都不存在)第一次追加也补得上计时', () => {
|
|
110
|
+
const job = { id: 'old', thinking: '旧内容' };
|
|
111
|
+
appendThinkingToJob(job, '新的', '2026-10-08T04:00:00.000Z');
|
|
112
|
+
assert.equal(job.thinkingStartedAt, '2026-10-08T04:00:00.000Z');
|
|
113
|
+
assert.equal(job.thinkingEndedAt, '2026-10-08T04:00:00.000Z');
|
|
114
|
+
assert.equal(job.thinking, '旧内容新的');
|
|
115
|
+
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import"./rolldown-runtime-C0FnF6B9.js";import{At as e,Cn as t,Ct as n,Dn as r,En as i,Gr as a,Hn as o,J as ee,Jt as te,M as s,Mn as c,Mr as l,Pn as u,Rn as d,Tn as f,Tt as p,Vt as ne,W as re,Wt as m,Xr as h,Yn as g,Zn as _,a as v,dr as y,er as b,et as x,gr as S,hn as C,i as w,ir as T,j as ie,jn as E,kt as ae,ln as D,lt as O,mt as k,or as A,qr as j,r as M,rn as oe,sr as N,st as P,tt as se,vr as F,wn as I,wr as L,yn as R}from"./element-plus-CZdvD4lq.js";import{a as z,l as B}from"./vendor-BD09UDuP.js";import{n as V,t as H}from"./_plugin-vue_export-helper-UTW98kcD.js";import{t as ce}from"./configStore-H-n3ukZ_.js";import{t as le}from"./CommonDialog-2zVHBuqT.js";import{a as U,i as ue,n as de,o as W,r as G,s as K,t as q}from"./agentConversations-B9LNft3v.js";import{n as J,t as fe}from"./AgentEngineSelector-CKiVaqrY.js";d(),y(),D(),l();var Y={class:`marketplace-panel`},pe={class:`mp-toolbar`},me={class:`mp-search`},he=[`placeholder`],ge={class:`mp-toolbar-sub`},_e={class:`mp-target-hint`},ve={class:`mp-source-filter`},X=[`onClick`],ye={class:`mp-body`},be={class:`mp-group-header`},xe={class:`mp-group-title`},Se={key:0,class:`mp-group-count`},Ce={key:1,class:`mp-group-error`},we=[`href`,`title`],Te={key:0,class:`mp-grid`},Ee={class:`mp-card-head`},Z=[`title`],De={key:0,class:`mp-card-metric`},Oe=[`title`],Q={class:`mp-card-meta`},$=[`title`],ke=[`title`],Ae={key:2,class:`mp-tag remote`},je={class:`mp-card-foot`},Me=[`href`],Ne={key:1,class:`mp-installed-chip`},Pe=[`disabled`,`onClick`],Fe={key:3,class:`mp-not-installable`},Ie={key:1,class:`mp-empty`},Le={key:0,class:`mp-group installed`},Re={class:`mp-group-header`},ze={class:`mp-group-title`},Be={class:`mp-group-count`},Ve={key:0,class:`mp-installed-block`},He={class:`mp-installed-target`},Ue={class:`mp-installed-list`},We=[`title`],Ge=[`title`],Ke={key:1,class:`mp-meta-pkg`},qe={key:2,class:`mp-tag warn`},Je=[`disabled`,`title`,`onClick`],Ye=[`disabled`,`onClick`],Xe={key:1,class:`mp-empty all`},Ze={key:0,class:`mkt-form`},Qe={class:`mkt-form-name`},$e=[`onUpdate:modelValue`,`placeholder`],et={key:0,class:`mkt-field`},tt={class:`mkt-hint`},nt=H(u({__name:`MarketplacePanel`,props:{type:{}},setup(e){let o=e,l=ce(),u=F([]),d=F([]),p=F(!1),y=F(``),b=F(``),x=F([]),D=F(`project`),j=F(new Set),P=F(new Set),z=F(new Set),B=t(()=>l.currentDirectory||``),H=null;async function U(){if(!p.value){p.value=!0;try{let e=new URLSearchParams({type:o.type,cwd:B.value});b.value&&e.set(`q`,b.value),x.value.length&&e.set(`sources`,x.value.join(`,`));let t=await(await fetch(`/api/agent/marketplace/catalog?${e}`)).json();t?.success?(u.value=t.groups||[],d.value=t.installed||[]):w.error(t?.error||V(`@MKT:加载失败`))}catch{w.error(V(`@MKT:加载失败`))}finally{p.value=!1}}}T(y,e=>{H&&clearTimeout(H),H=setTimeout(()=>{b.value=e.trim(),U()},400)}),T(x,()=>U()),T(()=>o.type,()=>{x.value=[],b.value=``,y.value=``,U()}),T(B,()=>U()),U();let ue=t(()=>{let e=B.value?B.value.split(/[\\/]/).filter(Boolean).pop():``;return D.value===`project`?e||V(`@MKT:当前项目`):V(`@MKT:g ai 智能体`)});function de(e){return e.stars?`${W(e.stars)} ★`:e.downloads?`${W(e.downloads)} ${V(`@MKT:周下载`)}`:e.uses?`${W(e.uses)} ${V(`@MKT:次使用`)}`:``}function W(e){return e>=1e3?`${(e/1e3).toFixed(e>=1e4?0:1)}k`:String(e)}function G(e){return`${e.id}`}function K(e){return j.value.has(G(e))}let q=t(()=>{let e={project:[],global:[]};for(let t of d.value)(e[t.target]||=[]).push(t);return e}),J=S({visible:!1,item:null,env:{},args:``});function fe(e){return o.type===`mcp`&&(!!e.envKeys?.length||!!e.args?.length)}function nt(e){J.item=e,J.env=Object.fromEntries((e.envKeys||[]).map(e=>[e,``])),J.args=(e.args||[]).join(` `),J.visible=!0}function rt(){let e=J.item;if(J.visible=!1,!e)return;let t=Object.fromEntries(Object.entries(J.env).filter(([,e])=>e.trim()!==``)),n=J.args.trim()?J.args.trim().match(/(?:[^\s"]+|"[^"]*")+/g)?.map(e=>e.replace(/^"|"$/g,``))??void 0:void 0;at(e,{env:t,...n?{args:n}:{}})}async function it(e){if(!e.installed||await ot(e)){if(fe(e)){nt(e);return}await at(e,{})}}async function at(e,t){let n=G(e);j.value.add(n);try{let n=await fetch(`/api/agent/marketplace/install`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({type:o.type,target:D.value,cwd:B.value,item:{...e,...t}})}),r=await n.json().catch(()=>null);if(!n.ok||!r?.success){w.error(r?.error||V(`@MKT:安装失败`));return}r.item?.warning&&w.warning(r.item.warning),r.item?.envKeys?.length?w.warning(`${V(`@MKT:还缺环境变量`)}: ${r.item.envKeys.join(`, `)}`):w.success(V(`@MKT:安装成功`)),await U()}catch{w.error(V(`@MKT:安装失败`))}finally{j.value.delete(n)}}async function ot(e){try{return await M.confirm(`${e.name} ${V(`@MKT:已安装,要重新安装吗?`)}`,V(`@MKT:重新安装`),{confirmButtonText:V(`@MKT:重装`),cancelButtonText:V(`@MKT:取消`),type:`warning`}),!0}catch{return!1}}async function st(e){let t=`${e.target}:${e.id}`;z.value.add(t);try{let t=await fetch(`/api/agent/marketplace/reveal`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({type:o.type,target:e.target,cwd:B.value,id:e.id})}),n=await t.json().catch(()=>null);(!t.ok||!n?.success)&&w.error(n?.error||V(`@MKT:打开失败`))}catch{w.error(V(`@MKT:打开失败`))}finally{z.value.delete(t)}}async function ct(e){try{await M.confirm(`${V(`@MKT:确定卸载`)} ${e.name}?`,V(`@MKT:卸载`),{confirmButtonText:V(`@MKT:卸载`),cancelButtonText:V(`@MKT:取消`),type:`warning`})}catch{return}let t=`${e.target}:${e.id}`;P.value.add(t);try{let t=new URLSearchParams({target:e.target,cwd:B.value}),n=await fetch(`/api/agent/marketplace/item/${o.type}/${encodeURIComponent(e.id)}?${t}`,{method:`DELETE`}),r=await n.json().catch(()=>null);if(!n.ok||!r?.success){w.error(r?.error||V(`@MKT:卸载失败`));return}w.success(V(`@MKT:已卸载`)),await U()}catch{w.error(V(`@MKT:卸载失败`))}finally{P.value.delete(t)}}return(t,o)=>{let l=ee,b=ie,S=s,w=re,T=v;return g(),r(`div`,Y,[I(`div`,pe,[I(`div`,me,[c(l,{class:`mp-search-icon`},{default:A(()=>[c(L(m))]),_:1}),N(I(`input`,{"onUpdate:modelValue":o[0]||=e=>y.value=e,class:`mp-search-input`,type:`text`,placeholder:e.type===`skill`?L(V)(`@MKT:搜索 Skill...`):L(V)(`@MKT:搜索 MCP 服务...`)},null,8,he),[[C,y.value]])]),c(S,{modelValue:D.value,"onUpdate:modelValue":o[1]||=e=>D.value=e,size:`small`,class:`mp-target`},{default:A(()=>[c(b,{value:`project`},{default:A(()=>[E(h(L(V)(`@MKT:当前项目`)),1)]),_:1}),c(b,{value:`global`},{default:A(()=>[E(h(L(V)(`@MKT:g ai 智能体`)),1)]),_:1})]),_:1},8,[`modelValue`]),c(w,{content:L(V)(`@MKT:刷新`),placement:`top`,"show-after":300},{default:A(()=>[I(`button`,{class:a([`mp-refresh`,{spinning:p.value}]),onClick:U},[c(l,null,{default:A(()=>[c(L(ne))]),_:1})],2)]),_:1},8,[`content`])]),I(`div`,ge,[I(`span`,_e,[E(h(L(V)(`@MKT:安装到`))+` `,1),I(`b`,null,h(ue.value),1)]),I(`div`,ve,[(g(!0),r(R,null,_(u.value,e=>(g(),r(`button`,{key:e.id,class:a([`mp-chip`,{active:x.value.includes(e.id)}]),onClick:()=>{let t=x.value.indexOf(e.id);t>=0?x.value.splice(t,1):x.value.push(e.id)}},h(e.label),11,X))),128)),x.value.length?(g(),r(`button`,{key:0,class:`mp-chip clear`,onClick:o[2]||=e=>x.value=[]},h(L(V)(`@MKT:全部来源`)),1)):i(``,!0)])]),N((g(),r(`div`,ye,[(g(!0),r(R,null,_(u.value,e=>(g(),r(`section`,{key:e.id,class:`mp-group`},[I(`header`,be,[I(`h3`,xe,h(e.label),1),e.status===`ok`?(g(),r(`span`,Se,h(e.items.length),1)):(g(),r(`span`,Ce,[c(l,null,{default:A(()=>[c(L(oe))]),_:1}),E(` `+h(e.error||L(V)(`@MKT:来源不可用`)),1)])),e.homepage?(g(),r(`a`,{key:2,class:`mp-group-link`,href:e.homepage,target:`_blank`,rel:`noopener noreferrer`,title:e.homepage},[c(l,null,{default:A(()=>[c(L(ae))]),_:1})],8,we)):i(``,!0)]),e.status===`ok`&&e.items.length?(g(),r(`div`,Te,[(g(!0),r(R,null,_(e.items,e=>(g(),r(`article`,{key:G(e),class:`mp-card`},[I(`div`,Ee,[I(`span`,{class:`mp-card-name`,title:e.name},h(e.name),9,Z),de(e)?(g(),r(`span`,De,[c(l,null,{default:A(()=>[e.stars?(g(),f(L(te),{key:0})):(g(),f(L(k),{key:1}))]),_:2},1024),E(` `+h(de(e)),1)])):i(``,!0)]),I(`p`,{class:`mp-card-desc`,title:e.description},h(e.description||L(V)(`@MKT:暂无描述`)),9,Oe),I(`div`,Q,[e.package?(g(),r(`code`,{key:0,class:`mp-meta-pkg`,title:e.package},h(e.package),9,$)):e.repository?(g(),r(`span`,{key:1,class:`mp-meta-repo`,title:e.repository+(e.subpath?` · `+e.subpath:``)},[E(h(e.repository),1),e.subpath?(g(),r(R,{key:0},[E(` · `+h(e.subpath),1)],64)):i(``,!0)],8,ke)):i(``,!0),e.transport===`remote`?(g(),r(`span`,Ae,h(L(V)(`@MKT:远程服务`)),1)):i(``,!0),(g(!0),r(R,null,_((e.tags||[]).slice(0,2),e=>(g(),r(`span`,{key:e,class:`mp-tag`},h(e),1))),128))]),I(`div`,je,[e.upstream?(g(),r(`a`,{key:0,class:`mp-card-link`,href:e.upstream,target:`_blank`,rel:`noopener noreferrer`},h(L(V)(`@MKT:查看来源`)),9,Me)):i(``,!0),o[6]||=I(`span`,{class:`mp-foot-spacer`},null,-1),e.installed?(g(),r(`span`,Ne,[c(l,null,{default:A(()=>[c(L(se))]),_:1}),E(h(L(V)(`@MKT:已安装`)),1)])):e.installable===!1?(g(),r(`span`,Fe,h(L(V)(`@MKT:暂不支持一键安装`)),1)):(g(),r(`button`,{key:2,class:`mp-install-btn`,disabled:K(e),onClick:t=>it(e)},h(K(e)?L(V)(`@MKT:安装中...`):L(V)(`@MKT:安装`)),9,Pe))])]))),128))])):e.status===`ok`?(g(),r(`div`,Ie,h(L(V)(`@MKT:该来源暂无结果`)),1)):i(``,!0)]))),128)),d.value.length?(g(),r(`section`,Le,[I(`header`,Re,[I(`h3`,ze,h(L(V)(`@MKT:已安装`)),1),I(`span`,Be,h(d.value.length),1)]),(g(),r(R,null,_([`project`,`global`],e=>I(`div`,{key:e},[q.value[e]?.length?(g(),r(`div`,Ve,[I(`div`,He,h(e===`project`?L(V)(`@MKT:当前项目`):L(V)(`@MKT:g ai 智能体`)),1),I(`div`,Ue,[(g(!0),r(R,null,_(q.value[e],t=>(g(),r(`div`,{key:e+t.id,class:`mp-installed-row`},[I(`span`,{class:`mp-installed-name`,title:t.name},h(t.name),9,We),t.id&&t.id!==t.name?(g(),r(`code`,{key:0,class:`mp-installed-id`,title:t.dir||t.file||t.id},h(t.id),9,Ge)):i(``,!0),t.package?(g(),r(`code`,Ke,h(t.package),1)):i(``,!0),t.requiredEnv?.length?(g(),r(`span`,qe,h(L(V)(`@MKT:待配置`))+`: `+h(t.requiredEnv.join(`, `)),1)):i(``,!0),o[7]||=I(`span`,{class:`mp-foot-spacer`},null,-1),I(`button`,{class:`mp-reveal-btn`,disabled:z.value.has(e+t.id),title:t.dir||t.file||``,onClick:e=>st(t)},[c(l,null,{default:A(()=>[c(L(n))]),_:1}),E(` `+h(L(V)(`@MKT:打开文件夹`)),1)],8,Je),I(`button`,{class:`mp-remove-btn`,disabled:P.value.has(e+t.id),onClick:e=>ct(t)},[c(l,null,{default:A(()=>[c(L(O))]),_:1}),E(` `+h(P.value.has(e+t.id)?L(V)(`@MKT:卸载中...`):L(V)(`@MKT:卸载`)),1)],8,Ye)]))),128))])])):i(``,!0)])),64))])):i(``,!0),!p.value&&!u.value.length?(g(),r(`div`,Xe,h(L(V)(`@MKT:加载失败`)),1)):i(``,!0)])),[[T,p.value]]),c(le,{modelValue:J.visible,"onUpdate:modelValue":o[5]||=e=>J.visible=e,title:L(V)(`@MKT:配置 MCP`),width:`460px`,type:`flex`,"close-on-click-modal":!1,"append-to-body":``},{footer:A(()=>[I(`button`,{class:`mkt-cancel`,onClick:o[4]||=e=>J.visible=!1},h(L(V)(`@MKT:取消`)),1),I(`button`,{class:`mkt-confirm`,onClick:rt},h(L(V)(`@MKT:安装`)),1)]),default:A(()=>[J.item?(g(),r(`div`,Ze,[I(`p`,Qe,h(J.item.name),1),(g(!0),r(R,null,_(Object.keys(J.env),e=>(g(),r(`div`,{key:e,class:`mkt-field`},[I(`label`,null,h(e),1),N(I(`input`,{"onUpdate:modelValue":t=>J.env[e]=t,type:`text`,autocomplete:`off`,placeholder:L(V)(`@MKT:环境变量值`),spellcheck:`false`},null,8,$e),[[C,J.env[e]]])]))),128)),J.item.args?.length?(g(),r(`div`,et,[I(`label`,null,h(L(V)(`@MKT:启动参数`)),1),N(I(`input`,{"onUpdate:modelValue":o[3]||=e=>J.args=e,type:`text`,autocomplete:`off`,spellcheck:`false`},null,512),[[C,J.args]]),I(`p`,tt,h(L(V)(`@MKT:参数提示`)),1)])):i(``,!0)])):i(``,!0)]),_:1},8,[`modelValue`,`title`])])}}}),[[`__scopeId`,`data-v-536d7952`]]);d(),y(),l();var rt={class:`agent-chat-area`},it={class:`agent-tabs`,role:`tablist`},at=[`aria-selected`,`onClick`],ot={class:`agent-tab-body`},st={key:0,class:`agent-chat-pane`},ct={key:0,class:`agent-list-page`},lt={key:0,class:`agent-page-bar`},ut=[`title`,`aria-label`],dt={class:`agent-page-title`},ft={key:0,class:`chat-loading`},pt=H(u({__name:`AgentView`,setup(n){let te=ce(),s=F(null),{narrow:l}=J(s),u=F(`chat`),d=F(`chat`),ne=t(()=>d.value===`mcp`?`mcp`:`skill`),re=t(()=>[{id:`chat`,label:V(`@AGENT:对话`),icon:x},{id:`skill`,label:V(`@AGENT:Skill 广场`),icon:p},{id:`mcp`,label:V(`@AGENT:MCP 广场`),icon:P}]),{sessions:m,sessionsLoading:v,currentSessionId:y,messages:S,isStreaming:C,sessionLoading:w,loadSessions:ie,loadSession:E,deleteSession:ae,renameSession:D,newSession:O,sendMessage:k,pendingQuestion:M,answeringQuestion:oe,answerQuestion:N,isSessionGenerating:se,currentEngine:H,pendingEngine:le,isEngineLocked:Y,pickEngine:pe,stop:me,inputContextUsage:he}=K(),ge=t(()=>Y.value?H.value:le.value);function _e(e){Y.value||pe(e)}let ve=t(()=>{let e=te.theme;return e===`dark`||e===`auto`&&window.matchMedia(`(prefers-color-scheme: dark)`).matches?`dark`:`light`}),X=t(()=>U(m.value,se)),ye=G(),be=t(()=>X.value.find(e=>e.id===y.value)?.title||V(`@AGENT:对话`)),xe={"--welcome-avatar":`url("${q}")`},Se=t(()=>[{id:`p1`,label:V(`@AGENT:查看项目结构`),prompt:V(`@AGENT:prompt_p1`)},{id:`p2`,label:V(`@AGENT:分析代码质量`),prompt:V(`@AGENT:prompt_p2`)},{id:`p3`,label:V(`@AGENT:帮我写测试`),prompt:V(`@AGENT:prompt_p3`)},{id:`p4`,label:V(`@AGENT:Git 状态检查`),prompt:V(`@AGENT:prompt_p4`)},{id:`p5`,label:V(`@AGENT:帮我启动项目`),prompt:V(`@AGENT:prompt_p5`)}]);async function Ce(e){await k(e.text,e.files),await o(),Z()}async function we(e){await k(e.prompt),await o(),Z()}let Te=ue(),Ee=F(null);function Z(e=!0){Ee.value?.scrollToBottom(e)}T(()=>S.value.length,()=>{o(()=>Z(!1))});function De(e){E(e),u.value=`chat`}function Oe(){O(),u.value=`chat`}let Q=F(280),$=F(!1);function ke(e){$.value=!0;let t=e.clientX,n=Q.value,r=e=>{let r=e.clientX-t,i=Math.max(200,Math.min(500,n+r));Q.value=i},i=()=>{$.value=!1,document.removeEventListener(`mousemove`,r),document.removeEventListener(`mouseup`,i)};document.addEventListener(`mousemove`,r),document.addEventListener(`mouseup`,i)}return T(l,e=>{e||(u.value=`chat`)}),T(()=>[te.currentDirectory,C.value],async([e,t],n)=>{let r=!n||e!==n[0],i=!!n&&n[1]===!0&&!t;(r||i)&&await ie(),y.value&&!C.value&&!m.value.some(e=>e.sessionId===y.value)&&O()},{immediate:!0}),(t,n)=>(g(),r(`div`,{ref_key:`rootRef`,ref:s,class:`agent-view`},[d.value===`chat`&&!L(l)?(g(),r(R,{key:0},[I(`aside`,{class:`agent-sidebar`,style:j({width:Q.value+`px`})},[c(L(B),{class:`agent-conversations`,items:X.value,"active-id":L(y),loading:L(v),labels:L(ye),onSelect:De,onNew:Oe,onRename:L(D),onDelete:L(ae)},null,8,[`items`,`active-id`,`loading`,`labels`,`onRename`,`onDelete`])],4),I(`div`,{class:a([`sidebar-resizer`,{active:$.value}]),onMousedown:ke},null,34)],64)):i(``,!0),I(`main`,rt,[I(`nav`,it,[(g(!0),r(R,null,_(re.value,e=>(g(),r(`button`,{key:e.id,type:`button`,class:a([`agent-tab`,{active:d.value===e.id}]),role:`tab`,"aria-selected":d.value===e.id,onClick:t=>d.value=e.id},[c(L(ee),null,{default:A(()=>[(g(),f(b(e.icon)))]),_:2},1024),I(`span`,null,h(e.label),1)],10,at))),128)),d.value===`chat`?(g(),f(fe,{key:0,class:`agent-engine`,engine:ge.value,locked:L(Y),onSelect:_e},null,8,[`engine`,`locked`])):i(``,!0)]),I(`div`,ot,[d.value===`chat`?(g(),r(`div`,st,[L(l)&&u.value===`list`?(g(),r(`div`,ct,[c(L(B),{class:`agent-conversations`,items:X.value,"active-id":L(y),loading:L(v),labels:L(ye),onSelect:De,onNew:Oe,onRename:L(D),onDelete:L(ae)},null,8,[`items`,`active-id`,`loading`,`labels`,`onRename`,`onDelete`])])):(g(),r(R,{key:1},[L(l)?(g(),r(`div`,lt,[I(`button`,{type:`button`,class:`agent-page-back`,title:L(V)(`@AGENT:返回会话列表`),"aria-label":L(V)(`@AGENT:返回会话列表`),onClick:n[0]||=e=>u.value=`list`},[...n[1]||=[I(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[I(`line`,{x1:`19`,y1:`12`,x2:`5`,y2:`12`}),I(`polyline`,{points:`12 19 5 12 12 5`})],-1)]],8,ut),I(`span`,dt,h(be.value),1)])):i(``,!0),I(`div`,{class:`agent-chat-host`,style:xe},[L(w)?(g(),r(`div`,ft,[c(L(ee),{class:`is-loading`,size:32},{default:A(()=>[c(L(e))]),_:1}),I(`span`,null,h(L(V)(`@AGENT:加载会话中...`)),1)])):(g(),f(L(z),{key:1,ref_key:`chatContainerRef`,ref:Ee,messages:L(S),"preset-questions":Se.value,"welcome-title":L(V)(`@AGENT:智能体助手`),"welcome-description":L(V)(`@AGENT:我可以帮你阅读代码、执行命令、修改文件。选择下方话题或直接输入你的问题。`),"assistant-name":L(de),"assistant-avatar":L(q),theme:ve.value,disabled:L(C),generating:L(C),"upload-config":{accept:L(W)},"context-usage":L(he),placeholder:L(C)?L(V)(`@AGENT:正在生成中...`):L(V)(`@AGENT:输入消息,Enter 发送`),question:L(M),"question-submitting":L(oe),"question-labels":L(Te),"plan-config":{labels:{title:L(V)(`@AGENT:计划`),raw:L(V)(`@AGENT:原始参数`)}},onSend:Ce,onSelect:we,onStop:L(me),onAnswer:L(N)},null,8,[`messages`,`preset-questions`,`welcome-title`,`welcome-description`,`assistant-name`,`assistant-avatar`,`theme`,`disabled`,`generating`,`upload-config`,`context-usage`,`placeholder`,`question`,`question-submitting`,`question-labels`,`plan-config`,`onStop`,`onAnswer`]))])],64))])):(g(),f(nt,{key:1,type:ne.value},null,8,[`type`]))])])],512))}}),[[`__scopeId`,`data-v-794cbc00`]]);export{pt as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import"./rolldown-runtime-C0FnF6B9.js";import{An as e,Cn as t,Dn as n,En as r,Gn as i,Gr as a,Hn as o,Mn as s,Mr as c,Pn as l,Rn as u,Tn as d,W as ee,Xr as f,Yn as p,Zn as te,_n as ne,dr as m,gn as re,hn as ie,i as h,ir as g,jn as _,ln as v,or as ae,qn as oe,qr as y,r as se,sr as b,vn as ce,vr as x,wn as S,wr as C,xn as le,yn as w,yr as ue}from"./element-plus-CZdvD4lq.js";import{a as de,l as T,n as fe}from"./vendor-BD09UDuP.js";import{n as E,t as D}from"./_plugin-vue_export-helper-UTW98kcD.js";import{t as pe}from"./SvgIcon-CaefOO1F.js";import{t as me}from"./configStore-H-n3ukZ_.js";import{a as he,c as ge,i as _e,n as ve,o as ye,r as be,s as xe}from"./monaco-CoYCcK3Q.js";import{n as Se,r as O}from"./flow-mindmap-4kZ-2J2Y.js";import{A as Ce,F as we,I as Te,M as Ee,N as De,O as Oe,P as k,d as ke,i as Ae,j as je,k as Me}from"./index-CD7otmb_.js";import{a as Ne,i as Pe,n as Fe,o as Ie,r as Le,s as Re,t as ze}from"./agentConversations-B9LNft3v.js";import{n as Be,t as A}from"./AgentEngineSelector-CKiVaqrY.js";function j(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`}u(),m();var M={class:`mindmap-preview`},N={class:`mindmap-preview-canvas`},Ve=D(l({__name:`MindmapPreview`,props:{content:{}},setup(e){let r=e,i=t(()=>O(r.content||``,`未命名文档`));return(e,t)=>(p(),n(`div`,M,[t[0]||=S(`div`,{class:`mindmap-preview-header`},[S(`span`,{class:`mindmap-preview-title`},`整篇导图`),S(`span`,{class:`mindmap-preview-hint`},`基于整篇 Markdown 自动生成 · 阅读模式`)],-1),S(`div`,N,[s(C(Se),{data:i.value,"preview-mode":``},null,8,[`data`])])]))}}),[[`__scopeId`,`data-v-d2fe328b`]]);u(),m(),c(),v();var He={class:`agent-panel-header`},Ue=[`title`,`aria-label`],We={class:`agent-panel-title`},Ge={key:1,class:`agent-panel-title`},Ke=[`title`,`aria-label`],qe=[`title`],Je={class:`agent-panel-convs`},Ye=[`data-theme`],P=[`title`],F={class:`agent-context-att-name`},I=[`title`,`aria-label`],L=D(l({__name:`EditorAgentPanel`,props:{activeFilePath:{},activeFileName:{},active:{type:Boolean}},emits:[`close`],setup(c,{emit:l}){let u=c,ee=l,{theme:te}=De(),ne=t(()=>te.value===`dark`?`dark`:`light`),{sessions:m,sessionsLoading:ie,currentSessionId:h,messages:_,isStreaming:v,pendingQuestion:ae,answeringQuestion:y,isSessionGenerating:se,currentEngine:ce,pendingEngine:ue,isEngineLocked:D,pickEngine:pe,loadSessions:me,loadSession:he,deleteSession:ge,renameSession:_e,newSession:ve,sendMessage:ye,answerQuestion:be,stop:xe,inputContextUsage:Se}=Re(),O=t(()=>D.value?ce.value:ue.value);function Ce(e){D.value||pe(e)}let we=t(()=>Ne(m.value,se)),Te=Le(),Ee=Pe(),Oe=x(null),k=x(null),ke=x(null),Ae=x(null),je=x(null),{width:Me,narrow:j}=Be(je),M=x(`chat`),N=x(null),Ve=x(!1),L=null,Xe=t(()=>!!u.activeFileName&&!Ve.value);function Ze(e){return Array.from(e.children).find(e=>e.classList?.contains(`acu-input-attachments`))??null}function Qe(){let e=k.value?.$el;if(!e)return;let t=e.querySelector(`.agent-context-slot`);if(!Xe.value){if(!t)return;N.value=null,o(()=>t.remove());return}let n=N.value&&e.contains(N.value)?N.value:t;n||(n=document.createElement(`div`),n.className=`agent-context-slot`);let r=Ze(e),i=r??e;n.parentElement!==i&&i.insertBefore(n,r?r.firstChild:e.firstChild),N.value=n}function $e(e=!0){Oe.value?.scrollToBottom(e)}async function et(e){let t=Ve.value?void 0:u.activeFilePath||void 0;await ye(e.text,e.files,{openFilePath:t}),await o(),$e()}function tt(e){he(e),M.value=`chat`}function nt(){ve(),M.value=`chat`}g(()=>_.value.length,()=>{o(()=>$e(!1))});function rt(){let e=Ae.value;!e||typeof MutationObserver>`u`||(L?.disconnect(),L=new MutationObserver(()=>Qe()),L.observe(e,{childList:!0,subtree:!0}))}return g(()=>u.active,e=>{e&&(M.value=`chat`,me().catch(()=>{}),o(()=>{Qe(),$e(!1)}))}),g(j,e=>{e||(M.value=`chat`)}),g(()=>u.activeFilePath,()=>{Ve.value=!1}),g(Xe,e=>{e&&o(Qe)}),oe(()=>{me().catch(()=>{}),o(()=>{Qe(),rt()})}),i(()=>{L?.disconnect(),L=null,N.value=null}),(t,i)=>(p(),n(`div`,{ref_key:`rootRef`,ref:je,class:`editor-agent-panel`},[S(`div`,He,[C(j)&&M.value===`list`?(p(),n(w,{key:0},[S(`button`,{class:`agent-panel-icon-btn agent-panel-back-btn`,title:C(E)(`@EDITOR:返回对话`),"aria-label":C(E)(`@EDITOR:返回对话`),onClick:i[0]||=e=>M.value=`chat`},[...i[4]||=[S(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[S(`line`,{x1:`19`,y1:`12`,x2:`5`,y2:`12`}),S(`polyline`,{points:`12 19 5 12 12 5`})],-1)]],8,Ue),S(`span`,We,f(C(E)(`@EDITOR:会话列表`)),1)],64)):(p(),n(`span`,Ge,f(C(E)(`@EDITOR:g ai 对话`)),1)),i[7]||=S(`div`,{class:`agent-panel-spacer`},null,-1),!C(j)||M.value===`chat`?(p(),d(A,{key:2,class:`agent-panel-engine`,engine:O.value,locked:C(D),onSelect:Ce},null,8,[`engine`,`locked`])):r(``,!0),C(j)&&M.value===`chat`?(p(),n(`button`,{key:3,class:`agent-panel-icon-btn agent-panel-list-btn`,title:C(E)(`@EDITOR:会话列表`),"aria-label":C(E)(`@EDITOR:会话列表`),onClick:i[1]||=e=>M.value=`list`},[...i[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-150c2cc6><line x1="8" y1="6" x2="21" y2="6" data-v-150c2cc6></line><line x1="8" y1="12" x2="21" y2="12" data-v-150c2cc6></line><line x1="8" y1="18" x2="21" y2="18" data-v-150c2cc6></line><line x1="3" y1="6" x2="3.01" y2="6" data-v-150c2cc6></line><line x1="3" y1="12" x2="3.01" y2="12" data-v-150c2cc6></line><line x1="3" y1="18" x2="3.01" y2="18" data-v-150c2cc6></line></svg>`,1)]],8,Ke)):r(``,!0),S(`button`,{class:`agent-panel-icon-btn`,title:C(E)(`@EDITOR:关闭对话`),onClick:i[2]||=e=>ee(`close`)},[...i[6]||=[S(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"stroke-linecap":`round`},[S(`line`,{x1:`18`,y1:`6`,x2:`6`,y2:`18`}),S(`line`,{x1:`6`,y1:`6`,x2:`18`,y2:`18`})],-1)]],8,qe)]),S(`div`,{class:a([`agent-panel-body`,{"is-wide":!C(j)}])},[b(S(`div`,Je,[s(C(T),{"show-search":!0,items:we.value,"active-id":C(h),loading:C(ie),labels:C(Te),onSelect:tt,onNew:nt,onRename:C(_e),onDelete:C(ge)},null,8,[`items`,`active-id`,`loading`,`labels`,`onRename`,`onDelete`])],512),[[re,!C(j)||M.value===`list`]]),b(S(`div`,{ref_key:`chatHostRef`,ref:ke,class:`agent-panel-chat`},[s(C(de),{ref_key:`chatRef`,ref:Oe,"show-input":!1,messages:C(_),"assistant-name":C(Fe),"assistant-avatar":C(ze),theme:ne.value,question:C(ae),"question-submitting":C(y),"question-labels":C(Ee),"plan-config":{labels:{title:C(E)(`@AGENT:计划`),raw:C(E)(`@AGENT:原始参数`)}},onAnswer:C(be)},null,8,[`messages`,`assistant-name`,`assistant-avatar`,`theme`,`question`,`question-submitting`,`question-labels`,`plan-config`,`onAnswer`])],512),[[re,!C(j)||M.value===`chat`]]),C(Me)>0?(p(),n(`div`,{key:0,ref_key:`composerRef`,ref:Ae,class:`agent-panel-composer acu-root`,"data-theme":ne.value},[s(C(fe),{ref_key:`inputRef`,ref:k,disabled:C(v),generating:C(v),placeholder:C(v)?C(E)(`@AGENT:正在生成中...`):C(E)(`@AGENT:输入消息,Enter 发送`),"upload-config":{accept:C(Ie)},"context-usage":C(Se),onSend:et,onStop:C(xe)},null,8,[`disabled`,`generating`,`placeholder`,`upload-config`,`context-usage`,`onStop`]),N.value?(p(),d(le,{key:0,to:N.value},[Xe.value?(p(),n(`div`,{key:0,class:`agent-context-att`,title:c.activeFilePath||``},[i[9]||=S(`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`},[S(`path`,{d:`M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z`}),S(`polyline`,{points:`14 3 14 8 19 8`})],-1),S(`span`,F,f(c.activeFileName),1),S(`button`,{type:`button`,class:`agent-context-att-remove`,title:C(E)(`@EDITOR:不引用当前文档`),"aria-label":C(E)(`@EDITOR:不引用当前文档`),onClick:i[3]||=e=>Ve.value=!0},[...i[8]||=[S(`svg`,{viewBox:`0 0 24 24`,width:`10`,height:`10`,fill:`none`,stroke:`currentColor`,"stroke-width":`3`,"stroke-linecap":`round`,"aria-hidden":`true`},[S(`line`,{x1:`18`,y1:`6`,x2:`6`,y2:`18`}),S(`line`,{x1:`6`,y1:`6`,x2:`18`,y2:`18`})],-1)]],8,I)],8,P)):r(``,!0)],8,[`to`])):r(``,!0)],8,Ye)):r(``,!0)],2)],512))}}),[[`__scopeId`,`data-v-150c2cc6`]]);u(),m(),c(),v();var Xe={class:`sidebar-header`},Ze={class:`sidebar-title`},Qe={class:`sidebar-actions`},$e={class:`sidebar-search`},et=[`placeholder`,`title`],tt=[`title`,`aria-label`],nt={key:0,class:`sidebar-tree`},rt={key:1,class:`tree-arrow-spacer`},it={class:`tree-icon mit-icon`,"aria-hidden":`true`},at=[`xlink:href`],ot=[`onClick`,`onContextmenu`],st={key:1,class:`tree-arrow-spacer`},ct={key:2,class:`tree-icon mit-icon`,"aria-hidden":`true`},lt=[`xlink:href`],ut={key:3,class:`tree-icon mit-icon`,"aria-hidden":`true`},dt=[`xlink:href`],ft=[`title`],pt={key:0,class:`tree-name-hit`},mt={key:4,class:`tree-loading`},ht={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-dark)`}},gt={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-meta)`}},_t=[`placeholder`],vt={key:0,class:`tree-node tree-inline-input-row`,style:{paddingLeft:`12px`}},yt={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-dark)`}},bt={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-meta)`}},xt=[`placeholder`],St={key:1,class:`tree-empty`},Ct={key:1,class:`sidebar-loading`},wt={class:`editor-main`},Tt={key:0,class:`editor-tabs`},Et=[`onClick`,`title`],Dt={class:`tab-name`},Ot={key:0,class:`tab-dirty-dot`},kt=[`onClick`],At=[`title`],jt=[`disabled`,`title`],Mt=[`title`],Nt={class:`editor-body`},Pt={key:0,class:`image-tab-placeholder`},Ft={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`}},It={class:`image-tab-placeholder-title`},Lt={class:`image-tab-placeholder-hint`},Rt={class:`preview-header`},zt={class:`preview-title`},Bt={class:`preview-ext-badge`},Vt=[`title`],Ht={class:`preview-body`},Ut=[`sandbox`,`srcdoc`],Wt=6e4,Gt=3e4,Kt=D(l({__name:`EditorView`,props:{pendingFilePath:{}},setup(c){self.MonacoEnvironment={getWorker(e,t){return t===`json`?new xe:t===`css`||t===`scss`||t===`less`?new ye:t===`html`||t===`handlebars`||t===`razor`?new he:t===`typescript`||t===`javascript`?new _e:new ge}};let l=c,u=me(),m=ke(),v=x([]),de=x(!1),T=x(``),fe=x(``),D=null;function Se(){T.value=``,fe.value=``,D&&=(clearTimeout(D),null)}g(T,e=>{D&&clearTimeout(D),D=setTimeout(()=>{fe.value=e,D=null},180)}),i(()=>{D&&clearTimeout(D),Pe(),gn()});let O=null;function Ne(){Pe(),u.ui.fileTreeAutoRefresh&&(O=setInterval(()=>{document.hidden||u.currentDirectory&&(T.value.trim()||A())},Wt))}function Pe(){O&&=(clearInterval(O),null)}g(()=>u.currentDirectory,async()=>{if(Zt=!1,Ne(),await Ie(),P.value.some(e=>e.isDirty)){Zt=!0;return}P.value=[],F.value=null,rn(),await en()}),g(()=>u.ui.fileTreeAutoRefresh,()=>{Ne()});async function Fe(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 Ie(){let e=u.currentDirectory;if(e){de.value=!0;try{v.value=await Fe(e,0)}finally{de.value=!1}}}function Le(e,t=new Set){for(let n of e)n.type===`directory`&&n.expanded&&(t.add(n.path),n.children&&Le(n.children,t));return t}function Re(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=Re(e.children,t+1),n.expanded=!0),n})}async function ze(e){let t=u.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:Re(n.items,0)}catch{return null}}function Be(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)?Be(a.children,i.children)&&(a.children=i.children,r=!0):(a.children=i.children,r=!0)))}return r}async function A(e={}){if(!u.currentDirectory)return;let t=await ze([...Le(v.value)]);if(!t){e.notifyOnError&&h.error(E(`@EDITOR:刷新失败`));return}if(v.value.length===0){v.value=t;return}Be(v.value,t)&&(v.value=t)}async function M(e){if(e.type===`directory`){if(e.expanded)e.expanded=!1;else{if(!e.children){e.loading=!0;try{e.children=await Fe(e.path,e.depth+1)}finally{e.loading=!1}}e.expanded=!0}}}function N(e){let t=[];for(let n of e)t.push(n),n.type===`directory`&&n.expanded&&n.children&&t.push(...N(n.children));return t}let He=t(()=>fe.value.trim().toLowerCase());function Ue(e,t){if(!t)return e;let n=[];for(let r of e){let e=r.children?Ue(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 We=t(()=>Ue(v.value,He.value)),Ge=t(()=>He.value.length>0&&We.value.length===0);function Ke(e){let t=fe.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 qe=x(null);function Je(){let e=qe.value;e&&(e.focus(),e.select())}function Ye(){T.value?(Se(),qe.value?.focus()):(qe.value?.blur(),R.value?.focus())}let P=x([]),F=x(null),I=x(null);async function Kt(e){if(I.value=e,e.type!==`file`){M(e);return}let t=P.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:P.value.length}),t){F.value=e.path,o(()=>on());return}let n=e.name.split(`.`).pop()||``;if(q.has(n.toLowerCase())){let t={path:e.path,name:e.name,content:``,originalContent:``,isDirty:!1,language:`plaintext`,diskMtimeMs:null};P.value.push(t),F.value=e.path,J.value=!0;return}if(k(e.name)){let t={path:e.path,name:e.name,content:``,originalContent:``,isDirty:!1,language:`office`,diskMtimeMs:null};P.value.push(t),F.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){h.error(`${E(`@EDITOR:打开文件失败: `)}${r.error}`);return}let i=j(n),a=z.get(e.path);a&&!a.isDisposed()&&a.setValue(r.content);let o={path:e.path,name:e.name,content:r.content,originalContent:r.content,isDirty:!1,language:i,diskMtimeMs:typeof r.mtimeMs==`number`?r.mtimeMs:null};console.log(`[debug-open-in-editor] EditorView pushing tab:`,{path:o.path,name:o.name,contentLen:o.content.length,lang:o.language}),P.value.push(o),F.value=e.path,console.log(`[debug-open-in-editor] EditorView tabs after push:`,P.value.length,`activeTabPath=`,F.value)}catch(e){console.log(`[debug-open-in-editor] EditorView fetch threw:`,e),h.error(`${E(`@EDITOR:打开文件失败: `)}${e.message}`)}}g(()=>l.pendingFilePath,async e=>{if(console.log(`[debug-open-in-editor] EditorView watcher fired, filePath=`,e),!e)return;await o();let t=e.split(/[\\/]/).pop()||e;console.log(`[debug-open-in-editor] EditorView calling openFile, name=`,t,`path=`,e),await Kt({name:t,path:e,type:`file`,depth:0}),console.log(`[debug-open-in-editor] EditorView openFile returned`)},{immediate:!0});function qt(e,t){t.stopPropagation();let n=P.value.findIndex(t=>t.path===e);n!==-1&&(!P.value[n].isDirty||confirm(E(`@EDITOR:文件未保存,确认关闭?`)))&&(P.value.splice(n,1),F.value===e&&(F.value=P.value[Math.min(n,P.value.length-1)]?.path??null))}let Jt=()=>P.value.find(e=>e.path===F.value)??null,Yt=t(()=>({expandedDirs:[...Le(v.value)],tabs:P.value.map(e=>e.path),activeTab:F.value})),Xt=!1,Zt=!1;function Qt(){Zt&&!Xt&&u.isUiLoaded&&u.saveEditorWorkspace(Yt.value)}g(Yt,()=>Qt());async function $t(e){if(P.value.some(t=>t.path===e))return;let t=e.split(/[\\/]/).pop()||e,n=(t.split(`.`).pop()||``).toLowerCase();if(q.has(n)){P.value.push({path:e,name:t,content:``,originalContent:``,isDirty:!1,language:`plaintext`,diskMtimeMs:null});return}if(k(t)){P.value.push({path:e,name:t,content:``,originalContent:``,isDirty:!1,language:`office`,diskMtimeMs:null});return}try{let r=await(await fetch(`/api/editor/file?path=${encodeURIComponent(e)}`)).json();if(!r.success)return;let i=z.get(e);i&&!i.isDisposed()&&R.value?.getModel()!==i&&(i.dispose(),z.delete(e)),P.value.push({path:e,name:t,content:r.content,originalContent:r.content,isDirty:!1,language:j(n),diskMtimeMs:typeof r.mtimeMs==`number`?r.mtimeMs:null})}catch{}}async function en(){try{for(let e=0;e<100&&!u.isUiLoaded;e++)await new Promise(e=>setTimeout(e,50));if(!u.isUiLoaded)return;V.value=u.ui.editorSidebarWidth;let e=u.getEditorWorkspace();if(!e)return;Xt=!0;try{if(e.expandedDirs.length>0){let t=await ze(e.expandedDirs);t&&(v.value=t)}for(let t of e.tabs)await $t(t);if(!l.pendingFilePath&&e.activeTab&&P.value.some(t=>t.path===e.activeTab)){F.value=e.activeTab;let t=Jt(),n=(t?.name.split(`.`).pop()||``).toLowerCase();t&&(q.has(n)||k(t.name))&&(J.value=!0)}}finally{Xt=!1}}finally{Zt=!0,Qt()}}let tn=x(null),R=ue(null),z=new Map;function nn(e){let t=z.get(e.path);return(!t||t.isDisposed())&&(t=be.createModel(e.content,e.language,ve.file(e.path)),z.set(e.path,t)),t}function rn(){R.value?.setModel(null);for(let e of z.values())e.isDisposed()||e.dispose();z.clear()}function an(){if(!tn.value)return;let e=document.documentElement.getAttribute(`data-theme`)===`dark`;R.value=be.create(tn.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}),R.value.onDidChangeModelContent(()=>{let e=Jt();if(!e)return;let t=R.value.getValue();e.content=t,e.isDirty=t!==e.originalContent}),R.value.onDidBlurEditorText(()=>{u.ui.editorAutoSave&&Jt()?.isDirty&&yn(!1),requestAnimationFrame(()=>{if(!B.value||B.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`))||on()})})}g(F,e=>{if(!R.value||!e)return;let t=P.value.find(t=>t.path===e);if(!t)return;let n=nn(t);R.value.setModel(n),o(()=>on()),fn(e)});function on(){if(!R.value)return;R.value.focus();let e=document.querySelector(`.monaco-editor .native-edit-context`);e&&document.activeElement!==e&&requestAnimationFrame(()=>e.focus?.())}let sn=0,cn=new Map;async function ln(e){try{let t=await(await fetch(`/api/editor/file?path=${encodeURIComponent(e)}&meta=1`)).json();return!t?.success||typeof t.mtimeMs!=`number`?null:{mtimeMs:t.mtimeMs}}catch{return null}}async function un(e){try{let t=await(await fetch(`/api/editor/file?path=${encodeURIComponent(e)}`)).json();return t?.success?{content:t.content,mtimeMs:typeof t.mtimeMs==`number`?t.mtimeMs:null}:null}catch{return null}}function dn(e,t,n){e.content=t,e.originalContent=t,e.isDirty=!1,e.diskMtimeMs=n;let r=z.get(e.path);if(!r||r.isDisposed())return;let i=R.value;if(!i||i.getModel()!==r){r.setValue(t);return}let a=i.saveViewState();r.pushEditOperations([],[{range:r.getFullModelRange(),text:t}],()=>null),i.restoreViewState(a)}async function fn(e){if(!e)return;let t=P.value.find(t=>t.path===e);if(!t||t.diskMtimeMs===null)return;let n=++sn,r=await ln(e);if(n!==sn||P.value.find(t=>t.path===e)!==t||!r||r.mtimeMs===t.diskMtimeMs)return;if(t.isDirty){if(cn.get(e)===r.mtimeMs)return;cn.set(e,r.mtimeMs);try{await se.confirm(E(`@EDITOR:这个文件在磁盘上已被改动,你这边也有未保存的编辑。重新加载会丢弃你的改动。`),E(`@EDITOR:文件已被外部改动`),{confirmButtonText:E(`@EDITOR:重新加载`),cancelButtonText:E(`@EDITOR:保留我的`),type:`warning`})}catch{return}if(t.isDirty)return}let i=await un(e);i&&P.value.find(t=>t.path===e)===t&&dn(t,i.content,i.mtimeMs)}function pn(){document.hidden||fn(F.value)}let mn=null;function hn(){gn(),mn=setInterval(()=>{document.hidden||fn(F.value)},Gt)}function gn(){mn&&=(clearInterval(mn),null)}g(()=>P.value.filter(e=>e.isDirty).length,e=>{m.setDirtyCount(e)},{immediate:!0}),i(()=>m.setDirtyCount(0)),De(()=>{let e=document.documentElement.getAttribute(`data-theme`)===`dark`;be.setTheme(e?`vs-dark`:`vs`)});let _n=null;function vn(){if(_n||!B.value)return;let e=[B.value],t=B.value.parentElement;for(;t;){if(t.classList.contains(`view-pane`)||t.classList.contains(`editor-pane`)){e.push(t);break}t=t.parentElement}_n=new MutationObserver(()=>{B.value&&B.value.offsetParent!==null&&F.value&&R.value&&(fn(F.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`))||on()}))});let n=_n;e.forEach(e=>n.observe(e,{attributes:!0,attributeFilter:[`style`,`class`,`hidden`]}))}oe(async()=>{an(),await Ie(),await en(),vn(),Ne(),window.addEventListener(`focus`,pn),document.addEventListener(`visibilitychange`,pn),hn(),F.value&&o(()=>on())}),i(()=>{_n?.disconnect(),_n=null,window.removeEventListener(`focus`,pn),document.removeEventListener(`visibilitychange`,pn),R.value?.dispose(),z.forEach(e=>e.dispose()),z.clear()});async function yn(e=!1){let t=Jt();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){h.error(`${E(`@EDITOR:保存失败: `)}${n.error}`);return}t.originalContent=t.content,t.isDirty=!1,typeof n.mtimeMs==`number`&&(t.diskMtimeMs=n.mtimeMs),e||h.success(E(`@EDITOR:已保存`))}catch(e){h.error(`${E(`@EDITOR:保存失败: `)}${e.message}`)}}function bn(e){let t=e.ctrlKey||e.metaKey;if(t&&e.key.toLowerCase()===`f`){e.preventDefault(),Je();return}t&&e.key===`s`&&(e.preventDefault(),yn())}oe(()=>window.addEventListener(`keydown`,bn)),i(()=>window.removeEventListener(`keydown`,bn));let B=x(null),V=x(u.ui.editorSidebarWidth),xn=!1,Sn=0,Cn=0;function wn(e){xn=!0,Sn=e.clientX,Cn=V.value,document.addEventListener(`mousemove`,Tn),document.addEventListener(`mouseup`,En),e.preventDefault()}function Tn(e){if(!xn)return;let t=e.clientX-Sn;V.value=Math.max(140,Math.min(400,Cn+t))}function En(){xn=!1,document.removeEventListener(`mousemove`,Tn),document.removeEventListener(`mouseup`,En),V.value!==u.ui.editorSidebarWidth&&u.setEditorSidebarWidth(V.value)}function Dn(e){return e.type===`directory`?Te(e.name):we(e.name)}let H=x(null),U=x(null),W=x(null),On=x(null);function kn(){let e=I.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(/[\\/][^\\/]+$/,``):u.currentDirectory??``,afterNode:e,depth:e.depth}:{parentPath:u.currentDirectory??``,afterNode:null,depth:0}}async function An(){let e=kn();I.value?.type===`directory`&&!I.value.expanded&&await M(I.value),H.value={...e,kind:`file`,value:``},await o(),W.value?.focus()}async function jn(){let e=kn();I.value?.type===`directory`&&!I.value.expanded&&await M(I.value),H.value={...e,kind:`directory`,value:``},await o(),W.value?.focus()}function Mn(){H.value=null}async function Nn(){let e=H.value;if(!e||!e.value.trim()){H.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){h.error(e.error);return}h.success(E(`@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){h.error(e.error);return}h.success(E(`@EDITOR:创建成功`))}H.value=null,await A()}function Pn(e){e.key===`Enter`&&(e.preventDefault(),Nn()),e.key===`Escape`&&(e.preventDefault(),Mn())}let G=x(null),Fn=x(null);function In(e,t){e.preventDefault(),G.value={x:e.clientX,y:e.clientY,node:t}}function K(){G.value=null}async function Ln(){let e=G.value?.node;K(),e&&(I.value=e),e?.type===`directory`&&!e.expanded&&await M(e);let t=kn();H.value={...t,kind:`file`,value:``},await o(),W.value?.focus()}async function Rn(){let e=G.value?.node;K(),e&&(I.value=e),e?.type===`directory`&&!e.expanded&&await M(e);let t=kn();H.value={...t,kind:`directory`,value:``},await o(),W.value?.focus()}async function zn(){let e=G.value?.node;K(),e&&(U.value={node:e,value:e.name},await o(),On.value?.focus(),On.value?.select())}async function Bn(){let e=U.value;if(!e||!e.value.trim()||e.value.trim()===e.node.name){U.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){h.error(r.error);return}let i=P.value.find(t=>t.path===e.node.path);i&&(i.path=n,i.name=t,F.value===e.node.path&&(F.value=n)),U.value=null,await A()}function Vn(e){e.key===`Enter`&&(e.preventDefault(),Bn()),e.key===`Escape`&&(e.preventDefault(),U.value=null)}async function Hn(){let e=G.value?.node;if(K(),!e)return;let t=e.type===`directory`?E(`@EDITOR:文件夹`):E(`@EDITOR:文件`);if(!confirm(`${E(`@EDITOR:确认删除`)} ${t} "${e.name}"?`))return;let n=await(await fetch(`/api/editor/entry?path=${encodeURIComponent(e.path)}`,{method:`DELETE`})).json();if(!n.success){h.error(n.error);return}let r=P.value.findIndex(t=>t.path===e.path);r!==-1&&(P.value.splice(r,1),F.value===e.path&&(F.value=P.value[Math.max(0,r-1)]?.path??null)),h.success(E(`@EDITOR:已删除`)),await A()}async function Un(){let e=G.value?.node;if(K(),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||h.error(t.error)}catch(e){h.error(e?.message||String(e))}}function Wn(e){let t=u.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 Gn(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 Kn(){let e=G.value?.node;K(),e&&(await Gn(e.path)?h.success(E(`@EDITOR:已复制到剪贴板`)):h.error(E(`@EDITOR:复制失败`)))}async function qn(){let e=G.value?.node;K(),e&&(await Gn(Wn(e.path))?h.success(E(`@EDITOR:已复制到剪贴板`)):h.error(E(`@EDITOR:复制失败`)))}async function Jn(){let e=G.value?.node;if(K(),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||h.error(t.error||E(`@EDITOR:VSCode 未安装`))}catch(e){h.error(e?.message||String(e))}}let Yn=new Set([`html`,`htm`]),Xn=t(()=>{let e=G.value?.node;if(!e||e.type!==`file`)return!1;let t=e.name.slice(e.name.lastIndexOf(`.`)+1).toLowerCase();return Yn.has(t)});async function Zn(){let e=G.value?.node;if(K(),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||h.error(t.error||E(`@EDITOR:浏览器打开失败`))}catch(e){h.error(e?.message||String(e))}}oe(()=>document.addEventListener(`click`,K)),i(()=>document.removeEventListener(`click`,K));let Qn=new Set([`md`,`html`,`htm`,`svg`]),q=new Set([`png`,`jpg`,`jpeg`,`gif`,`webp`,`ico`,`bmp`]),J=x(!1),Y=x(!1),X=x(!1),$n=x(!1),er=x(0),Z=t(()=>P.value.find(e=>e.path===F.value)??null),tr=t(()=>Z.value?.language===`plaintext`&&Z.value?.content===``),nr=t(()=>Z.value?.language===`office`),Q=t(()=>(Z.value?.name??``).split(`.`).pop()?.toLowerCase()??``),rr=t(()=>Qn.has(Q.value)||q.has(Q.value)||k(Q.value)),ir=t(()=>((Z.value?.content??``).match(/^#{1,6}\s+/gm)||[]).length),$=t(()=>Q.value===`md`&&ir.value>0);g(F,()=>{J.value&&!rr.value&&(J.value=!1),Y.value&&!$.value&&(Y.value=!1)});function ar(){rr.value&&(J.value||(Y.value=!1,X.value=!1),J.value=!J.value)}function or(){$.value&&(Y.value||(J.value=!1,X.value=!1),Y.value=!Y.value)}function sr(){X.value||(J.value=!1,Y.value=!1),X.value=!X.value,$n.value=!0}let cr=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`?Me(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>`:``}),lr=!1,ur=0,dr=0;function fr(e){lr=!0,ur=e.clientX,dr=er.value,document.addEventListener(`mousemove`,pr),document.addEventListener(`mouseup`,mr),e.preventDefault()}function pr(e){if(!lr)return;let t=e.clientX-ur;er.value=Math.max(200,Math.min(900,dr+t))}function mr(){lr=!1,document.removeEventListener(`mousemove`,pr),document.removeEventListener(`mouseup`,mr)}return(t,i)=>(p(),n(w,null,[S(`div`,{class:`editor-view`,ref_key:`containerRef`,ref:B},[S(`div`,{class:`editor-sidebar`,style:y({width:V.value+`px`})},[S(`div`,Xe,[S(`span`,Ze,f(C(E)(`@EDITOR:资源管理器`)),1),S(`div`,Qe,[s(C(ee),{content:C(E)(`@EDITOR:新建文件`),placement:`bottom`,"show-after":300},{default:ae(()=>[S(`button`,{class:`sidebar-action-btn`,onClick:An},[...i[11]||=[S(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[S(`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`}),S(`polyline`,{points:`14 2 14 8 20 8`}),S(`line`,{x1:`12`,y1:`13`,x2:`12`,y2:`19`}),S(`line`,{x1:`9`,y1:`16`,x2:`15`,y2:`16`})],-1)]])]),_:1},8,[`content`]),s(C(ee),{content:C(E)(`@EDITOR:新建文件夹`),placement:`bottom`,"show-after":300},{default:ae(()=>[S(`button`,{class:`sidebar-action-btn`,onClick:jn},[...i[12]||=[S(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[S(`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`}),S(`line`,{x1:`12`,y1:`11`,x2:`12`,y2:`17`}),S(`line`,{x1:`9`,y1:`14`,x2:`15`,y2:`14`})],-1)]])]),_:1},8,[`content`]),s(C(ee),{content:C(E)(`@EDITOR:刷新`),placement:`bottom`,"show-after":300},{default:ae(()=>[S(`button`,{class:`sidebar-action-btn`,onClick:i[0]||=e=>A({notifyOnError:!0})},[...i[13]||=[S(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[S(`polyline`,{points:`1 4 1 10 7 10`}),S(`polyline`,{points:`23 20 23 14 17 14`}),S(`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`])])]),S(`div`,$e,[i[15]||=S(`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`},[S(`circle`,{cx:`11`,cy:`11`,r:`7`}),S(`line`,{x1:`21`,y1:`21`,x2:`16.65`,y2:`16.65`})],-1),b(S(`input`,{ref_key:`searchInputRef`,ref:qe,"onUpdate:modelValue":i[1]||=e=>T.value=e,type:`text`,class:`sidebar-search-input`,placeholder:C(E)(`@EDITOR:搜索文件...`),title:C(E)(`@EDITOR:搜索文件...`),spellcheck:`false`,autocomplete:`off`,onKeydown:ne(Ye,[`escape`])},null,40,et),[[ie,T.value]]),T.value?(p(),n(`button`,{key:0,class:`sidebar-search-clear`,title:C(E)(`@EDITOR:清除搜索`),"aria-label":C(E)(`@EDITOR:清除搜索`),onClick:Se},[...i[14]||=[S(`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`},[S(`line`,{x1:`18`,y1:`6`,x2:`6`,y2:`18`}),S(`line`,{x1:`6`,y1:`6`,x2:`18`,y2:`18`})],-1)]],8,tt)):r(``,!0)]),de.value?(p(),n(`div`,Ct,[...i[24]||=[S(`span`,{class:`spin-icon`},null,-1)]])):(p(),n(`div`,nt,[(p(!0),n(w,null,te(N(We.value),e=>(p(),n(w,{key:e.path},[U.value&&U.value.node.path===e.path?(p(),n(`div`,{key:0,class:`tree-node tree-inline-input-row`,style:y({paddingLeft:12+e.depth*14+`px`})},[e.type===`directory`?(p(),n(`span`,{key:0,class:a([`tree-arrow`,{expanded:e.expanded}])},[...i[16]||=[S(`svg`,{viewBox:`0 0 24 24`,width:`10`,height:`10`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[S(`polyline`,{points:`9 18 15 12 9 6`})],-1)]],2)):(p(),n(`span`,rt)),(p(),n(`svg`,it,[S(`use`,{"xlink:href":`#${Dn(e)}`},null,8,at)])),b(S(`input`,{ref_for:!0,ref_key:`renameInputRef`,ref:On,"onUpdate:modelValue":i[2]||=e=>U.value.value=e,onKeydown:Vn,onBlur:Bn,onClick:i[3]||=ce(()=>{},[`stop`])},null,544),[[ie,U.value.value]])],4)):(p(),n(`div`,{key:1,class:a([`tree-node`,{"tree-node--dir":e.type===`directory`,"tree-node--file":e.type===`file`,"tree-node--active":F.value===e.path,"tree-node--selected":I.value?.path===e.path&&F.value!==e.path}]),style:y({paddingLeft:12+e.depth*14+`px`}),onClick:t=>Kt(e),onContextmenu:t=>In(t,e)},[e.type===`directory`?(p(),n(`span`,{key:0,class:a([`tree-arrow`,{expanded:e.expanded}])},[...i[17]||=[S(`svg`,{viewBox:`0 0 24 24`,width:`10`,height:`10`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[S(`polyline`,{points:`9 18 15 12 9 6`})],-1)]],2)):(p(),n(`span`,st)),e.type===`directory`?(p(),n(`svg`,ct,[S(`use`,{"xlink:href":`#${Dn(e)}`},null,8,lt)])):(p(),n(`svg`,ut,[S(`use`,{"xlink:href":`#${Dn(e)}`},null,8,dt)])),S(`span`,{class:`tree-name`,title:e.path},[(p(!0),n(w,null,te(Ke(e.name),(e,t)=>(p(),n(w,{key:t},[e.hit?(p(),n(`span`,pt,f(e.text),1)):(p(),n(w,{key:1},[_(f(e.text),1)],64))],64))),128))],8,ft),e.loading?(p(),n(`span`,mt)):r(``,!0)],46,ot)),H.value&&H.value.afterNode?.path===e.path?(p(),n(`div`,{key:2,class:`tree-node tree-inline-input-row`,style:y({paddingLeft:12+H.value.depth*14+`px`})},[i[20]||=S(`span`,{class:`tree-arrow-spacer`},null,-1),H.value.kind===`directory`?(p(),n(`svg`,ht,[...i[18]||=[S(`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)]])):(p(),n(`svg`,gt,[...i[19]||=[S(`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),S(`polyline`,{points:`14 2 14 8 20 8`},null,-1)]])),b(S(`input`,{ref_for:!0,ref_key:`inlineInputRef`,ref:W,class:`tree-inline-input`,"onUpdate:modelValue":i[4]||=e=>H.value.value=e,placeholder:H.value.kind===`file`?C(E)(`@EDITOR:输入文件名`):C(E)(`@EDITOR:输入文件夹名`),onKeydown:Pn,onBlur:Mn,onClick:i[5]||=ce(()=>{},[`stop`])},null,40,_t),[[ie,H.value.value]])],4)):r(``,!0)],64))),128)),H.value&&H.value.afterNode===null?(p(),n(`div`,vt,[i[23]||=S(`span`,{class:`tree-arrow-spacer`},null,-1),H.value.kind===`directory`?(p(),n(`svg`,yt,[...i[21]||=[S(`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)]])):(p(),n(`svg`,bt,[...i[22]||=[S(`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),S(`polyline`,{points:`14 2 14 8 20 8`},null,-1)]])),b(S(`input`,{ref_key:`inlineInputRef`,ref:W,class:`tree-inline-input`,"onUpdate:modelValue":i[6]||=e=>H.value.value=e,placeholder:H.value.kind===`file`?C(E)(`@EDITOR:输入文件名`):C(E)(`@EDITOR:输入文件夹名`),onKeydown:Pn,onBlur:Mn,onClick:i[7]||=ce(()=>{},[`stop`])},null,40,xt),[[ie,H.value.value]])])):r(``,!0),!H.value&&(Ge.value||v.value.length===0)?(p(),n(`div`,St,f(Ge.value?C(E)(`@EDITOR:未找到匹配文件`):C(E)(`@EDITOR:暂无文件`)),1)):r(``,!0)]))],4),S(`div`,{class:`editor-resizer`,onMousedown:wn},null,32),S(`div`,wt,[P.value.length>0?(p(),n(`div`,Tt,[(p(!0),n(w,null,te(P.value,e=>(p(),n(`div`,{key:e.path,class:a([`editor-tab`,{active:F.value===e.path,dirty:e.isDirty}]),onClick:t=>F.value=e.path,title:e.path},[S(`span`,Dt,f(e.name),1),e.isDirty?(p(),n(`span`,Ot)):r(``,!0),S(`button`,{class:`tab-close`,onClick:t=>qt(e.path,t)},[...i[25]||=[S(`svg`,{viewBox:`0 0 24 24`,width:`12`,height:`12`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"stroke-linecap":`round`},[S(`line`,{x1:`18`,y1:`6`,x2:`6`,y2:`18`}),S(`line`,{x1:`6`,y1:`6`,x2:`18`,y2:`18`})],-1)]],8,kt)],10,Et))),128)),i[29]||=S(`div`,{class:`editor-tabs-spacer`},null,-1),rr.value?(p(),n(`button`,{key:0,class:a([`preview-toggle-btn`,{active:J.value}]),title:J.value?C(E)(`@EDITOR:关闭预览`):C(E)(`@EDITOR:打开预览`),onClick:ar},[i[26]||=S(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[S(`path`,{d:`M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z`}),S(`circle`,{cx:`12`,cy:`12`,r:`3`})],-1),S(`span`,null,f(C(E)(`@EDITOR:预览`)),1)],10,At)):r(``,!0),$.value?(p(),n(`button`,{key:1,class:a([`preview-toggle-btn mindmap-toggle-btn`,{active:Y.value,disabled:!$.value}]),disabled:!$.value,title:$.value?Y.value?C(E)(`@EDITOR:关闭思维导图`):C(E)(`@EDITOR:打开思维导图`):C(E)(`@EDITOR:需要至少一个 # 标题`),onClick:or},[i[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-c65c2d3f><circle cx="12" cy="12" r="2" data-v-c65c2d3f></circle><circle cx="5" cy="6" r="1.6" data-v-c65c2d3f></circle><circle cx="19" cy="6" r="1.6" data-v-c65c2d3f></circle><circle cx="5" cy="18" r="1.6" data-v-c65c2d3f></circle><circle cx="19" cy="18" r="1.6" data-v-c65c2d3f></circle><line x1="11" y1="11" x2="6.4" y2="7" data-v-c65c2d3f></line><line x1="13" y1="11" x2="17.6" y2="7" data-v-c65c2d3f></line><line x1="11" y1="13" x2="6.4" y2="17" data-v-c65c2d3f></line><line x1="13" y1="13" x2="17.6" y2="17" data-v-c65c2d3f></line></svg>`,1),S(`span`,null,f(C(E)(`@EDITOR:思维导图`)),1)],10,jt)):r(``,!0),S(`button`,{class:a([`preview-toggle-btn agent-toggle-btn`,{active:X.value}]),title:X.value?C(E)(`@EDITOR:关闭 g ai 对话`):C(E)(`@EDITOR:打开 g ai 对话`),onClick:sr},[i[28]||=S(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[S(`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`}),S(`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),S(`span`,null,f(C(E)(`@EDITOR:g ai 对话`)),1)],10,Mt)])):r(``,!0),P.value.length===0?(p(),d(Ae,{key:1,class:`editor-empty`,title:C(E)(`@EDITOR:从左侧选择文件打开`),hint:C(E)(`@EDITOR:Ctrl+S 保存`)},{icon:ae(()=>[...i[30]||=[S(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[S(`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`}),S(`polyline`,{points:`14 2 14 8 20 8`})],-1)]]),_:1},8,[`title`,`hint`])):r(``,!0),S(`div`,Nt,[S(`div`,{class:a([`monaco-container`,{hidden:P.value.length===0||tr.value||nr.value}]),ref_key:`editorContainerRef`,ref:tn},null,2),tr.value&&P.value.length>0&&!J.value&&!Y.value?(p(),n(`div`,Pt,[(p(),n(`svg`,Ft,[...i[31]||=[S(`rect`,{x:`3`,y:`3`,width:`18`,height:`18`,rx:`2`},null,-1),S(`circle`,{cx:`9`,cy:`9`,r:`2`},null,-1),S(`path`,{d:`m21 15-5-5L5 21`},null,-1)]])),S(`p`,It,f(Z.value?.name),1),S(`p`,Lt,f(C(E)(`@EDITOR:这是图片文件,已在右侧预览面板中打开`)),1)])):r(``,!0),(J.value||Y.value||X.value)&&P.value.length>0?(p(),n(`div`,{key:1,class:`preview-resizer`,onMousedown:fr},null,32)):r(``,!0),$n.value?b((p(),d(L,{key:2,active:X.value&&P.value.length>0,"active-file-path":F.value,"active-file-name":Z.value?.name??``,style:y({flexBasis:er.value+`px`}),onClose:i[8]||=e=>X.value=!1},null,8,[`active`,`active-file-path`,`active-file-name`,`style`])),[[re,X.value&&P.value.length>0]]):r(``,!0),(J.value||Y.value)&&P.value.length>0?(p(),n(`div`,{key:3,class:`preview-panel`,style:y({flexBasis:er.value+`px`})},[S(`div`,Rt,[S(`span`,zt,f(Y.value?C(E)(`@EDITOR:思维导图`):C(E)(`@EDITOR:预览`)),1),S(`span`,Bt,f(Q.value.toUpperCase()),1),i[33]||=S(`div`,{class:`preview-header-spacer`},null,-1),S(`button`,{class:`preview-close-btn`,title:Y.value?C(E)(`@EDITOR:关闭思维导图`):C(E)(`@EDITOR:关闭预览`),onClick:i[9]||=e=>Y.value?Y.value=!1:J.value=!1},[...i[32]||=[S(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"stroke-linecap":`round`},[S(`line`,{x1:`18`,y1:`6`,x2:`6`,y2:`18`}),S(`line`,{x1:`6`,y1:`6`,x2:`18`,y2:`18`})],-1)]],8,Vt)]),S(`div`,Ht,[Y.value&&Q.value===`md`&&Z.value?(p(),d(Ve,{key:0,content:Z.value.content,class:`preview-mindmap`},null,8,[`content`])):J.value&&Q.value===`md`&&Z.value?(p(),d(je,{key:Z.value.path,content:Z.value.content,class:`preview-markdown`},null,8,[`content`])):J.value&&[`html`,`htm`,`svg`].includes(Q.value)?(p(),n(`iframe`,{key:2,class:`preview-iframe`,sandbox:C(Oe),srcdoc:cr.value},null,8,Ut)):J.value&&C(q).has(Q.value)&&Z.value?(p(),d(Ee,{key:3,"file-path":Z.value.path,"file-name":Z.value.name},null,8,[`file-path`,`file-name`])):J.value&&nr.value&&Z.value?(p(),d(Ce,{key:4,"file-path":Z.value.path},null,8,[`file-path`])):r(``,!0)])],4)):r(``,!0)])])],512),(p(),d(le,{to:`body`},[G.value?(p(),n(`div`,{key:0,ref_key:`ctxMenuRef`,ref:Fn,class:`ctx-menu`,style:y({left:G.value.x+`px`,top:G.value.y+`px`}),onClick:i[10]||=ce(()=>{},[`stop`])},[S(`button`,{class:`ctx-menu-item`,onClick:Ln},[i[34]||=S(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[S(`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`}),S(`polyline`,{points:`14 2 14 8 20 8`}),S(`line`,{x1:`12`,y1:`13`,x2:`12`,y2:`19`}),S(`line`,{x1:`9`,y1:`16`,x2:`15`,y2:`16`})],-1),_(` `+f(C(E)(`@EDITOR:新建文件`)),1)]),S(`button`,{class:`ctx-menu-item`,onClick:Rn},[i[35]||=S(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[S(`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`}),S(`line`,{x1:`12`,y1:`11`,x2:`12`,y2:`17`}),S(`line`,{x1:`9`,y1:`14`,x2:`15`,y2:`14`})],-1),_(` `+f(C(E)(`@EDITOR:新建文件夹`)),1)]),i[42]||=S(`div`,{class:`ctx-menu-sep`},null,-1),S(`button`,{class:`ctx-menu-item`,onClick:Kn},[i[36]||=S(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[S(`rect`,{x:`9`,y:`9`,width:`13`,height:`13`,rx:`2`,ry:`2`}),S(`path`,{d:`M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1`})],-1),_(` `+f(C(E)(`@EDITOR:复制绝对路径`)),1)]),S(`button`,{class:`ctx-menu-item`,onClick:qn},[i[37]||=S(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[S(`path`,{d:`M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71`}),S(`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),_(` `+f(C(E)(`@EDITOR:复制相对路径`)),1)]),i[43]||=S(`div`,{class:`ctx-menu-sep`},null,-1),Xn.value?(p(),n(`button`,{key:0,class:`ctx-menu-item`,onClick:Zn},[i[38]||=S(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[S(`circle`,{cx:`12`,cy:`12`,r:`9`}),S(`line`,{x1:`3`,y1:`12`,x2:`21`,y2:`12`}),S(`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),_(` `+f(C(E)(`@EDITOR:在浏览器中打开`)),1)])):r(``,!0),S(`button`,{class:`ctx-menu-item`,onClick:Un},[i[39]||=S(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[S(`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`}),S(`path`,{d:`M3 7v10a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2`})],-1),_(` `+f(C(E)(`@EDITOR:在资源管理器中打开`)),1)]),S(`button`,{class:`ctx-menu-item`,onClick:Jn},[s(pe,{"icon-class":`vscode`,"class-name":`ctx-menu-icon`}),_(` `+f(C(E)(`@EDITOR:在 VSCode 中打开`)),1)]),S(`button`,{class:`ctx-menu-item`,onClick:zn},[i[40]||=S(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[S(`path`,{d:`M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7`}),S(`path`,{d:`M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z`})],-1),_(` `+f(C(E)(`@EDITOR:重命名`)),1)]),S(`button`,{class:`ctx-menu-item ctx-menu-item--danger`,onClick:Hn},[i[41]||=S(`svg`,{viewBox:`0 0 24 24`,width:`13`,height:`13`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[S(`polyline`,{points:`3 6 5 6 21 6`}),S(`path`,{d:`M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6`}),S(`path`,{d:`M10 11v6`}),S(`path`,{d:`M14 11v6`}),S(`path`,{d:`M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2`})],-1),_(` `+f(C(E)(`@EDITOR:删除`)),1)])],4)):r(``,!0)]))],64))}}),[[`__scopeId`,`data-v-c65c2d3f`]]);export{Kt as default};
|