zen-gitsync 2.17.14 → 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 +211 -185
- package/package.json +2 -2
- package/scripts/release.js +33 -16
- package/src/cli/ai/agent.js +24 -2
- package/src/cli/ai/runtime.test.js +1 -1
- package/src/cli/ai/tools.js +69 -14
- package/src/cli/ai/tools.test.js +46 -1
- package/src/config.js +8 -4
- package/src/gitCommit.js +18 -1
- 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-oON3sAj4.js +2 -0
- package/src/ui/public/assets/{BranchSelector-XIN87Mkw.js → BranchSelector-Cpj7eGqY.js} +1 -1
- package/src/ui/public/assets/CommitForm-D_ovYhVw.js +6 -0
- package/src/ui/public/assets/{CommonDialog-BiNTGpA-.js → CommonDialog-ChZbqfRF.js} +1 -1
- package/src/ui/public/assets/EditorView-BPzpI0GV.js +1 -0
- package/src/ui/public/assets/FileDiffViewer-B_qEKA9L.js +15 -0
- package/src/ui/public/assets/{FlowExecutionViewer-D9Vzgh91.js → FlowExecutionViewer-Drw4hlJG.js} +1 -1
- package/src/ui/public/assets/FlowOrchestrationWorkspace-C7yTD1gj.js +21 -0
- package/src/ui/public/assets/{IconButton-DysyaC1j.js → IconButton-DEARmMkZ.js} +1 -1
- package/src/ui/public/assets/{LogList-QDgok-UJ.js → LogList-BA_gowxE.js} +5 -5
- package/src/ui/public/assets/MindmapView-8X6z245q.css +1 -0
- package/src/ui/public/assets/MindmapView-K-XcLLXr.js +2 -0
- package/src/ui/public/assets/MonitorView-C0RL5K9W.js +1 -0
- package/src/ui/public/assets/ProjectStartupButton-DC36_vvU.js +1 -0
- package/src/ui/public/assets/RemoteManagerDialog-Bkqja660.js +4 -0
- package/src/ui/public/assets/{RemoteRepoCard-Bn9cKt1D.js → RemoteRepoCard-Bsm7cj_H.js} +2 -2
- package/src/ui/public/assets/SourceMapView-Y5NKdIk6.js +3 -0
- package/src/ui/public/assets/{SvgIcon-CvtoU5yo.js → SvgIcon-D_mFHXP4.js} +1 -1
- package/src/ui/public/assets/{TemplateManager-saqC9kdQ.js → TemplateManager-BzKVXZhy.js} +1 -1
- package/src/ui/public/assets/UserInputNode-BPLK4aYx.js +1 -0
- package/src/ui/public/assets/WorkbenchView-xbGdiVMQ.js +56 -0
- package/src/ui/public/assets/_plugin-vue_export-helper-dg2VUnSQ.js +19 -0
- package/src/ui/public/assets/configStore-DtjAc3w9.js +1 -0
- package/src/ui/public/assets/{css.worker-DFdt6_zu.js → css.worker-BDCmgL4U.js} +9 -9
- package/src/ui/public/assets/editor.worker-GCPm6rMv.js +26 -0
- package/src/ui/public/assets/{element-plus-Dc1iTOWq.css → element-plus-Cwwq-Gje.css} +1 -1
- package/src/ui/public/assets/element-plus-DxBPQwL7.js +48 -0
- package/src/ui/public/assets/{flow-mindmap-CHxAWdLw.js → flow-mindmap-BqFb1WO5.js} +1 -1
- package/src/ui/public/assets/{gitStore-BgC8OY0k.js → gitStore-BZo9_zyy.js} +5 -5
- package/src/ui/public/assets/{html.worker-JUzsMP-j.js → html.worker-DG8hnSJR.js} +8 -8
- package/src/ui/public/assets/index-CHuCYLWm.js +111 -0
- package/src/ui/public/assets/index-CmbatbSR.css +1 -0
- package/src/ui/public/assets/json.worker-CxwlJRnL.js +58 -0
- package/src/ui/public/assets/{monaco-DkJuNcCr.js → monaco-BScz9v63.js} +6 -6
- package/src/ui/public/assets/{office-docx-CmBY5bpF.js → office-docx-CZXLkCf5.js} +1 -1
- package/src/ui/public/assets/{office-excel-BEhsBUNX.js → office-excel-CBKszjVA.js} +1 -1
- package/src/ui/public/assets/{office-pptx-DWfi413x.js → office-pptx-NeUSnN3k.js} +3 -3
- package/src/ui/public/assets/previewSandbox-BTTTXooN.js +0 -0
- package/src/ui/public/assets/{ts.worker-CmEKzkmF.js → ts.worker-DgFMIcEs.js} +49 -49
- package/src/ui/public/assets/{useThemeObserver-DhCU3SIo.js → useThemeObserver-E7Hk50l3.js} +1 -1
- package/src/ui/public/assets/vendor-DnB9EJa3.css +1 -0
- package/src/ui/public/assets/{vendor-CZnXb2r9.js → vendor-bdHhLiED.js} +28 -28
- package/src/ui/public/assets/{vue-flow-7_n4vJqi.js → vue-flow-fLUQ0_kE.js} +1 -1
- package/src/ui/public/index.html +19 -19
- package/src/ui/server/index.js +4 -0
- package/src/ui/server/routes/explorerContextMenu.js +208 -0
- package/src/ui/server/routes/explorerContextMenu.test.js +180 -0
- package/src/ui/server/routes/workbench/agentChat.js +14 -3
- 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-DLHlVWRg.js +0 -5
- package/src/ui/public/assets/AppVersionBadge-JxpMuGwP.js +0 -2
- package/src/ui/public/assets/CommitForm-CW53Er5m.js +0 -6
- package/src/ui/public/assets/EditorView-D0JoJhgt.js +0 -1
- package/src/ui/public/assets/FileDiffViewer-Yas2nO2U.js +0 -15
- package/src/ui/public/assets/FlowOrchestrationWorkspace-DQ3fg5b9.js +0 -21
- package/src/ui/public/assets/MindmapView-BQTqx842.css +0 -1
- package/src/ui/public/assets/MindmapView-CeZsQNBK.js +0 -2
- package/src/ui/public/assets/MonitorView-D1tgmjjS.js +0 -1
- package/src/ui/public/assets/ProjectStartupButton-COntA4q1.js +0 -1
- package/src/ui/public/assets/RemoteManagerDialog-3dihAOab.js +0 -4
- package/src/ui/public/assets/SourceMapView-C8UdzQXF.js +0 -3
- package/src/ui/public/assets/UserInputNode-CvEfvX3i.js +0 -1
- package/src/ui/public/assets/WorkbenchView-B7WAu1Ay.js +0 -56
- package/src/ui/public/assets/_plugin-vue_export-helper-BdTxl34g.js +0 -19
- package/src/ui/public/assets/configStore-AQMSazCM.js +0 -1
- package/src/ui/public/assets/editor.worker-O-CH8JUO.js +0 -26
- package/src/ui/public/assets/element-plus-CMSkP_w2.js +0 -48
- package/src/ui/public/assets/index-Dpx9Bcqn.css +0 -1
- package/src/ui/public/assets/index-qAmzFO10.js +0 -104
- package/src/ui/public/assets/json.worker-B4dEhy0e.js +0 -58
- package/src/ui/public/assets/previewSandbox-CyuMMYaq.js +0 -0
- package/src/ui/public/assets/vendor-4ojsjDYc.css +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 N,j as P,kt as F,mt as I,o as L,ot as ne,pt as re,qr 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-CMSkP_w2.js";import{i as oe,n as G,t as K}from"./vendor-CZnXb2r9.js";import{n as q,t as J}from"./_plugin-vue_export-helper-BdTxl34g.js";import{t as Y}from"./configStore-AQMSazCM.js";A();var X=65536;function Z(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:$(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 a=``;typeof i.content==`string`&&(a=i.content),a.length>X&&(a=`…(前文已截断)\n${a.slice(-65536)}`);let o=[];if(i.tool_calls&&i.tool_calls.length>0)for(let e of i.tool_calls)o.push({id:e.id||e.function?.name||K(),name:e.function?.name||``,arguments:e.function?.arguments||``,argsPreview:Q(e.function?.name||``,e.function?.arguments||``),status:`done`,result:``});let s=r+1;for(;s<n&&e.messages[s].role===`tool`;){let t=e.messages[s],n=t.tool_call_id||t.name||``,i=o.find(e=>e.id===n);if(i){let e=t.content;typeof e!=`string`&&(e=`(non-text result)`),e.length>X&&(e=`…(前文已截断)\n${e.slice(-65536)}`),i.result=e}r=s,s++}let c=!!a,l=o.length>0;(c||l)&&t.push({id:`msg-${r}`,role:`assistant`,content:a||``,toolCalls:l?o:void 0,status:`done`,createdAt:Date.now()})}}}return t}function Q(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 se(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 $(e){let t=/^data:([^;,]+)/.exec(e);return t?t[1]:``}function ce(){let e=Y(),t=U([]),n=U(!1),r=U(null),i=U([]),a=U(!1),o=U(!1),s=U(null),c=U(!1),l=null,u=0,d=0;async function f(){let r=++d,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!==d)return;if(!n.success){T.error(n.error||q(`@AGENT:加载会话列表失败`));return}t.value=Array.isArray(n.sessions)?n.sessions:[]}catch(e){if(r!==d)return;T.error(q(`@AGENT:加载会话列表失败`)+`: `+(e?.message||e))}finally{r===d&&(n.value=!1)}}function p(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,source:`web`,cwd:e.currentDirectory||``,model:``,createdAt:i,updatedAt:i,messageCount:1,size:0,isGenerating:!0},...t.value]}function m(e){let n=t.value.find(t=>t.sessionId===e);n&&(n.isGenerating=!1)}async function h(e){o.value=!0,r.value=e;try{let t=await fetch(`/api/agent/sessions/${encodeURIComponent(e)}`).then(e=>e.json());if(!t.success){T.error(t.error||q(`@AGENT:加载会话失败`));return}i.value=Z(t.session)}catch(e){T.error(q(`@AGENT:加载会话失败`)+`: `+(e?.message||e))}finally{o.value=!1}}async function g(e){try{await M.confirm(q(`@AGENT:确认删除该会话`),q(`@AGENT:删除后无法恢复`),{type:`warning`})}catch{return}try{let n=await fetch(`/api/agent/sessions/${encodeURIComponent(e)}`,{method:`DELETE`}).then(e=>e.json());if(!n.success){T.error(n.error||q(`@AGENT:删除失败`));return}t.value=t.value.filter(t=>t.sessionId!==e),r.value===e&&(r.value=null,i.value=[]),T.success(q(`@AGENT:已删除`))}catch(e){T.error(q(`@AGENT:删除失败`)+`: `+(e?.message||e))}}async function _(e,n){try{let r=await fetch(`/api/agent/sessions/${encodeURIComponent(e)}`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({title:n})}).then(e=>e.json());if(!r.success){T.error(r.error||q(`@AGENT:重命名失败`));return}let i=t.value.find(t=>t.sessionId===e);i&&(i.title=n),T.success(q(`@AGENT:已重命名`))}catch(e){T.error(q(`@AGENT:重命名失败`)+`: `+(e?.message||e))}}function v(){r.value=null,i.value=[],s.value=null,t.value=t.value.filter(e=>!e.isGenerating)}async function y(t,n=[]){let o=n.filter(e=>e?.file?.type?.startsWith(`image/`));if(o.length<n.length&&T.warning(q(`@AGENT:仅支持发送图片,非图片文件已忽略`)),!t.trim()&&o.length===0||a.value)return;let d=(await Promise.allSettled(o.map(e=>se(e.file)))).map(e=>e.status===`fulfilled`?e.value:``).filter(e=>e.startsWith(`data:image/`)),h=++u;l=new AbortController;let g=l,_={id:K(),role:`user`,content:t,status:`done`,createdAt:Date.now()};o.length>0&&(_.attachments=o.map(e=>({id:e.id,name:e.file.name||`image`,size:e.file.size||0,type:e.file.type||``,preview:e.preview}))),i.value.push(_);let v=w({id:K(),role:`assistant`,content:``,status:`pending`,createdAt:Date.now()});i.value.push(v),a.value=!0;let y=[],b=null;try{let n=await fetch(`/api/agent/chat`,{method:`POST`,headers:{"Content-Type":`application/json`,Accept:`text/event-stream`},body:JSON.stringify({sessionId:r.value||``,userMessage:t,cwd:e.currentDirectory||``,...d.length>0?{images:d}:{}}),signal:g.signal});if(h!==u)return;if(!n.ok||!n.body){let e=await n.text().catch(()=>``);throw Error(e||`HTTP ${n.status}`)}let a=n.body.getReader(),o=new TextDecoder(`utf-8`),c=``,l=r.value;for(;;){let{value:e,done:n}=await a.read();if(h!==u)return;if(n)break;c+=o.decode(e,{stream:!0});let d=c.split(`
|
|
2
|
-
`);c=d.pop()??``;for(let e of d){let n=e.trim();if(!n.startsWith(`data:`))continue;let i=n.slice(5).trim();if(!i)continue;let a;try{a=JSON.parse(i)}catch{continue}switch(a.type){case`meta`:if(a.sessionId){l=a.sessionId,b=a.sessionId,r.value=a.sessionId;let e=String(a.title||``).trim()||t.trim().split(`
|
|
3
|
-
`)[0].trim().slice(0,40)||q(`@AGENT:无标题`);p(a.sessionId,e)}break;case`thinking`:v.reasoning||(v.reasoning=``,v.reasoningStatus=`streaming`),v.reasoning+=String(a.delta||``),v.status=`streaming`;break;case`content`:v.status===`pending`&&(v.status=`streaming`);{let e=String(a.delta||``);v.content+=e;let t=G(v.content);t.reasoning&&(v.reasoning||(v.reasoning=``,v.reasoningStatus=`streaming`),v.reasoning=t.reasoning,v.content=t.content)}break;case`tool_call_start`:{let e=w({id:a.toolCallId||K(),name:a.name||``,argsPreview:a.argsPreview||``,arguments:a.argsPreview||``,status:`running`,result:``});y.push(e),v.toolCalls||=[],v.toolCalls.push(e),v.status===`pending`&&(v.status=`streaming`);break}case`tool_result`:{let e=y.find(e=>e.id===a.toolCallId);e&&(e.result=String(a.result||``),e.status=`done`,e.name===`ask_user`&&(s.value=null));break}case`ask_user`:s.value={interactionId:String(a.interactionId||``),question:String(a.question||``),options:Array.isArray(a.options)?a.options.map(e=>String(e)):[],allowFreeText:a.allowFreeText!==!1};break;case`done`:{let e=a.content||v.content,t=G(e);t.reasoning&&!v.reasoning&&(v.reasoning=t.reasoning),v.content=t.content,v.status=`done`,v.reasoningStatus===`streaming`&&(v.reasoningStatus=`done`);break}case`error`:v.status=`error`,v.error=String(a.error||q(`@AGENT:未知错误`)),v.reasoningStatus===`streaming`&&(v.reasoningStatus=`done`)}}i.value=[...i.value]}if(h!==u)return;v.status===`pending`&&(v.status=`done`),l&&l!==r.value&&(r.value=l),f().catch(()=>{})}catch(e){if(h!==u)return;e?.name===`AbortError`||g.signal.aborted?(v.content=(v.content||``)+`
|
|
4
|
-
|
|
5
|
-
[`+q(`@AGENT:已停止`)+`]`,v.status=`done`,v.reasoningStatus===`streaming`&&(v.reasoningStatus=`done`)):(v.status=`error`,v.error=e?.message||String(e),T.error(v.error||q(`@AGENT:对话失败`)))}finally{h===u&&(a.value=!1,s.value=null,c.value=!1,l=null,b&&m(b))}}async function b(e){let t=s.value,n=r.value,i=String(e||``).trim();if(!t||!n||!i||c.value)return!1;c.value=!0;try{let e=await fetch(`/api/agent/respond`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sessionId:n,interactionId:t.interactionId,answer:i})}).then(e=>e.json());if(!e.success)throw Error(e.error||q(`@AGENT:回答提交失败`));return s.value=null,!0}catch(e){return T.error(e?.message||q(`@AGENT:回答提交失败`)),!1}finally{c.value=!1}}function x(){l&&=(l.abort(),null)}return{sessions:t,sessionsLoading:n,currentSessionId:r,messages:i,isStreaming:a,sessionLoading:o,pendingQuestion:s,answeringQuestion:c,loadSessions:f,loadSession:h,deleteSession:g,renameSession:_,newSession:v,sendMessage:y,answerQuestion:b,stop:x}}W(),A();var le=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||[]):T.error(t?.error||q(`@MKT:加载失败`))}catch{T.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 D(e){return f.value.has(C(e))}let O=V(()=>{let e={project:[],global:[]};for(let t of a.value)(e[t.target]||=[]).push(t);return e}),k=w({visible:!1,item:null,env:{},args:``});function A(e){return n.type===`mcp`&&(!!e.envKeys?.length||!!e.args?.length)}function j(e){k.item=e,k.env=Object.fromEntries((e.envKeys||[]).map(e=>[e,``])),k.args=(e.args||[]).join(` `),k.visible=!0}function P(){let e=k.item;if(k.visible=!1,!e)return;let t=Object.fromEntries(Object.entries(k.env).filter(([,e])=>e.trim()!==``)),n=k.args.trim()?k.args.trim().match(/(?:[^\s"]+|"[^"]*")+/g)?.map(e=>e.replace(/^"|"$/g,``))??void 0:void 0;I(e,{env:t,...n?{args:n}:{}})}async function F(e){if(!e.installed||await L(e)){if(A(e)){j(e);return}await I(e,{})}}async function I(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){T.error(i?.error||q(`@MKT:安装失败`));return}i.item?.warning&&T.warning(i.item.warning),i.item?.envKeys?.length?T.warning(`${q(`@MKT:还缺环境变量`)}: ${i.item.envKeys.join(`, `)}`):T.success(q(`@MKT:安装成功`)),await _()}catch{T.error(q(`@MKT:安装失败`))}finally{f.value.delete(r)}}async function L(e){try{return await M.confirm(`${e.name} ${q(`@MKT:已安装,要重新安装吗?`)}`,q(`@MKT:重新安装`),{confirmButtonText:q(`@MKT:重装`),cancelButtonText:q(`@MKT:取消`),type:`warning`}),!0}catch{return!1}}async function ne(e){try{await M.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){T.error(i?.error||q(`@MKT:卸载失败`));return}T.success(q(`@MKT:已卸载`)),await _()}catch{T.error(q(`@MKT:卸载失败`))}finally{m.value.delete(t)}}let R={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:D,installedByTarget:O,configDialog:k,needsConfig:A,openConfigDialog:j,confirmConfig:P,onInstall:F,doInstall:I,confirmReinstall:L,onRemove:ne,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 re},get Warning(){return N}};return Object.defineProperty(R,"__isScriptSetup",{enumerable:!1,value:!0}),R}});W(),B(),m();var ue={class:`marketplace-panel`},de={class:`mp-toolbar`},fe={class:`mp-search`},pe=[`placeholder`],me={class:`mp-toolbar-sub`},he={class:`mp-target-hint`},ge={class:`mp-source-filter`},_e=[`onClick`],ve={class:`mp-body`},ye={class:`mp-group-header`},be={class:`mp-group-title`},xe={key:0,class:`mp-group-count`},Se={key:1,class:`mp-group-error`},Ce=[`href`,`title`],we={key:0,class:`mp-grid`},Te={class:`mp-card-head`},Ee=[`title`],De={key:0,class:`mp-card-metric`},Oe=[`title`],ke={class:`mp-card-meta`},Ae=[`title`],je=[`title`],Me={key:2,class:`mp-tag remote`},Ne={class:`mp-card-foot`},Pe=[`href`],Fe={key:1,class:`mp-installed-chip`},Ie=[`disabled`,`onClick`],Le={key:3,class:`mp-not-installable`},Re={key:1,class:`mp-empty`},ze={key:0,class:`mp-group installed`},Be={class:`mp-group-header`},Ve={class:`mp-group-title`},He={class:`mp-group-count`},Ue={key:0,class:`mp-installed-block`},We={class:`mp-installed-target`},Ge={class:`mp-installed-list`},Ke={class:`mp-installed-name`},qe={key:0,class:`mp-meta-pkg`},Je={key:1,class:`mp-tag warn`},Ye=[`disabled`,`onClick`],Xe={key:1,class:`mp-empty all`},Ze={key:0,class:`mkt-form`},Qe={class:`mkt-form-name`},$e=[`onUpdate:modelValue`,`placeholder`],et={key:0,class:`mkt-field`},tt={class:`mkt-hint`};function nt(e,o,c,p,m,h){let _=l,y=n,b=P,x=s,C=i,w=L;return S(),f(`div`,ue,[r(` ── 工具栏 ───────────────────────────────── `),v(`div`,de,[v(`div`,fe,[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,pe),[[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:R([`mp-refresh`,{spinning:p.loading}]),onClick:p.loadCatalog},[d(_,null,{default:z(()=>[d(p.Refresh)]),_:1})],2)]),_:1},8,[`content`])]),v(`div`,me,[v(`span`,he,[u(t(p.$t(`@MKT:安装到`))+` `,1),v(`b`,null,t(p.targetLabel),1)]),v(`div`,ge,[(S(!0),f(D,null,g(p.groups,e=>(S(),f(`button`,{key:e.id,class:R([`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,_e))),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`,ve,[(S(!0),f(D,null,g(p.groups,e=>(S(),f(`section`,{key:e.id,class:`mp-group`},[v(`header`,ye,[v(`h3`,be,t(e.label),1),e.status===`ok`?(S(),f(`span`,xe,t(e.items.length),1)):(S(),f(`span`,Se,[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,Ce)):r(`v-if`,!0)]),e.status===`ok`&&e.items.length?(S(),f(`div`,we,[(S(!0),f(D,null,g(e.items,e=>(S(),f(`article`,{key:p.cardKey(e),class:`mp-card`},[v(`div`,Te,[v(`span`,{class:`mp-card-name`,title:e.name},t(e.name),9,Ee),p.metricText(e)?(S(),f(`span`,De,[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,Oe),v(`div`,ke,[e.package?(S(),f(`code`,{key:0,class:`mp-meta-pkg`,title:e.package},t(e.package),9,Ae)):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,je)):r(`v-if`,!0),e.transport===`remote`?(S(),f(`span`,Me,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`,Ne,[e.upstream?(S(),f(`a`,{key:0,class:`mp-card-link`,href:e.upstream,target:`_blank`,rel:`noopener noreferrer`},t(p.$t(`@MKT:查看来源`)),9,Pe)):r(`v-if`,!0),o[6]||=v(`span`,{class:`mp-foot-spacer`},null,-1),e.installed?(S(),f(`span`,Fe,[d(_,null,{default:z(()=>[d(p.Check)]),_:1}),u(t(p.$t(`@MKT:已安装`)),1)])):e.installable===!1?(S(),f(`span`,Le,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,Ie))])]))),128))])):e.status===`ok`?(S(),f(`div`,Re,t(p.$t(`@MKT:该来源暂无结果`)),1)):r(`v-if`,!0)]))),128)),r(` ── 已安装 ─────────────────────────────── `),p.installed.length?(S(),f(`section`,ze,[v(`header`,Be,[v(`h3`,Ve,t(p.$t(`@MKT:已安装`)),1),v(`span`,He,t(p.installed.length),1)]),(S(),f(D,null,g([`project`,`global`],e=>v(`div`,{key:e},[p.installedByTarget[e]?.length?(S(),f(`div`,Ue,[v(`div`,We,t(e===`project`?p.$t(`@MKT:当前项目`):p.$t(`@MKT:g ai 智能体`)),1),v(`div`,Ge,[(S(!0),f(D,null,g(p.installedByTarget[e],n=>(S(),f(`div`,{key:e+n.id,class:`mp-installed-row`},[v(`span`,Ke,t(n.name),1),n.package?(S(),f(`code`,qe,t(n.package),1)):r(`v-if`,!0),n.requiredEnv?.length?(S(),f(`span`,Je,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,Ye)]))),128))])])):r(`v-if`,!0)])),64))])):r(`v-if`,!0),!p.loading&&!p.groups.length?(S(),f(`div`,Xe,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`,Ze,[v(`p`,Qe,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,$e),[[j,p.configDialog.env[e]]])]))),128)),p.configDialog.item.args?.length?(S(),f(`div`,et,[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`,tt,t(p.$t(`@MKT:参数提示`)),1)])):r(`v-if`,!0)])):r(`v-if`,!0)]),_:1},8,[`modelValue`,`title`])])}var rt=J(le,[[`render`,nt],[`__scopeId`,`data-v-e9f9e851`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/components/MarketplacePanel.vue`]]);W(),A();var it=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:ne}]),{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:D,answeringQuestion:O,answerQuestion:k,stop:A}=ce(),j=V(()=>{let e=r.theme;return e===`dark`||e===`auto`&&window.matchMedia(`(prefers-color-scheme: dark)`).matches?`dark`:`light`}),N=U(``),P=V(()=>{if(!N.value.trim())return c.value;let e=N.value.toLowerCase();return c.value.filter(t=>(t.title||``).toLowerCase().includes(e)||(t.model||``).toLowerCase().includes(e))}),L=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 re(e){await w(e.text,e.files),await y(),H()}async function R(e){await w(e.prompt),await y(),H()}let z=U(``);async function ie(e=z.value){await k(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){if(p.value){T.warning(q(`@AGENT:请先停止当前生成`));return}v(e)}function G(){if(p.value){T.warning(q(`@AGENT:请先停止当前生成`));return}C()}function K(e,t){if(t.stopPropagation(),p.value&&d.value===e){T.warning(q(`@AGENT:请先停止当前生成`));return}b(e)}async function J(e,t,n){n.stopPropagation();try{let{value:n}=await M.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:D,answeringQuestion:O,answerQuestion:k,stop:A,chatTheme:j,searchQuery:N,filteredSessions:P,presetQuestions:L,onSend:re,onSelectPreset:R,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 I},get ChatLineRound(){return e},get Loading(){return F},get Check(){return te},get ChatContainer(){return oe},MarketplacePanel:rt};return Object.defineProperty($,"__isScriptSetup",{enumerable:!1,value:!0}),$}});W(),m(),B();var at={class:`agent-view`},ot={class:`sidebar-header`},st={class:`sidebar-search`},ct=[`placeholder`],lt={class:`session-list`},ut={key:0,class:`empty-state`},dt={class:`empty-text`},ft={key:0,class:`empty-hint`},pt=[`onClick`],mt={class:`session-item-main`},ht={class:`session-item-title`},gt={class:`session-item-meta`},_t={key:0,class:`meta-generating`},vt={class:`meta-time`},yt={class:`meta-count`},bt={key:2,class:`meta-source cli`},xt=[`onClick`],St=[`onClick`],Ct={class:`agent-chat-area`},wt={class:`agent-tabs`,role:`tablist`},Tt=[`aria-selected`,`onClick`],Et={class:`agent-tab-body`},Dt={key:0,class:`agent-chat-pane`},Ot={key:0,class:`chat-loading`},kt={key:0,class:`ask-user-panel`,"aria-live":`polite`},At={class:`ask-user-title`},jt={class:`ask-user-question`},Mt={key:0,class:`ask-user-options`},Nt=[`disabled`,`onClick`],Pt=[`disabled`,`placeholder`,`aria-label`],Ft=[`disabled`],It={key:0,class:`stop-button-bar`};function Lt(e,n,i,o,s,c){let l=L;return S(),f(`div`,at,[r(` ═══ 左侧:会话列表(只在「对话」Tab 显示)═══ `),o.activeTab===`chat`?(S(),f(D,{key:0},[v(`aside`,{class:`agent-sidebar`,style:C({width:o.sidebarWidth+`px`})},[r(` 顶部操作栏 `),v(`div`,ot,[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`,st,[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,ct),[[j,o.searchQuery]])]),r(` 会话列表 `),k((S(),f(`div`,lt,[o.filteredSessions.length===0&&!o.sessionsLoading?(S(),f(`div`,ut,[d(o.ElIcon,{size:28,color:`var(--text-tertiary)`},{default:z(()=>[d(o.ChatLineRound)]),_:1}),v(`div`,dt,t(o.searchQuery?o.$t(`@AGENT:未找到匹配的会话`):o.$t(`@AGENT:暂无会话`)),1),o.searchQuery?r(`v-if`,!0):(S(),f(`div`,ft,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:R([`session-item`,{active:o.currentSessionId===e.sessionId}]),onClick:t=>o.selectSession(e.sessionId)},[v(`div`,mt,[v(`div`,ht,t(e.title||o.$t(`@AGENT:无标题`)),1),v(`div`,gt,[e.isGenerating?(S(),f(`span`,_t,[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`,vt,t(o.formatDate(e.updatedAt)),1),n[5]||=v(`span`,{class:`meta-dot`},`·`,-1),v(`span`,yt,t(e.messageCount)+` `+t(o.$t(`@AGENT:条`)),1)],64)),e.source===`cli`?(S(),f(`span`,bt,`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,xt)]),_: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,St)]),_:2},1032,[`content`])])],10,pt))),128))])),[[l,o.sessionsLoading]])],4),r(` 拖拽分隔条 `),v(`div`,{class:R([`sidebar-resizer`,{active:o.isResizing}]),onMousedown:o.startResize},null,34)],64)):r(`v-if`,!0),r(` ═══ 右侧:Tab 栏 + 内容区 ═══ `),v(`main`,Ct,[v(`nav`,wt,[(S(!0),f(D,null,g(o.tabs,e=>(S(),f(`button`,{key:e.id,type:`button`,class:R([`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,Tt))),128))]),v(`div`,Et,[r(` ── 对话 ── `),o.activeTab===`chat`?(S(),f(`div`,Dt,[r(` 加载中 `),o.sessionLoading?(S(),f(`div`,Ot,[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`,kt,[v(`div`,At,[d(o.ElIcon,null,{default:z(()=>[d(o.ChatLineRound)]),_:1}),v(`span`,null,t(o.$t(`@AGENT:等待你的回答`)),1)]),v(`div`,jt,t(o.pendingQuestion.question),1),o.pendingQuestion.options.length?(S(),f(`div`,Mt,[(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,Nt))),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,Pt),[[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,Ft)],32)):r(`v-if`,!0)])):r(`v-if`,!0)]),_:1}),r(` 停止按钮浮层 `),d(O,{name:`fade`},{default:z(()=>[o.isStreaming?(S(),f(`div`,It,[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 Rt=J(it,[[`render`,Lt],[`__scopeId`,`data-v-bd681ddd`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/views/AgentView.vue`]]);export{Rt as default};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import"./rolldown-runtime-C0FnF6B9.js";import{$r as e,Dn as t,E as n,En as r,Fn as i,H as a,Jn as o,K as s,Kn as c,L as l,Mn as u,Nn as d,On as f,Pr as p,Tn as m,Un as h,Xn as g,a as _,ar as v,fr as y,i as b,kt as x,nt as S,qr as C,sr as w,tt as T,wn as E,yr as D,zn as O}from"./element-plus-CMSkP_w2.js";import{n as k,t as A}from"./_plugin-vue_export-helper-BdTxl34g.js";async function j(e,t){let n=e.body.getReader(),r=new TextDecoder(`utf-8`),i=``;for(;;){let{done:e,value:a}=await n.read();if(e)break;i+=r.decode(a,{stream:!0});let o=i.split(`
|
|
2
|
-
`);i=o.pop()??``;for(let e of o)e.trim()&&t(e)}i.trim()&&t(i)}async function M(){let e=await fetch(`/api/app-version`);return e.ok?e.json():{success:!1,current:``,latest:null,hasUpdate:!1,error:`HTTP ${e.status}`}}async function N(e){let t=await fetch(`/api/app-upgrade`,{method:`POST`});if(!t.ok){let n=`HTTP ${t.status}`;try{let e=await t.json();e?.error&&(n=e.error)}catch{}e({type:`error`,message:n}),e({type:`done`,code:t.status});return}if(!t.body){e({type:`error`,message:`响应无 body`}),e({type:`done`,code:-1});return}await j(t,t=>{try{e(JSON.parse(t))}catch{}})}async function P(){let e=await fetch(`/api/app-restart`,{method:`POST`});if(!e.ok){let t=`HTTP ${e.status}`;try{let n=await e.json();n?.error&&(t=n.error)}catch{}throw Error(t)}if(!e.body)throw Error(`响应无 body`);return new Promise((t,n)=>{let r=!1,i=e=>{r||(r=!0,e())};j(e,e=>{try{let r=JSON.parse(e);r.type===`ready`&&typeof r.port==`number`&&r.port>0?i(()=>t(r.port)):r.type===`timeout`?i(()=>n(Error(`restart.timeout`))):r.type===`error`&&i(()=>n(Error(r.message||`restart.failed`)))}catch{}}).then(()=>{i(()=>n(Error(`restart.stream-closed`)))}).catch(()=>{})})}O(),y();var F=`npm install -g zen-gitsync --registry https://registry.npmjs.org/`,I=i({__name:`UpgradeDialog`,props:{modelValue:{type:Boolean,required:!0},logs:{type:String,required:!0},status:{type:String,required:!0},countdown:{type:Number,required:!1,default:0}},emits:[`update:modelValue`,`retry`,`restart`,`cancel`],setup(e,{expose:t,emit:n}){t();let r=e,i=n,a=D(null);v(()=>r.logs,async()=>{await h(),a.value&&(a.value.scrollTop=a.value.scrollHeight)});function o(){r.status!==`running`&&(r.status===`success`&&r.countdown>0&&i(`cancel`),i(`update:modelValue`,!1))}function s(){i(`retry`)}function c(){i(`restart`)}function l(){i(`cancel`),i(`update:modelValue`,!1)}async function u(){try{await navigator.clipboard.writeText(F),_.success(k(`@F13B4:已复制升级命令`))}catch{_.warning(k(`@F13B4:复制失败,请手动复制`))}}let d={MANUAL_COMMAND:F,props:r,emit:i,logEl:a,close:o,onRetry:s,onRestart:c,onLater:l,onCopyCommand:u,get Loading(){return x},get CircleCheck(){return T},get CircleClose(){return S},get $t(){return k}};return Object.defineProperty(d,"__isScriptSetup",{enumerable:!1,value:!0}),d}});O(),p();var L={key:3},R={key:4},z={key:5},B={key:0,class:`upgrade-hint`},V={key:0,class:`upgrade-countdown`},H={key:1,class:`upgrade-manual`},U={class:`upgrade-manual__label`};function W(i,a,o,c,p,h){let _=s,v=l,y=n;return g(),r(y,{"model-value":o.modelValue,"onUpdate:modelValue":a[0]||=e=>c.emit(`update:modelValue`,e),title:c.$t(`@F13B4:升级`),width:`680px`,"close-on-click-modal":!1,"close-on-press-escape":!1,"show-close":o.status!==`running`,"append-to-body":``,onClose:c.close},{footer:w(()=>[o.status===`failed`?(g(),r(v,{key:0,type:`primary`,onClick:c.onRetry},{default:w(()=>[u(e(c.$t(`@F13B4:重试`)),1)]),_:1})):t(`v-if`,!0),o.status===`failed`?(g(),r(v,{key:1,onClick:c.onCopyCommand},{default:w(()=>[u(e(c.$t(`@F13B4:复制升级命令`)),1)]),_:1})):t(`v-if`,!0),o.status===`success`?(g(),r(v,{key:2,type:`primary`,onClick:c.onRestart},{default:w(()=>[u(e(c.$t(`@F13B4:立即重启并刷新`)),1)]),_:1})):t(`v-if`,!0),o.status===`success`?(g(),r(v,{key:3,onClick:c.onLater},{default:w(()=>[u(e(c.$t(`@F13B4:稍后手动重启`)),1)]),_:1})):t(`v-if`,!0),o.status===`running`?(g(),r(v,{key:4,disabled:``},{default:w(()=>[u(e(c.$t(`@F13B4:升级中`))+`... `,1)]),_:1})):t(`v-if`,!0)]),default:w(()=>[m(`div`,{class:C([`upgrade-status`,`is-${o.status}`])},[o.status===`running`?(g(),r(_,{key:0,class:`is-loading`},{default:w(()=>[d(c.Loading)]),_:1})):o.status===`success`?(g(),r(_,{key:1,color:`#67c23a`},{default:w(()=>[d(c.CircleCheck)]),_:1})):(g(),r(_,{key:2,color:`#f56c6c`},{default:w(()=>[d(c.CircleClose)]),_:1})),o.status===`running`?(g(),f(`span`,L,e(c.$t(`@F13B4:升级中`)),1)):o.status===`success`?(g(),f(`span`,R,e(c.$t(`@F13B4:升级完成`)),1)):(g(),f(`span`,z,e(c.$t(`@F13B4:升级失败`)),1))],2),o.status===`success`?(g(),f(`p`,B,[u(e(c.$t(`@F13B4:新版本已全局安装,需要重启服务才能生效`))+` `,1),o.countdown>0?(g(),f(`span`,V,e(c.$t(`@F13B4:{seconds} 秒后自动刷新`,{seconds:o.countdown})),1)):t(`v-if`,!0)])):t(`v-if`,!0),o.status===`failed`?(g(),f(`p`,H,[m(`span`,U,e(c.$t(`@F13B4:手动升级命令`)),1),m(`code`,{class:`upgrade-manual__cmd`},e(c.MANUAL_COMMAND))])):t(`v-if`,!0),m(`pre`,{ref:`logEl`,class:`upgrade-log`},e(o.logs||c.$t(`@F13B4:等待日志输出`)),513)]),_:1},8,[`model-value`,`title`,`show-close`])}var G=A(I,[[`render`,W],[`__scopeId`,`data-v-bc566bba`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/components/UpgradeDialog.vue`]]);O(),y();var K=`https://github.com/xz333221/zen-gitsync/releases`,q=5,J=`app-version-check`,Y=36e5,X=i({__name:`AppVersionBadge`,setup(e,{expose:t}){t();let n=`2.17.14`,r=D(n),i=E(()=>r.value||n),a=D(null),s=D(!1),l=D(``),u=D(`running`),d=D(0),f=null,p=D(!1);function m(){try{let e=sessionStorage.getItem(J);if(!e)return null;let{at:t,data:n}=JSON.parse(e);return Date.now()-t>Y?null:n}catch{return null}}function h(e){try{sessionStorage.setItem(J,JSON.stringify({at:Date.now(),data:e}))}catch{}}async function g(e=!1){let t=m();t&&(a.value=t);try{let t=await M();a.value=t,h(t),t.current&&(r.value=t.current),!e&&t.success&&t.hasUpdate&&_({type:`success`,message:k(`@F13B4:发现新版本 {version}`,{version:t.latest??``}),duration:4e3})}catch(t){e||_({type:`warning`,message:k(`@F13B4:检查更新失败 {error}`,{error:t?.message||``})})}}async function v(){if(a.value?.hasUpdate){try{await b.confirm(k(`@F13B4:确定要从 {current} 升级到 {latest} 吗?`,{current:a.value.current,latest:a.value.latest}),k(`@F13B4:升级`),{confirmButtonText:k(`@F13B4:确定升级`),cancelButtonText:k(`@F13B4:取消`),type:`info`})}catch{return}l.value=``,u.value=`running`,s.value=!0,await N(e=>{if(e.type===`done`){if(u.value=e.code===0?`success`:`failed`,e.code===0){try{sessionStorage.removeItem(J)}catch{}a.value?.latest&&(r.value=a.value.latest),y()}}else e.message&&(l.value+=e.message)})}}function y(){x(),d.value=q,f=setInterval(()=>{--d.value,d.value<=0&&(f&&=(clearInterval(f),null),C())},1e3)}function x(){f&&=(clearInterval(f),null),d.value=0}function S(){x()}async function C(){if(x(),!p.value){p.value=!0;try{let e=await P(),{pathname:t,search:n,hash:r}=window.location;window.location.href=`http://localhost:${e}${t}${n}${r}`}catch(e){let t=e?.message||``,n={"restart.timeout":`@F13B4:重启超时`,"restart.stream-closed":`@F13B4:重启失败,请刷新页面重试`,"restart.failed":`@F13B4:重启失败`}[t];_({type:`warning`,message:n?k(n):k(`@F13B4:重启失败 {error}`,{error:t})}),p.value=!1}}}c(()=>{x()}),o(()=>{g(!0)});let w={buildVersion:n,releasesUrl:K,runtimeVersion:r,displayVersion:i,latestInfo:a,upgradeDialogVisible:s,upgradeLogs:l,upgradeStatus:u,AUTO_REFRESH_SECONDS:q,countdown:d,get countdownTimer(){return f},set countdownTimer(e){f=e},restartInFlight:p,CACHE_KEY:J,CACHE_TTL_MS:Y,readCache:m,writeCache:h,checkUpdate:g,handleUpgrade:v,startAutoRefreshCountdown:y,cancelAutoRefreshCountdown:x,handleCancelAutoRefresh:S,handleRestart:C,get $t(){return k},UpgradeDialog:G};return Object.defineProperty(w,"__isScriptSetup",{enumerable:!1,value:!0}),w}});O(),p();var Z={class:`app-version-badge`},Q=[`aria-label`],$=[`aria-label`],ee=[`title`,`aria-label`],te={class:`upgrade-btn__label`},ne={class:`upgrade-btn__version`};function re(n,r,i,o,s,c){let l=a;return g(),f(`div`,Z,[t(` GitHub 链接 `),d(l,{content:o.$t(`@F13B4:在 GitHub 上查看源码`),placement:`top`,effect:`dark`,"show-after":300},{default:w(()=>[m(`a`,{href:`https://github.com/xz333221/zen-gitsync`,target:`_blank`,rel:`noopener noreferrer`,class:`badge-icon-link`,"aria-label":o.$t(`@F13B4:在 GitHub 上查看源码`)},[...r[1]||=[m(`svg`,{viewBox:`0 0 24 24`,width:`15`,height:`15`,"aria-hidden":`true`,fill:`currentColor`,xmlns:`http://www.w3.org/2000/svg`},[m(`path`,{d:`M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0 1 12 6.844a9.59 9.59 0 0 1 2.504.337c1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.02 10.02 0 0 0 22 12.017C22 6.484 17.522 2 12 2z`})],-1)]],8,Q)]),_:1},8,[`content`]),t(` NPM 链接 `),d(l,{content:o.$t(`@F13B4:在 npm 上查看包`),placement:`top`,effect:`dark`,"show-after":300},{default:w(()=>[m(`a`,{href:`https://www.npmjs.com/package/zen-gitsync`,target:`_blank`,rel:`noopener noreferrer`,class:`badge-icon-link badge-icon-link--npm`,"aria-label":o.$t(`@F13B4:在 npm 上查看包`)},[...r[2]||=[m(`svg`,{viewBox:`0 0 24 24`,width:`15`,height:`15`,"aria-hidden":`true`,fill:`currentColor`,xmlns:`http://www.w3.org/2000/svg`},[m(`path`,{d:`M2 2v20h20V2H2zm17.167 17.167H12.5v-10h-3.333v10H4.833V4.833h14.334v14.334z`})],-1)]],8,$)]),_:1},8,[`content`]),t(` 版本号 `),d(l,{content:o.$t(`@F13B4:查看更新`),placement:`top`,effect:`dark`,"show-after":300},{default:w(()=>[m(`a`,{href:o.releasesUrl,target:`_blank`,rel:`noopener noreferrer`,class:`version-link`},`v`+e(o.displayVersion),1)]),_:1},8,[`content`]),o.latestInfo?.hasUpdate?(g(),f(`button`,{key:0,type:`button`,class:`upgrade-btn`,title:o.$t(`@F13B4:发现新版本 {version},点击升级`,{version:o.latestInfo.latest??``}),"aria-label":o.$t(`@F13B4:发现新版本 {version},点击升级`,{version:o.latestInfo.latest??``}),onClick:o.handleUpgrade},[r[3]||=m(`span`,{class:`upgrade-btn__dot`,"aria-hidden":`true`},null,-1),m(`span`,te,e(o.$t(`@F13B4:升级`)),1),m(`span`,ne,`v`+e(o.latestInfo.latest),1)],8,ee)):t(`v-if`,!0),d(o.UpgradeDialog,{modelValue:o.upgradeDialogVisible,"onUpdate:modelValue":r[0]||=e=>o.upgradeDialogVisible=e,logs:o.upgradeLogs,status:o.upgradeStatus,countdown:o.countdown,onRetry:o.handleUpgrade,onRestart:o.handleRestart,onCancel:o.handleCancelAutoRefresh},null,8,[`modelValue`,`logs`,`status`,`countdown`])])}var ie=A(X,[[`render`,re],[`__scopeId`,`data-v-7e0300ec`],[`__file`,`C:/workspace/github_workspace/xz333221/zen-gitsync/src/ui/client/src/components/AppVersionBadge.vue`]]);export{ie as default};
|