zen-gitsync 2.17.15 → 2.17.16
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 +6 -6
- package/package.json +1 -1
- package/src/cli/ai/agent.js +24 -2
- package/src/cli/ai/runtime.test.js +1 -1
- package/src/cli/ai/tools.js +7 -1
- package/src/cli/ai/tools.test.js +11 -0
- package/src/config.js +4 -4
- package/src/ui/public/assets/AgentView-DOyN97Ve.js +5 -0
- package/src/ui/public/assets/{AgentView-vvVhbIQ5.css → AgentView-DkM2KXuc.css} +1 -1
- package/src/ui/public/assets/{AppVersionBadge-D5iXcAEV.js → AppVersionBadge-oON3sAj4.js} +2 -2
- package/src/ui/public/assets/{BranchSelector-DP4u1f_B.js → BranchSelector-Cpj7eGqY.js} +1 -1
- package/src/ui/public/assets/{CommitForm-boOw8uGS.js → CommitForm-D_ovYhVw.js} +1 -1
- package/src/ui/public/assets/{CommonDialog-B_qUsIGr.js → CommonDialog-ChZbqfRF.js} +1 -1
- package/src/ui/public/assets/{EditorView-ZULtfIzl.js → EditorView-BPzpI0GV.js} +1 -1
- package/src/ui/public/assets/{FileDiffViewer-C4xxq5S0.js → FileDiffViewer-B_qEKA9L.js} +1 -1
- package/src/ui/public/assets/{FlowExecutionViewer-BmfstdaT.js → FlowExecutionViewer-Drw4hlJG.js} +1 -1
- package/src/ui/public/assets/{FlowOrchestrationWorkspace-28kErqrn.js → FlowOrchestrationWorkspace-C7yTD1gj.js} +1 -1
- package/src/ui/public/assets/{IconButton-DcOAqpq0.js → IconButton-DEARmMkZ.js} +1 -1
- package/src/ui/public/assets/{LogList-FEP7EeJt.js → LogList-BA_gowxE.js} +1 -1
- package/src/ui/public/assets/{MindmapView-NDJvfSCn.js → MindmapView-K-XcLLXr.js} +1 -1
- package/src/ui/public/assets/{MonitorView-DU4aBCK0.js → MonitorView-C0RL5K9W.js} +1 -1
- package/src/ui/public/assets/{ProjectStartupButton-JQk4Etsu.js → ProjectStartupButton-DC36_vvU.js} +1 -1
- package/src/ui/public/assets/{RemoteManagerDialog-Di2WizMS.js → RemoteManagerDialog-Bkqja660.js} +1 -1
- package/src/ui/public/assets/{RemoteRepoCard-DxB8Q8yE.js → RemoteRepoCard-Bsm7cj_H.js} +1 -1
- package/src/ui/public/assets/{SourceMapView-CfmrPMBm.js → SourceMapView-Y5NKdIk6.js} +1 -1
- package/src/ui/public/assets/{SvgIcon-yefEMV0-.js → SvgIcon-D_mFHXP4.js} +1 -1
- package/src/ui/public/assets/{TemplateManager-CCy_WcSK.js → TemplateManager-BzKVXZhy.js} +1 -1
- package/src/ui/public/assets/{UserInputNode-3Gv_9YZx.js → UserInputNode-BPLK4aYx.js} +1 -1
- package/src/ui/public/assets/{WorkbenchView-Dgp6A83v.js → WorkbenchView-xbGdiVMQ.js} +25 -25
- package/src/ui/public/assets/{_plugin-vue_export-helper-B1mHBne9.js → _plugin-vue_export-helper-dg2VUnSQ.js} +3 -3
- package/src/ui/public/assets/configStore-DtjAc3w9.js +1 -0
- package/src/ui/public/assets/{gitStore-D5CWxPLv.js → gitStore-BZo9_zyy.js} +1 -1
- package/src/ui/public/assets/{index-gpuX9fhG.js → index-CHuCYLWm.js} +45 -45
- package/src/ui/public/assets/{previewSandbox-qLKxghfr.js → previewSandbox-BTTTXooN.js} +0 -0
- package/src/ui/public/assets/{vendor-C5qX_I8r.css → vendor-DnB9EJa3.css} +1 -1
- package/src/ui/public/assets/{vendor-IQQMq-1c.js → vendor-bdHhLiED.js} +43 -43
- package/src/ui/public/index.html +12 -12
- package/src/ui/server/routes/workbench/agentChat.js +3 -2
- package/src/ui/server/routes/workbench/agentMarketplace.js +23 -9
- package/src/ui/server/routes/workbench/agentMarketplace.test.js +32 -0
- package/src/ui/server/routes/workbench/agentRoutes.js +14 -7
- package/src/ui/server/routes/workbench/agentRoutes.test.js +47 -1
- package/src/ui/server/routes/workbench/taskRunner.codex.test.js +173 -0
- package/src/ui/server/routes/workbench/taskRunner.js +259 -10
- package/src/ui/server/routes/workbench/taskRunner.opencode.test.js +4 -2
- package/src/ui/public/assets/AgentView-Bz9LFamz.js +0 -5
- package/src/ui/public/assets/configStore-BDxel6Co.js +0 -1
|
@@ -15,13 +15,15 @@
|
|
|
15
15
|
// 任务执行引擎:spawn 本地 agent CLI 跑子任务,流式收集输出,更新 job 状态。
|
|
16
16
|
// 拆分自原 routes/workbench.js 1108-1564 行。
|
|
17
17
|
//
|
|
18
|
-
//
|
|
18
|
+
// 支持三种执行器(executor):
|
|
19
19
|
// - claude —— claude -p --output-format stream-json(默认,历史行为)
|
|
20
20
|
// - opencode —— opencode run --format json --auto(sst/opencode CLI,跟随其自身默认模型)
|
|
21
|
+
// - codex —— codex exec --json(OpenAI Codex CLI,跟随其自身配置;2026-09-27 加入)
|
|
21
22
|
//
|
|
22
23
|
// 核心 API:
|
|
23
24
|
// - launchClaudeInNewWindow(cwd, prompt, resumeSessionId) spawn claude,返回 {pid, child}
|
|
24
25
|
// - launchOpencodeRun(cwd, prompt, resumeSessionId) spawn opencode,返回 {pid, child}
|
|
26
|
+
// - launchCodexExec(cwd, prompt, resumeSessionId) spawn codex,返回 {pid, child}
|
|
25
27
|
// - normalizeTaskExecutor(value) 非法值回落 'claude'
|
|
26
28
|
// - runSingleSubtask(task, sub, repoPath, branch, opts) 跑一次任务(sub 是运行载体,见下)
|
|
27
29
|
// - waitProcessExit(pid) polling 等进程退出
|
|
@@ -185,10 +187,11 @@ function attachPromptStdin(child, promptText, resolve, reject) {
|
|
|
185
187
|
}
|
|
186
188
|
|
|
187
189
|
// ── 执行器(executor) ──────────────────────────────────────────────────
|
|
188
|
-
// 工作台任务默认由 claude CLI 执行;opencode
|
|
189
|
-
//
|
|
190
|
-
// 差异只在协议:claude 是 stream-json,opencode 是 --format json 的事件 NDJSON
|
|
191
|
-
|
|
190
|
+
// 工作台任务默认由 claude CLI 执行;opencode(2026-09-20)、codex(2026-09-27)
|
|
191
|
+
// 作为可选执行器。三者都用「stdin 喂 prompt + stdout 结构化 JSON 事件流」的同构形态,
|
|
192
|
+
// 差异只在协议:claude 是 stream-json,opencode 是 --format json 的事件 NDJSON,
|
|
193
|
+
// codex 是 exec --json 的 thread/item 事件 NDJSON。
|
|
194
|
+
export const TASK_EXECUTORS = ['claude', 'opencode', 'codex'];
|
|
192
195
|
|
|
193
196
|
/** 非法/缺省的 executor 一律回落 'claude'(历史行为的兼容兜底)。
|
|
194
197
|
* body.executor 来自网络,做一次 trim + 小写归一,与 config.js 同名函数同语义。 */
|
|
@@ -269,6 +272,95 @@ export function launchOpencodeRun(cwd, promptText, resumeSessionId) {
|
|
|
269
272
|
});
|
|
270
273
|
}
|
|
271
274
|
|
|
275
|
+
// ── codex 执行器(2026-09-27 加入) ──────────────────────────────────────
|
|
276
|
+
// codex exec 是非交互模式,形态与另两个执行器同构(stdin 喂 prompt + stdout NDJSON):
|
|
277
|
+
//
|
|
278
|
+
// codex exec [resume <thread_id>] --json --skip-git-repo-check
|
|
279
|
+
// --dangerously-bypass-approvals-and-sandbox - (`-` = prompt 从 stdin 读)
|
|
280
|
+
//
|
|
281
|
+
// - --json 输出 JSONL 事件流(thread.started / item.* / turn.*)
|
|
282
|
+
// - --dangerously-bypass-approvals-and-sandbox
|
|
283
|
+
// 免批准 + 免沙箱,对应 claude 的 bypassPermissions、opencode 的 --auto。
|
|
284
|
+
// 工作台任务全程无人应答批准提示,不跳过的话一遇审批就卡死
|
|
285
|
+
// - --skip-git-repo-check
|
|
286
|
+
// 工作台允许在非 git 目录建任务,不跳过的话 codex 直接拒绝启动
|
|
287
|
+
// - 不传 -m / -s:模型与沙箱跟随 codex 自身配置(同 opencode 的口径)
|
|
288
|
+
// - 续聊:codex exec resume <thread_id>,thread_id 来自 thread.started 事件
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Windows 下把 codex 解析成可直接 spawn 的 exe。
|
|
292
|
+
*
|
|
293
|
+
* npm 全局安装的 codex 是 .cmd shim(Node 23+ 拒绝 spawn .cmd,EINVAL),shim 指向
|
|
294
|
+
* `node bin/codex.js`;而 bin/codex.js 自己也只是一层壳,真正干活的原生二进制在平台
|
|
295
|
+
* 子包里:node_modules/@openai/codex/node_modules/@openai/codex-win32-<arch>/vendor/
|
|
296
|
+
* <triple>/bin/codex.exe(与 bin/codex.js 的查找口径一致,另留一份无平台子包的兜底路径)。
|
|
297
|
+
*
|
|
298
|
+
* 为什么不直接 spawn(process.execPath, [bin/codex.js, ...]):那层壳会再 spawn 一次原生
|
|
299
|
+
* 二进制,取消任务时 kill 到的只是壳进程,原生 codex 会变孤儿继续改文件。
|
|
300
|
+
*/
|
|
301
|
+
function resolveCodexExe() {
|
|
302
|
+
try {
|
|
303
|
+
const lines = execFileSync('where', ['codex'], { encoding: 'utf8', windowsHide: true })
|
|
304
|
+
.split(/\r?\n/).map(s => s.trim()).filter(Boolean);
|
|
305
|
+
// 独立安装(scoop / 手动下载 / 包管理器直装)优先:PATH 上直接就是原生 exe
|
|
306
|
+
const directExe = lines.find(s => /\.exe$/i.test(s));
|
|
307
|
+
if (directExe && fs.existsSync(directExe)) return directExe;
|
|
308
|
+
const cmdShim = lines.find(s => /\.cmd$/i.test(s));
|
|
309
|
+
if (cmdShim) {
|
|
310
|
+
const prefix = path.dirname(cmdShim);
|
|
311
|
+
const triple = process.arch === 'arm64' ? 'aarch64-pc-windows-msvc' : 'x86_64-pc-windows-msvc';
|
|
312
|
+
const archTag = process.arch === 'arm64' ? 'arm64' : 'x64';
|
|
313
|
+
const candidates = [
|
|
314
|
+
path.join(prefix, 'node_modules', '@openai', 'codex', 'node_modules', '@openai',
|
|
315
|
+
`codex-win32-${archTag}`, 'vendor', triple, 'bin', 'codex.exe'),
|
|
316
|
+
path.join(prefix, 'node_modules', '@openai', 'codex', 'vendor', triple, 'bin', 'codex.exe'),
|
|
317
|
+
];
|
|
318
|
+
for (const exe of candidates) {
|
|
319
|
+
if (fs.existsSync(exe)) return exe;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
} catch { /* fallback */ }
|
|
323
|
+
// 兜底交给 PATH:装在非 npm 全局目录时通常有 codex.exe
|
|
324
|
+
return 'codex.exe';
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* codex 子进程环境。
|
|
329
|
+
* RUST_LOG=error:codex 默认把 tracing 的 INFO 日志写 stderr,而 stderr 里非 JSON 行
|
|
330
|
+
* 会被当正文贴进输出面板(实测一次执行能刷出上百行);压到 error 档即可清干净,
|
|
331
|
+
* 真正的报错走 stdout 的 JSON 事件流(error / turn.failed),信息不丢。
|
|
332
|
+
*/
|
|
333
|
+
function buildCodexEnv() {
|
|
334
|
+
return { ...process.env, LANG: 'zh_CN.UTF-8', RUST_LOG: 'error' };
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/** spawn codex exec 跑一个 prompt,返回 { pid, child }(参数口径见上方注释)。 */
|
|
338
|
+
export function launchCodexExec(cwd, promptText, resumeSessionId) {
|
|
339
|
+
return new Promise((resolve, reject) => {
|
|
340
|
+
const flags = ['--json', '--skip-git-repo-check', '--dangerously-bypass-approvals-and-sandbox'];
|
|
341
|
+
const args = resumeSessionId
|
|
342
|
+
? ['exec', 'resume', ...flags, String(resumeSessionId), '-']
|
|
343
|
+
: ['exec', ...flags, '-'];
|
|
344
|
+
let child;
|
|
345
|
+
if (process.platform === 'win32') {
|
|
346
|
+
child = spawn(resolveCodexExe(), args, {
|
|
347
|
+
cwd,
|
|
348
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
349
|
+
windowsHide: false,
|
|
350
|
+
env: buildCodexEnv()
|
|
351
|
+
});
|
|
352
|
+
} else {
|
|
353
|
+
child = spawn('codex', args, {
|
|
354
|
+
cwd,
|
|
355
|
+
detached: true,
|
|
356
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
357
|
+
env: buildCodexEnv()
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
attachPromptStdin(child, promptText, resolve, reject);
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
|
|
272
364
|
// ── 工具调用(tool_use)收集 ──────────────────────────────────────────────
|
|
273
365
|
// 为什么要有这一层:job.output 只承载「模型说的话」。工具调用(读了哪个文件、跑了什么命令、
|
|
274
366
|
// 拿到了什么结果)原本在两个事件处理器里被整段丢掉,于是前端只剩「思考 + 正文」两块,
|
|
@@ -585,6 +677,156 @@ export function createOpencodeEventHandler(job, appendOutput, appendThinking, to
|
|
|
585
677
|
};
|
|
586
678
|
}
|
|
587
679
|
|
|
680
|
+
/**
|
|
681
|
+
* codex `exec --json` 事件处理器。
|
|
682
|
+
*
|
|
683
|
+
* 事件形态(codex-cli 0.157.x;schema 源:openai/codex codex-rs/exec/src/exec_events.rs):
|
|
684
|
+
* { type:'thread.started', thread_id } 会话续接标识(exec resume <id>)
|
|
685
|
+
* { type:'turn.started' } / { type:'turn.completed', usage }
|
|
686
|
+
* { type:'turn.failed', error:{ message } } 本轮终态失败(进程退出码可能仍是 0)
|
|
687
|
+
* { type:'item.started'|'item.updated'|'item.completed', item:{ id, type, ... } }
|
|
688
|
+
* { type:'error', message } 重试等非终止信息(真失败走 turn.failed)
|
|
689
|
+
*
|
|
690
|
+
* item.type(snake_case)分派:
|
|
691
|
+
* agent_message 正文 → output(按 item.id 做累积/增量去重,两种推送语义都兼容)
|
|
692
|
+
* reasoning 思考 → thinking
|
|
693
|
+
* command_execution 命令 → 工具调用(command 作参数摘要,aggregated_output 作结果)
|
|
694
|
+
* file_change 改动文件清单 → 工具调用
|
|
695
|
+
* mcp_tool_call MCP 工具 → 工具调用(server.tool 作名字)
|
|
696
|
+
* web_search 搜索 → 工具调用
|
|
697
|
+
* error 非致命告警(配置项被忽略 / 模型元信息缺失等)→ 贴进 output,不判失败
|
|
698
|
+
* 其余(todo_list / collab_tool_call / 未来新增)忽略 —— 事件枚举是 non_exhaustive,
|
|
699
|
+
* 未知类型不能影响正文收集与终态判定。
|
|
700
|
+
* (导出仅为回归测试可见:taskRunner.codex.test.js)
|
|
701
|
+
*/
|
|
702
|
+
export function createCodexEventHandler(job, appendOutput, appendThinking, toolCalls) {
|
|
703
|
+
const tracker = toolCalls || createToolCallTracker(job);
|
|
704
|
+
const seenTextItems = new Map(); // item.id -> 已落地的累计文本
|
|
705
|
+
|
|
706
|
+
const appendItemText = (item, isThinking) => {
|
|
707
|
+
const text = typeof item?.text === 'string' ? item.text : '';
|
|
708
|
+
if (!text) return;
|
|
709
|
+
const id = typeof item?.id === 'string' ? item.id : '';
|
|
710
|
+
const prev = id ? seenTextItems.get(id) : undefined;
|
|
711
|
+
let delta = text;
|
|
712
|
+
if (prev !== undefined) {
|
|
713
|
+
delta = text.startsWith(prev) ? text.slice(prev.length) : text;
|
|
714
|
+
}
|
|
715
|
+
if (!delta) return;
|
|
716
|
+
if (id) seenTextItems.set(id, prev !== undefined ? prev + delta : text);
|
|
717
|
+
if (isThinking) appendThinking(delta);
|
|
718
|
+
else appendOutput(delta);
|
|
719
|
+
};
|
|
720
|
+
|
|
721
|
+
// codex 的 status: in_progress | completed | failed | declined(snake_case)
|
|
722
|
+
const mapItemStatus = (raw) => {
|
|
723
|
+
const s = typeof raw === 'string' ? raw.toLowerCase() : '';
|
|
724
|
+
if (s === 'completed') return 'done';
|
|
725
|
+
if (s === 'failed' || s === 'declined') return 'error';
|
|
726
|
+
return 'running';
|
|
727
|
+
};
|
|
728
|
+
|
|
729
|
+
const changesText = (changes) => (Array.isArray(changes) ? changes : [])
|
|
730
|
+
.map(c => (c && c.path ? `${c.kind || 'update'} ${c.path}` : ''))
|
|
731
|
+
.filter(Boolean)
|
|
732
|
+
.join('\n');
|
|
733
|
+
|
|
734
|
+
const handleItem = (item) => {
|
|
735
|
+
if (!item || typeof item !== 'object') return;
|
|
736
|
+
switch (item.type) {
|
|
737
|
+
case 'agent_message':
|
|
738
|
+
appendItemText(item, false);
|
|
739
|
+
return;
|
|
740
|
+
case 'reasoning':
|
|
741
|
+
appendItemText(item, true);
|
|
742
|
+
return;
|
|
743
|
+
case 'error':
|
|
744
|
+
// 非致命告警:原样贴出来让用户看得见,但不置 agentError —— 那会把告警变成任务失败
|
|
745
|
+
if (item.message) appendOutput(`\n> [codex] ${item.message}\n`);
|
|
746
|
+
return;
|
|
747
|
+
case 'command_execution': {
|
|
748
|
+
const status = mapItemStatus(item.status);
|
|
749
|
+
tracker.record({
|
|
750
|
+
id: item.id,
|
|
751
|
+
name: 'command_execution',
|
|
752
|
+
input: { command: item.command },
|
|
753
|
+
status,
|
|
754
|
+
output: status === 'running' ? undefined : item.aggregated_output,
|
|
755
|
+
error: status === 'error' ? `命令未成功完成(exit_code=${item.exit_code ?? 'null'})` : ''
|
|
756
|
+
});
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
case 'file_change': {
|
|
760
|
+
const status = mapItemStatus(item.status);
|
|
761
|
+
tracker.record({
|
|
762
|
+
id: item.id,
|
|
763
|
+
name: 'file_change',
|
|
764
|
+
input: { changes: item.changes },
|
|
765
|
+
status,
|
|
766
|
+
output: status === 'running' ? undefined : changesText(item.changes),
|
|
767
|
+
error: status === 'error' ? '文件改动未应用' : ''
|
|
768
|
+
});
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
case 'mcp_tool_call': {
|
|
772
|
+
const status = mapItemStatus(item.status);
|
|
773
|
+
tracker.record({
|
|
774
|
+
id: item.id,
|
|
775
|
+
name: item.server && item.tool ? `${item.server}.${item.tool}` : (item.tool || 'mcp_tool_call'),
|
|
776
|
+
input: item.arguments,
|
|
777
|
+
// result.content 是 MCP 的内容块数组(与 claude 的 tool_result 同形态),
|
|
778
|
+
// 直接喂给 extractToolText 能压成文本;没有 content 时整包 JSON 兜底
|
|
779
|
+
status,
|
|
780
|
+
output: status === 'running' ? undefined : (item.result?.content ?? item.result),
|
|
781
|
+
error: item.error?.message || (status === 'error' ? 'MCP 工具调用失败' : '')
|
|
782
|
+
});
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
case 'web_search': {
|
|
786
|
+
const status = mapItemStatus(item.status);
|
|
787
|
+
tracker.record({
|
|
788
|
+
id: item.id,
|
|
789
|
+
name: 'web_search',
|
|
790
|
+
input: { query: item.query },
|
|
791
|
+
status,
|
|
792
|
+
output: status === 'running' ? undefined : item.results
|
|
793
|
+
});
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
default:
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
};
|
|
800
|
+
|
|
801
|
+
return (evt) => {
|
|
802
|
+
if (!evt || typeof evt !== 'object') return;
|
|
803
|
+
// thread_id 是 codex 的会话续接标识(exec resume <id>)。复用 claudeSessionId 字段:
|
|
804
|
+
// 前端与续接路由都认它,换执行器只是取值来源不同。
|
|
805
|
+
if (evt.type === 'thread.started') {
|
|
806
|
+
if (typeof evt.thread_id === 'string' && evt.thread_id && job.claudeSessionId !== evt.thread_id) {
|
|
807
|
+
job.claudeSessionId = evt.thread_id;
|
|
808
|
+
publish('job:update', job);
|
|
809
|
+
}
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
812
|
+
if (evt.type === 'item.started' || evt.type === 'item.updated' || evt.type === 'item.completed') {
|
|
813
|
+
handleItem(evt.item);
|
|
814
|
+
return;
|
|
815
|
+
}
|
|
816
|
+
if (evt.type === 'turn.failed') {
|
|
817
|
+
const msg = evt.error?.message
|
|
818
|
+
|| (evt.error?.additional_details ? String(evt.error.additional_details) : '')
|
|
819
|
+
|| 'codex 执行出错';
|
|
820
|
+
if (!job.agentError) job.agentError = msg;
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
if (evt.type === 'error') {
|
|
824
|
+
// 非终止信息(如 "Reconnecting... 1/5" 重试提示):贴进 output,终态仍由 turn.* 决定
|
|
825
|
+
if (evt.message) appendOutput(`\n> [codex] ${evt.message}\n`);
|
|
826
|
+
}
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
|
|
588
830
|
/**
|
|
589
831
|
* 执行一次任务。任务一次只跑一个进程,本函数是唯一的执行入口
|
|
590
832
|
* (首次执行、手动重跑、续聊都走它)。
|
|
@@ -595,10 +837,11 @@ export function createOpencodeEventHandler(job, appendOutput, appendThinking, to
|
|
|
595
837
|
* @param {string} branch 分支名(可空)
|
|
596
838
|
* @param {object} [options]
|
|
597
839
|
* @param {string|null} [options.resumeSessionId]
|
|
598
|
-
* 续接历史会话:claude 走 --resume <id>,opencode 走 --session <id
|
|
599
|
-
*
|
|
840
|
+
* 续接历史会话:claude 走 --resume <id>,opencode 走 --session <id>,
|
|
841
|
+
* codex 走 exec resume <thread_id>。
|
|
842
|
+
* id 来自上一轮 stream 事件捕获的会话标识(三者都记在 job.claudeSessionId)。
|
|
600
843
|
* @param {string} [options.executor]
|
|
601
|
-
* 执行器 'claude' | 'opencode'。缺省回落 'claude';路由层负责把
|
|
844
|
+
* 执行器 'claude' | 'opencode' | 'codex'。缺省回落 'claude';路由层负责把
|
|
602
845
|
* "body 指定 > 配置默认"先解析好再传进来。
|
|
603
846
|
* @returns {Promise<'done'|'cancelled'|'error'>} 本次运行的终态
|
|
604
847
|
*/
|
|
@@ -677,7 +920,11 @@ export async function runSingleSubtask(task, sub, repoPath, branch, options) {
|
|
|
677
920
|
let toolTracker = null;
|
|
678
921
|
|
|
679
922
|
try {
|
|
680
|
-
const launcher = executor === 'opencode'
|
|
923
|
+
const launcher = executor === 'opencode'
|
|
924
|
+
? launchOpencodeRun
|
|
925
|
+
: executor === 'codex'
|
|
926
|
+
? launchCodexExec
|
|
927
|
+
: launchClaudeInNewWindow;
|
|
681
928
|
const { pid, child } = await launcher(repoPath || process.cwd(), prompt, resumeSessionId);
|
|
682
929
|
job.pid = pid;
|
|
683
930
|
// 保存 child 引用,供 cancel 接口调用 kill
|
|
@@ -729,7 +976,9 @@ export async function runSingleSubtask(task, sub, repoPath, branch, options) {
|
|
|
729
976
|
|
|
730
977
|
const handleEvent = executor === 'opencode'
|
|
731
978
|
? createOpencodeEventHandler(job, appendOutput, appendThinking, toolTracker)
|
|
732
|
-
:
|
|
979
|
+
: executor === 'codex'
|
|
980
|
+
? createCodexEventHandler(job, appendOutput, appendThinking, toolTracker)
|
|
981
|
+
: createClaudeEventHandler(job, appendOutput, appendThinking, toolTracker);
|
|
733
982
|
|
|
734
983
|
const handleLine = (line, channel) => {
|
|
735
984
|
const trimmed = line.trim();
|
|
@@ -54,12 +54,14 @@ function makeSink() {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
test('normalizeTaskExecutor:白名单 + 大小写 + 非法回落', () => {
|
|
57
|
-
assert.deepEqual(TASK_EXECUTORS, ['claude', 'opencode']);
|
|
57
|
+
assert.deepEqual(TASK_EXECUTORS, ['claude', 'opencode', 'codex']);
|
|
58
58
|
assert.equal(normalizeTaskExecutor('opencode'), 'opencode');
|
|
59
|
+
assert.equal(normalizeTaskExecutor('codex'), 'codex');
|
|
59
60
|
// 大小写不敏感(存储前统一小写)
|
|
60
61
|
assert.equal(normalizeTaskExecutor('OpenCode'), 'opencode');
|
|
61
62
|
assert.equal(normalizeTaskExecutor('opencode '), 'opencode');
|
|
62
|
-
assert.equal(normalizeTaskExecutor('
|
|
63
|
+
assert.equal(normalizeTaskExecutor('Codex '), 'codex');
|
|
64
|
+
assert.equal(normalizeTaskExecutor('gpt'), 'claude');
|
|
63
65
|
assert.equal(normalizeTaskExecutor(undefined), 'claude');
|
|
64
66
|
assert.equal(normalizeTaskExecutor(null), 'claude');
|
|
65
67
|
});
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import"./rolldown-runtime-C0FnF6B9.js";import{$ as e,$r as t,A as n,Dn as r,E as i,En as a,Fn as o,H as s,Jt as c,K as l,Mn as u,Nn as d,On as f,Ot as p,Pr as m,Q as h,Qn as g,Rt as _,Tn as v,Un as y,Vt as b,Wt as x,Xn as S,Yr as C,_r as w,a as T,ar as E,bn as D,cn as O,cr as k,ct as ee,et as te,fr as A,gn as j,i as M,in as ne,j as N,kt as P,mt as F,ot as re,pt as I,qr as L,r as R,sr as z,tr as ie,un as B,wn as V,wt as ae,yn as H,yr as U,zn as W}from"./element-plus-DxBPQwL7.js";import{i as oe,n as G,t as K}from"./vendor-IQQMq-1c.js";import{n as q,t as J}from"./_plugin-vue_export-helper-B1mHBne9.js";import{t as Y}from"./configStore-BDxel6Co.js";W(),A();var X=65536,Z=`local-`;function Q(e){if(!e||!Array.isArray(e.messages))return[];let t=[],n=e.messages.length;for(let r=0;r<n;r++){let i=e.messages[r];if(i.role!==`system`){if(i.role===`user`){let e=``,n;if(typeof i.content==`string`)e=i.content;else if(Array.isArray(i.content)){e=i.content.filter(e=>e?.type===`text`).map(e=>e.text||``).join(` `);let t=i.content.filter(e=>e?.type===`image_url`&&typeof e.image_url?.url==`string`).map((e,t)=>({id:`att-${r}-${t}`,name:`image`,size:0,type:ce(e.image_url?.url||``)||`image/*`,preview:e.image_url?.url}));t.length>0&&(n=t)}(e||n)&&t.push({id:`msg-${r}`,role:`user`,content:e,attachments:n,status:`done`,createdAt:Date.now()})}else if(i.role===`assistant`){let i=`msg-${r}`,a=``,o=[],s=r;for(;s<n;){let t=e.messages[s];if(t.role!==`assistant`&&t.role!==`tool`)break;if(t.role===`assistant`){if(typeof t.content==`string`&&(a+=t.content),t.tool_calls&&t.tool_calls.length>0)for(let e of t.tool_calls)o.push({id:e.id||e.function?.name||K(),name:e.function?.name||``,arguments:e.function?.arguments||``,argsPreview:se(e.function?.name||``,e.function?.arguments||``),status:`done`,result:``})}else{let e=t.tool_call_id||t.name||``,n=o.find(t=>t.id===e);if(n){let e=t.content;typeof e!=`string`&&(e=`(non-text result)`),e.length>X&&(e=`…(前文已截断)\n${e.slice(-65536)}`),n.result=e}}s++}r=s-1,a.length>X&&(a=`…(前文已截断)\n${a.slice(-65536)}`);let c=!!a,l=o.length>0;(c||l)&&t.push({id:i,role:`assistant`,content:a,toolCalls:l?o:void 0,status:`done`,createdAt:Date.now()})}}}return t}function se(e,t){try{let n=JSON.parse(t);switch(e){case`run_command`:return String(n.command||``).slice(0,200);case`read_file`:case`write_file`:case`edit_file`:return String(n.path||``);case`list_files`:return String(n.path||`.`);case`search_text`:return String(n.pattern||``);default:return JSON.stringify(n).slice(0,200)}}catch{return t.slice(0,200)}}function $(e){return new Promise((t,n)=>{let r=new FileReader;r.onload=()=>t(String(r.result||``)),r.onerror=()=>n(r.error||Error(`FileReader failed`)),r.readAsDataURL(e)})}function ce(e){let t=/^data:([^;,]+)/.exec(e);return t?t[1]:``}function le(){let e=Y(),t=U([]),n=U(!1),r=w(new Map),i=U(null),a=U(!1),o=0,s=0;function c(e){return{key:e,sessionId:e.startsWith(Z)?null:e,title:``,messages:[],isStreaming:!1,abortController:null,nonce:0,pendingQuestion:null,answeringQuestion:!1}}function l(e){let t=r.get(e);return t||=(r.set(e,c(e)),r.get(e)),t}let u=V(()=>i.value?r.get(i.value)??null:null),d=V(()=>u.value?.messages??[]),f=V(()=>u.value?.isStreaming??!1),p=V(()=>u.value?.pendingQuestion??null),m=V(()=>u.value?.answeringQuestion??!1);function h(e){return!!r.get(e)?.isStreaming}function g(t){let n=[...t];for(let t of r.values()){if(!t.isStreaming||!t.sessionId)continue;let r=n.findIndex(e=>e.sessionId===t.sessionId);if(r===-1){let r=new Date().toISOString();n.unshift({sessionId:t.sessionId,title:t.title||q(`@AGENT:无标题`),source:`web`,cwd:e.currentDirectory||``,model:``,createdAt:r,updatedAt:r,messageCount:t.messages.filter(e=>e.role===`user`).length||1,size:0,isGenerating:!0})}else n[r]={...n[r],isGenerating:!0}}return n}async function _(){let r=++o,i=e.currentDirectory||``;if(!i){t.value=[],n.value=!1;return}n.value=!0;try{let e=`/api/agent/sessions?cwd=${encodeURIComponent(i)}`,n=await fetch(e).then(e=>e.json());if(r!==o)return;if(!n.success){M.error(n.error||q(`@AGENT:加载会话列表失败`));return}let a=Array.isArray(n.sessions)?n.sessions:[];t.value=g(a)}catch(e){if(r!==o)return;M.error(q(`@AGENT:加载会话列表失败`)+`: `+(e?.message||e))}finally{r===o&&(n.value=!1)}}function v(n,r){let i=new Date().toISOString(),a=t.value.find(e=>e.sessionId===n);if(a){a.isGenerating=!0,a.updatedAt=i;return}t.value=[{sessionId:n,title:r||q(`@AGENT:无标题`),source:`web`,cwd:e.currentDirectory||``,model:``,createdAt:i,updatedAt:i,messageCount:1,size:0,isGenerating:!0},...t.value]}function y(e){let n=t.value.find(t=>t.sessionId===e);n&&(n.isGenerating=!1)}async function b(e){if(r.get(e)?.isStreaming){i.value=e;return}a.value=!0,i.value=e;try{let t=await fetch(`/api/agent/sessions/${encodeURIComponent(e)}`).then(e=>e.json());if(!t.success){M.error(t.error||q(`@AGENT:加载会话失败`));return}let n=l(e);n.sessionId=e,n.messages=Q(t.session),t.session?.title&&(n.title=t.session.title)}catch(e){M.error(q(`@AGENT:加载会话失败`)+`: `+(e?.message||e))}finally{a.value=!1}}async function x(e){try{await R.confirm(q(`@AGENT:确认删除该会话`),q(`@AGENT:删除后无法恢复`),{type:`warning`})}catch{return}let n=r.get(e);if(n?.abortController)try{n.abortController.abort()}catch{}r.delete(e);try{let n=await fetch(`/api/agent/sessions/${encodeURIComponent(e)}`,{method:`DELETE`}).then(e=>e.json());if(!n.success){M.error(n.error||q(`@AGENT:删除失败`));return}t.value=t.value.filter(t=>t.sessionId!==e),i.value===e&&(i.value=null),M.success(q(`@AGENT:已删除`))}catch(e){M.error(q(`@AGENT:删除失败`)+`: `+(e?.message||e))}}async function S(e,n){try{let i=await fetch(`/api/agent/sessions/${encodeURIComponent(e)}`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({title:n})}).then(e=>e.json());if(!i.success){M.error(i.error||q(`@AGENT:重命名失败`));return}let a=t.value.find(t=>t.sessionId===e);a&&(a.title=n);let o=r.get(e);o&&(o.title=n),M.success(q(`@AGENT:已重命名`))}catch(e){M.error(q(`@AGENT:重命名失败`)+`: `+(e?.message||e))}}function C(){i.value=null}async function T(t,n=[]){let a=n.filter(e=>e?.file?.type?.startsWith(`image/`));a.length<n.length&&M.warning(q(`@AGENT:仅支持发送图片,非图片文件已忽略`));let o=l(i.value||`${Z}${Date.now()}-${++s}`);if(!t.trim()&&a.length===0||o.isStreaming)return;let c=(await Promise.allSettled(a.map(e=>$(e.file)))).map(e=>e.status===`fulfilled`?e.value:``).filter(e=>e.startsWith(`data:image/`));i.value=o.key,o.nonce+=1;let u=o.nonce;o.abortController=new AbortController;let d=o.abortController;o.pendingQuestion=null,o.answeringQuestion=!1;let f={id:K(),role:`user`,content:t,status:`done`,createdAt:Date.now()};a.length>0&&(f.attachments=a.map(e=>({id:e.id,name:e.file.name||`image`,size:e.file.size||0,type:e.file.type||``,preview:e.preview}))),o.messages.push(f);let p=w({id:K(),role:`assistant`,content:``,status:`pending`,createdAt:Date.now()});o.messages.push(p),o.isStreaming=!0;let m=[],h=o.sessionId;try{let n=await fetch(`/api/agent/chat`,{method:`POST`,headers:{"Content-Type":`application/json`,Accept:`text/event-stream`},body:JSON.stringify({sessionId:o.sessionId||``,userMessage:t,cwd:e.currentDirectory||``,...c.length>0?{images:c}:{}}),signal:d.signal});if(u!==o.nonce)return;if(!n.ok||!n.body){let e=await n.text().catch(()=>``);throw Error(e||`HTTP ${n.status}`)}let a=n.body.getReader(),s=new TextDecoder(`utf-8`),l=``;for(;;){let{value:e,done:n}=await a.read();if(u!==o.nonce)return;if(n)break;l+=s.decode(e,{stream:!0});let c=l.split(`
|
|
2
|
-
`);l=c.pop()??``;for(let e of c){let n=e.trim();if(!n.startsWith(`data:`))continue;let a=n.slice(5).trim();if(!a)continue;let s;try{s=JSON.parse(a)}catch{continue}switch(s.type){case`meta`:if(s.sessionId){let e=String(s.sessionId);if(h=e,o.sessionId!==e){let t=o.key;o.sessionId=e,o.key=e,t!==e&&(r.delete(t),r.set(e,o),i.value===t&&(i.value=e))}let n=String(s.title||``).trim()||t.trim().split(`
|
|
3
|
-
`)[0].trim().slice(0,40)||q(`@AGENT:无标题`);o.title||=n,v(e,n)}break;case`thinking`:p.reasoning||(p.reasoning=``,p.reasoningStatus=`streaming`),p.reasoning+=String(s.delta||``),p.status=`streaming`;break;case`content`:p.status===`pending`&&(p.status=`streaming`);{let e=String(s.delta||``);p.content+=e;let t=G(p.content);t.reasoning&&(p.reasoning||(p.reasoning=``,p.reasoningStatus=`streaming`),p.reasoning=t.reasoning,p.content=t.content)}break;case`tool_call_start`:{let e=w({id:s.toolCallId||K(),name:s.name||``,argsPreview:s.argsPreview||``,arguments:s.argsPreview||``,status:`running`,result:``});m.push(e),p.toolCalls||=[],p.toolCalls.push(e),p.status===`pending`&&(p.status=`streaming`);break}case`tool_output`:{let e=m.find(e=>e.id===s.toolCallId);if(e){let t=`${e.result||``}${String(s.chunk||``)}`;e.result=t.length>X?`…(前文已截断)\n${t.slice(-65536)}`:t}break}case`tool_result`:{let e=m.find(e=>e.id===s.toolCallId);e&&(e.result=String(s.result||``),e.status=`done`,e.name===`ask_user`&&(o.pendingQuestion=null));break}case`ask_user`:o.pendingQuestion={interactionId:String(s.interactionId||``),question:String(s.question||``),options:Array.isArray(s.options)?s.options.map(e=>String(e)):[],allowFreeText:s.allowFreeText!==!1};break;case`done`:{let e=s.content||p.content,t=G(e);t.reasoning&&!p.reasoning&&(p.reasoning=t.reasoning),p.content=t.content,p.status=`done`,p.reasoningStatus===`streaming`&&(p.reasoningStatus=`done`);break}case`error`:p.status=`error`,p.error=String(s.error||q(`@AGENT:未知错误`)),p.reasoningStatus===`streaming`&&(p.reasoningStatus=`done`)}}}if(u!==o.nonce)return;p.status===`pending`&&(p.status=`done`)}catch(e){if(u!==o.nonce)return;e?.name===`AbortError`||d.signal.aborted?(p.content=(p.content||``)+`
|
|
4
|
-
|
|
5
|
-
[`+q(`@AGENT:已停止`)+`]`,p.status=`done`,p.reasoningStatus===`streaming`&&(p.reasoningStatus=`done`)):(p.status=`error`,p.error=e?.message||String(e),M.error(p.error||q(`@AGENT:对话失败`)))}finally{u===o.nonce&&(o.isStreaming=!1,o.pendingQuestion=null,o.answeringQuestion=!1,o.abortController=null),h&&y(h),_().catch(()=>{})}}async function E(e){let t=u.value,n=t?.pendingQuestion,r=t?.sessionId,i=String(e||``).trim();if(!t||!n||!r||!i||t.answeringQuestion)return!1;t.answeringQuestion=!0;try{let e=await fetch(`/api/agent/respond`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sessionId:r,interactionId:n.interactionId,answer:i})}).then(e=>e.json());if(!e.success)throw Error(e.error||q(`@AGENT:回答提交失败`));return t.pendingQuestion=null,!0}catch(e){return M.error(e?.message||q(`@AGENT:回答提交失败`)),!1}finally{t.answeringQuestion=!1}}function D(){let e=u.value;e?.abortController&&(e.abortController.abort(),e.abortController=null)}return{sessions:t,sessionsLoading:n,currentSessionId:i,messages:d,isStreaming:f,sessionLoading:a,pendingQuestion:p,answeringQuestion:m,isSessionGenerating:h,loadSessions:_,loadSession:b,deleteSession:x,renameSession:S,newSession:C,sendMessage:T,answerQuestion:E,stop:D}}W(),A();var ue=o({__name:`MarketplacePanel`,props:{type:{type:String,required:!0}},setup(e,{expose:t}){t();let n=e,r=Y(),i=U([]),a=U([]),o=U(!1),s=U(``),l=U(``),u=U([]),d=U(`project`),f=U(new Set),m=U(new Set),h=V(()=>r.currentDirectory||``),g=null;async function _(){if(!o.value){o.value=!0;try{let e=new URLSearchParams({type:n.type,cwd:h.value});l.value&&e.set(`q`,l.value),u.value.length&&e.set(`sources`,u.value.join(`,`));let t=await(await fetch(`/api/agent/marketplace/catalog?${e}`)).json();t?.success?(i.value=t.groups||[],a.value=t.installed||[]):M.error(t?.error||q(`@MKT:加载失败`))}catch{M.error(q(`@MKT:加载失败`))}finally{o.value=!1}}}E(s,e=>{g&&clearTimeout(g),g=setTimeout(()=>{l.value=e.trim(),_()},400)}),E(u,()=>_()),E(()=>n.type,()=>{u.value=[],l.value=``,s.value=``,_()}),E(h,()=>_()),_();let v=V(()=>{let e=h.value?h.value.split(/[\\/]/).filter(Boolean).pop():``;return d.value===`project`?e||q(`@MKT:当前项目`):q(`@MKT:g ai 智能体`)});function y(e){return e.stars?`${S(e.stars)} ★`:e.downloads?`${S(e.downloads)} ${q(`@MKT:周下载`)}`:e.uses?`${S(e.uses)} ${q(`@MKT:次使用`)}`:``}function S(e){return e>=1e3?`${(e/1e3).toFixed(e>=1e4?0:1)}k`:String(e)}function C(e){return`${e.id}`}function T(e){return f.value.has(C(e))}let D=V(()=>{let e={project:[],global:[]};for(let t of a.value)(e[t.target]||=[]).push(t);return e}),O=w({visible:!1,item:null,env:{},args:``});function k(e){return n.type===`mcp`&&(!!e.envKeys?.length||!!e.args?.length)}function A(e){O.item=e,O.env=Object.fromEntries((e.envKeys||[]).map(e=>[e,``])),O.args=(e.args||[]).join(` `),O.visible=!0}function j(){let e=O.item;if(O.visible=!1,!e)return;let t=Object.fromEntries(Object.entries(O.env).filter(([,e])=>e.trim()!==``)),n=O.args.trim()?O.args.trim().match(/(?:[^\s"]+|"[^"]*")+/g)?.map(e=>e.replace(/^"|"$/g,``))??void 0:void 0;P(e,{env:t,...n?{args:n}:{}})}async function N(e){if(!e.installed||await F(e)){if(k(e)){A(e);return}await P(e,{})}}async function P(e,t){let r=C(e);f.value.add(r);try{let r=await fetch(`/api/agent/marketplace/install`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({type:n.type,target:d.value,cwd:h.value,item:{...e,...t}})}),i=await r.json().catch(()=>null);if(!r.ok||!i?.success){M.error(i?.error||q(`@MKT:安装失败`));return}i.item?.warning&&M.warning(i.item.warning),i.item?.envKeys?.length?M.warning(`${q(`@MKT:还缺环境变量`)}: ${i.item.envKeys.join(`, `)}`):M.success(q(`@MKT:安装成功`)),await _()}catch{M.error(q(`@MKT:安装失败`))}finally{f.value.delete(r)}}async function F(e){try{return await R.confirm(`${e.name} ${q(`@MKT:已安装,要重新安装吗?`)}`,q(`@MKT:重新安装`),{confirmButtonText:q(`@MKT:重装`),cancelButtonText:q(`@MKT:取消`),type:`warning`}),!0}catch{return!1}}async function re(e){try{await R.confirm(`${q(`@MKT:确定卸载`)} ${e.name}?`,q(`@MKT:卸载`),{confirmButtonText:q(`@MKT:卸载`),cancelButtonText:q(`@MKT:取消`),type:`warning`})}catch{return}let t=`${e.target}:${e.id}`;m.value.add(t);try{let t=new URLSearchParams({target:e.target,cwd:h.value}),r=await fetch(`/api/agent/marketplace/item/${n.type}/${encodeURIComponent(e.id)}?${t}`,{method:`DELETE`}),i=await r.json().catch(()=>null);if(!r.ok||!i?.success){M.error(i?.error||q(`@MKT:卸载失败`));return}M.success(q(`@MKT:已卸载`)),await _()}catch{M.error(q(`@MKT:卸载失败`))}finally{m.value.delete(t)}}let L={props:n,configStore:r,groups:i,installed:a,loading:o,searchInput:s,query:l,selectedSources:u,installTarget:d,installing:f,removing:m,cwd:h,get searchTimer(){return g},set searchTimer(e){g=e},loadCatalog:_,targetLabel:v,metricText:y,formatCount:S,cardKey:C,isBusy:T,installedByTarget:D,configDialog:O,needsConfig:k,openConfigDialog:A,confirmConfig:j,onInstall:N,doInstall:P,confirmReinstall:F,onRemove:re,get $t(){return q},get Search(){return x},get Refresh(){return b},get Delete(){return ee},get Link(){return p},get Check(){return te},get Star(){return c},get Download(){return I},get Warning(){return ne}};return Object.defineProperty(L,"__isScriptSetup",{enumerable:!1,value:!0}),L}});W(),B(),m();var de={class:`marketplace-panel`},fe={class:`mp-toolbar`},pe={class:`mp-search`},me=[`placeholder`],he={class:`mp-toolbar-sub`},ge={class:`mp-target-hint`},_e={class:`mp-source-filter`},ve=[`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`},De=[`title`],Oe={key:0,class:`mp-card-metric`},ke=[`title`],Ae={class:`mp-card-meta`},je=[`title`],Me=[`title`],Ne={key:2,class:`mp-tag remote`},Pe={class:`mp-card-foot`},Fe=[`href`],Ie={key:1,class:`mp-installed-chip`},Le=[`disabled`,`onClick`],Re={key:3,class:`mp-not-installable`},ze={key:1,class:`mp-empty`},Be={key:0,class:`mp-group installed`},Ve={class:`mp-group-header`},He={class:`mp-group-title`},Ue={class:`mp-group-count`},We={key:0,class:`mp-installed-block`},Ge={class:`mp-installed-target`},Ke={class:`mp-installed-list`},qe={class:`mp-installed-name`},Je={key:0,class:`mp-meta-pkg`},Ye={key:1,class:`mp-tag warn`},Xe=[`disabled`,`onClick`],Ze={key:1,class:`mp-empty all`},Qe={key:0,class:`mkt-form`},$e={class:`mkt-form-name`},et=[`onUpdate:modelValue`,`placeholder`],tt={key:0,class:`mkt-field`},nt={class:`mkt-hint`};function rt(e,o,c,p,m,h){let _=l,y=n,b=N,x=s,C=i,w=T;return S(),f(`div`,de,[r(` ── 工具栏 ───────────────────────────────── `),v(`div`,fe,[v(`div`,pe,[d(_,{class:`mp-search-icon`},{default:z(()=>[d(p.Search)]),_:1}),k(v(`input`,{"onUpdate:modelValue":o[0]||=e=>p.searchInput=e,class:`mp-search-input`,type:`text`,placeholder:c.type===`skill`?p.$t(`@MKT:搜索 Skill...`):p.$t(`@MKT:搜索 MCP 服务...`)},null,8,me),[[j,p.searchInput]])]),d(b,{modelValue:p.installTarget,"onUpdate:modelValue":o[1]||=e=>p.installTarget=e,size:`small`,class:`mp-target`},{default:z(()=>[d(y,{value:`project`},{default:z(()=>[u(t(p.$t(`@MKT:当前项目`)),1)]),_:1}),d(y,{value:`global`},{default:z(()=>[u(t(p.$t(`@MKT:g ai 智能体`)),1)]),_:1})]),_:1},8,[`modelValue`]),d(x,{content:p.$t(`@MKT:刷新`),placement:`top`,"show-after":300},{default:z(()=>[v(`button`,{class:L([`mp-refresh`,{spinning:p.loading}]),onClick:p.loadCatalog},[d(_,null,{default:z(()=>[d(p.Refresh)]),_:1})],2)]),_:1},8,[`content`])]),v(`div`,he,[v(`span`,ge,[u(t(p.$t(`@MKT:安装到`))+` `,1),v(`b`,null,t(p.targetLabel),1)]),v(`div`,_e,[(S(!0),f(D,null,g(p.groups,e=>(S(),f(`button`,{key:e.id,class:L([`mp-chip`,{active:p.selectedSources.includes(e.id)}]),onClick:()=>{let t=p.selectedSources.indexOf(e.id);t>=0?p.selectedSources.splice(t,1):p.selectedSources.push(e.id)}},t(e.label),11,ve))),128)),p.selectedSources.length?(S(),f(`button`,{key:0,class:`mp-chip clear`,onClick:o[2]||=e=>p.selectedSources=[]},t(p.$t(`@MKT:全部来源`)),1)):r(`v-if`,!0)])]),r(` ── 内容 ─────────────────────────────────── `),k((S(),f(`div`,ye,[(S(!0),f(D,null,g(p.groups,e=>(S(),f(`section`,{key:e.id,class:`mp-group`},[v(`header`,be,[v(`h3`,xe,t(e.label),1),e.status===`ok`?(S(),f(`span`,Se,t(e.items.length),1)):(S(),f(`span`,Ce,[d(_,null,{default:z(()=>[d(p.Warning)]),_:1}),u(` `+t(e.error||p.$t(`@MKT:来源不可用`)),1)])),e.homepage?(S(),f(`a`,{key:2,class:`mp-group-link`,href:e.homepage,target:`_blank`,rel:`noopener noreferrer`,title:e.homepage},[d(_,null,{default:z(()=>[d(p.Link)]),_:1})],8,we)):r(`v-if`,!0)]),e.status===`ok`&&e.items.length?(S(),f(`div`,Te,[(S(!0),f(D,null,g(e.items,e=>(S(),f(`article`,{key:p.cardKey(e),class:`mp-card`},[v(`div`,Ee,[v(`span`,{class:`mp-card-name`,title:e.name},t(e.name),9,De),p.metricText(e)?(S(),f(`span`,Oe,[d(_,null,{default:z(()=>[e.stars?(S(),a(p.Star,{key:0})):(S(),a(p.Download,{key:1}))]),_:2},1024),u(` `+t(p.metricText(e)),1)])):r(`v-if`,!0)]),v(`p`,{class:`mp-card-desc`,title:e.description},t(e.description||p.$t(`@MKT:暂无描述`)),9,ke),v(`div`,Ae,[e.package?(S(),f(`code`,{key:0,class:`mp-meta-pkg`,title:e.package},t(e.package),9,je)):e.repository?(S(),f(`span`,{key:1,class:`mp-meta-repo`,title:e.repository+(e.subpath?` · `+e.subpath:``)},[u(t(e.repository),1),e.subpath?(S(),f(D,{key:0},[u(` · `+t(e.subpath),1)],64)):r(`v-if`,!0)],8,Me)):r(`v-if`,!0),e.transport===`remote`?(S(),f(`span`,Ne,t(p.$t(`@MKT:远程服务`)),1)):r(`v-if`,!0),(S(!0),f(D,null,g((e.tags||[]).slice(0,2),e=>(S(),f(`span`,{key:e,class:`mp-tag`},t(e),1))),128))]),v(`div`,Pe,[e.upstream?(S(),f(`a`,{key:0,class:`mp-card-link`,href:e.upstream,target:`_blank`,rel:`noopener noreferrer`},t(p.$t(`@MKT:查看来源`)),9,Fe)):r(`v-if`,!0),o[6]||=v(`span`,{class:`mp-foot-spacer`},null,-1),e.installed?(S(),f(`span`,Ie,[d(_,null,{default:z(()=>[d(p.Check)]),_:1}),u(t(p.$t(`@MKT:已安装`)),1)])):e.installable===!1?(S(),f(`span`,Re,t(p.$t(`@MKT:暂不支持一键安装`)),1)):(S(),f(`button`,{key:2,class:`mp-install-btn`,disabled:p.isBusy(e),onClick:t=>p.onInstall(e)},t(p.isBusy(e)?p.$t(`@MKT:安装中...`):p.$t(`@MKT:安装`)),9,Le))])]))),128))])):e.status===`ok`?(S(),f(`div`,ze,t(p.$t(`@MKT:该来源暂无结果`)),1)):r(`v-if`,!0)]))),128)),r(` ── 已安装 ─────────────────────────────── `),p.installed.length?(S(),f(`section`,Be,[v(`header`,Ve,[v(`h3`,He,t(p.$t(`@MKT:已安装`)),1),v(`span`,Ue,t(p.installed.length),1)]),(S(),f(D,null,g([`project`,`global`],e=>v(`div`,{key:e},[p.installedByTarget[e]?.length?(S(),f(`div`,We,[v(`div`,Ge,t(e===`project`?p.$t(`@MKT:当前项目`):p.$t(`@MKT:g ai 智能体`)),1),v(`div`,Ke,[(S(!0),f(D,null,g(p.installedByTarget[e],n=>(S(),f(`div`,{key:e+n.id,class:`mp-installed-row`},[v(`span`,qe,t(n.name),1),n.package?(S(),f(`code`,Je,t(n.package),1)):r(`v-if`,!0),n.requiredEnv?.length?(S(),f(`span`,Ye,t(p.$t(`@MKT:待配置`))+`: `+t(n.requiredEnv.join(`, `)),1)):r(`v-if`,!0),o[7]||=v(`span`,{class:`mp-foot-spacer`},null,-1),v(`button`,{class:`mp-remove-btn`,disabled:p.removing.has(e+n.id),onClick:e=>p.onRemove(n)},[d(_,null,{default:z(()=>[d(p.Delete)]),_:1}),u(` `+t(p.removing.has(e+n.id)?p.$t(`@MKT:卸载中...`):p.$t(`@MKT:卸载`)),1)],8,Xe)]))),128))])])):r(`v-if`,!0)])),64))])):r(`v-if`,!0),!p.loading&&!p.groups.length?(S(),f(`div`,Ze,t(p.$t(`@MKT:加载失败`)),1)):r(`v-if`,!0)])),[[w,p.loading]]),r(` ── MCP 安装前配置 ───────────────────────── `),d(C,{modelValue:p.configDialog.visible,"onUpdate:modelValue":o[5]||=e=>p.configDialog.visible=e,title:p.$t(`@MKT:配置 MCP`),width:`460px`,"close-on-click-modal":!1,"append-to-body":``},{footer:z(()=>[v(`button`,{class:`mkt-cancel`,onClick:o[4]||=e=>p.configDialog.visible=!1},t(p.$t(`@MKT:取消`)),1),v(`button`,{class:`mkt-confirm`,onClick:p.confirmConfig},t(p.$t(`@MKT:安装`)),1)]),default:z(()=>[p.configDialog.item?(S(),f(`div`,Qe,[v(`p`,$e,t(p.configDialog.item.name),1),(S(!0),f(D,null,g(Object.keys(p.configDialog.env),e=>(S(),f(`div`,{key:e,class:`mkt-field`},[v(`label`,null,t(e),1),k(v(`input`,{"onUpdate:modelValue":t=>p.configDialog.env[e]=t,type:`text`,autocomplete:`off`,placeholder:p.$t(`@MKT:环境变量值`),spellcheck:`false`},null,8,et),[[j,p.configDialog.env[e]]])]))),128)),p.configDialog.item.args?.length?(S(),f(`div`,tt,[v(`label`,null,t(p.$t(`@MKT:启动参数`)),1),k(v(`input`,{"onUpdate:modelValue":o[3]||=e=>p.configDialog.args=e,type:`text`,autocomplete:`off`,spellcheck:`false`},null,512),[[j,p.configDialog.args]]),v(`p`,nt,t(p.$t(`@MKT:参数提示`)),1)])):r(`v-if`,!0)])):r(`v-if`,!0)]),_:1},8,[`modelValue`,`title`])])}var it=J(ue,[[`render`,rt],[`__scopeId`,`data-v-e9f9e851`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/components/MarketplacePanel.vue`]]);W(),A();var at=o({__name:`AgentView`,setup(t,{expose:n}){n();let r=Y(),i=U(`chat`),a=V(()=>i.value===`mcp`?`mcp`:`skill`),o=V(()=>[{id:`chat`,label:q(`@AGENT:对话`),icon:h},{id:`skill`,label:q(`@AGENT:Skill 广场`),icon:ae},{id:`mcp`,label:q(`@AGENT:MCP 广场`),icon:re}]),{sessions:c,sessionsLoading:u,currentSessionId:d,messages:f,isStreaming:p,sessionLoading:m,loadSessions:g,loadSession:v,deleteSession:b,renameSession:S,newSession:C,sendMessage:w,pendingQuestion:T,answeringQuestion:D,answerQuestion:O,isSessionGenerating:k,stop:A}=le(),j=V(()=>{let e=r.theme;return e===`dark`||e===`auto`&&window.matchMedia(`(prefers-color-scheme: dark)`).matches?`dark`:`light`}),M=U(``),ne=V(()=>{if(!M.value.trim())return c.value;let e=M.value.toLowerCase();return c.value.filter(t=>(t.title||``).toLowerCase().includes(e)||(t.model||``).toLowerCase().includes(e))}),N=V(()=>[{id:`p1`,label:q(`@AGENT:查看项目结构`),prompt:q(`@AGENT:prompt_p1`)},{id:`p2`,label:q(`@AGENT:分析代码质量`),prompt:q(`@AGENT:prompt_p2`)},{id:`p3`,label:q(`@AGENT:帮我写测试`),prompt:q(`@AGENT:prompt_p3`)},{id:`p4`,label:q(`@AGENT:Git 状态检查`),prompt:q(`@AGENT:prompt_p4`)},{id:`p5`,label:q(`@AGENT:帮我启动项目`),prompt:q(`@AGENT:prompt_p5`)}]);async function I(e){await w(e.text,e.files),await y(),H()}async function L(e){await w(e.prompt),await y(),H()}let z=U(``);async function ie(e=z.value){await O(e)&&(z.value=``)}let B=U(null);function H(e=!0){B.value?.scrollToBottom(e)}E(()=>f.value.length,()=>{y(()=>H(!1))});function W(e){v(e)}function G(){C()}function K(e,t){t.stopPropagation(),b(e)}async function J(e,t,n){n.stopPropagation();try{let{value:n}=await R.prompt(q(`@AGENT:请输入新的会话标题`),q(`@AGENT:重命名会话`),{inputValue:t,inputPattern:/.+/,inputErrorMessage:q(`@AGENT:标题不能为空`)});n&&n!==t&&await S(e,n)}catch{}}function X(e){if(!e)return``;try{let t=new Date(e);if(Number.isNaN(t.getTime()))return e;let n=new Date,r=n.getTime()-t.getTime(),i=e=>String(e).padStart(2,`0`);if(t.toDateString()===n.toDateString())return`${i(t.getHours())}:${i(t.getMinutes())}`;if(r<6048e5){let e=Math.floor(r/864e5);return e===0?q(`@AGENT:今天`):`${e}${q(`@AGENT:天前`)}`}return`${t.getFullYear()}-${i(t.getMonth()+1)}-${i(t.getDate())}`}catch{return e}}let Z=U(280),Q=U(!1);function se(e){Q.value=!0;let t=e.clientX,n=Z.value,r=e=>{let r=e.clientX-t,i=Math.max(200,Math.min(500,n+r));Z.value=i},i=()=>{Q.value=!1,document.removeEventListener(`mousemove`,r),document.removeEventListener(`mouseup`,i)};document.addEventListener(`mousemove`,r),document.addEventListener(`mouseup`,i)}E(()=>[r.currentDirectory,p.value],async([e,t],n)=>{let r=!n||e!==n[0],i=!!n&&n[1]===!0&&!t;(r||i)&&await g(),d.value&&!p.value&&!c.value.some(e=>e.sessionId===d.value)&&C()},{immediate:!0});let $={configStore:r,activeTab:i,marketplaceType:a,tabs:o,sessions:c,sessionsLoading:u,currentSessionId:d,messages:f,isStreaming:p,sessionLoading:m,loadSessions:g,loadSession:v,deleteSession:b,renameSession:S,newSession:C,sendMessage:w,pendingQuestion:T,answeringQuestion:D,answerQuestion:O,isSessionGenerating:k,stop:A,chatTheme:j,searchQuery:M,filteredSessions:ne,presetQuestions:N,onSend:I,onSelectPreset:L,pendingAnswer:z,submitPendingAnswer:ie,chatContainerRef:B,scrollToBottom:H,selectSession:W,handleNewSession:G,handleDelete:K,handleRename:J,formatDate:X,sidebarWidth:Z,isResizing:Q,startResize:se,get $t(){return q},get ElTooltip(){return s},get ElIcon(){return l},get Plus(){return _},get Search(){return x},get Delete(){return ee},get Edit(){return F},get ChatLineRound(){return e},get Loading(){return P},get Check(){return te},get ChatContainer(){return oe},MarketplacePanel:it};return Object.defineProperty($,"__isScriptSetup",{enumerable:!1,value:!0}),$}});W(),m(),B();var ot={class:`agent-view`},st={class:`sidebar-header`},ct={class:`sidebar-search`},lt=[`placeholder`],ut={class:`session-list`},dt={key:0,class:`empty-state`},ft={class:`empty-text`},pt={key:0,class:`empty-hint`},mt=[`onClick`],ht={class:`session-item-main`},gt={class:`session-item-title`},_t={class:`session-item-meta`},vt={key:0,class:`meta-generating`},yt={class:`meta-time`},bt={class:`meta-count`},xt={key:2,class:`meta-source cli`},St=[`onClick`],Ct=[`onClick`],wt={class:`agent-chat-area`},Tt={class:`agent-tabs`,role:`tablist`},Et=[`aria-selected`,`onClick`],Dt={class:`agent-tab-body`},Ot={key:0,class:`agent-chat-pane`},kt={key:0,class:`chat-loading`},At={key:0,class:`ask-user-panel`,"aria-live":`polite`},jt={class:`ask-user-title`},Mt={class:`ask-user-question`},Nt={key:0,class:`ask-user-options`},Pt=[`disabled`,`onClick`],Ft=[`disabled`,`placeholder`,`aria-label`],It=[`disabled`],Lt={key:0,class:`stop-button-bar`};function Rt(e,n,i,o,s,c){let l=T;return S(),f(`div`,ot,[r(` ═══ 左侧:会话列表(只在「对话」Tab 显示)═══ `),o.activeTab===`chat`?(S(),f(D,{key:0},[v(`aside`,{class:`agent-sidebar`,style:C({width:o.sidebarWidth+`px`})},[r(` 顶部操作栏 `),v(`div`,st,[v(`button`,{class:`new-session-btn`,onClick:o.handleNewSession},[d(o.ElIcon,null,{default:z(()=>[d(o.Plus)]),_:1}),v(`span`,null,t(o.$t(`@AGENT:新建会话`)),1)])]),r(` 搜索框 `),v(`div`,ct,[d(o.ElIcon,{class:`search-icon`},{default:z(()=>[d(o.Search)]),_:1}),k(v(`input`,{"onUpdate:modelValue":n[0]||=e=>o.searchQuery=e,placeholder:o.$t(`@AGENT:搜索会话...`),class:`search-input`,type:`text`},null,8,lt),[[j,o.searchQuery]])]),r(` 会话列表 `),k((S(),f(`div`,ut,[o.filteredSessions.length===0&&!o.sessionsLoading?(S(),f(`div`,dt,[d(o.ElIcon,{size:28,color:`var(--text-tertiary)`},{default:z(()=>[d(o.ChatLineRound)]),_:1}),v(`div`,ft,t(o.searchQuery?o.$t(`@AGENT:未找到匹配的会话`):o.$t(`@AGENT:暂无会话`)),1),o.searchQuery?r(`v-if`,!0):(S(),f(`div`,pt,t(o.$t(`@AGENT:点击上方按钮开始对话`)),1))])):r(`v-if`,!0),(S(!0),f(D,null,g(o.filteredSessions,e=>(S(),f(`div`,{key:e.sessionId,class:L([`session-item`,{active:o.currentSessionId===e.sessionId}]),onClick:t=>o.selectSession(e.sessionId)},[v(`div`,ht,[v(`div`,gt,t(e.title||o.$t(`@AGENT:无标题`)),1),v(`div`,_t,[e.isGenerating||o.isSessionGenerating(e.sessionId)?(S(),f(`span`,vt,[d(o.ElIcon,{class:`is-loading`},{default:z(()=>[d(o.Loading)]),_:1}),u(` `+t(o.$t(`@AGENT:正在生成中...`)),1)])):(S(),f(D,{key:1},[v(`span`,yt,t(o.formatDate(e.updatedAt)),1),n[5]||=v(`span`,{class:`meta-dot`},`·`,-1),v(`span`,bt,t(e.messageCount)+` `+t(o.$t(`@AGENT:条`)),1)],64)),e.source===`cli`?(S(),f(`span`,xt,`CLI`)):r(`v-if`,!0)])]),v(`div`,{class:`session-item-actions`,onClick:n[1]||=H(()=>{},[`stop`])},[d(o.ElTooltip,{content:o.$t(`@AGENT:重命名`),placement:`top`,"show-after":500},{default:z(()=>[v(`button`,{class:`item-action-btn`,onClick:t=>o.handleRename(e.sessionId,e.title,t)},[d(o.ElIcon,null,{default:z(()=>[d(o.Edit)]),_:1})],8,St)]),_:2},1032,[`content`]),d(o.ElTooltip,{content:o.$t(`@AGENT:删除`),placement:`top`,"show-after":500},{default:z(()=>[v(`button`,{class:`item-action-btn danger`,onClick:t=>o.handleDelete(e.sessionId,t)},[d(o.ElIcon,null,{default:z(()=>[d(o.Delete)]),_:1})],8,Ct)]),_:2},1032,[`content`])])],10,mt))),128))])),[[l,o.sessionsLoading]])],4),r(` 拖拽分隔条 `),v(`div`,{class:L([`sidebar-resizer`,{active:o.isResizing}]),onMousedown:o.startResize},null,34)],64)):r(`v-if`,!0),r(` ═══ 右侧:Tab 栏 + 内容区 ═══ `),v(`main`,wt,[v(`nav`,Tt,[(S(!0),f(D,null,g(o.tabs,e=>(S(),f(`button`,{key:e.id,type:`button`,class:L([`agent-tab`,{active:o.activeTab===e.id}]),role:`tab`,"aria-selected":o.activeTab===e.id,onClick:t=>o.activeTab=e.id},[d(o.ElIcon,null,{default:z(()=>[(S(),a(ie(e.icon)))]),_:2},1024),v(`span`,null,t(e.label),1)],10,Et))),128))]),v(`div`,Dt,[r(` ── 对话 ── `),o.activeTab===`chat`?(S(),f(`div`,Ot,[r(` 加载中 `),o.sessionLoading?(S(),f(`div`,kt,[d(o.ElIcon,{class:`is-loading`,size:32},{default:z(()=>[d(o.Loading)]),_:1}),v(`span`,null,t(o.$t(`@AGENT:加载会话中...`)),1)])):(S(),f(D,{key:1},[r(` ChatContainer `),d(o.ChatContainer,{ref:`chatContainerRef`,messages:o.messages,"preset-questions":o.presetQuestions,"welcome-title":o.$t(`@AGENT:智能体助手`),"welcome-description":o.$t(`@AGENT:我可以帮你阅读代码、执行命令、修改文件。选择下方话题或直接输入你的问题。`),"assistant-name":`g ai`,theme:o.chatTheme,disabled:o.isStreaming,"upload-config":{accept:`image/*`},placeholder:o.isStreaming?o.$t(`@AGENT:正在生成中...`):o.$t(`@AGENT:输入消息,Enter 发送`),onSend:o.onSend,onSelect:o.onSelectPreset},null,8,[`messages`,`preset-questions`,`welcome-title`,`welcome-description`,`theme`,`disabled`,`placeholder`])],2112)),d(O,{name:`fade`},{default:z(()=>[o.pendingQuestion?(S(),f(`section`,At,[v(`div`,jt,[d(o.ElIcon,null,{default:z(()=>[d(o.ChatLineRound)]),_:1}),v(`span`,null,t(o.$t(`@AGENT:等待你的回答`)),1)]),v(`div`,Mt,t(o.pendingQuestion.question),1),o.pendingQuestion.options.length?(S(),f(`div`,Nt,[(S(!0),f(D,null,g(o.pendingQuestion.options,e=>(S(),f(`button`,{key:e,type:`button`,class:`ask-user-option`,disabled:o.answeringQuestion,onClick:t=>o.submitPendingAnswer(e)},[d(o.ElIcon,null,{default:z(()=>[d(o.Check)]),_:1}),v(`span`,null,t(e),1)],8,Pt))),128))])):r(`v-if`,!0),o.pendingQuestion.allowFreeText||o.pendingQuestion.options.length===0?(S(),f(`form`,{key:1,class:`ask-user-form`,onSubmit:n[3]||=H(e=>o.submitPendingAnswer(),[`prevent`])},[k(v(`input`,{"onUpdate:modelValue":n[2]||=e=>o.pendingAnswer=e,type:`text`,disabled:o.answeringQuestion,placeholder:o.$t(`@AGENT:输入回答`),"aria-label":o.$t(`@AGENT:输入回答`)},null,8,Ft),[[j,o.pendingAnswer]]),v(`button`,{type:`submit`,disabled:o.answeringQuestion||!o.pendingAnswer.trim()},[d(o.ElIcon,null,{default:z(()=>[d(o.Check)]),_:1}),v(`span`,null,t(o.$t(`@AGENT:提交回答`)),1)],8,It)],32)):r(`v-if`,!0)])):r(`v-if`,!0)]),_:1}),r(` 停止按钮浮层 `),d(O,{name:`fade`},{default:z(()=>[o.isStreaming?(S(),f(`div`,Lt,[v(`button`,{class:`stop-button`,onClick:n[4]||=(...e)=>o.stop&&o.stop(...e)},[d(o.ElIcon,null,{default:z(()=>[d(o.Loading,{class:`is-loading`})]),_:1}),v(`span`,null,t(o.$t(`@AGENT:停止生成`)),1)])])):r(`v-if`,!0)]),_:1})])):(S(),f(D,{key:1},[r(` ── Skill 广场 / MCP 广场 ── `),d(o.MarketplacePanel,{type:o.marketplaceType},null,8,[`type`])],2112))])])])}var zt=J(at,[[`render`,Rt],[`__scopeId`,`data-v-bd681ddd`],[`__file`,`D:/workspace/github_workspace/zen-gitsync/src/ui/client/src/views/AgentView.vue`]]);export{zt as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import"./rolldown-runtime-C0FnF6B9.js";import{ar as e,fr as t,i as n,n as r,t as i,wn as a,yr as o,zn as s}from"./element-plus-DxBPQwL7.js";import{m as c}from"./vendor-IQQMq-1c.js";import{a as l,n as u,r as d}from"./_plugin-vue_export-helper-B1mHBne9.js";var f={"zh-CN":r,"en-US":i};function p(e){return f[e]||r}t(),s();var m=c(`locale`,()=>{let e=o(d()),t=a(()=>p(e.value));async function n(t){l(t),e.value=t;let n=h();n.locale!==t&&await n.saveGeneralSettings({locale:t})}return{currentLocale:e,elementPlusLocale:t,changeLocale:n}});t(),s();var h=c(`config`,()=>{let t=o(``),r=o([]),i=o([]),s=o([]),c=o([]),d=o([]),f=o([]),p=o([]),h=o([]),g=o(!1),_=o({enabled:!1,type:`command`,refId:``}),v=o(!1),y=o(!1),b=o(``),x=o(``),S=o(``),C=o(!0),w=o(!1),T=o(!0),E=o(!1),D=o(!1),O=o(!0),k=o(`light`),A=o(`zh-CN`),j=o([]),M=o(200),N=o(`claude`),P=o(!1),F={layout:{leftRatio:.25,midRatio:.375,rightRatio:.375,topRatio:.5},layoutsByProject:{},aiDiffSummaryByProject:{},fileListViewMode:`list`,fileDiffSplitPercent:35,diffPreviewSplitPercent:55,commandConsole:{expanded:!0,useTerminal:!0,showTerminalSessions:!0,splitPercent:25},editorAutoSave:!1,mindmapDirs:[],mindmapDir:``,headerToolsHidden:[],pickerGlobalSearch:!1},I=o(JSON.parse(JSON.stringify(F))),L=o(!1);function R(e){S.value=e||``}let z=a(()=>{let e=S.value;return e?I.value.aiDiffSummaryByProject[e]!==!1:!1});function ee(){let e=S.value;if(e&&I.value.layoutsByProject?.[e]){I.value.layout={...I.value.layoutsByProject[e]};return}}function B(e){let t=document.documentElement;e===`dark`?t.setAttribute(`data-theme`,`dark`):e===`light`?t.removeAttribute(`data-theme`):window.matchMedia(`(prefers-color-scheme: dark)`).matches?t.setAttribute(`data-theme`,`dark`):t.removeAttribute(`data-theme`)}function te(){let e=document.documentElement.getAttribute(`data-theme`)===`dark`?`light`:`dark`;return k.value=e,B(e),$({theme:e}).catch(e=>{console.error(`保存主题切换结果失败:`,e)}),e}B(k.value);let V=a(()=>({defaultCommitMessage:t.value,descriptionTemplates:r.value,scopeTemplates:i.value,messageTemplates:s.value,commandTemplates:c.value,lockedFiles:d.value,customCommands:f.value,orchestrations:p.value,startupItems:h.value,startupAutoRun:g.value,afterQuickPushAction:_.value,currentDirectory:S.value})),ne=a(()=>!!(b.value&&b.value.trim()));async function H(){try{let e=await fetch(`/api/config/open-file`,{method:`POST`,headers:{"Content-Type":`application/json`}}),t=await e.json().catch(()=>({}));return e.ok&&t?.success?(n.success(u(`@D50BB:已打开系统配置文件`)),!0):(n.error(`${u(`@D50BB:打开系统配置文件失败: `)}${t?.error||``}`),!1)}catch(e){return n.error(`${u(`@D50BB:打开系统配置文件失败: `)}${e.message}`),!1}}async function U(e=!1){if(!e&&y.value&&!v.value)return console.log(u(`@D50BB:使用缓存的配置信息`)),V.value;v.value=!0;try{v.value=!0,console.log(u(`@D50BB:加载配置信息...`));let e=await fetch(`/api/config/getConfig`),a=await e.json().catch(()=>({}));if(!e.ok||a&&a.success===!1){let e=String(a?.error||u(`@D50BB:加载配置失败`)),t=String(a?.configPath||``),r=t?`\n${u(`@D50BB:配置文件`)}: ${t}`:``;return n.error(`${u(`@D50BB:加载配置失败: `)}${e}${r}`),b.value=e,x.value=t,null}if(b.value=``,x.value=``,t.value=a.defaultCommitMessage||``,r.value=a.descriptionTemplates||[],i.value=a.scopeTemplates||[],s.value=a.messageTemplates||[],c.value=a.commandTemplates||[],d.value=a.lockedFiles||[],f.value=a.customCommands||[],p.value=a.orchestrations||[],h.value=(a.startupItems||[]).map(e=>({id:String(e?.id??``),type:e?.type===`workflow`?`workflow`:`command`,refId:String(e?.refId??e?.commandId??``),createdAt:Number(e?.createdAt??Date.now()),enabled:typeof e?.enabled!=`boolean`||e.enabled})).filter(e=>e.id&&e.refId),g.value=a.startupAutoRun||!1,_.value={enabled:!!a?.afterQuickPushAction?.enabled,type:a?.afterQuickPushAction?.type===`workflow`?`workflow`:`command`,refId:String(a?.afterQuickPushAction?.refId||``).trim()},a.isStandardCommit!==void 0&&(T.value=!!a.isStandardCommit),a.skipHooks!==void 0&&(E.value=!!a.skipHooks),a.autoQuickPushOnEnter!==void 0&&(D.value=!!a.autoQuickPushOnEnter),a.autoSetDefaultMessage!==void 0&&(w.value=!!a.autoSetDefaultMessage),a.autoClosePushModal!==void 0&&(C.value=!!a.autoClosePushModal),a.pullBeforePush!==void 0&&(O.value=!!a.pullBeforePush),Array.isArray(a.models)&&(j.value=a.models),Number.isFinite(Number(a.aiMaxToolIterations))&&Number(a.aiMaxToolIterations)>0&&(M.value=Math.floor(Number(a.aiMaxToolIterations))),(a.taskExecutor===`claude`||a.taskExecutor===`opencode`)&&(N.value=a.taskExecutor),typeof a.notifyOnTaskDone==`boolean`&&(P.value=a.notifyOnTaskDone),a.theme&&[`light`,`dark`,`auto`].includes(a.theme)&&(k.value=a.theme,B(a.theme)),a.locale&&[`zh-CN`,`en-US`].includes(a.locale)){A.value=a.locale,l(a.locale);let e=m();e.currentLocale=a.locale}if(a.currentDirectory&&(S.value=a.currentDirectory),a.ui==null){let e=e=>{try{return localStorage.getItem(e)}catch{return null}},t={},n=e(`zen-gitsync-layout-left-ratio`),r=e(`zen-gitsync-layout-mid-ratio`),i=e(`zen-gitsync-layout-right-ratio`),a=e(`zen-gitsync-layout-top-ratio`);if(n||r||i||a){let e=(e,t)=>{let n=e==null?NaN:parseFloat(e);return Number.isFinite(n)?n:t};t.layout={leftRatio:e(n,F.layout.leftRatio),midRatio:e(r,F.layout.midRatio),rightRatio:e(i,F.layout.rightRatio),topRatio:e(a,F.layout.topRatio)}}let o=e(`zen-gitsync-file-list-view-mode`);(o===`list`||o===`tree`)&&(t.fileListViewMode=o);let s=e(`zen-gitsync-filediff-ratio`)??e(`fileDiff.splitPercent`);if(s!=null){let e=parseFloat(s);Number.isFinite(e)&&(t.fileDiffSplitPercent=Math.min(85,Math.max(15,e)))}let c=e(`useTerminal`),l=e(`isConsoleExpanded`),u=e(`showTerminalSessions`),d=e(`zen-gitsync-commandconsole-ratio`);if(c!==null||l!==null||u!==null||d!=null){let e=d==null?NaN:parseFloat(d);t.commandConsole={useTerminal:c!==`false`,expanded:l!==`false`,showTerminalSessions:u==null||u===`true`,splitPercent:Number.isFinite(e)?Math.min(85,Math.max(15,e)):F.commandConsole.splitPercent}}let f=e(`zen-gitsync-editor-auto-save`);f!=null&&(t.editorAutoSave=f===`true`),Object.keys(t).length>0&&(I.value={...I.value,...t}),Object.keys(t).length>0&&J(t,{immediate:!0}).catch(e=>{console.error(`迁移 UI 设置到文件失败:`,e)});try{[`zen-gitsync-theme`,`zen-gitsync-locale`,`zen-gitsync-editor-auto-save`,`zen-gitsync-file-list-view-mode`,`zen-gitsync-filediff-ratio`,`fileDiff.splitPercent`,`isConsoleExpanded`,`useTerminal`,`showTerminalSessions`,`zen-gitsync-commandconsole-ratio`,`zen-gitsync-layout-left-ratio`,`zen-gitsync-layout-mid-ratio`,`zen-gitsync-layout-right-ratio`,`zen-gitsync-layout-top-ratio`,`locale`].forEach(e=>localStorage.removeItem(e))}catch{}}else{let e=a.ui.layoutsByProject&&typeof a.ui.layoutsByProject==`object`&&!Array.isArray(a.ui.layoutsByProject)?a.ui.layoutsByProject:{},t={};for(let[n,r]of Object.entries(e))if(r&&typeof r==`object`&&!Array.isArray(r)){let e=r;t[n]={leftRatio:Number.isFinite(Number(e.leftRatio))?Number(e.leftRatio):F.layout.leftRatio,midRatio:Number.isFinite(Number(e.midRatio))?Number(e.midRatio):F.layout.midRatio,rightRatio:Number.isFinite(Number(e.rightRatio))?Number(e.rightRatio):F.layout.rightRatio,topRatio:Number.isFinite(Number(e.topRatio))?Number(e.topRatio):F.layout.topRatio}}let n=a.ui.aiDiffSummaryByProject&&typeof a.ui.aiDiffSummaryByProject==`object`&&!Array.isArray(a.ui.aiDiffSummaryByProject)?a.ui.aiDiffSummaryByProject:{},r={};for(let[e,t]of Object.entries(n))typeof t==`boolean`&&(r[e]=t);let i=typeof a.ui.mindmapDir==`string`?a.ui.mindmapDir.trim():``,o=[],s=new Set,c=Array.isArray(a.ui.mindmapDirs)?a.ui.mindmapDirs:[];for(let e of c){if(typeof e!=`string`)continue;let t=e.trim();if(!t)continue;let n=t.toLowerCase();s.has(n)||(s.add(n),o.push(t))}o.length===0&&i&&o.push(i);let l={...F.layout,...a.ui.layout||{}};I.value={layout:l,layoutsByProject:t,aiDiffSummaryByProject:r,fileListViewMode:a.ui.fileListViewMode===`tree`?`tree`:`list`,fileDiffSplitPercent:Number.isFinite(Number(a.ui.fileDiffSplitPercent))?Math.min(85,Math.max(15,Number(a.ui.fileDiffSplitPercent))):F.fileDiffSplitPercent,diffPreviewSplitPercent:Number.isFinite(Number(a.ui.diffPreviewSplitPercent))?Math.min(85,Math.max(25,Number(a.ui.diffPreviewSplitPercent))):F.diffPreviewSplitPercent,commandConsole:{expanded:typeof a.ui.commandConsole?.expanded==`boolean`?a.ui.commandConsole.expanded:F.commandConsole.expanded,useTerminal:typeof a.ui.commandConsole?.useTerminal==`boolean`?a.ui.commandConsole.useTerminal:F.commandConsole.useTerminal,showTerminalSessions:typeof a.ui.commandConsole?.showTerminalSessions==`boolean`?a.ui.commandConsole.showTerminalSessions:F.commandConsole.showTerminalSessions,splitPercent:Number.isFinite(Number(a.ui.commandConsole?.splitPercent))?Math.min(85,Math.max(15,Number(a.ui.commandConsole.splitPercent))):F.commandConsole.splitPercent},editorAutoSave:typeof a.ui.editorAutoSave==`boolean`?a.ui.editorAutoSave:F.editorAutoSave,mindmapDirs:o,mindmapDir:i,headerToolsHidden:Array.isArray(a.ui.headerToolsHidden)?a.ui.headerToolsHidden.filter(e=>typeof e==`string`):[],pickerGlobalSearch:typeof a.ui.pickerGlobalSearch==`boolean`?a.ui.pickerGlobalSearch:F.pickerGlobalSearch}}return ee(),L.value=!0,y.value=!0,console.log(u(`@D50BB:配置信息加载完成`)),V.value}catch(e){return console.error(`加载配置失败:`,e),n.error(`${u(`@D50BB:加载配置失败: `)}${e.message}`),b.value=e.message,null}finally{v.value=!1}}async function W(){try{await fetch(`/api/config/save-commit-settings`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({isStandardCommit:T.value,skipHooks:E.value,autoQuickPushOnEnter:D.value,autoSetDefaultMessage:w.value,autoClosePushModal:C.value,pullBeforePush:O.value})})}catch(e){console.error(`保存提交设置失败:`,e)}}e([T,E,D,w,C,O],()=>{y.value&&W()});let G=null,K={};async function q(){if(G&&=(clearTimeout(G),null),Object.keys(K).length===0)return;let e=K;K={};try{await fetch(`/api/config/save-ui-settings`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)})}catch(e){console.error(`保存 UI 设置失败:`,e)}}async function J(e,t={}){if(L.value){if(t.immediate){Object.assign(K,e),await q();return}Object.assign(K,e),G&&clearTimeout(G),G=setTimeout(()=>{q()},300)}}async function Y(){I.value.layout={...F.layout};let e=S.value;return e&&(I.value.layoutsByProject={...I.value.layoutsByProject,[e]:{...I.value.layout}}),await J({layoutsByProject:I.value.layoutsByProject},{immediate:!0}),I.value.layout}async function X(e){let t=S.value;t&&(I.value.aiDiffSummaryByProject={...I.value.aiDiffSummaryByProject,[t]:e},await J({aiDiffSummaryByProject:{[t]:e}},{immediate:!0}))}e(()=>I.value.fileListViewMode,e=>{L.value&&J({fileListViewMode:e})}),e(()=>I.value.fileDiffSplitPercent,e=>{L.value&&J({fileDiffSplitPercent:e})}),e(()=>I.value.diffPreviewSplitPercent,e=>{L.value&&e!=null&&J({diffPreviewSplitPercent:e})}),e(()=>I.value.editorAutoSave,e=>{L.value&&J({editorAutoSave:e})}),e(()=>I.value.headerToolsHidden,e=>{L.value&&Array.isArray(e)&&J({headerToolsHidden:e})}),e(()=>I.value.mindmapDirs,e=>{L.value&&Array.isArray(e)&&J({mindmapDirs:e})}),e(()=>I.value.pickerGlobalSearch,e=>{L.value&&J({pickerGlobalSearch:e})}),e(()=>I.value.layout,e=>{if(!L.value)return;let t=S.value;t&&(I.value.layoutsByProject={...I.value.layoutsByProject,[t]:e},J({layoutsByProject:I.value.layoutsByProject}))},{deep:!0}),e(()=>I.value.commandConsole,e=>{L.value&&J({commandConsole:e})},{deep:!0}),typeof window<`u`&&window.addEventListener(`beforeunload`,()=>{q()});async function re(e){try{let r=await(await fetch(`/api/config/saveDefaultMessage`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({defaultCommitMessage:e})})).json();return r.success?(t.value=e,n.success(u(`@D50BB:默认提交信息已保存`)),!0):(n.error(`${u(`@D50BB:保存失败: `)}${r.error}`),!1)}catch(e){return n.error(`${u(`@D50BB:保存失败: `)}${e.message}`),!1}}async function ie(e){try{let t=await(await fetch(`/api/config/save-after-quick-push-action`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({afterQuickPushAction:{enabled:!!e?.enabled,type:e?.type===`workflow`?`workflow`:`command`,refId:String(e?.refId||``).trim()}})})).json();return t.success?(_.value={enabled:!!e?.enabled,type:e?.type===`workflow`?`workflow`:`command`,refId:String(e?.refId||``).trim()},!0):(n.error(`保存提交后启动项失败: ${t.error}`),!1)}catch(e){return n.error(`保存提交后启动项失败: ${e.message}`),!1}}async function ae(e,t){try{let a=await(await fetch(`/api/config/save-template`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({template:e,type:t})})).json();return a.success?(t===`description`?r.value.includes(e)||r.value.push(e):t===`scope`?i.value.includes(e)||i.value.push(e):t===`message`?s.value.includes(e)||s.value.push(e):t===`command`&&(c.value.includes(e)||c.value.push(e)),n.success(u(`@D50BB:模板已保存`)),!0):(n.error(`${u(`@D50BB:保存模板失败: `)}${a.error}`),!1)}catch(e){return n.error(`${u(`@D50BB:保存模板失败: `)}${e.message}`),!1}}async function oe(e,t){try{let a=await(await fetch(`/api/config/delete-template`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({template:e,type:t})})).json();return a.success?(t===`description`?r.value=r.value.filter(t=>t!==e):t===`scope`?i.value=i.value.filter(t=>t!==e):t===`message`?s.value=s.value.filter(t=>t!==e):t===`command`&&(c.value=c.value.filter(t=>t!==e)),n.success(u(`@D50BB:模板已删除`)),!0):(n.error(`${u(`@D50BB:删除模板失败: `)}${a.error}`),!1)}catch(e){return n.error(`${u(`@D50BB:删除模板失败: `)}${e.message}`),!1}}async function se(e,t,a){try{let o=await(await fetch(`/api/config/update-template`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({oldTemplate:e,newTemplate:t,type:a})})).json();if(o.success){if(a===`description`){let n=r.value.indexOf(e);n!==-1&&(r.value[n]=t)}else if(a===`scope`){let n=i.value.indexOf(e);n!==-1&&(i.value[n]=t)}else if(a===`message`){let n=s.value.indexOf(e);n!==-1&&(s.value[n]=t)}else if(a===`command`){let n=c.value.indexOf(e);n!==-1&&(c.value[n]=t)}return n.success(u(`@D50BB:模板已更新`)),!0}return n.error(`${u(`@D50BB:更新模板失败: `)}${o.error}`),!1}catch(e){return n.error(`${u(`@D50BB:更新模板失败: `)}${e.message}`),!1}}async function ce(e,t){try{let a=await(await fetch(`/api/config/pin-template`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({template:e,type:t})})).json();return a.success?(t===`description`?(r.value=r.value.filter(t=>t!==e),r.value.unshift(e)):t===`scope`?(i.value=i.value.filter(t=>t!==e),i.value.unshift(e)):t===`message`?(s.value=s.value.filter(t=>t!==e),s.value.unshift(e)):t===`command`&&(c.value=c.value.filter(t=>t!==e),c.value.unshift(e)),n.success(u(`@D50BB:模板已置顶`)),!0):(n.error(`${u(`@D50BB:置顶模板失败: `)}${a.error}`),!1)}catch(e){return n.error(`${u(`@D50BB:置顶模板失败: `)}${e.message}`),!1}}async function Z(){try{let e=await(await fetch(`/api/locked-files`)).json();return e.success?(d.value=e.lockedFiles||[],e.lockedFiles):(n.error(`${u(`@D50BB:加载锁定文件列表失败: `)}${e.error}`),[])}catch(e){return console.error(`加载锁定文件列表失败:`,e),n.error(`${u(`@D50BB:加载锁定文件列表失败: `)}${e.message}`),[]}}async function le(e){try{let t=await(await fetch(`/api/lock-file`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({filePath:e})})).json();return t.success?(await Z(),n.success(`${u(`@D50BB:文件已锁定: `)}${e}`),!0):(n.error(`${u(`@D50BB:锁定文件失败: `)}${t.error}`),!1)}catch(e){return console.error(`锁定文件失败:`,e),n.error(`${u(`@D50BB:锁定文件失败: `)}${e.message}`),!1}}async function ue(e){try{let t=await(await fetch(`/api/unlock-file`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({filePath:e})})).json();return t.success?(await Z(),n.success(`${u(`@D50BB:文件已解锁: `)}${e}`),!0):(n.error(`${u(`@D50BB:解锁文件失败: `)}${t.error}`),!1)}catch(e){return console.error(`解锁文件失败:`,e),n.error(`${u(`@D50BB:解锁文件失败: `)}${e.message}`),!1}}async function de(e){try{let t=await(await fetch(`/api/check-file-lock`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({filePath:e})})).json();return t.success?t.isLocked:(console.error(`检查文件锁定状态失败:`,t.error),!1)}catch(e){return console.error(`检查文件锁定状态失败:`,e),!1}}async function fe(e){try{let t=await(await fetch(`/api/config/save-custom-command`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({command:e})})).json();return t.success?(await U(!0),n.success(u(`@CMD01:命令已保存`)),!0):(n.error(`${u(`@CMD01:保存命令失败: `)}${t.error}`),!1)}catch(e){return n.error(`${u(`@CMD01:保存命令失败: `)}${e.message}`),!1}}async function Q(e){try{let t=await(await fetch(`/api/config/delete-custom-command`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({id:e})})).json();return t.success?(await U(!0),n.success(u(`@CMD01:命令已删除`)),!0):(n.error(`${u(`@CMD01:删除命令失败: `)}${t.error}`),!1)}catch(e){return n.error(`${u(`@CMD01:删除命令失败: `)}${e.message}`),!1}}async function pe(e,t){try{let r=await(await fetch(`/api/config/update-custom-command`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({id:e,command:t})})).json();return r.success?(await U(!0),n.success(u(`@CMD01:命令已更新`)),!0):(n.error(`${u(`@CMD01:更新命令失败: `)}${r.error}`),!1)}catch(e){return n.error(`${u(`@CMD01:更新命令失败: `)}${e.message}`),!1}}async function me(e){try{let t=await(await fetch(`/api/config/pin-custom-command`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({id:e})})).json();return t.success?(await U(!0),!0):(n.error(t.error),!1)}catch(e){return n.error(e.message),!1}}async function he(e){try{let t=await(await fetch(`/api/config/save-orchestration`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({orchestration:e})})).json();return t.success?(await U(!0),n.success(u(`@ORCH:编排已保存`)),t.orchestration||null):(n.error(`${u(`@ORCH:保存编排失败: `)}${t.error}`),null)}catch(e){return n.error(`${u(`@ORCH:保存编排失败: `)}${e.message}`),null}}async function ge(e){try{let t=await(await fetch(`/api/config/delete-orchestration`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({id:e})})).json();return t.success?(await U(!0),n.success(u(`@ORCH:编排已删除`)),!0):(n.error(`${u(`@ORCH:删除编排失败: `)}${t.error}`),!1)}catch(e){return n.error(`${u(`@ORCH:删除编排失败: `)}${e.message}`),!1}}async function _e(e,t){try{let r=await(await fetch(`/api/config/update-orchestration`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({id:e,orchestration:t})})).json();return r.success?(await U(!0),n.success(u(`@ORCH:编排已更新`)),!0):(n.error(`${u(`@ORCH:更新编排失败: `)}${r.error}`),!1)}catch(e){return n.error(`${u(`@ORCH:更新编排失败: `)}${e.message}`),!1}}async function ve(e,t){try{let r=await(await fetch(`/api/config/save-startup-items`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({startupItems:e,startupAutoRun:t===void 0?g.value:t})})).json();return r.success?(h.value=e,t!==void 0&&(g.value=t),!0):(n.error(`保存启动项失败: ${r.error}`),!1)}catch(e){return n.error(`保存启动项失败: ${e.message}`),!1}}async function ye(e){try{let t=await(await fetch(`/api/config/save-ai-settings`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({aiMaxToolIterations:e.aiMaxToolIterations})})).json();return t.success?(M.value=Number(t.aiMaxToolIterations)||e.aiMaxToolIterations,!0):(n.error(`${u(`@D50BB:保存 AI 设置失败: `)}${t.error}`),!1)}catch(e){return n.error(`${u(`@D50BB:保存 AI 设置失败: `)}${e.message}`),!1}}async function be(e){try{let t=await(await fetch(`/api/config/save-models`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({models:e})})).json();return t.success?(j.value=e,!0):(n.error(`${u(`@D50BB:保存模型失败: `)}${t.error}`),!1)}catch(e){return n.error(`${u(`@D50BB:保存模型失败: `)}${e.message}`),!1}}async function $(e){try{let t=await(await fetch(`/api/config/save-general-settings`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)})).json();if(t.success){if(e.theme&&(k.value=e.theme,B(e.theme)),e.locale){A.value=e.locale,l(e.locale);let t=m();t.currentLocale=e.locale}return(e.taskExecutor===`claude`||e.taskExecutor===`opencode`)&&(N.value=e.taskExecutor),typeof e.notifyOnTaskDone==`boolean`&&(P.value=e.notifyOnTaskDone),!0}return n.error(`保存通用设置失败: ${t.error}`),!1}catch(e){return n.error(`保存通用设置失败: ${e.message}`),!1}}return{models:j,aiMaxToolIterations:M,taskExecutor:N,notifyOnTaskDone:P,defaultCommitMessage:t,descriptionTemplates:r,scopeTemplates:i,messageTemplates:s,commandTemplates:c,lockedFiles:d,customCommands:f,orchestrations:p,startupItems:h,startupAutoRun:g,afterQuickPushAction:_,isLoading:v,isLoaded:y,configLoadError:b,configFilePath:x,hasConfigLoadError:ne,currentDirectory:S,config:V,autoClosePushModal:C,autoSetDefaultMessage:w,isStandardCommit:T,skipHooks:E,autoQuickPushOnEnter:D,pullBeforePush:O,theme:k,locale:A,ui:I,isUiLoaded:L,aiDiffSummaryEnabled:z,loadConfig:U,setCurrentDirectory:R,openSystemConfigFile:H,saveTemplate:ae,saveModels:be,saveAiSettings:ye,saveGeneralSettings:$,saveUiSettings:J,setAiDiffSummaryEnabled:X,resetUiLayout:Y,applyTheme:B,toggleTheme:te,saveDefaultMessage:re,deleteTemplate:oe,updateTemplate:se,pinTemplate:ce,loadLockedFiles:Z,lockFile:le,unlockFile:ue,isFileLocked:de,saveCustomCommand:fe,deleteCustomCommand:Q,updateCustomCommand:pe,pinCustomCommand:me,saveOrchestration:he,deleteOrchestration:ge,updateOrchestration:_e,saveStartupItems:ve,saveAfterQuickPushAction:ie,saveCommitSettings:W}});export{m as n,h as t};
|