zen-gitsync 2.13.14 → 2.13.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.
Files changed (28) hide show
  1. package/README.md +2 -0
  2. package/package.json +6 -3
  3. package/scripts/README_COLOR_CONVERTER.md +196 -196
  4. package/scripts/README_FONTSIZE_CONVERTER.md +278 -278
  5. package/scripts/README_SPACING_CONVERTER.md +126 -126
  6. package/scripts/README_STYLE_VARS.md +180 -180
  7. package/src/ui/public/assets/{EditorView-S6HDGyLD.js → EditorView-CRpjzBS1.js} +0 -0
  8. package/src/ui/public/assets/{SourceMapView-C10WxgGh.js → SourceMapView-ByHkwMwM.js} +1 -1
  9. package/src/ui/public/assets/WorkbenchView-Dhle7BQe.css +1 -0
  10. package/src/ui/public/assets/WorkbenchView-cBXTpeWC.js +9 -0
  11. package/src/ui/public/assets/{_plugin-vue_export-helper-8__zdPsB.js → _plugin-vue_export-helper-CT67BnrS.js} +2 -2
  12. package/src/ui/public/assets/{index-D-XpqSmG.js → index-C19XAWFW.js} +15 -14
  13. package/src/ui/public/assets/index-C3VghkAQ.css +1 -0
  14. package/src/ui/public/favicon.svg +75 -75
  15. package/src/ui/public/index.html +20 -20
  16. package/src/ui/public/logo.svg +74 -74
  17. package/src/ui/server/index.js +2 -1
  18. package/src/ui/server/routes/exec.js +10 -9
  19. package/src/ui/server/routes/status.js +16 -17
  20. package/src/ui/server/routes/terminal.js +12 -13
  21. package/src/ui/server/routes/workbench.js +433 -33
  22. package/src/ui/server/utils/shellQuote.js +68 -0
  23. package/src/ui/server/utils/shellQuote.test.js +110 -0
  24. package/src/utils/index.js +60 -29
  25. package/src/utils/parseCwdArg.test.js +86 -0
  26. package/src/ui/public/assets/WorkbenchView-7COIW5s0.js +0 -9
  27. package/src/ui/public/assets/WorkbenchView-zVvptY6a.css +0 -1
  28. package/src/ui/public/assets/index-CHX2_Fog.css +0 -1
@@ -0,0 +1,68 @@
1
+ // Copyright 2026 xz333221
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ //
15
+
16
+ /**
17
+ * Shell / PowerShell 字符串转义工具
18
+ *
19
+ * 提供三种转义策略:
20
+ * - shQuote: POSIX shell 单引号包字符串(git add / osascript / gnome-terminal 用)
21
+ * - psEscape: PowerShell 双引号内安全转义(terminal.js 的 PowerShell 脚本用)
22
+ * - appleEscape: AppleScript 双引号字符串内安全转义(macOS 终端用)
23
+ *
24
+ * 三种都不依赖外部包,纯字符串操作。
25
+ *
26
+ * @typedef {string | number | null | undefined} ShellInput
27
+ */
28
+
29
+ /**
30
+ * POSIX shell 单引号包裹
31
+ * 单引号内不解释 $ ` " \,只把单引号自身转义为 '\''
32
+ * 例: shQuote('a"b$c') === "'a\"b$c'"
33
+ *
34
+ * @param {ShellInput} input
35
+ * @returns {string}
36
+ */
37
+ export function shQuote(input) {
38
+ if (input === null || input === undefined) return "''"
39
+ return `'${String(input).replace(/'/g, `'\\''`)}'`
40
+ }
41
+
42
+ /**
43
+ * PowerShell 双引号字符串内安全转义
44
+ * 需要把 $ (变量/子表达式) 和 ` (子表达式) 各自前置一个反引号
45
+ * 双引号本身用 "" 转义;反引号自身先用 `` 转义避免吃掉后续转义
46
+ *
47
+ * @param {ShellInput} input
48
+ * @returns {string}
49
+ */
50
+ export function psEscape(input) {
51
+ if (input === null || input === undefined) return '""'
52
+ return String(input)
53
+ .replace(/`/g, '``')
54
+ .replace(/\$/g, '`$')
55
+ .replace(/"/g, '""')
56
+ }
57
+
58
+ /**
59
+ * AppleScript 双引号字符串内安全转义
60
+ * 反斜杠和双引号都需要前置反斜杠
61
+ *
62
+ * @param {ShellInput} input
63
+ * @returns {string}
64
+ */
65
+ export function appleEscape(input) {
66
+ if (input === null || input === undefined) return '""'
67
+ return String(input).replace(/\\/g, '\\\\').replace(/"/g, '\\"')
68
+ }
@@ -0,0 +1,110 @@
1
+ // Copyright 2026 xz333221
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ //
15
+ // shellQuote 单元测试(node:test 内置)
16
+ import { test } from 'node:test'
17
+ import assert from 'node:assert/strict'
18
+ import { shQuote, psEscape, appleEscape } from '../utils/shellQuote.js'
19
+
20
+ test('shQuote 普通字符串', () => {
21
+ assert.equal(shQuote('hello'), "'hello'")
22
+ })
23
+
24
+ test('shQuote 单引号需要转义', () => {
25
+ // POSIX shell: 单引号字符串里唯一需要处理的就是单引号自身
26
+ // 关闭单引号 + 转义 + 开启单引号 = '\''
27
+ assert.equal(shQuote("a'b"), "'a'\\''b'")
28
+ })
29
+
30
+ test('shQuote 注入字符也能合法包裹', () => {
31
+ // POSIX shell 单引号内 $ ` " \ 都不展开,所以原样包住就是安全的
32
+ // 函数职责只保证产出一个语法合法的单引号字符串
33
+ const evil = '$(rm -rf /); `whoami` "$PATH" \\path'
34
+ const quoted = shQuote(evil)
35
+ // 必须以单引号开头和结尾,内部任何单引号都被 '\'' 转义
36
+ assert.ok(quoted.startsWith("'"))
37
+ assert.ok(quoted.endsWith("'"))
38
+ // 内部裸的单引号不会破坏字符串:
39
+ // 统计未配对的单引号数量,被正确转义的 ' 必须成对出现 '\''
40
+ // 这里因为输入不含单引号,所以 quoted 形如 '<evil>'
41
+ assert.equal(quoted.length, evil.length + 2)
42
+ })
43
+
44
+ test('shQuote null / undefined / number 都安全', () => {
45
+ assert.equal(shQuote(null), "''")
46
+ assert.equal(shQuote(undefined), "''")
47
+ assert.equal(shQuote(42), "'42'")
48
+ })
49
+
50
+ test('shQuote 文件名场景:含空格和双引号', () => {
51
+ // 模拟 git status --porcelain 解出的文件名
52
+ assert.equal(shQuote('my file.txt'), "'my file.txt'")
53
+ assert.equal(shQuote('a"b.txt'), `'a"b.txt'`)
54
+ })
55
+
56
+ test('psEscape $ 变量必须前置反引号', () => {
57
+ // 原: $(rm -rf /) → 期望: `$(rm -rf /)
58
+ // (PowerShell 双引号内 $ 会触发子表达式求值,前置 ` 取消求值)
59
+ assert.equal(psEscape('$(rm -rf /)'), '`$(rm -rf /)')
60
+ })
61
+
62
+ test('psEscape 反引号自身先转义', () => {
63
+ // 反引号是 PowerShell 转义符,先自身转义避免吃掉后续的转义符
64
+ // 原: `n → 期望: ``n
65
+ assert.equal(psEscape('`n'), '``n')
66
+ // 原: $`n (3 字符) → 期望: `$``n (5 字符: ` $ ` ` n)
67
+ // 反引号先转: $``n (4) → 然后 $ 前置: `$``n (5)
68
+ assert.equal(psEscape('$`n'), '`$``n')
69
+ })
70
+
71
+ test('psEscape 双引号用 "" 转义', () => {
72
+ assert.equal(psEscape('a"b'), 'a""b')
73
+ })
74
+
75
+ test('psEscape 普通字符串不变', () => {
76
+ assert.equal(psEscape('hello world'), 'hello world')
77
+ })
78
+
79
+ test('psEscape null / undefined → 空字符串', () => {
80
+ assert.equal(psEscape(null), '""')
81
+ assert.equal(psEscape(undefined), '""')
82
+ })
83
+
84
+ test('psEscape 工作目录路径 (Windows 含反斜杠和 $)', () => {
85
+ // PowerShell 里 $env:TEMP 是变量; $ 开头的路径是注入面
86
+ const path = '$env:TEMP\\evil$(rm).txt'
87
+ const escaped = psEscape(path)
88
+ // 所有 $ 必须前置反引号
89
+ assert.ok(!escaped.match(/(?<!`)\$/), '不应有未转义的 $')
90
+ assert.ok(escaped.includes('`$env:'))
91
+ assert.ok(escaped.includes('`$(rm)'))
92
+ })
93
+
94
+ test('appleEscape 双引号前置反斜杠', () => {
95
+ assert.equal(appleEscape('a"b'), 'a\\"b')
96
+ })
97
+
98
+ test('appleEscape 反斜杠先转义', () => {
99
+ // 反斜杠要双写避免吃掉后面的 "
100
+ assert.equal(appleEscape('a\\"b'), 'a\\\\\\"b')
101
+ })
102
+
103
+ test('appleEscape 普通字符串不变', () => {
104
+ assert.equal(appleEscape('cd /tmp && ls'), 'cd /tmp && ls')
105
+ })
106
+
107
+ test('appleEscape null / undefined → 空字符串', () => {
108
+ assert.equal(appleEscape(null), '""')
109
+ assert.equal(appleEscape(undefined), '""')
110
+ })
@@ -101,20 +101,7 @@ const printTableWithHeaderUnderline = (head, content, style) => {
101
101
 
102
102
  // printTableWithHeaderUnderline();
103
103
 
104
- const colors = [
105
- '\x1b[31m', // 红色
106
- '\x1b[32m', // 绿色
107
- '\x1b[33m', // 黄色
108
- '\x1b[34m', // 蓝色
109
- '\x1b[35m', // 紫色
110
- '\x1b[36m', // 青色
111
- ];
112
-
113
- function getRandomColor() {
114
- return `\x1b[0m`;
115
- // const randomIndex = Math.floor(Math.random() * colors.length);
116
- // return colors[randomIndex];
117
- }
104
+ // getRandomColor 已删除(原实现永远返回 \x1b[0m,是死代码)
118
105
 
119
106
  function resetColor() {
120
107
  return '\x1b[0m';
@@ -246,7 +233,8 @@ function execSyncGitCommand(command, options = {}) {
246
233
  } catch (e) {
247
234
  // console.log(`执行命令出错 ==> `, command, e)
248
235
  log && coloredLog(command, e, 'error')
249
- throw new Error(e)
236
+ // 透传原始 error,保留 stack + 已挂载的 stdout/stderr
237
+ throw e
250
238
  }
251
239
  }
252
240
 
@@ -456,15 +444,34 @@ function addCommandToHistory(command, stdout = '', stderr = '', error = null, ex
456
444
  return historyItem;
457
445
  }
458
446
 
459
- const getCwd = () => {
460
- const cwdArg = process.argv.find(arg => arg.startsWith('--path')) || process.argv.find(arg => arg.startsWith('--cwd'));
461
- if (cwdArg) {
462
- // console.log(`cwdArg ==> `, cwdArg)
463
- const [, value] = cwdArg.split('=')
464
- // console.log(`value ==> `, value)
465
- return value || process.cwd()
447
+ /**
448
+ * argv 数组里解析出 --path / --cwd 的值
449
+ * 严格匹配 `--path` / `--path=<v>` / `--cwd` / `--cwd=<v>`,避免误匹配 `--pathTo=...`
450
+ *
451
+ * @param {readonly string[]} argv - 类似 process.argv 的参数数组
452
+ * @returns {string | null} 解析到的值,没匹配到返回 null
453
+ */
454
+ function parseCwdArg(argv) {
455
+ if (!Array.isArray(argv)) return null
456
+ const cwdArg = argv.find((arg) => {
457
+ if (typeof arg !== 'string') return false
458
+ if (arg === '--path' || arg === '--cwd') return true
459
+ return arg.startsWith('--path=') || arg.startsWith('--cwd=')
460
+ })
461
+ if (!cwdArg) return null
462
+ const eqIdx = cwdArg.indexOf('=')
463
+ if (eqIdx >= 0) {
464
+ const value = cwdArg.slice(eqIdx + 1)
465
+ return value || null
466
466
  }
467
- return process.cwd()
467
+ // 空格分隔形式: `--path <value>`,取下一个 argv
468
+ const next = argv[argv.indexOf(cwdArg) + 1]
469
+ return next || null
470
+ }
471
+
472
+ const getCwd = () => {
473
+ const parsed = parseCwdArg(process.argv)
474
+ return parsed || process.cwd()
468
475
  }
469
476
  const judgePlatform = () => {
470
477
  // 判断是否是 Windows 系统
@@ -889,15 +896,39 @@ async function execGitAddWithLockFilter() {
889
896
  }
890
897
 
891
898
  // 逐个添加未锁定的文件
899
+ // 注意:用单引号包文件名,单引号内不解释 $ ` " \ 等元字符,
900
+ // 只需把单引号自身转义为 '\''
901
+ // 避免文件名含特殊字符(如 " $ ` ;) 导致 shell 注入或命令错乱
902
+ // null/undefined 显式返回 '' 而非 'null'/'undefined' (与 src/ui/server/utils/shellQuote.js shQuote 契约一致)
903
+ const shellQuote = (s) => {
904
+ if (s === null || s === undefined) return "''"
905
+ return `'${String(s).replace(/'/g, `'\\''`)}'`
906
+ }
907
+ let successCount = 0
908
+ let failedFiles = []
892
909
  for (const file of filesToAdd) {
893
- await execGitCommand(`git add "${file}"`, {
894
- head: `git add ${file}`,
895
- log: false
896
- });
910
+ try {
911
+ await execGitCommand(`git add -- ${shellQuote(file)}`, {
912
+ head: `git add ${file}`,
913
+ log: false
914
+ })
915
+ successCount++
916
+ } catch (err) {
917
+ // 单文件失败不阻断整批,记录失败清单让用户感知
918
+ failedFiles.push({ file, error: err?.message || String(err) })
919
+ console.warn(chalk.yellow(`⚠️ 添加失败: ${file} — ${err?.message || err}`))
920
+ }
897
921
  }
898
922
 
899
923
  const skippedCount = modifiedFiles.length - filesToAdd.length;
900
- console.log(chalk.green(`✅ 已添加 ${filesToAdd.length} 个文件到暂存区${skippedCount > 0 ? ` (跳过 ${skippedCount} 个锁定文件)` : ''}`));
924
+ const failSuffix = failedFiles.length > 0 ? `, ${failedFiles.length} 个失败` : ''
925
+ console.log(chalk.green(`✅ 已添加 ${successCount} 个文件到暂存区${skippedCount > 0 ? ` (跳过 ${skippedCount} 个锁定文件)` : ''}${failSuffix}`));
926
+ if (failedFiles.length > 0) {
927
+ // 把失败列表挂到 thrown error 上,上层可选择性展示
928
+ const e = new Error(`git add 部分失败 (${failedFiles.length}/${filesToAdd.length})`)
929
+ e.failedFiles = failedFiles
930
+ throw e
931
+ }
901
932
 
902
933
  } catch (error) {
903
934
  console.error(chalk.red('执行 git add 时出错:'), error.message);
@@ -1050,7 +1081,7 @@ export {
1050
1081
  clearCommandHistory,
1051
1082
  checkAndClearGitLock,
1052
1083
  registerSocketIO, // 导出注册Socket.io的函数
1053
- getCwd, judgePlatform, showHelp, judgeLog, printGitLog,
1084
+ getCwd, parseCwdArg, judgePlatform, showHelp, judgeLog, printGitLog,
1054
1085
  judgeHelp, exec_exit, judgeUnmerged, delay, formatDuration,
1055
1086
  exec_push, execPull, judgeRemote, execDiff, execAddAndCommit,
1056
1087
  execGitAddWithLockFilter, // 导出新的 git add 函数
@@ -0,0 +1,86 @@
1
+ // Copyright 2026 xz333221
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ //
15
+ // parseCwdArg 单元测试(node:test 内置)
16
+ import { test } from 'node:test'
17
+ import assert from 'node:assert/strict'
18
+ import { parseCwdArg } from './index.js'
19
+
20
+ test('--path=<v> 形式解析', () => {
21
+ assert.equal(parseCwdArg(['node', 'g.js', '--path=/tmp/proj']), '/tmp/proj')
22
+ })
23
+
24
+ test('--cwd=<v> 形式解析', () => {
25
+ assert.equal(parseCwdArg(['node', 'g.js', '--cwd=E:\\project']), 'E:\\project')
26
+ })
27
+
28
+ test('--path <v> 空格分隔形式解析', () => {
29
+ assert.equal(parseCwdArg(['node', 'g.js', '--path', '/tmp/proj']), '/tmp/proj')
30
+ })
31
+
32
+ test('--cwd <v> 空格分隔形式解析', () => {
33
+ assert.equal(parseCwdArg(['node', 'g.js', '--cwd', '/tmp/proj']), '/tmp/proj')
34
+ })
35
+
36
+ test('没有 --path / --cwd 时返回 null', () => {
37
+ assert.equal(parseCwdArg(['node', 'g.js', '-y', '-m', 'msg']), null)
38
+ })
39
+
40
+ test('空 argv 返回 null', () => {
41
+ assert.equal(parseCwdArg([]), null)
42
+ })
43
+
44
+ test('非数组输入返回 null', () => {
45
+ assert.equal(parseCwdArg(null), null)
46
+ assert.equal(parseCwdArg(undefined), null)
47
+ assert.equal(parseCwdArg('not array'), null)
48
+ })
49
+
50
+ test('--pathTo / --cwd-prefix 不会误匹配', () => {
51
+ // 修复前: startsWith('--path') 会把 --pathTo=... 误判
52
+ assert.equal(parseCwdArg(['--pathTo=/etc']), null)
53
+ assert.equal(parseCwdArg(['--cwd-prefix=foo']), null)
54
+ assert.equal(parseCwdArg(['--pathway=evil', '--path=/good']), '/good')
55
+ })
56
+
57
+ test('--path= 但值为空返回 null', () => {
58
+ // 空值视为非法,解析失败
59
+ assert.equal(parseCwdArg(['--path=']), null)
60
+ // find() 只取第一个匹配的形参,即使后续有合法 --cwd 也不会 fallback
61
+ // (语义明确:第一个出现的 cwd 参数生效,避免歧义)
62
+ assert.equal(parseCwdArg(['--path=', '--cwd=/fallback']), null)
63
+ })
64
+
65
+ test('--path 后面没有参数也返回 null', () => {
66
+ assert.equal(parseCwdArg(['--path']), null)
67
+ })
68
+
69
+ test('多个候选只取第一个', () => {
70
+ assert.equal(parseCwdArg(['--path=/first', '--path=/second']), '/first')
71
+ })
72
+
73
+ test('混合 -y -m --path 也正确', () => {
74
+ assert.equal(
75
+ parseCwdArg(['node', 'g', '-y', '-m', 'fix', '--path=/repo']),
76
+ '/repo'
77
+ )
78
+ })
79
+
80
+ test('--cwd 优先 --path 之前出现', () => {
81
+ // 顺序: --cwd 出现在 --path 之前,find() 取第一个,行为明确
82
+ assert.equal(
83
+ parseCwdArg(['--cwd=/c', '--path=/p']),
84
+ '/c'
85
+ )
86
+ })
@@ -1,9 +0,0 @@
1
- import"./rolldown-runtime-CMxvf4Kt.js";import{$n as e,$t as t,B as n,Bn as r,Ct as i,Fn as a,Gn as o,Hn as s,In as c,J as l,Kn as u,L as d,Ln as f,M as p,N as m,Nt as h,Ot as g,P as _,Pt as v,Rn as y,Sr as b,St as x,Tt as S,Un as C,V as w,Vt as T,Wn as E,Wt as D,Xn as O,Y as k,Yn as A,Zn as j,_r as M,ar as N,br as P,bt as ee,cr as F,ct as te,dr as ne,dt as I,en as re,et as L,fr as R,ft as ie,gr as ae,hr as z,ir as oe,it as se,jt as ce,l as B,ln as le,lt as ue,mr as de,mt as fe,nn as pe,nr as V,on as me,or as H,pr as U,q as he,qn as W,qt as ge,rr as _e,rt as G,sn as ve,st as ye,tt as be,un as K,vt as xe,wt as Se,xr as Ce,xt as we,yr as q,zn as J,zt as Te}from"./vendor-D72Z0Jmi.js";import{n as Y,t as Ee}from"./_plugin-vue_export-helper-8__zdPsB.js";import{n as De}from"./index-D-XpqSmG.js";var X={class:`ai-split-direct-pane`},Oe={key:0,class:`ai-split-status`},ke={key:1,class:`ai-split-status is-error`},Ae={key:2,class:`ai-split-idle`},Z={class:`ai-split-idle__title`},je={class:`ai-split-idle__desc`},Me={class:`ai-split-prompt-actions`},Ne={key:0,class:`ai-split-prompt-editor`},Pe={class:`ai-split-prompt-editor__actions`},Fe={key:1,class:`ai-split-pre`},Ie={class:`ai-split-subhead`},Le={class:`ai-split-pre`},Re={key:0,class:`ai-split-tab-count`},ze={class:`ai-split-pre ai-split-pre--think`},Be={key:0,class:`ai-split-tab-count`},Ve={class:`ai-split-parse-error__detail`},He={class:`ai-split-parse-error__hint`},Ue={class:`ai-split-parse-error__actions`},Q={key:1,class:`ai-split-raw-toolbar`},We={class:`ai-split-raw-tip`},Ge={key:0,class:`ai-split-tab-count`},Ke={key:0,class:`ai-split-empty`},qe={key:1,class:`ai-split-list`},Je={class:`ai-split-list__no`},Ye={class:`ai-split-list__body`},Xe={class:`ai-split-list__title`},Ze={class:`ai-split-list__desc`},Qe={key:4,class:`ai-split-footer-hint`},$e={class:`ai-split-direct-footer`},et=Ee(e({__name:`AISplitDirectPane`,props:{title:{},desc:{},taskId:{},promptId:{}},emits:[`confirm`],setup(e,{emit:t}){let a=e,s=t,c=M(`idle`),l=M(`prompt`),d=M(``),f=M(``),p=M(``),h=M(``),g=M(``),_=M([]),v=M(``),y=M(``),S=M(``),T=null,D=0,k=C(()=>p.value.length),N=C(()=>h.value.length),P=C(()=>c.value===`result`&&_.value.length>0),ee=C(()=>c.value===`running`);function te(){T&&=(T.abort(),null)}function ne(){te(),c.value=`idle`,l.value=`prompt`,d.value=``,f.value=``,p.value=``,h.value=``,g.value=``,_.value=[],v.value=``,y.value=``,S.value=``}async function I(){if(!a.title.trim()){m.warning(Y(`@WORKBENCH:请先填写任务标题`));return}ne();let e=++D;c.value=`running`,l.value=`thinking`,T=new AbortController;let t=T;try{let n=await fetch(`/api/workbench/tasks/ai-split-subtasks`,{method:`POST`,headers:{"Content-Type":`application/json`,Accept:`text/event-stream`},body:JSON.stringify({title:a.title,desc:a.desc,taskId:a.taskId||``,promptId:a.promptId||``}),signal:t.signal});if(e!==D)return;if(!n.ok||!n.body){let e=await n.text().catch(()=>``);throw Error(e||`HTTP ${n.status}`)}let r=n.body.getReader(),i=new TextDecoder(`utf-8`),o=``,s=null;for(;;){let{value:t,done:n}=await r.read();if(e!==D)return;if(n)break;o+=i.decode(t,{stream:!0});let a=o.split(`
2
- `);o=a.pop()??``;for(let e of a){let t=e.trim();if(!t.startsWith(`data:`))continue;let n=t.slice(5).trim();if(!n)continue;let r;try{r=JSON.parse(n)}catch{continue}switch(r.type){case`meta`:d.value=r.prompt?.system||``,f.value=r.prompt?.user||``;break;case`thinking`:p.value+=String(r.delta||``);break;case`content`:h.value+=String(r.delta||``);break;case`done`:s=r;break;case`error`:throw Error(r.error||`AI 拆分失败`)}}}if(e!==D)return;if(!s)throw Error(Y(`@WORKBENCH:AI 未返回结果`));_.value=Array.isArray(s.subtasks)?s.subtasks:[],g.value=s.raw||h.value,y.value=String(s.parseError||``),S.value=String(s.parseStage||``),p.value||=Y(`@WORKBENCH:(当前模型未返回独立的思考内容,可切换到「原始结果」查看完整输出)`),c.value=`result`,l.value=_.value.length>0?`confirm`:`raw`}catch(n){if(e!==D)return;if(n?.name===`AbortError`||t.signal.aborted){c.value=`idle`,l.value=`prompt`;return}c.value=`error`,v.value=n?.message||String(n)}finally{e===D&&(T=null)}}function L(){P.value&&s(`confirm`,_.value.slice())}function ie(){I()}function ae(){T&&(T.abort(),T=null,m.info(Y(`@WORKBENCH:已停止拆分`)))}let z=M(!1);async function oe(){if(!h.value.trim()){m.warning(Y(`@WORKBENCH:原始结果为空,无法解析`));return}z.value=!0;try{let e=await fetch(`/api/workbench/tasks/parse-subtasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({raw:h.value})}).then(e=>e.json());if(!e.success){m.error(e.error||Y(`@WORKBENCH:解析失败`));return}_.value=Array.isArray(e.subtasks)?e.subtasks:[],y.value=String(e.parseError||``),S.value=String(e.parseStage||``),g.value=h.value,_.value.length>0?(m.success(Y(`@WORKBENCH:解析成功,已识别 {n} 个子任务`,{n:_.value.length})),l.value=`confirm`):m.warning(Y(`@WORKBENCH:仍未解析到子任务,请继续修改原始结果`))}catch(e){m.error(Y(`@WORKBENCH:解析失败: `)+(e?.message||e))}finally{z.value=!1}}R(()=>a.taskId,()=>{ne()});let se=M(!1),B=M(``),ue=M(!1);function de(){B.value=d.value,se.value=!0}async function pe(){if(!B.value.trim()){m.warning(Y(`@WORKBENCH:指令内容不能为空`));return}ue.value=!0;try{let e=await fetch(`/api/workbench/tasks/ai-subtask-instruction`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({instruction:B.value})}).then(e=>e.json());e.success?(m.success(Y(`@WORKBENCH:已保存指令`)),se.value=!1,ie()):m.error(e.error||Y(`@WORKBENCH:保存失败`))}catch(e){m.error(Y(`@WORKBENCH:保存失败: `)+(e?.message||e))}finally{ue.value=!1}}function V(){se.value=!1}return(e,t)=>{let a=i,s=fe,m=xe,g=n,S=x,C=w;return H(),W(`div`,X,[ee.value?(H(),W(`div`,Oe,[j(a,{class:`is-loading`},{default:U(()=>[j(q(re))]),_:1}),E(`span`,null,b(q(Y)(`@WORKBENCH:AI 正在拆分…`)),1),j(s,{size:`small`,link:``,type:`danger`,class:`ai-split-status__stop`,onClick:ae},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:停止拆分`)),1)]),_:1})])):c.value===`error`?(H(),W(`div`,ke,[j(a,{color:`#f56c6c`},{default:U(()=>[j(q(ce))]),_:1}),E(`span`,null,b(v.value),1)])):c.value===`idle`?(H(),W(`div`,Ae,[t[4]||=A(`<div class="ai-split-idle__icon" aria-hidden="true" data-v-e5c8a5b7><svg viewBox="0 0 24 24" width="36" height="36" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" data-v-e5c8a5b7><path d="M12 3v3" data-v-e5c8a5b7></path><path d="M12 18v3" data-v-e5c8a5b7></path><path d="M3 12h3" data-v-e5c8a5b7></path><path d="M18 12h3" data-v-e5c8a5b7></path><path d="M5.6 5.6l2.1 2.1" data-v-e5c8a5b7></path><path d="M16.3 16.3l2.1 2.1" data-v-e5c8a5b7></path><path d="M5.6 18.4l2.1-2.1" data-v-e5c8a5b7></path><path d="M16.3 7.7l2.1-2.1" data-v-e5c8a5b7></path><circle cx="12" cy="12" r="4" data-v-e5c8a5b7></circle></svg></div>`,1),E(`div`,Z,b(q(Y)(`@WORKBENCH:准备用 AI 拆分任务`)),1),E(`div`,je,b(q(Y)(`@WORKBENCH:点击下方按钮开始生成。生成期间可切换到「思考 / 原始结果」实时查看模型输出。`)),1),j(s,{type:`primary`,icon:q(le),onClick:I},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:开始拆分`)),1)]),_:1},8,[`icon`])])):u(``,!0),c.value===`idle`?u(``,!0):(H(),o(C,{key:3,modelValue:l.value,"onUpdate:modelValue":t[3]||=e=>l.value=e,class:`ai-split-tabs`},{default:U(()=>[j(g,{label:q(Y)(`@WORKBENCH:提示词`),name:`prompt`},{default:U(()=>[E(`div`,Me,[j(s,{size:`small`,disabled:ee.value,onClick:de},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:编辑指令`)),1)]),_:1},8,[`disabled`])]),se.value?(H(),W(`div`,Ne,[j(m,{modelValue:B.value,"onUpdate:modelValue":t[0]||=e=>B.value=e,type:`textarea`,rows:12,placeholder:q(Y)(`@WORKBENCH:指令内容`)},null,8,[`modelValue`,`placeholder`]),E(`div`,Pe,[j(s,{size:`small`,onClick:V},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:取消`)),1)]),_:1}),j(s,{size:`small`,type:`primary`,loading:ue.value,onClick:pe},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:保存并重跑`)),1)]),_:1},8,[`loading`])])])):(H(),W(`pre`,Fe,b(d.value||`(等待 LLM 启动…)`),1)),E(`h4`,Ie,b(q(Y)(`@WORKBENCH:用户提示词(拼装后)`)),1),E(`pre`,Le,b(f.value||`(等待 LLM 启动…)`),1)]),_:1},8,[`label`]),j(g,{name:`thinking`},{label:U(()=>[E(`span`,null,[O(b(q(Y)(`@WORKBENCH:思考`))+` `,1),k.value>0?(H(),W(`span`,Re,`(`+b(k.value)+`)`,1)):u(``,!0)])]),default:U(()=>[E(`pre`,ze,b(p.value||q(Y)(`@WORKBENCH:(暂无输出)`)),1)]),_:1}),j(g,{name:`raw`},{label:U(()=>[E(`span`,null,[O(b(q(Y)(`@WORKBENCH:原始结果`))+` `,1),N.value>0?(H(),W(`span`,Be,`(`+b(N.value)+`)`,1)):u(``,!0)])]),default:U(()=>[y.value&&c.value===`result`?(H(),o(S,{key:0,type:`warning`,"show-icon":``,closable:!1,class:`ai-split-parse-error`},{title:U(()=>[O(b(q(Y)(`@WORKBENCH:模型返回内容解析失败,无法识别为有效的子任务 JSON`)),1)]),default:U(()=>[E(`div`,Ve,b(y.value),1),E(`div`,He,b(q(Y)(`@WORKBENCH:常见原因:desc 内夹杂了 ASCII 双引号、出现尾随逗号,或输出被截断。可在下方文本框中手动修改后点「重新解析」,或重新生成。`)),1),E(`div`,Ue,[j(s,{size:`small`,type:`primary`,loading:z.value,onClick:oe},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:重新解析`)),1)]),_:1},8,[`loading`]),j(s,{size:`small`,onClick:ie},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:重新生成`)),1)]),_:1}),j(s,{size:`small`,onClick:t[1]||=e=>l.value=`prompt`},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:去编辑指令`)),1)]),_:1})])]),_:1})):u(``,!0),c.value===`result`||h.value?(H(),W(`div`,Q,[E(`span`,We,b(q(Y)(`@WORKBENCH:可直接编辑下方文本,修正后点「重新解析」即可入库`)),1),j(s,{size:`small`,type:`primary`,loading:z.value,disabled:!h.value.trim(),onClick:oe},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:重新解析`)),1)]),_:1},8,[`loading`,`disabled`])])):u(``,!0),j(m,{modelValue:h.value,"onUpdate:modelValue":t[2]||=e=>h.value=e,type:`textarea`,rows:14,placeholder:q(Y)(`@WORKBENCH:(暂无输出)`),readonly:ee.value,class:`ai-split-raw-editor`,resize:`none`},null,8,[`modelValue`,`placeholder`,`readonly`])]),_:1}),j(g,{name:`confirm`,disabled:_.value.length===0},{label:U(()=>[E(`span`,null,[O(b(q(Y)(`@WORKBENCH:确认入库`))+` `,1),_.value.length>0?(H(),W(`span`,Ge,`(`+b(_.value.length)+`)`,1)):u(``,!0)])]),default:U(()=>[_.value.length===0?(H(),W(`div`,Ke,b(q(Y)(`@WORKBENCH:(暂无子任务)`)),1)):(H(),W(`ul`,qe,[(H(!0),W(r,null,F(_.value,(e,t)=>(H(),W(`li`,{key:t,class:`ai-split-list__item`},[E(`div`,Je,b(t+1),1),E(`div`,Ye,[E(`div`,Xe,b(e.title),1),E(`div`,Ze,b(e.desc),1)])]))),128))]))]),_:1},8,[`disabled`])]),_:1},8,[`modelValue`])),y.value&&c.value===`result`&&_.value.length===0?(H(),W(`div`,Qe,[j(a,{color:`#e6a23c`},{default:U(()=>[j(q(ce))]),_:1}),E(`span`,null,b(q(Y)(`@WORKBENCH:解析失败,未能从模型输出中提取出子任务 — 请查看「原始结果」`)),1)])):u(``,!0),E(`div`,$e,[c.value===`error`||c.value===`result`&&y.value&&_.value.length===0?(H(),o(s,{key:0,onClick:ie},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:重新生成`)),1)]),_:1})):u(``,!0),c.value===`result`&&_.value.length>0?(H(),o(s,{key:1,onClick:ie},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:重新拆分`)),1)]),_:1})):u(``,!0),j(s,{type:`primary`,disabled:!P.value,onClick:L},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:确认入库`))+` (`+b(_.value.length)+`) `,1)]),_:1},8,[`disabled`])])])}}}),[[`__scopeId`,`data-v-e5c8a5b7`]]),tt={class:`ai-chat-pane`},nt={key:0,class:`ai-chat-streaming-banner`},rt={key:1,class:`ai-chat-empty`},it={class:`ai-chat-empty__title`},at={class:`ai-chat-empty__desc`},ot={key:0,class:`ai-chat-bubble user`},st={class:`ai-chat-content`},ct={key:1,class:`ai-chat-bubble assistant`},lt={class:`ai-chat-pre ai-chat-pre--think`},ut={key:1,class:`ai-chat-content-text`},dt={key:2,class:`ai-chat-subtasks`},ft={class:`ai-chat-subtasks__head`},pt={class:`ai-chat-subtasks__count`},mt={class:`ai-chat-list`},ht={class:`ai-chat-list__no`},gt={class:`ai-chat-list__body`},_t={class:`ai-chat-list__title`},vt={class:`ai-chat-list__desc`},yt={class:`ai-chat-parse-error__detail`},bt={class:`ai-chat-pre`},xt={key:5,class:`ai-chat-turn__actions`},St={class:`ai-chat-input`},Ct={class:`ai-chat-input__actions`},wt={key:0,class:`ai-chat-history__loading`},Tt={key:1,class:`ai-chat-history__empty`},Et={key:2,class:`ai-chat-history__list`},Dt={class:`ai-chat-history__title`},Ot={class:`ai-chat-history__meta`},kt={class:`ai-chat-history__actions`},$=Ee(e({__name:`AISplitChatPane`,props:{title:{},desc:{},taskId:{},promptId:{},initialSessionId:{}},emits:[`confirm`],setup(e,{emit:t}){let n=e,a=t,s=M(`idle`),c=M(``),l=M([]),d=M(``),f=M(``),_=null,v=0,x=M(null),S=C(()=>s.value===`streaming`),w=C(()=>{if(!S.value)return``;let e=[...l.value].reverse().find(e=>e.role===`assistant`);return e?e.content?Y(`@WORKBENCH:AI 正在输出…`):e.thinking?Y(`@WORKBENCH:AI 正在思考… (已思考 {n} 字)`,{n:e.thinking.length}):Y(`@WORKBENCH:AI 正在思考…`):Y(`@WORKBENCH:AI 正在思考…`)}),T=M(!1),D=M(!1),k=M([]);function A(){x.value&&(x.value.scrollTop=x.value.scrollHeight)}async function N(){let e=d.value.trim();if(!e||S.value)return;if(!c.value&&!n.title.trim()){m.warning(Y(`@WORKBENCH:请先填写任务标题`));return}let t=++v;_=new AbortController;let r=_,i={role:`user`,content:e};l.value.push(i),d.value=``;let a={role:`assistant`,content:``,thinking:``};l.value.push(a),s.value=`streaming`,await V(),A();try{let i=await fetch(`/api/workbench/tasks/ai-chat-split`,{method:`POST`,headers:{"Content-Type":`application/json`,Accept:`text/event-stream`},body:JSON.stringify({sessionId:c.value,title:n.title,desc:n.desc,taskId:n.taskId||``,promptId:n.promptId||``,userMessage:e}),signal:r.signal});if(t!==v)return;if(!i.ok||!i.body){let e=await i.text().catch(()=>``);throw Error(e||`HTTP ${i.status}`)}let o=i.body.getReader(),u=new TextDecoder(`utf-8`),d=``,f=null,p=!1;for(;;){let{value:e,done:n}=await o.read();if(t!==v)return;if(n)break;d+=u.decode(e,{stream:!0});let r=d.split(`
3
- `);d=r.pop()??``;for(let e of r){let t=e.trim();if(!t.startsWith(`data:`))continue;let n=t.slice(5).trim();if(!n)continue;let r;try{r=JSON.parse(n)}catch{continue}switch(r.type){case`meta`:r.sessionId&&(c.value=r.sessionId);break;case`user_echo`:p=!0;break;case`thinking`:a.thinking=(a.thinking||``)+String(r.delta||``);break;case`content`:a.content+=String(r.delta||``);break;case`done`:f=r;break;case`error`:throw Error(r.error||`对话拆分失败`)}}l.value=[...l.value],await V(),A()}if(t!==v)return;if(!p&&!f)throw Error(Y(`@WORKBENCH:AI 未返回结果`));f&&(a.subtasks=Array.isArray(f.subtasks)?f.subtasks:[],a.raw=String(f.raw||a.content),a.parseError=String(f.parseError||``),a.parseStage=String(f.parseStage||``)),l.value=[...l.value],await V(),A(),s.value=`idle`}catch(e){if(t!==v)return;if(e?.name===`AbortError`||r.signal.aborted){a.content=(a.content||``)+`
4
-
5
- [已停止]`,l.value=[...l.value],s.value=`idle`;return}s.value=`error`,f.value=e?.message||String(e),m.error(f.value)}finally{t===v&&(_=null)}}function ee(){_&&=(_.abort(),null)}function te(){if(S.value){m.warning(Y(`@WORKBENCH:请先停止当前生成`));return}l.value=[],c.value=``,f.value=``,s.value=`idle`}function ne(e){if(!e.subtasks||e.subtasks.length===0){m.warning(Y(`@WORKBENCH:当前没有可应用的子任务`));return}a(`confirm`,e.subtasks.slice())}async function I(){T.value=!0,D.value=!0;try{let e=await fetch(`/api/workbench/tasks/ai-chat-sessions`).then(e=>e.json());if(!e.success){m.error(e.error||Y(`@WORKBENCH:加载历史会话失败`));return}k.value=Array.isArray(e.sessions)?e.sessions:[]}catch(e){m.error(Y(`@WORKBENCH:加载历史会话失败: `)+(e?.message||e))}finally{D.value=!1}}async function R(e){if(T.value=!1,S.value){m.warning(Y(`@WORKBENCH:请先停止当前生成`));return}try{let t=await fetch(`/api/workbench/tasks/ai-chat-sessions/${encodeURIComponent(e)}`).then(e=>e.json());if(!t.success){m.error(t.error||Y(`@WORKBENCH:加载历史会话失败`));return}let n=t.session;c.value=n.sessionId;let r=(n.messages||[]).filter(e=>e.role===`user`||e.role===`assistant`).map(e=>({role:e.role,content:e.content||``,thinking:``,subtasks:void 0,raw:void 0,parseError:``,parseStage:``})),i=[...r].reverse().find(e=>e.role===`assistant`);i&&Array.isArray(n.latestSubtasks)&&(i.subtasks=n.latestSubtasks,i.raw=n.latestRaw,i.parseStage=n.latestParseStage),l.value=r,s.value=`idle`,m.success(Y(`@WORKBENCH:已恢复历史会话`)),await V(),A()}catch(e){m.error(Y(`@WORKBENCH:加载历史会话失败: `)+(e?.message||e))}}async function ie(e){try{await p.confirm(Y(`@WORKBENCH:确认删除该会话`),Y(`@WORKBENCH:删除后无法恢复`),{type:`warning`})}catch{return}try{let t=await fetch(`/api/workbench/tasks/ai-chat-sessions/${encodeURIComponent(e)}`,{method:`DELETE`}).then(e=>e.json());if(!t.success){m.error(t.error||Y(`@WORKBENCH:删除失败`));return}k.value=k.value.filter(t=>t.sessionId!==e),m.success(Y(`@WORKBENCH:已删除`))}catch(e){m.error(Y(`@WORKBENCH:删除失败: `)+(e?.message||e))}}function ae(e){if(!e)return``;try{let t=new Date(e);if(Number.isNaN(t.getTime()))return e;let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:${n(t.getMinutes())}`}catch{return e}}function z(e){return e?e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/1024/1024).toFixed(2)} MB`:`0 B`}return n.initialSessionId&&R(n.initialSessionId),(e,t)=>{let n=i,a=se,s=G,c=fe,f=xe,p=L;return H(),W(`div`,tt,[E(`div`,{ref_key:`streamEl`,ref:x,class:`ai-chat-stream`},[S.value?(H(),W(`div`,nt,[j(n,{class:`is-loading`},{default:U(()=>[j(q(re))]),_:1}),E(`span`,null,b(w.value),1)])):u(``,!0),l.value.length===0&&!S.value?(H(),W(`div`,rt,[j(n,{size:32,color:`#909399`},{default:U(()=>[j(q(g))]),_:1}),E(`div`,it,b(q(Y)(`@WORKBENCH:开始与 AI 对话拆分`)),1),E(`div`,at,b(q(Y)(`@WORKBENCH:输入你想让 AI 怎么拆分或调整(Enter 发送,Shift+Enter 换行)`)),1)])):u(``,!0),(H(!0),W(r,null,F(l.value,(e,t)=>(H(),W(`div`,{key:t,class:P([`ai-chat-turn`,`ai-chat-turn--${e.role}`])},[e.role===`user`?(H(),W(`div`,ot,[E(`pre`,st,b(e.content),1)])):(H(),W(`div`,ct,[e.thinking?(H(),o(s,{key:0,class:`ai-chat-collapse`},{default:U(()=>[j(a,{title:q(Y)(`@WORKBENCH:思考过程`)+` (${e.thinking.length})`,name:`think`},{default:U(()=>[E(`pre`,lt,b(e.thinking),1)]),_:2},1032,[`title`])]),_:2},1024)):u(``,!0),e.content?(H(),W(`div`,ut,b(e.content),1)):u(``,!0),e.subtasks&&e.subtasks.length>0?(H(),W(`div`,dt,[E(`div`,ft,[E(`span`,pt,b(q(Y)(`@WORKBENCH:识别到 {n} 个子任务`,{n:e.subtasks.length})),1)]),E(`ul`,mt,[(H(!0),W(r,null,F(e.subtasks,(e,t)=>(H(),W(`li`,{key:t,class:`ai-chat-list__item`},[E(`div`,ht,b(t+1),1),E(`div`,gt,[E(`div`,_t,b(e.title),1),E(`div`,vt,b(e.desc),1)])]))),128))])])):u(``,!0),e.parseError&&(!e.subtasks||e.subtasks.length===0)?(H(),o(s,{key:3,class:`ai-chat-collapse`},{default:U(()=>[j(a,{title:q(Y)(`@WORKBENCH:查看解析详情`),name:`diag`},{default:U(()=>[E(`div`,yt,b(e.parseError),1)]),_:2},1032,[`title`])]),_:2},1024)):u(``,!0),e.raw&&e.raw!==e.content?(H(),o(s,{key:4,class:`ai-chat-collapse`},{default:U(()=>[j(a,{title:q(Y)(`@WORKBENCH:查看原始 LLM 输出`),name:`raw`},{default:U(()=>[E(`pre`,bt,b(e.raw),1)]),_:2},1032,[`title`])]),_:2},1024)):u(``,!0),e.subtasks&&e.subtasks.length>0?(H(),W(`div`,xt,[j(c,{type:`primary`,size:`small`,icon:q(le),onClick:t=>ne(e)},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:应用本轮`))+` (`+b(e.subtasks.length)+`) `,1)]),_:2},1032,[`icon`,`onClick`])])):u(``,!0)]))],2))),128))],512),E(`div`,St,[j(f,{modelValue:d.value,"onUpdate:modelValue":t[0]||=e=>d.value=e,type:`textarea`,rows:3,disabled:S.value,placeholder:q(Y)(`@WORKBENCH:输入你想让 AI 怎么拆分或调整(Enter 发送,Shift+Enter 换行)`),onKeydown:y(J(N,[`exact`,`prevent`]),[`enter`])},null,8,[`modelValue`,`disabled`,`placeholder`,`onKeydown`]),E(`div`,Ct,[S.value?(H(),o(c,{key:0,type:`danger`,icon:q(ce),onClick:ee},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:停止`)),1)]),_:1},8,[`icon`])):(H(),o(c,{key:1,type:`primary`,icon:q(le),disabled:!d.value.trim(),onClick:N},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:发送`)),1)]),_:1},8,[`icon`,`disabled`])),j(c,{disabled:S.value,icon:q(K),onClick:te},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:清空对话`)),1)]),_:1},8,[`disabled`,`icon`]),j(c,{disabled:S.value,icon:q(h),onClick:I},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:历史会话`)),1)]),_:1},8,[`disabled`,`icon`])])]),j(p,{modelValue:T.value,"onUpdate:modelValue":t[1]||=e=>T.value=e,title:q(Y)(`@WORKBENCH:历史会话`),direction:`rtl`,size:`420px`},{default:U(()=>[D.value?(H(),W(`div`,wt,[j(n,{class:`is-loading`},{default:U(()=>[j(q(re))]),_:1})])):k.value.length===0?(H(),W(`div`,Tt,b(q(Y)(`@WORKBENCH:暂无历史会话`)),1)):(H(),W(`ul`,Et,[(H(!0),W(r,null,F(k.value,e=>(H(),W(`li`,{key:e.sessionId,class:`ai-chat-history__item`},[E(`div`,Dt,b(e.title||`(无标题)`),1),E(`div`,Ot,[E(`span`,null,b(ae(e.updatedAt)),1),t[2]||=E(`span`,null,`·`,-1),E(`span`,null,b(e.messageCount)+` 条消息`,1),t[3]||=E(`span`,null,`·`,-1),E(`span`,null,b(e.latestSubtaskCount)+` 个子任务`,1),t[4]||=E(`span`,null,`·`,-1),E(`span`,null,b(z(e.size)),1)]),E(`div`,kt,[j(c,{size:`small`,type:`primary`,onClick:t=>R(e.sessionId)},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:恢复`)),1)]),_:1},8,[`onClick`]),j(c,{size:`small`,type:`danger`,onClick:t=>ie(e.sessionId)},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:删除`)),1)]),_:1},8,[`onClick`])])]))),128))]))]),_:1},8,[`modelValue`,`title`])])}}}),[[`__scopeId`,`data-v-e5b87036`]]),At={class:`ai-split-mode-bar`},jt=Ee(e({__name:`AISplitDialog`,props:{modelValue:{type:Boolean},title:{},desc:{},taskId:{},promptId:{}},emits:[`update:modelValue`,`confirm`],setup(e,{emit:t}){let n=e,r=t,i=M(`direct`),a=C(()=>[{label:Y(`@WORKBENCH:直接拆分`),value:`direct`},{label:Y(`@WORKBENCH:对话拆分`),value:`chat`}]);function s(e){r(`confirm`,e),r(`update:modelValue`,!1)}return R(()=>n.modelValue,e=>{e&&(i.value=`direct`)}),(t,n)=>{let c=d,l=be;return H(),o(l,{"model-value":e.modelValue,"onUpdate:modelValue":n[1]||=e=>r(`update:modelValue`,e),title:q(Y)(`@WORKBENCH:AI 拆分任务`),width:`800px`,"close-on-click-modal":!1,"close-on-press-escape":!0,"show-close":!0},{default:U(()=>[E(`div`,At,[j(c,{modelValue:i.value,"onUpdate:modelValue":n[0]||=e=>i.value=e,options:a.value,block:!1},null,8,[`modelValue`,`options`])]),i.value===`direct`?(H(),o(et,{key:0,title:e.title,desc:e.desc,"task-id":e.taskId,"prompt-id":e.promptId,onConfirm:s},null,8,[`title`,`desc`,`task-id`,`prompt-id`])):(H(),o($,{key:1,title:e.title,desc:e.desc,"task-id":e.taskId,"prompt-id":e.promptId,onConfirm:s},null,8,[`title`,`desc`,`task-id`,`prompt-id`]))]),_:1},8,[`model-value`,`title`])}}}),[[`__scopeId`,`data-v-2732cf4b`]]),Mt={class:`wb-attachments__head`},Nt={class:`wb-attachments__label`},Pt={class:`wb-attachments__count`},Ft=[`disabled`],It={key:0,class:`wb-attachments__paste-hint`},Lt={key:1,class:`wb-attachments__list`},Rt=[`title`,`onClick`,`onContextmenu`],zt=[`src`,`alt`],Bt={key:1},Vt={class:`wb-attachment__meta`},Ht=[`title`],Ut=[`onClick`,`title`],Wt=Ee(e({__name:`AttachmentZone`,props:{attachments:{},isImage:{type:Function},humanSize:{type:Function},isUploading:{type:Boolean},isPasteHover:{type:Boolean},maxCount:{},onPick:{type:Function},onRemove:{type:Function}},emits:[`paste`,`drop`,`dragover`,`dragenter`,`dragleave`],setup(e,{emit:t}){let n=e,i=t,a=C(()=>n.attachments.filter(e=>n.isImage(e))),c=C(()=>a.value.map(e=>`/api/workbench/attachments/${e.id}/raw`)),l=M(0),d=M(!1);function f(e){if(n.isImage(e)){let t=a.value.findIndex(t=>t.id===e.id);l.value=t>=0?t:0,d.value=!0}else window.open(`/api/workbench/attachments/${e.id}/raw`,`_blank`,`noopener`)}function p(){d.value=!1}let h=M({visible:!1,x:0,y:0,att:null}),g=M(!1);function _(e,t){if(!n.isImage(e))return;t.preventDefault();let r=window.innerWidth-180,i=window.innerHeight-120;h.value={visible:!0,x:Math.min(t.clientX,r),y:Math.min(t.clientY,i),att:e}}function v(){h.value.visible&&(h.value.visible=!1)}async function y(){let e=h.value.att;if(!(!e||g.value)){if(v(),!navigator.clipboard||typeof ClipboardItem>`u`){m({type:`warning`,message:Y(`@WORKBENCH:当前浏览器不支持复制图片`)});return}g.value=!0;try{let t=await fetch(`/api/workbench/attachments/${e.id}/raw`,{credentials:`same-origin`});if(!t.ok)throw Error(`HTTP ${t.status}`);let n=await t.blob(),r=[`image/png`,`image/jpeg`,`image/webp`,`image/gif`].includes(n.type)?n.type:`image/png`,i=new ClipboardItem({[r]:n});await navigator.clipboard.write([i]),m({type:`success`,message:Y(`@WORKBENCH:图片已复制到剪贴板`),duration:1800})}catch(e){m({type:`error`,message:Y(`@WORKBENCH:复制失败 {error}`,{error:e?.message||``})})}finally{g.value=!1}}}return typeof window<`u`&&(window.addEventListener(`click`,v),window.addEventListener(`scroll`,v,!0),window.addEventListener(`blur`,v)),_e(()=>{typeof window>`u`||(window.removeEventListener(`click`,v),window.removeEventListener(`scroll`,v,!0),window.removeEventListener(`blur`,v))}),(t,n)=>(H(),W(r,null,[E(`div`,{class:P([`wb-attachments`,{"is-paste-hover":e.isPasteHover}]),onPaste:n[1]||=e=>i(`paste`,e),onDrop:n[2]||=J(e=>i(`drop`,e),[`prevent`]),onDragover:n[3]||=J(e=>i(`dragover`,e),[`prevent`]),onDragenter:n[4]||=J(e=>i(`dragenter`,e),[`prevent`]),onDragleave:n[5]||=e=>i(`dragleave`,e)},[E(`div`,Mt,[E(`span`,Nt,[O(b(q(Y)(`@WORKBENCH:附件`))+` `,1),E(`span`,Pt,b(e.attachments.length)+` / `+b(e.maxCount),1)]),E(`button`,{class:`wb-attachments__add wb-soft-btn`,disabled:e.isUploading||e.attachments.length>=e.maxCount,onClick:n[0]||=(...t)=>e.onPick&&e.onPick(...t)},b(e.isUploading?q(Y)(`@WORKBENCH:上传中…`):q(Y)(`@WORKBENCH:添加附件`)),9,Ft)]),e.isPasteHover?(H(),W(`div`,It,b(q(Y)(`@WORKBENCH:粘贴图片以快速添加`)),1)):u(``,!0),e.attachments.length>0?(H(),W(`ul`,Lt,[(H(!0),W(r,null,F(e.attachments,t=>(H(),W(`li`,{key:t.id,class:`wb-attachment`},[E(`button`,{type:`button`,class:`wb-attachment__preview`,title:q(Y)(`@WORKBENCH:点击预览`),onClick:e=>f(t),onContextmenu:e=>_(t,e)},[E(`div`,{class:P([`wb-attachment__icon`,{"wb-attachment__icon--img":e.isImage(t)}])},[e.isImage(t)?(H(),W(`img`,{key:0,src:`/api/workbench/attachments/${t.id}/raw`,alt:t.originalName,loading:`lazy`},null,8,zt)):(H(),W(`span`,Bt,b(t.ext.toUpperCase()),1))],2),E(`div`,Vt,[E(`div`,{class:`wb-attachment__name`,title:`${t.originalName} (${e.humanSize(t.size)})`},b(t.originalName),9,Ht)])],40,Rt),E(`button`,{class:`wb-attachment__del`,onClick:J(n=>e.onRemove(t),[`stop`]),title:q(Y)(`@WORKBENCH:删除`)},`×`,8,Ut)]))),128))])):u(``,!0)],34),(H(),o(s,{to:`body`},[d.value&&c.value.length>0?(H(),o(q(k),{key:0,"url-list":c.value,"initial-index":l.value,"hide-on-click-modal":!0,onClose:p},null,8,[`url-list`,`initial-index`])):u(``,!0)])),(H(),o(s,{to:`body`},[h.value.visible&&h.value.att&&e.isImage(h.value.att)?(H(),W(`ul`,{key:0,class:`wb-ctx-menu`,style:Ce({top:h.value.y+`px`,left:h.value.x+`px`}),onContextmenu:n[6]||=J(()=>{},[`prevent`])},[E(`li`,{class:P([`wb-ctx-menu__item`,{"is-disabled":g.value}]),onClick:y},[n[7]||=E(`span`,{class:`wb-ctx-menu__icon`,"aria-hidden":`true`},[E(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.8`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[E(`rect`,{x:`9`,y:`9`,width:`11`,height:`11`,rx:`2`}),E(`path`,{d:`M5 15V5a2 2 0 0 1 2-2h10`})])],-1),E(`span`,null,b(q(Y)(`@WORKBENCH:复制图片`)),1)],2)],36)):u(``,!0)]))],64))}}),[[`__scopeId`,`data-v-9e1ed466`]]),Gt=[`aria-expanded`],Kt={class:`wb-log-summary__left`},qt={key:0,class:`wb-log-summary__status wb-log-summary__status--running`},Jt={class:`wb-log-summary__label`},Yt={key:0,class:`wb-log-summary__elapsed`},Xt={key:1,class:`wb-log-summary__status wb-log-summary__status--pending`},Zt={class:`wb-log-summary__label`},Qt={key:2,class:`wb-log-summary__status wb-log-summary__status--done`},$t={key:0,class:`wb-log-summary__icon`},en={key:1,class:`wb-log-summary__icon`},tn={class:`wb-log-summary__label`},nn={key:2,class:`wb-log-summary__elapsed`},rn={key:3},an={class:`wb-log-summary__right`},on={class:`wb-log-summary__meta`},sn=[`title`],cn={class:`wb-log-details__body`},ln=[`open`],un={class:`wb-log-section__summary`},dn={class:`wb-log-section__tag wb-log-section__tag--user`},fn={class:`wb-log-section__count`},pn=[`title`],mn={class:`wb-log-section__pre wb-log-section__pre--user`},hn=[`open`],gn={class:`wb-log-section__summary`},_n={class:`wb-log-section__tag wb-log-section__tag--think`},vn={class:`wb-log-section__count`},yn=[`title`],bn={class:`wb-log-section__pre wb-log-section__pre--think`},xn={class:`wb-log-pre__head`},Sn={class:`wb-log-pre__label`},Cn={class:`wb-log-pre__meta`},wn=[`title`],Tn=[`title`,`disabled`],En={key:1,class:`wb-log-pre__empty`},Dn={key:1,class:`wb-log-fullscreen__empty`},On=64*1024,kn=60,An=Ee(e({__name:`JobLogDetails`,props:{job:{}},setup(e){let t=e,n=M(!1);function r(){n.value=!n.value}function i(){let e=t.job.output||``;return e?e.length<=On?e:`${Y(`@WORKBENCH:…(前文已截断)`)}\n${e.slice(-65536)}`:``}async function a(e){try{if(navigator?.clipboard?.writeText)return await navigator.clipboard.writeText(e),!0}catch{}try{let t=document.createElement(`textarea`);t.value=e,t.style.position=`fixed`,t.style.opacity=`0`,t.style.left=`-9999px`,document.body.appendChild(t),t.select();let n=document.execCommand(`copy`);return document.body.removeChild(t),n}catch{return!1}}async function s(e){let n=t.job[e]||``;if(!n){m.warning(Y(`@WORKBENCH:暂无内容可复制`));return}await a(n)?m.success(Y(`@WORKBENCH:已复制到剪贴板`)):m.error(Y(`@WORKBENCH:复制失败`))}async function c(){let e=[];if(t.job.prompt&&e.push(`## ${Y(`@WORKBENCH:用户提示词`)}\n\n${t.job.prompt}`),t.job.thinking&&e.push(`## ${Y(`@WORKBENCH:Claude 思考`)}\n\n${t.job.thinking}`),t.job.output&&e.push(`## ${Y(`@WORKBENCH:模型返回`)}\n\n${t.job.output}`),!e.length){m.warning(Y(`@WORKBENCH:暂无内容可复制`));return}await a(e.join(`
6
-
7
- ---
8
-
9
- `))?m.success(Y(`@WORKBENCH:已复制到剪贴板`)):m.error(Y(`@WORKBENCH:复制失败`))}let l=C(()=>i()),d=C(()=>t.job.status===`running`||t.job.status===`pending`),p=C(()=>{let e=t.job.status;return e===`done`||e===`error`||e===`cancelled`}),h=M(0),g=null;function _(){v(),g=setInterval(()=>{let e=l.value.length;if(e===0){h.value=0,v();return}let t=Math.max(1,Math.ceil(kn/30));h.value<e&&(h.value=Math.min(e,h.value+t)),h.value>=e&&v()},33)}function v(){g&&=(clearInterval(g),null)}R(()=>[t.job.output?.length||0,t.job.status],([e,t])=>{t===`done`||t===`error`||t===`cancelled`?(v(),h.value=e):h.value<e&&!g&&_()},{immediate:!0}),N(()=>v());let y=C(()=>l.value.slice(0,h.value)),x=C(()=>(t.job.output||``).slice(0,h.value)),S=C(()=>h.value>=(t.job.output||``).length),w=M(null);R(()=>t.job.status,(e,t)=>{e===`running`&&t!==`running`&&(w.value=w.value??Date.now())});let T=C(()=>{if(!w.value)return``;let e=w.value,n=t.job.endedAt?new Date(t.job.endedAt).getTime():Date.now(),r=Math.max(0,Math.floor((n-e)/1e3));return r<60?`${r}s`:`${Math.floor(r/60)}分${(r%60).toString().padStart(2,`0`)}秒`}),D=M(null),O=!1,k=M(!1);function A(){if(O)return;let e=t.job.status;e===`running`||e===`pending`?k.value=(t.job.thinking||``).length>0:k.value=!1}function ee(e){let t=e.target;O=!0,k.value=t.open}R(()=>t.job.status,(e,t)=>{!(t===`running`||t===`pending`)&&(e===`running`||e===`pending`)&&(O=!1),A()}),R(()=>(t.job.thinking||``).length,()=>A(),{immediate:!0});let F=!1,te=M(!0);function ne(e){let t=e.target;F=!0,te.value=t.open}R(()=>t.job.status,(e,t)=>{!(t===`running`||t===`pending`)&&(e===`running`||e===`pending`)?(F=!1,te.value=!0):F||(te.value=!0)}),R(()=>(t.job.output||``).length,async()=>{n.value||(await V(),D.value&&(D.value.scrollTop=D.value.scrollHeight))});let I=M(!1),re=C(()=>!!(t.job.output&&t.job.output.length)),L=M(null);R(I,async e=>{e&&(await V(),L.value&&(L.value.scrollTop=L.value.scrollHeight))}),R(()=>(t.job.output||``).length,async()=>{I.value&&(await V(),L.value&&(L.value.scrollTop=L.value.scrollHeight))});function ie(){}return(t,i)=>{let a=be;return H(),W(`div`,{class:P([`wb-log-details`,{"is-running":d.value,"is-pending":e.job.status===`pending`,"is-finished":p.value}])},[E(`div`,{class:`wb-log-summary`,onClick:r,role:`button`,"aria-expanded":!n.value},[E(`span`,Kt,[e.job.status===`running`?(H(),W(`span`,qt,[E(`span`,Jt,b(q(Y)(`@WORKBENCH:正在执行…`)),1),i[5]||=E(`span`,{class:`wb-log-dots`,"aria-hidden":`true`},[E(`span`,{class:`wb-log-dots__dot`}),E(`span`,{class:`wb-log-dots__dot`}),E(`span`,{class:`wb-log-dots__dot`})],-1),T.value?(H(),W(`span`,Yt,b(T.value),1)):u(``,!0)])):e.job.status===`pending`?(H(),W(`span`,Xt,[E(`span`,Zt,b(q(Y)(`@WORKBENCH:排队中…`)),1),i[6]||=E(`span`,{class:`wb-log-dots`,"aria-hidden":`true`},[E(`span`,{class:`wb-log-dots__dot`}),E(`span`,{class:`wb-log-dots__dot`}),E(`span`,{class:`wb-log-dots__dot`})],-1)])):p.value?(H(),W(`span`,Qt,[e.job.status===`error`?(H(),W(`span`,$t,`✗`)):(H(),W(`span`,en,`✓`)),E(`span`,tn,b(e.job.status===`error`?q(Y)(`@WORKBENCH:执行出错`):q(Y)(`@WORKBENCH:执行完成`)),1),T.value?(H(),W(`span`,nn,b(T.value),1)):u(``,!0)])):(H(),W(`span`,rn,b(q(Y)(`@WORKBENCH:查看执行日志`)),1))]),E(`span`,an,[E(`span`,on,b((e.job.output||``).length)+` `+b(q(Y)(`@WORKBENCH:字符`)),1),E(`button`,{type:`button`,class:`wb-log-copy`,title:q(Y)(`@WORKBENCH:复制全部(含提示词与输出)`),onClick:J(c,[`stop`])},` ⧉ `+b(q(Y)(`@WORKBENCH:复制全部`)),9,sn)])],8,Gt),de(E(`div`,cn,[e.job.prompt?(H(),W(`details`,{key:0,class:`wb-log-section`,open:te.value,onToggle:ne},[E(`summary`,un,[E(`span`,dn,b(q(Y)(`@WORKBENCH:用户提示词`)),1),E(`span`,fn,b((e.job.prompt||``).length)+` `+b(q(Y)(`@WORKBENCH:字符`)),1),E(`button`,{type:`button`,class:`wb-log-copy wb-log-copy--sm`,title:q(Y)(`@WORKBENCH:复制用户提示词`),onClick:i[0]||=J(e=>s(`prompt`),[`stop`])},` ⧉ `+b(q(Y)(`@WORKBENCH:复制`)),9,pn)]),E(`pre`,mn,b(e.job.prompt),1)],40,ln)):u(``,!0),e.job.thinking?(H(),W(`details`,{key:1,class:`wb-log-section`,open:k.value,onToggle:ee},[E(`summary`,gn,[E(`span`,_n,b(q(Y)(`@WORKBENCH:Claude 思考`)),1),E(`span`,vn,b((e.job.thinking||``).length)+` `+b(q(Y)(`@WORKBENCH:字符`)),1),E(`button`,{type:`button`,class:`wb-log-copy wb-copy--sm`,title:q(Y)(`@WORKBENCH:复制思考内容`),onClick:i[1]||=J(e=>s(`thinking`),[`stop`])},` ⧉ `+b(q(Y)(`@WORKBENCH:复制`)),9,yn)]),E(`pre`,bn,b(e.job.thinking),1)],40,hn)):u(``,!0),E(`div`,xn,[E(`span`,Sn,b(q(Y)(`@WORKBENCH:模型返回`)),1),E(`span`,Cn,b((e.job.output||``).length)+` `+b(q(Y)(`@WORKBENCH:字符`)),1),E(`button`,{type:`button`,class:`wb-log-copy wb-log-copy--sm`,title:q(Y)(`@WORKBENCH:复制模型返回`),onClick:i[2]||=J(e=>s(`output`),[`stop`])},` ⧉ `+b(q(Y)(`@WORKBENCH:复制`)),9,wn),E(`button`,{type:`button`,class:`wb-log-copy wb-log-copy--sm`,title:q(Y)(`@WORKBENCH:全屏查看模型返回`),disabled:!re.value,onClick:i[3]||=J(e=>I.value=!0,[`stop`])},` ⛶ `+b(q(Y)(`@WORKBENCH:全屏`)),9,Tn)]),E(`div`,{ref_key:`preRef`,ref:D,class:`wb-log-pre`},[re.value?(H(),o(q(B),{key:0,content:y.value,final:S.value,typewriter:!1,class:`wb-log-pre__render`},null,8,[`content`,`final`])):(H(),W(`div`,En,b(q(Y)(`@WORKBENCH:(暂无输出)`)),1))],512),j(a,{modelValue:I.value,"onUpdate:modelValue":i[4]||=e=>I.value=e,title:q(Y)(`@WORKBENCH:模型返回 - 全屏查看`),fullscreen:``,"close-on-click-modal":!1,class:`wb-log-fullscreen-dialog`,onClosed:ie},{default:U(()=>[E(`div`,{ref_key:`fullscreenContainerRef`,ref:L,class:`wb-log-fullscreen`},[re.value?(H(),o(q(B),{key:0,content:x.value,final:S.value,typewriter:!1,class:`wb-log-fullscreen__render`},null,8,[`content`,`final`])):(H(),W(`div`,Dn,b(q(Y)(`@WORKBENCH:(暂无输出)`)),1))],512)]),_:1},8,[`modelValue`,`title`])],512),[[f,!n.value]])],2)}}}),[[`__scopeId`,`data-v-c34148d0`]]);function jn(e){switch(e){case`todo`:return Y(`@WORKBENCH:待执行`);case`running`:return Y(`@WORKBENCH:执行中`);case`done`:return Y(`@WORKBENCH:已完成`);case`error`:return Y(`@WORKBENCH:出错`);case`cancelled`:return Y(`@WORKBENCH:已取消`);case`pending`:return Y(`@WORKBENCH:排队中`);default:return e}}function Mn(e){switch(e){case`running`:return`var(--color-primary)`;case`done`:return`#22c55e`;case`error`:return`#ef4444`;case`cancelled`:return`#9ca3af`;case`pending`:return`#f59e0b`;default:return`var(--text-tertiary)`}}var Nn={class:`exec-logs`},Pn={class:`exec-logs__head`},Fn={class:`exec-logs__title-block`},In={class:`exec-logs__stats`},Ln={class:`exec-logs__head-actions`},Rn={class:`exec-logs__config`},zn={class:`exec-logs__config-label`},Bn={class:`exec-logs__config-field`},Vn={class:`exec-logs__config-name`},Hn={class:`exec-logs__config-field`},Un={class:`exec-logs__config-name`},Wn={class:`exec-logs__filter`},Gn={key:0,class:`exec-logs__batch-meta`},Kn={key:0,class:`exec-logs__batch`},qn={class:`exec-logs__list`},Jn={key:0,class:`exec-logs__empty`},Yn={class:`exec-logs__empty-art`,"aria-hidden":`true`},Xn={class:`exec-logs__empty-title`},Zn={class:`exec-logs__empty-hint`},Qn={class:`exec-card__head`},$n=[`title`],er={class:`exec-card__meta`},tr={key:0,class:`exec-card__task`},nr={key:1,class:`exec-card__time`},rr={key:2,class:`exec-card__exit`},ir=[`title`,`onClick`],ar={key:0,class:`exec-card__error`},or={key:1,class:`exec-logs__pager`},sr=50,cr=Ee(e({__name:`ExecutionLogManager`,setup(e){function t(e){return e instanceof Error?e.message:String(e)}let n=M([]),a=M(0),o=ae({count:0,sizeMB:0,byStatus:{}}),s=M(!1),c=M(new Set),d=ae({q:``,status:``,page:1}),f=M({maxCount:500,maxSizeMB:256}),h=ae({maxCount:500,maxSizeMB:256}),g=M(!1),v=[{value:`pending`,label:Y(`@WORKBENCH:排队中`)},{value:`running`,label:Y(`@WORKBENCH:执行中`)},{value:`done`,label:Y(`@WORKBENCH:已完成`)},{value:`error`,label:Y(`@WORKBENCH:出错`)},{value:`cancelled`,label:Y(`@WORKBENCH:已取消`)}],x=C(()=>n.value.length>0&&n.value.every(e=>c.value.has(e.id))),S=C(()=>n.value.some(e=>c.value.has(e.id))&&!x.value);async function w(){s.value=!0;try{let e=new URLSearchParams;d.q&&e.set(`q`,d.q),d.status&&e.set(`status`,d.status),e.set(`limit`,String(sr)),e.set(`offset`,String((d.page-1)*sr));let t=await fetch(`/api/workbench/jobs/list?${e.toString()}`).then(e=>e.json());if(!t.success)throw Error(t.error||`list failed`);n.value=t.jobs,a.value=t.total,o.count=t.stats.count,o.sizeMB=t.stats.sizeMB,o.byStatus=t.stats.byStatus;let r=new Set(n.value.map(e=>e.id));for(let e of Array.from(c.value))r.has(e)||c.value.delete(e)}catch(e){m.error(Y(`@WORKBENCH:加载失败`)+`: `+t(e))}finally{s.value=!1}}async function D(){try{let e=await fetch(`/api/workbench/jobs/config`).then(e=>e.json());e.success&&(f.value=e.config,h.maxCount=e.config.maxCount,h.maxSizeMB=e.config.maxSizeMB)}catch{}}async function k(){g.value=!0;try{let e=await fetch(`/api/workbench/jobs/config`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({maxCount:h.maxCount,maxSizeMB:h.maxSizeMB})}).then(e=>e.json());if(!e.success)throw Error(e.error||`save failed`);f.value=e.config,m.success(Y(`@WORKBENCH:已保存策略`)),await w()}catch(e){m.error(Y(`@WORKBENCH:保存失败`)+`: `+t(e))}finally{g.value=!1}}function A(){d.page=1,w()}function N(){d.q=``,d.status=``,d.page=1,w()}function ee(e,t){t?c.value.add(e):c.value.delete(e),c.value=new Set(c.value)}function te(e){if(e)for(let e of n.value)c.value.add(e.id);else for(let e of n.value)c.value.delete(e.id);c.value=new Set(c.value)}async function ne(e){try{await p.confirm(Y(`@WORKBENCH:确定要删除所选的 {count} 条日志吗?`,{count:1}),Y(`@WORKBENCH:删除`),{type:`warning`})}catch{return}try{let t=await fetch(`/api/workbench/jobs/${e}`,{method:`DELETE`}).then(e=>e.json());if(!t.success)throw Error(t.error||`delete failed`);c.value.delete(e),c.value=new Set(c.value),await w()}catch(e){m.error(Y(`@WORKBENCH:保存失败`)+`: `+t(e))}}async function re(){let e=Array.from(c.value);if(e.length!==0){try{await p.confirm(Y(`@WORKBENCH:确定要删除所选的 {count} 条日志吗?`,{count:e.length}),Y(`@WORKBENCH:批量删除`),{type:`warning`})}catch{return}try{let t=await fetch(`/api/workbench/jobs/batch-delete`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({ids:e})}).then(e=>e.json());if(!t.success)throw Error(t.error||`batch delete failed`);m.success(Y(`@WORKBENCH:成功删除 {count} 条`,{count:t.removed||e.length})),c.value=new Set,await w()}catch(e){m.error(Y(`@WORKBENCH:保存失败`)+`: `+t(e))}}}async function L(){let e=o.count;if(e!==0){try{await p.confirm(Y(`@WORKBENCH:确定要清空所有 {count} 条执行日志吗?此操作不可恢复。`,{count:e}),Y(`@WORKBENCH:清空全部`),{type:`warning`,confirmButtonText:Y(`@WORKBENCH:清空全部`)})}catch{return}try{let t=await fetch(`/api/workbench/jobs/clear`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({confirm:!0})}).then(e=>e.json());if(!t.success)throw Error(t.error||`clear failed`);m.success(Y(`@WORKBENCH:成功删除 {count} 条`,{count:t.removed||e})),c.value=new Set,await w()}catch(e){m.error(Y(`@WORKBENCH:保存失败`)+`: `+t(e))}}}function R(e,t){if(!e)return``;let n=new Date(e).getTime(),r=t?new Date(t).getTime():Date.now(),i=Math.max(0,r-n);return i<1e3?`${i}ms`:i<6e4?`${(i/1e3).toFixed(1)}s`:i<36e5?`${Math.floor(i/6e4)}m ${Math.floor(i%6e4/1e3)}s`:`${Math.floor(i/36e5)}h ${Math.floor(i%36e5/6e4)}m`}return oe(()=>{w(),D()}),(e,t)=>{let f=fe,p=l,m=xe,C=I,D=ie,M=ue,ae=i,z=he,oe=_;return H(),W(`div`,Nn,[E(`header`,Pn,[E(`div`,Fn,[E(`span`,In,b(q(Y)(`@WORKBENCH:共 {count} 条,占 {size} MB`,{count:o.count,size:o.sizeMB})),1)]),E(`div`,Ln,[j(f,{icon:q(K),size:`small`,loading:s.value,onClick:w},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:刷新`)),1)]),_:1},8,[`icon`,`loading`]),j(f,{type:`danger`,plain:``,size:`small`,disabled:o.count===0,onClick:L},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:清空全部`)),1)]),_:1},8,[`disabled`])])]),E(`div`,Rn,[E(`span`,zn,b(q(Y)(`@WORKBENCH:保存策略`)),1),E(`span`,Bn,[E(`span`,Vn,b(q(Y)(`@WORKBENCH:最大条数`)),1),j(p,{modelValue:h.maxCount,"onUpdate:modelValue":t[0]||=e=>h.maxCount=e,min:0,max:1e4,step:50,size:`small`,"controls-position":`right`,style:{width:`130px`}},null,8,[`modelValue`])]),E(`span`,Hn,[E(`span`,Un,b(q(Y)(`@WORKBENCH:最大体积 (MB)`)),1),j(p,{modelValue:h.maxSizeMB,"onUpdate:modelValue":t[1]||=e=>h.maxSizeMB=e,min:0,max:10240,step:32,size:`small`,"controls-position":`right`,style:{width:`140px`}},null,8,[`modelValue`])]),j(f,{type:`primary`,size:`small`,loading:g.value,onClick:k},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:保存策略`)),1)]),_:1},8,[`loading`])]),E(`div`,Wn,[j(m,{modelValue:d.q,"onUpdate:modelValue":t[2]||=e=>d.q=e,placeholder:q(Y)(`@WORKBENCH:搜索标题 / 任务`),clearable:``,size:`small`,style:{width:`240px`},onKeyup:y(A,[`enter`]),onClear:A},null,8,[`modelValue`,`placeholder`]),j(D,{modelValue:d.status,"onUpdate:modelValue":t[3]||=e=>d.status=e,placeholder:q(Y)(`@WORKBENCH:全部状态`),clearable:``,size:`small`,style:{width:`130px`},onChange:A},{default:U(()=>[(H(),W(r,null,F(v,e=>j(C,{key:e.value,label:e.label,value:e.value},null,8,[`label`,`value`])),64))]),_:1},8,[`modelValue`,`placeholder`]),j(f,{size:`small`,onClick:N},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:重置`)),1)]),_:1}),t[5]||=E(`span`,{class:`exec-logs__filter-spacer`},null,-1),c.value.size>0?(H(),W(`span`,Gn,b(q(Y)(`@WORKBENCH:已选择 {count} 项`,{count:c.value.size})),1)):u(``,!0)]),c.value.size>0?(H(),W(`div`,Kn,[j(M,{"model-value":x.value,indeterminate:S.value,onChange:te},{default:U(()=>[O(b(x.value?q(Y)(`@WORKBENCH:取消全选`):q(Y)(`@WORKBENCH:全选`)),1)]),_:1},8,[`model-value`,`indeterminate`]),j(f,{type:`danger`,size:`small`,onClick:re},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:批量删除`)),1)]),_:1})])):u(``,!0),de((H(),W(`div`,qn,[!s.value&&n.value.length===0?(H(),W(`div`,Jn,[E(`div`,Yn,[j(ae,null,{default:U(()=>[j(q(T))]),_:1})]),E(`div`,Xn,b(q(Y)(`@WORKBENCH:暂无执行日志`)),1),E(`div`,Zn,b(q(Y)(`@WORKBENCH:点击「执行任务」开始一次执行,日志会出现在这里。`)),1)])):u(``,!0),(H(!0),W(r,null,F(n.value,e=>(H(),W(`article`,{key:e.id,class:P([`exec-card`,{"is-selected":c.value.has(e.id)}])},[E(`header`,Qn,[j(M,{"model-value":c.value.has(e.id),onChange:t=>ee(e.id,t)},null,8,[`model-value`,`onChange`]),E(`span`,{class:`exec-card__status`,style:Ce({color:q(Mn)(e.status),borderColor:q(Mn)(e.status)})},b(q(jn)(e.status)),5),E(`span`,{class:`exec-card__title`,title:e.title||q(Y)(`@WORKBENCH:无标题`)},b(e.title||q(Y)(`@WORKBENCH:无标题`)),9,$n),t[6]||=E(`span`,{class:`exec-card__spacer`},null,-1),E(`span`,er,[e.taskTitle?(H(),W(`span`,tr,`📁 `+b(e.taskTitle),1)):u(``,!0),e.startedAt?(H(),W(`span`,nr,`⏱ `+b(R(e.startedAt,e.endedAt)),1)):u(``,!0),e.exitCode===null?u(``,!0):(H(),W(`span`,rr,`exit `+b(e.exitCode),1))]),E(`button`,{type:`button`,class:`exec-card__del`,title:q(Y)(`@WORKBENCH:删除`),onClick:t=>ne(e.id)},`×`,8,ir)]),e.error?(H(),W(`p`,ar,`⚠ `+b(e.error),1)):u(``,!0),j(An,{job:e},null,8,[`job`])],2))),128))])),[[oe,s.value]]),a.value>sr?(H(),W(`footer`,or,[j(z,{"current-page":d.page,"onUpdate:currentPage":t[4]||=e=>d.page=e,"page-size":sr,total:a.value,layout:`prev, pager, next, total`,background:``,small:``,onCurrentChange:w},null,8,[`current-page`,`total`])])):u(``,!0)])}}}),[[`__scopeId`,`data-v-174a9b87`]]),lr={class:`workbench`},ur={class:`workbench__editor-row`},dr={class:`wb-sidebar`},fr={class:`wb-section`},pr={class:`wb-section__head`},mr={class:`wb-section__tag`},hr={class:`wb-section__title`},gr={class:`wb-pill wb-section__count`},_r={class:`wb-task-list`},vr=[`aria-expanded`,`title`,`onClick`,`onKeydown`],yr=[`title`],br={class:`wb-pill wb-task-group__count`},xr=[`data-icon`,`onClick`],Sr=[`data-icon`],Cr={class:`wb-task-item__body`},wr=[`title`],Tr={class:`wb-task-item__meta`},Er=[`title`],Dr={class:`wb-pill wb-task-item__num`},Or=[`title`],kr={class:`wb-pill wb-task-item__num`},Ar=[`title`],jr=[`title`,`aria-label`],Mr=[`title`],Nr=[`title`],Pr=[`onClick`,`title`,`aria-label`],Fr={key:0,class:`wb-empty wb-empty--rich`},Ir={class:`wb-empty__art`,"aria-hidden":`true`},Lr={class:`wb-empty__title`},Rr={class:`wb-empty__hint`},zr={class:`wb-empty__cta`},Br={class:`wb-section`},Vr={class:`wb-section__head`},Hr={class:`wb-section__tag wb-section__tag--accent`},Ur={class:`wb-section__title`},Wr={class:`wb-pill wb-section__count`},Gr=[`title`,`aria-label`],Kr={class:`wb-prompt-list`},qr={class:`wb-prompt-item__icon`},Jr=[`onClick`,`title`],Yr=[`title`],Xr=[`onClick`,`title`,`aria-label`],Zr={key:0,class:`wb-empty wb-empty--compact`},Qr={class:`wb-split`},$r={key:0,class:`wb-placeholder`},ei={class:`wb-split__header`},ti=[`placeholder`],ni=[`title`],ri={key:0,class:`wb-meta-save__dot`},ii={key:1,class:`wb-meta-save__check`},ai={key:2,class:`wb-meta-save__bang`},oi={key:3,class:`wb-meta-save__dot`},si={value:null},ci=[`value`],li=[`aria-label`],ui=[`aria-selected`],di=[`aria-selected`],fi=[`disabled`,`title`],pi=[`title`,`aria-label`],mi=[`open`],hi={class:`wb-task-desc__summary`},gi={class:`wb-task-desc__label`},_i={key:0,class:`wb-task-desc__tag`},vi={key:0},yi={key:1,class:`wb-task-desc__tag-attachment`},bi=[`placeholder`],xi={key:0,class:`wb-exec-list`},Si={class:`wb-exec-list__header`},Ci={class:`wb-exec-list__title`},wi={class:`wb-split__sub-actions`},Ti={key:0,class:`wb-dirty-badge`},Ei={class:`wb-exec-sub-list`},Di=[`onClick`],Oi={class:`wb-exec-sub-item__row1`},ki=[`title`],Ai=[`title`],ji={key:0,class:`wb-exec-sub-item__dirty-dot`,title:`未保存`},Mi={class:`wb-exec-sub-item__row2`},Ni={key:0,class:`wb-sub-item__pid`},Pi={class:`wb-exec-sub-item__actions`},Fi=[`title`,`onClick`],Ii=[`title`,`onClick`],Li=[`title`,`disabled`,`onClick`],Ri=[`title`,`disabled`,`onClick`],zi={key:0,class:`wb-empty wb-empty--rich`},Bi={class:`wb-empty__art`,"aria-hidden":`true`},Vi={class:`wb-empty__title`},Hi={class:`wb-empty__cta`},Ui={class:`wb-exec-detail`},Wi={key:0,class:`wb-placeholder`},Gi={class:`wb-exec-detail__head`},Ki=[`placeholder`],qi=[`title`],Ji=[`placeholder`],Yi={class:`wb-form-item__label wb-simple__override-summary`},Xi=[`title`],Zi=[`disabled`],Qi=[`placeholder`],$i={style:{display:`flex`,gap:`8px`,"align-items":`center`}},ea=`__simple`,ta=`__no_project__`,na=`.png,.jpg,.jpeg,.gif,.webp,.bmp,.svg,.pdf,.txt,.md,.csv,.json,.log`,ra=5*1024*1024,ia=Ee(e({__name:`WorkbenchView`,setup(e){let n=M([]),s=M([]),l=M([]),d=M(!1),f=M(null),h=C(()=>s.value.find(e=>e.id===f.value)||null),g=C(()=>h.value?.type===`simple`),_=M(null),x=C(()=>!h.value||g.value||!_.value?null:h.value.subtasks.find(e=>e.id===_.value)||null),w=M(new Map),k=M({title:``,desc:``,promptId:null,simpleOverride:``});function A(){let e=new Map;if(h.value)for(let t of h.value.subtasks)e.set(t.id,{id:t.id,title:t.title,desc:t.desc,promptOverride:t.promptOverride});w.value=e,h.value?k.value={title:h.value.title,desc:h.value.desc,promptId:h.value.promptId,simpleOverride:h.value.simpleOverride||``}:k.value={title:``,desc:``,promptId:null,simpleOverride:``}}let N=C(()=>{let e=new Set;if(!h.value)return e;for(let t of h.value.subtasks){let n=w.value.get(t.id);if(!n){e.add(t.id);continue}(n.title!==t.title||n.desc!==t.desc||n.promptOverride!==t.promptOverride)&&e.add(t.id)}return e}),re=C(()=>N.value.size>0),L=M(`idle`),se=M(0),ce=null,B=C(()=>{if(!h.value)return!1;let e=h.value;return k.value.title!==e.title||k.value.desc!==e.desc||k.value.promptId!==e.promptId||k.value.simpleOverride!==(e.simpleOverride||``)});function le(){ce!==null&&(clearTimeout(ce),ce=null)}async function ue(){if(!h.value)return!1;if(!B.value)return!0;if(L.value=`saving`,await _t(!1))return se.value=Date.now(),L.value=`saved`,setTimeout(()=>{L.value===`saved`&&Date.now()-se.value>=4e3&&(L.value=`idle`)},4e3),!0;L.value=`error`;let e=Date.now();return setTimeout(()=>{L.value===`error`&&Date.now()-e>=4e3&&(L.value=`idle`)},4e3),!1}R(()=>h.value?{id:h.value.id,title:h.value.title,desc:h.value.desc,promptId:h.value.promptId,simpleOverride:h.value.simpleOverride||``}:null,(e,t)=>{!e||!t||e.id!==t.id||(ce!==null&&clearTimeout(ce),ce=window.setTimeout(()=>{ue()},1500))},{deep:!0}),R(f,async(e,t)=>{le(),h.value&&B.value&&await ue()}),R(f,()=>{yt.value=!1});function V(e){try{let t=new Blob([JSON.stringify(e)],{type:`application/json`});navigator.sendBeacon?.(`/api/workbench/tasks`,t)}catch{}}function he(){h.value&&B.value&&V(h.value)}let G=ae({visible:!1,editing:null,name:``,content:``,aiLoading:!1}),K=ae({visible:!1,text:``,loading:!1,saving:!1}),Ee=M(!1),X=ae({visible:!1,editing:null,title:``,desc:``,promptId:null,type:`complex`,simpleOverride:``}),Oe=null,ke=De();function Ae(){ke.setRunning(l.value.filter(e=>e.status===`running`).length)}function Z(e){return l.value.find(t=>t.subId===e)||null}function je(e,t){if(e===`hello`){l.value=t.jobs||[],Ae();return}if(e===`job:update`){let e=t,n=l.value.findIndex(t=>t.id===e.id);n>=0?l.value[n]=e:l.value.push(e),Ae();return}if(e===`job:thinking-delta`||e===`job:output-delta`){let n=e===`job:thinking-delta`?`thinking`:`output`,r=t?.delta||``;if(!r)return;let i=l.value.findIndex(e=>e.id===t.id);if(i<0)return;let a=l.value[i][n]||``;l.value[i][n]=a+r;return}if(e===`sub:update`){let e=s.value.find(e=>e.id===t.taskId);if(e){let n=e.subtasks.findIndex(e=>e.id===t.sub.id);n>=0&&(e.subtasks[n]=t.sub)}}if(e===`task:update`){let e=s.value.findIndex(e=>e.id===t.id);e>=0&&(s.value[e]=t)}e===`task:error`&&m.error(t.error||Y(`@WORKBENCH:执行出错`))}let Me=[{key:`image`,patterns:[/图\s*片/,/上\s*传/,/upload/i,/image/i,/screenshot/i,/截图/,/附件/,/attachment/i]},{key:`icon`,patterns:[/图\s*标/,/icon/i,/svg/i]},{key:`test`,patterns:[/测\s*试/,/test/i,/spec/i,/\bqa\b/i]},{key:`ui`,patterns:[/ui\s*优\s*化/,/样\s*式/,/style/i,/css/i,/界面/,/视\s*觉/,/design/i]}];function Ne(e){let t=(e||``).trim();if(!t)return`doc`;for(let e of Me)if(e.patterns.some(e=>e.test(t)))return e.key;return`doc`}let Pe={icon:z(T),image:z(me),test:z(D),ui:z(pe),doc:z(T),idea:z(pe)};function Fe(e){return Pe[Ne(e.title)]}function Ie(e){return e?Z(`${e.id}${ea}`):null}function Le(e){return e?e.status===`pending`||e.status===`running`?`running`:e.status===`done`?`done`:e.status===`cancelled`?`cancelled`:`error`:`idle`}function Re(e){return Array.isArray(e.attachments)?e.attachments.length:0}function ze(e){return Array.isArray(e.subtasks)?e.subtasks.length:0}function Be(e){return Array.isArray(e.subtasks)?e.subtasks.filter(e=>e&&e.status===`done`).length:0}function Ve(e){if(Array.isArray(e.subtasks)&&e.subtasks.some(e=>e&&e.status===`running`))return!0;let t=l.value.find(t=>t.subId===`${e.id}__simple`);return!!(t&&(t.status===`running`||t.status===`pending`))}async function He(){n.value=(await fetch(`/api/workbench/prompts`).then(e=>e.json()).catch(()=>({prompts:[]}))).prompts||[]}async function Ue(){s.value=(await fetch(`/api/workbench/tasks`).then(e=>e.json()).catch(()=>({tasks:[]}))).tasks||[],!f.value&&s.value.length>0&&(f.value=s.value[0].id),A()}let Q=M({path:``,name:``});async function We(){let e=await fetch(`/api/workbench/current-project`).then(e=>e.json()).catch(()=>({}));e&&typeof e.projectPath==`string`&&(Q.value={path:e.projectPath,name:e.projectName||``})}let Ge=M(new Set);function Ke(e){return Ge.value.has(e)}function qe(e){Ge.value.has(e)?Ge.value.delete(e):Ge.value.add(e),Ge.value=new Set(Ge.value)}let Je=C(()=>{let e=s.value,t=new Map;for(let n of e){let e=(n.projectPath||``).trim()||ta;t.has(e)||t.set(e,[]),t.get(e).push(n)}let n=Q.value.path,r=Array.from(t.keys()).sort((e,t)=>e===n?-1:t===n||e===ta?1:t===ta?-1:e.localeCompare(t));return{groups:r.map(e=>({path:e,label:e===ta?Y(`@WORKBENCH:未关联项目`):e,tasks:t.get(e)})),hasMultiple:r.length>1}});function Ye(e){if(!e||e===ta)return e;let t=e.split(/[\\/]/).filter(Boolean);return t.length<=1?e:t.slice(-2).join(`/`)}R(()=>Je.value.groups.map(e=>e.path),e=>{let t=Q.value.path,n=new Set(Ge.value),r=!1;for(let i of e)i!==t&&!n.has(i)&&(n.add(i),r=!0);r&&(Ge.value=n)},{immediate:!0});async function Xe(){l.value=(await fetch(`/api/workbench/jobs`).then(e=>e.json()).catch(()=>({jobs:[]}))).jobs||[],Ae()}async function Ze(e){try{let t=await fetch(`/api/workbench/jobs/by-task/${encodeURIComponent(e)}`,{method:`DELETE`}).then(e=>e.json());return t?.success?(l.value=l.value.filter(t=>t.taskId!==e),Ae(),t.removed||0):(console.warn(`[clearJobsByTask] failed:`,t?.error),0)}catch(e){return console.warn(`[clearJobsByTask] error:`,e),0}}function Qe(){Oe&&=(Oe.close(),null),Oe=new EventSource(`/api/workbench/events`),Oe.onmessage=e=>{try{let t=JSON.parse(e.data);je(t.event,t.payload)}catch{}},Oe.onerror=()=>{Oe&&=(Oe.close(),null),setTimeout(Qe,3e3)}}function $e(){G.editing=null,G.name=``,G.content=``,G.aiLoading=!1,G.visible=!0}function et(e){G.editing=e,G.name=e.name,G.content=e.content,G.aiLoading=!1,G.visible=!0}async function tt(){if(!G.aiLoading){G.aiLoading=!0;try{let e=await fetch(`/api/workbench/prompts/ai-generate`,{method:`POST`}).then(e=>e.json());e.success?(G.name=e.name||G.name,G.content=e.result||``,m.success(Y(`@WORKBENCH:已生成,可继续编辑`))):m.error(e.error||Y(`@WORKBENCH:生成失败`))}catch(e){m.error(Y(`@WORKBENCH:网络错误: `)+(e&&e.message||e))}finally{G.aiLoading=!1}}}async function nt(){K.visible=!0,K.loading=!0;try{let e=await fetch(`/api/workbench/prompts/ai-instruction`).then(e=>e.json());e.success?K.text=e.instruction||``:m.error(e.error||Y(`@WORKBENCH:读取指令失败`))}catch(e){m.error(Y(`@WORKBENCH:读取指令失败`)+`: `+(e&&e.message||e))}finally{K.loading=!1}}async function rt(){if(!K.text.trim()){m.warning(Y(`@WORKBENCH:指令内容不能为空`));return}K.saving=!0;try{let e=await fetch(`/api/workbench/prompts/ai-instruction`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({instruction:K.text})}).then(e=>e.json());e.success?(m.success(Y(`@WORKBENCH:已保存指令`)),K.visible=!1):m.error(e.error||Y(`@WORKBENCH:保存失败`))}catch(e){m.error(Y(`@WORKBENCH:网络错误: `)+(e&&e.message||e))}finally{K.saving=!1}}async function it(){if(!G.name.trim()||!G.content.trim()){m.warning(Y(`@WORKBENCH:名称和内容不能为空`));return}let e={id:G.editing?.id,name:G.name.trim(),content:G.content},t=await fetch(`/api/workbench/prompts`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)}).then(e=>e.json());t.success?(m.success(Y(`@WORKBENCH:已保存`)),G.visible=!1,He()):m.error(t.error||Y(`@WORKBENCH:保存失败`))}async function at(e){await p.confirm(Y(`@WORKBENCH:删除提示词「{name}」?`,{name:e.name}),Y(`@WORKBENCH:确认`),{type:`warning`}),await fetch(`/api/workbench/prompts/${e.id}`,{method:`DELETE`}),He();for(let t of s.value)t.promptId===e.id&&(t.promptId=null,await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)}));Ue()}function ot(){X.editing=null,X.title=``,X.desc=``,X.promptId=null,X.type=`simple`,X.simpleOverride=``,X.visible=!0}async function st(){let e={id:X.editing?.id,title:X.title.trim(),desc:X.desc,promptId:X.promptId,type:X.type,simpleOverride:X.type===`simple`?X.simpleOverride:``,subtasks:X.editing?.subtasks||[]};!X.editing?.id&&Q.value.path&&(e.projectPath=Q.value.path);let t=await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)}).then(e=>e.json());if(t.success){m.success(Y(`@WORKBENCH:已保存`));let e=!X.editing?.id;X.visible=!1,await Ue(),e&&t.task?.id?(f.value=t.task.id,A()):f.value||=t.task.id}else m.error(t.error||Y(`@WORKBENCH:保存失败`))}async function ct(e,t){if(e.type===t)return;let n=e.type===`complex`&&t===`simple`&&(e.subtasks?.length??0)>0;if(n)try{await p.confirm(Y(`@WORKBENCH:任务「{title}」当前有 {n} 个子任务,切换为简单任务后会清空这些子任务,确认继续?`,{title:e.title,n:e.subtasks.length}),Y(`@WORKBENCH:切换任务类型`),{type:`warning`,confirmButtonText:Y(`@WORKBENCH:切换并清空`),cancelButtonText:Y(`@WORKBENCH:取消`)})}catch{return}let r={id:e.id,title:e.title,desc:e.desc,promptId:e.promptId,type:t,simpleOverride:e.simpleOverride||``,subtasks:n?[]:e.subtasks||[]},i=await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(r)}).then(e=>e.json());if(!i.success){m.error(i.error||Y(`@WORKBENCH:保存失败`));return}await Ue(),m.success(Y(t===`simple`?`@WORKBENCH:已切换为简单任务`:`@WORKBENCH:已切换为复杂任务`))}async function lt(e){h.value&&await ct(h.value,e)}async function ut(e){await p.confirm(Y(`@WORKBENCH:删除任务「{title}」及其所有子任务?`,{title:e.title}),Y(`@WORKBENCH:确认`),{type:`warning`}),await fetch(`/api/workbench/tasks/${e.id}`,{method:`DELETE`}),f.value===e.id&&(f.value=null),Ue()}async function dt(e){f.value!==e.id&&(le(),h.value&&B.value&&await ue(),f.value=e.id,A())}R(()=>h.value,e=>{if(!e||e.type===`simple`){_.value=null;return}_.value=e.subtasks.find(e=>e.status===`running`)?.id||e.subtasks[0]?.id||null},{immediate:!0}),R(()=>h.value?.subtasks?.length,()=>{!h.value||g.value||(!_.value||!h.value.subtasks.find(e=>e.id===_.value))&&(_.value=h.value.subtasks[0]?.id||null)});let ft=M(new Set);function pt(e){return ft.value.has(e)}function mt(e,t){t?ft.value.add(e):ft.value.delete(e),ft.value=new Set(ft.value)}async function ht(){if(!h.value)return;let e={id:`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,title:Y(`@WORKBENCH:新子任务`),desc:``,status:`todo`,promptOverride:``};h.value.subtasks.push(e),mt(e.id,!0);try{await _t(!1)}finally{mt(e.id,!1)}}async function gt(e){if(h.value){h.value.subtasks=h.value.subtasks.filter(t=>t.id!==e.id),mt(e.id,!0);try{await _t(!1)}finally{mt(e.id,!1)}}}async function _t(e){if(!h.value)return!1;let t=await fetch(`/api/workbench/tasks`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(h.value)}).then(e=>e.json());return t.success?(e&&m.success(Y(`@WORKBENCH:已保存拆分`)),await Ue(),!0):(m.error(t.error||Y(`@WORKBENCH:保存失败`)),!1)}async function vt(){await _t(!0)}let yt=M(!1);function bt(){if(h.value){if(!(h.value.title||``).trim()){m.warning(Y(`@WORKBENCH:请先填写任务标题`));return}yt.value=!0}}function xt(e){if(h.value){for(let t of e)h.value.subtasks.push({id:`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,title:t.title,desc:t.desc||``,status:`todo`,promptOverride:``,attachments:[]});m.success(Y(`@WORKBENCH:已生成 {n} 个子任务,请审阅后保存`,{n:e.length}))}}async function St(e){if(e.type===`simple`)return Ct(e);if(!e.subtasks||e.subtasks.length===0){m.warning(Y(`@WORKBENCH:请先拆分任务`));return}if(h.value&&h.value.id===e.id){let t=s.value.find(t=>t.id===e.id);if((!t||t.title!==h.value.title||t.desc!==h.value.desc||JSON.stringify(t.subtasks)!==JSON.stringify(h.value.subtasks)||t.promptId!==h.value.promptId)&&!await _t(!1))return}await Ze(e.id);let t=await fetch(`/api/workbench/tasks/${e.id}/run`,{method:`POST`}).then(e=>e.json());t.success?m.success(t.message||Y(`@WORKBENCH:已加入执行队列`)):m.error(t.error||Y(`@WORKBENCH:执行失败`))}async function Ct(e){if(h.value&&h.value.id===e.id){let t=s.value.find(t=>t.id===e.id);if((!t||t.title!==h.value.title||t.desc!==h.value.desc||t.promptId!==h.value.promptId||(t.simpleOverride||``)!==(h.value.simpleOverride||``))&&!await _t(!1))return}await Ze(e.id);let t=await fetch(`/api/workbench/tasks/${e.id}/run-simple`,{method:`POST`}).then(e=>e.json());t.success?m.success(t.message||Y(`@WORKBENCH:已加入执行队列`)):m.error(t.error||Y(`@WORKBENCH:执行失败`))}async function wt(e){if(!h.value)return;let t=h.value,n=Z(e.id);if(n&&(n.status===`running`||n.status===`pending`)){m.warning(Y(`@WORKBENCH:该子任务正在执行中`));return}let r=s.value.find(e=>e.id===t.id);if((!r||r.title!==t.title||r.desc!==t.desc||JSON.stringify(r.subtasks)!==JSON.stringify(t.subtasks)||r.promptId!==t.promptId)&&!await _t(!1))return;let i=await fetch(`/api/workbench/subtasks/${e.id}/run`,{method:`POST`}).then(e=>e.json()).catch(e=>({success:!1,error:e?.message||String(e)}));i.success?m.success(i.message||Y(`@WORKBENCH:已开始执行子任务`)):m.error(i.error||Y(`@WORKBENCH:执行失败`))}function Tt(e){if(e.status===`done`)return!1;let t=Z(e.id);return!(t&&(t.status===`running`||t.status===`pending`))}async function Et(e){if(h.value&&!pt(e.id)){mt(e.id,!0);try{let t=w.value.get(e.id);t&&w.value.set(e.id,{...t,status:`todo`}),e.status=`todo`,await _t(!1)}finally{mt(e.id,!1)}}}async function Dt(e){try{await p.confirm(Y(`@WORKBENCH:确认停止执行?已输出的内容会保留。`),Y(`@WORKBENCH:停止执行`),{confirmButtonText:Y(`@WORKBENCH:停止`),cancelButtonText:Y(`@WORKBENCH:取消`),type:`warning`})}catch{return}let t=await fetch(`/api/workbench/jobs/${e.id}/cancel`,{method:`POST`}).then(e=>e.json()).catch(e=>({success:!1,error:e?.message||String(e)}));t.success?m.success(Y(`@WORKBENCH:已发送停止信号`)):m.error(t.error||Y(`@WORKBENCH:停止失败`))}oe(async()=>{await Promise.all([He(),Ue(),We(),Xe()]),Qe(),window.addEventListener(`beforeunload`,he)}),_e(()=>{Oe&&=(Oe.close(),null),window.removeEventListener(`beforeunload`,he),h.value&&B.value&&V(h.value)});let Ot=new Set([`image/png`,`image/jpeg`,`image/jpg`,`image/gif`,`image/webp`,`image/bmp`,`image/svg+xml`,`application/pdf`,`text/plain`,`text/markdown`,`text/x-markdown`,`text/csv`,`application/json`,`text/json`,`text/x-log`]),kt=M({}),$=M(null);function At(e){return!!kt.value[e]}function Mt(e,t){if(e instanceof File)return e;let n=e.type||`application/octet-stream`;return new File([e],t,{type:n})}function Nt(e){return e.kind===`task`?`task-${e.task?.id??``}`:`sub-${e.sub.id}`}function Pt(e){let t=e.kind===`task`?e.task?.attachments:e.sub.attachments;return Array.isArray(t)?t:[]}function Ft(e,t){e.kind===`task`?e.task&&(e.task.attachments=t):e.sub.attachments=t}function It(e){return e.kind===`task`?`/api/workbench/tasks/${e.task?.id??``}/attachments`:`/api/workbench/subtasks/${e.sub.id}/attachments`}function Lt(e,t){return e.kind===`task`?`/api/workbench/tasks/${e.task?.id??``}/attachments/${t}`:`/api/workbench/subtasks/${e.sub.id}/attachments/${t}`}function Rt(e,t){if(!e.clipboardData)return;let n=Array.from(e.clipboardData.items).filter(e=>e.kind===`file`&&e.type.startsWith(`image/`));if(n.length>0){e.preventDefault();for(let e of n){let n=e.getAsFile();if(!n)continue;let r=(n.type.split(`/`)[1]||`png`).replace(`jpeg`,`jpg`);Bt(t,Mt(n,`paste-${new Date().toISOString().replace(/[:.]/g,`-`)}.${r}`))}return}let r=Array.from(e.clipboardData.items).filter(e=>e.kind===`file`&&!e.type.startsWith(`image/`));if(r.length>0){e.preventDefault();for(let e of r){let n=e.getAsFile();n&&Bt(t,Mt(n,n.name||`pasted-file`))}}}function zt(e,t){$.value=null,Array.from(e.dataTransfer?.files||[]).forEach(e=>Bt(t,e))}async function Bt(e,t){if(t.size>ra){m.error(`「${t.name}」${Y(`@WORKBENCH:超过 5MB 限制`)}`);return}if(!Ot.has(t.type)&&!t.name.match(/\.(png|jpg|jpeg|gif|webp|bmp|svg|pdf|txt|md|markdown|csv|json|log)$/i)){m.error(`${Y(`@WORKBENCH:不支持的文件类型`)}(${t.name})`);return}let n=Pt(e);if(n.length>=9){m.error(Y(`@WORKBENCH:单个任务最多 9 个附件`));return}if(n.find(e=>e.originalName===t.name&&e.size===t.size)){m.info(`${t.name} ${Y(`@WORKBENCH:已存在,已复用`)}`);return}let r=Nt(e);kt.value[r]=!0;try{let n=await fetch(It(e),{method:`POST`,headers:{"Content-Type":`application/octet-stream`,"X-Original-Name":t.name,"X-Mime-Type":t.type||`application/octet-stream`},body:t}).then(e=>e.json());if(n.success){let r=Pt(e);r.push(n.attachment),Ft(e,r),m.success(`${Y(`@WORKBENCH:已添加:`)}${t.name}`)}else m.error(n.error||Y(`@WORKBENCH:上传失败`))}catch(e){m.error(Y(`@WORKBENCH:上传失败`)+`:`+(e&&e.message||e))}finally{kt.value[r]=!1}}async function Vt(e,t){try{await p.confirm(Y(`@WORKBENCH:删除附件「{name}」?`,{name:t.originalName}),Y(`@WORKBENCH:确认`),{type:`warning`})}catch{return}let n=await fetch(Lt(e,t.id),{method:`DELETE`}).then(e=>e.json());n.success?(Ft(e,Pt(e).filter(e=>e.id!==t.id)),m.success(Y(`@WORKBENCH:已删除`))):m.error(n.error||Y(`@WORKBENCH:删除失败`))}function Ht(e){let t=document.createElement(`input`);t.type=`file`,t.accept=na,t.multiple=!0,t.onchange=()=>{Array.from(t.files||[]).forEach(t=>Bt(e,t))},t.click()}let Ut=new Set([`png`,`jpg`,`jpeg`,`gif`,`webp`,`bmp`,`svg`]);function Gt(e){return Ut.has(String(e.ext||``).toLowerCase())}function Kt(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/1024/1024).toFixed(2)} MB`}return(e,l)=>{let p=i,m=fe,C=be,w=xe,D=we,k=ee,A=ye,M=te,R=I,ae=ie;return H(),W(`div`,lr,[E(`div`,ur,[E(`aside`,dr,[E(`section`,fr,[E(`header`,pr,[E(`span`,mr,b(q(Y)(`@WORKBENCH:任务`)),1),E(`h3`,hr,b(q(Y)(`@WORKBENCH:任务列表`)),1),E(`span`,gr,b(s.value.length),1)]),E(`button`,{class:`wb-new-btn`,onClick:ot},[j(p,{class:`wb-new-btn__icon`},{default:U(()=>[j(q(ve))]),_:1}),E(`span`,null,b(q(Y)(`@WORKBENCH:新建任务`)),1),l[43]||=E(`span`,{class:`wb-new-btn__shortcut`},`N`,-1)]),E(`ul`,_r,[(H(!0),W(r,null,F(Je.value.groups,e=>(H(),W(r,{key:e.path},[Je.value.hasMultiple?(H(),W(`li`,{key:0,class:P([`wb-task-group__head`,{"is-current":e.path===Q.value.path,"is-collapsed":Ke(e.path)}]),role:`button`,tabindex:`0`,"aria-expanded":!Ke(e.path),title:Ke(e.path)?q(Y)(`@WORKBENCH:展开`):q(Y)(`@WORKBENCH:收起`),onClick:t=>qe(e.path),onKeydown:[y(J(t=>qe(e.path),[`prevent`]),[`enter`]),y(J(t=>qe(e.path),[`prevent`]),[`space`])]},[j(p,{class:`wb-task-group__caret`},{default:U(()=>[(H(),o(ne(Ke(e.path)?q(S):q(Se))))]),_:2},1024),j(p,{class:`wb-task-group__icon`},{default:U(()=>[j(q(ge))]),_:1}),E(`span`,{class:`wb-task-group__name`,title:e.path===Q.value.path?Q.value.path:e.label},b(e.path===Q.value.path?Q.value.name:Ye(e.label)),9,yr),E(`span`,br,b(e.tasks.length),1)],42,vr)):u(``,!0),Ke(e.path)?u(``,!0):(H(!0),W(r,{key:1},F(e.tasks,e=>(H(),W(`li`,{key:e.id,class:P([`wb-task-item`,{active:e.id===f.value,"has-attachment":Re(e)>0,"is-other-project":e.projectPath&&e.projectPath!==Q.value.path,"is-running":Ve(e)}]),"data-icon":Ne(e.title),onClick:t=>dt(e)},[E(`div`,{class:`wb-task-item__avatar`,"data-icon":Ne(e.title)},[j(p,null,{default:U(()=>[(H(),o(ne(Fe(e))))]),_:2},1024)],8,Sr),E(`div`,Cr,[E(`div`,{class:`wb-task-item__title`,title:e.title},b(e.title||q(Y)(`@WORKBENCH:未命名任务`)),9,wr),E(`div`,Tr,[ze(e)>0?(H(),W(`span`,{key:0,class:P([`wb-task-item__meta-item`,{"wb-task-item__meta-item--running":Ve(e)}]),title:q(Y)(`@WORKBENCH:个子任务`)},[j(p,{class:`wb-task-item__meta-icon`},{default:U(()=>[j(q(t))]),_:1}),E(`span`,Dr,b(Be(e))+`/`+b(ze(e)),1)],10,Er)):u(``,!0),Re(e)>0?(H(),W(`span`,{key:1,class:`wb-task-item__meta-item`,title:q(Y)(`@WORKBENCH:附件`)},[j(p,{class:`wb-task-item__meta-icon`},{default:U(()=>[j(q(me))]),_:1}),E(`span`,kr,b(Re(e)),1)],8,Or)):u(``,!0),e.promptId?(H(),W(`span`,{key:2,class:`wb-task-item__meta-item wb-task-item__meta-item--accent`,title:q(Y)(`@WORKBENCH:已绑定预置提示词`)},[j(p,{class:`wb-task-item__meta-icon`},{default:U(()=>[j(q(pe))]),_:1})],8,Ar)):u(``,!0),E(`button`,{type:`button`,class:P([`wb-task-item__meta-item wb-task-item__type-toggle`,e.type===`simple`?`wb-task-item__meta-item--simple`:`wb-task-item__meta-item--complex`]),title:e.type===`simple`?q(Y)(`@WORKBENCH:简单任务 - 点击切换为复杂任务`):q(Y)(`@WORKBENCH:复杂任务 - 点击切换为简单任务`),"aria-label":e.type===`simple`?q(Y)(`@WORKBENCH:切换为复杂任务`):q(Y)(`@WORKBENCH:切换为简单任务`)},b(e.type===`simple`?q(Y)(`@WORKBENCH:简单`):q(Y)(`@WORKBENCH:复杂`)),11,jr),e.projectPath&&e.projectPath!==Q.value.path?(H(),W(`span`,{key:3,class:`wb-task-item__meta-item wb-task-item__meta-item--project`,title:e.projectPath},b(Ye(e.projectPath)),9,Mr)):u(``,!0)])]),Ve(e)?(H(),W(`span`,{key:0,class:`wb-task-item__running-dot`,title:q(Y)(`@WORKBENCH:执行中`),"aria-hidden":`true`},null,8,Nr)):u(``,!0),E(`button`,{class:`wb-task-item__del`,onClick:J(t=>ut(e),[`stop`]),title:q(Y)(`@WORKBENCH:删除`),"aria-label":q(Y)(`@WORKBENCH:删除`)},[j(p,null,{default:U(()=>[j(q(v))]),_:1})],8,Pr)],10,xr))),128))],64))),128)),s.value.length===0?(H(),W(`li`,Fr,[E(`div`,Ir,[j(p,null,{default:U(()=>[j(q(Te))]),_:1})]),E(`div`,Lr,b(q(Y)(`@WORKBENCH:暂无任务`)),1),E(`div`,Rr,b(q(Y)(`@WORKBENCH:点击上方按钮新建`)),1),E(`div`,zr,[j(m,{type:`primary`,size:`small`,icon:q(ve),onClick:ot},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:新建任务`)),1)]),_:1},8,[`icon`])])])):u(``,!0)])]),E(`section`,Br,[E(`header`,Vr,[E(`span`,Hr,b(q(Y)(`@WORKBENCH:提示`)),1),E(`h3`,Ur,b(q(Y)(`@WORKBENCH:预置提示词`)),1),E(`span`,Wr,b(n.value.length),1),E(`button`,{class:`wb-section__action`,onClick:$e,title:q(Y)(`@WORKBENCH:新建提示词`),"aria-label":q(Y)(`@WORKBENCH:新建提示词`)},[j(p,null,{default:U(()=>[j(q(ve))]),_:1})],8,Gr)]),E(`ul`,Kr,[(H(!0),W(r,null,F(n.value,e=>(H(),W(`li`,{key:e.id,class:`wb-prompt-item`},[E(`div`,qr,[j(p,null,{default:U(()=>[j(q(pe))]),_:1})]),E(`span`,{class:`wb-prompt-item__name`,onClick:t=>et(e),title:e.content},b(e.name),9,Jr),Q.value.name?(H(),W(`span`,{key:0,class:`wb-prompt-item__project`,title:q(Y)(`@WORKBENCH:适用于当前项目`)+`:`+Q.value.path},b(Q.value.name),9,Yr)):u(``,!0),E(`button`,{class:`wb-prompt-item__del`,onClick:t=>at(e),title:q(Y)(`@WORKBENCH:删除`),"aria-label":q(Y)(`@WORKBENCH:删除`)},[j(p,null,{default:U(()=>[j(q(v))]),_:1})],8,Xr)]))),128)),n.value.length===0?(H(),W(`li`,Zr,b(q(Y)(`@WORKBENCH:暂无提示词`)),1)):u(``,!0)])])]),E(`section`,Qr,[h.value?(H(),W(r,{key:1},[E(`div`,ei,[de(E(`input`,{class:`wb-input wb-input--title`,"onUpdate:modelValue":l[0]||=e=>h.value.title=e,placeholder:q(Y)(`@WORKBENCH:任务标题`)},null,8,ti),[[c,h.value.title]]),L.value!==`idle`||B.value?(H(),W(`span`,{key:0,class:P([`wb-meta-save`,{"is-saving":L.value===`saving`,"is-saved":L.value===`saved`,"is-error":L.value===`error`,"is-dirty":B.value&&L.value===`idle`}]),title:L.value===`saving`?q(Y)(`@WORKBENCH:保存中…`):L.value===`error`?q(Y)(`@WORKBENCH:保存失败`):L.value===`saved`?q(Y)(`@WORKBENCH:已保存`):``},[L.value===`saving`?(H(),W(`span`,ri)):L.value===`saved`?(H(),W(`span`,ii,`✓`)):L.value===`error`?(H(),W(`span`,ai,`!`)):(H(),W(`span`,oi)),O(` `+b(L.value===`saving`?q(Y)(`@WORKBENCH:保存中…`):L.value===`saved`?q(Y)(`@WORKBENCH:已保存`):L.value===`error`?q(Y)(`@WORKBENCH:保存失败`):q(Y)(`@WORKBENCH:有未保存的更改`)),1)],10,ni)):u(``,!0),de(E(`select`,{class:`wb-select`,"onUpdate:modelValue":l[1]||=e=>h.value.promptId=e},[E(`option`,si,b(q(Y)(`@WORKBENCH:不绑定预置提示词`)),1),(H(!0),W(r,null,F(n.value,e=>(H(),W(`option`,{key:e.id,value:e.id},b(e.name),9,ci))),128))],512),[[a,h.value.promptId]]),E(`div`,{class:`wb-mode-switch`,role:`tablist`,"aria-label":q(Y)(`@WORKBENCH:任务类型`)},[E(`button`,{type:`button`,role:`tab`,class:P([`wb-mode-switch__btn`,{"is-active":!g.value}]),"aria-selected":!g.value,onClick:l[2]||=e=>lt(`complex`)},b(q(Y)(`@WORKBENCH:复杂`)),11,ui),E(`button`,{type:`button`,role:`tab`,class:P([`wb-mode-switch__btn`,{"is-active":g.value}]),"aria-selected":g.value,onClick:l[3]||=e=>lt(`simple`)},b(q(Y)(`@WORKBENCH:简单`)),11,di),E(`span`,{class:P([`wb-mode-switch__indicator`,{"is-right":g.value}]),"aria-hidden":`true`},null,2)],8,li),g.value?u(``,!0):(H(),W(`button`,{key:1,type:`button`,class:`wb-ai-split-btn`,disabled:!h.value.title||!h.value.title.trim(),title:q(Y)(`@WORKBENCH:AI 拆分`),onClick:bt},[l[44]||=E(`svg`,{class:`wb-ai-split-btn__icon`,viewBox:`0 0 16 16`,width:`14`,height:`14`,"aria-hidden":`true`},[E(`path`,{d:`M8 1.5l1.6 3.4 3.4 1.6-3.4 1.6L8 11.5 6.4 8.1 3 6.5l3.4-1.6L8 1.5zM2.5 9.5l.8 1.6 1.6.8-1.6.8-.8 1.6-.8-1.6L.1 11.9l1.6-.8.8-1.6zm11 0l.8 1.6 1.6.8-1.6.8-.8 1.6-.8-1.6-1.6-.8 1.6-.8.8-1.6z`,fill:`currentColor`})],-1),E(`span`,null,b(q(Y)(`@WORKBENCH:AI 拆分`)),1)],8,fi)),j(m,{type:`primary`,loading:!1,onClick:l[4]||=e=>St(h.value)},{default:U(()=>[O(b(g.value?q(Y)(`@WORKBENCH:执行`):q(Y)(`@WORKBENCH:执行任务`)),1)]),_:1}),E(`button`,{type:`button`,class:`wb-logs-inline-btn`,title:q(Y)(`@WORKBENCH:执行日志`),"aria-label":q(Y)(`@WORKBENCH:执行日志`),onClick:l[5]||=e=>d.value=!0},[j(p,{class:`wb-logs-inline-btn__icon`},{default:U(()=>[j(q(T))]),_:1}),E(`span`,null,b(q(Y)(`@WORKBENCH:执行日志`)),1)],8,pi)]),E(`details`,{class:`wb-task-desc`,open:Ee.value,onToggle:l[13]||=e=>Ee.value=e.target.open},[E(`summary`,hi,[j(p,{class:`wb-task-desc__caret`},{default:U(()=>[(H(),o(ne(Ee.value?q(Se):q(S))))]),_:1}),E(`span`,gi,b(q(Y)(`@WORKBENCH:任务描述(可选)`)),1),h.value.desc&&h.value.desc.length>0||h.value.attachments&&h.value.attachments.length>0?(H(),W(`span`,_i,[h.value.desc&&h.value.desc.length>0?(H(),W(`span`,vi,b(q(Y)(`@WORKBENCH:已填写`)),1)):u(``,!0),h.value.attachments&&h.value.attachments.length>0?(H(),W(`span`,yi,b(h.value.attachments.length),1)):u(``,!0)])):u(``,!0)]),de(E(`textarea`,{class:`wb-textarea`,"onUpdate:modelValue":l[6]||=e=>h.value.desc=e,placeholder:q(Y)(`@WORKBENCH:任务描述(可选)`),rows:`2`,onPaste:l[7]||=e=>Rt(e,{kind:`task`,task:h.value})},null,40,bi),[[c,h.value.desc]]),j(Wt,{attachments:h.value.attachments||[],"is-image":Gt,"human-size":Kt,"is-uploading":At(`task-`+h.value.id),"is-paste-hover":$.value===`task-`+h.value.id,"max-count":9,"on-pick":()=>Ht({kind:`task`,task:h.value}),"on-remove":e=>Vt({kind:`task`,task:h.value},e),onPaste:l[8]||=e=>Rt(e,{kind:`task`,task:h.value}),onDrop:l[9]||=J(e=>zt(e,{kind:`task`,task:h.value}),[`prevent`]),onDragover:l[10]||=J(e=>$.value=`task-`+h.value.id,[`prevent`]),onDragenter:l[11]||=J(e=>$.value=`task-`+h.value.id,[`prevent`]),onDragleave:l[12]||=e=>$.value=$.value===`task-`+h.value.id?null:$.value},null,8,[`attachments`,`is-uploading`,`is-paste-hover`,`on-pick`,`on-remove`])],40,mi),E(`div`,{class:P([`wb-execution-body`,{"wb-execution-body--simple":g.value}])},[g.value?u(``,!0):(H(),W(`div`,xi,[E(`div`,Si,[E(`h4`,Ci,b(q(Y)(`@WORKBENCH:子任务拆分`)),1),E(`div`,wi,[j(m,{size:`small`,plain:``,icon:q(ve),disabled:h.value.subtasks.length===0,onClick:ht},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:添加子任务`)),1)]),_:1},8,[`icon`,`disabled`]),j(m,{size:`small`,type:re.value?`primary`:`default`,disabled:h.value.subtasks.length===0,onClick:vt},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:保存拆分`))+` `,1),re.value?(H(),W(`span`,Ti,b(N.value.size),1)):u(``,!0)]),_:1},8,[`type`,`disabled`])])]),E(`ul`,Ei,[(H(!0),W(r,null,F(h.value.subtasks,e=>(H(),W(`li`,{key:e.id,class:P([`wb-exec-sub-item`,{"is-selected":_.value===e.id,"is-running":e.status===`running`,"is-done":e.status===`done`,"is-dirty":N.value.has(e.id),"is-persisting":pt(e.id)}]),onClick:t=>_.value=e.id},[E(`div`,Oi,[E(`span`,{class:`wb-sub-item__status wb-sub-item__status--dot`,style:Ce({background:q(Mn)(e.status)}),title:q(Y)(`@WORKBENCH:任务完成状态`)},[...l[45]||=[E(`span`,{class:`wb-simple__status-dot`,"aria-hidden":`true`},null,-1)]],12,ki),E(`span`,{class:`wb-exec-sub-item__title`,title:e.title},b(e.title||q(Y)(`@WORKBENCH:未命名子任务`)),9,Ai),N.value.has(e.id)?(H(),W(`span`,ji)):u(``,!0)]),E(`div`,Mi,[Z(e.id)?(H(),W(`span`,Ni,`PID: `+b(Z(e.id)?.pid),1)):u(``,!0),E(`span`,Pi,[Tt(e)?(H(),W(`button`,{key:0,class:`wb-exec-sub-btn wb-exec-sub-btn--run`,title:q(Y)(`@WORKBENCH:单独执行此子任务`),onClick:J(t=>wt(e),[`stop`])},b(q(Y)(`@WORKBENCH:执行`)),9,Fi)):u(``,!0),Z(e.id)&&(Z(e.id)?.status===`running`||Z(e.id)?.status===`pending`)?(H(),W(`button`,{key:1,class:`wb-exec-sub-btn wb-exec-sub-btn--stop`,title:q(Y)(`@WORKBENCH:停止执行`),onClick:J(t=>Dt(Z(e.id)),[`stop`])},b(q(Y)(`@WORKBENCH:停止`)),9,Ii)):u(``,!0),e.status===`done`?(H(),W(`button`,{key:2,class:`wb-exec-sub-btn wb-exec-sub-btn--undo`,title:q(Y)(`@WORKBENCH:取消完成`),disabled:pt(e.id),onClick:J(t=>Et(e),[`stop`])},b(q(Y)(`@WORKBENCH:取消完成`)),9,Li)):u(``,!0),E(`button`,{class:`wb-exec-sub-btn wb-exec-sub-btn--del`,title:q(Y)(`@WORKBENCH:删除`),disabled:pt(e.id),onClick:J(t=>gt(e),[`stop`])},`×`,8,Ri)])])],10,Di))),128)),h.value.subtasks.length===0?(H(),W(`li`,zi,[E(`div`,Bi,[j(p,null,{default:U(()=>[j(q(t))]),_:1})]),E(`div`,Vi,b(q(Y)(`@WORKBENCH:拆分任务,逐项执行`)),1),E(`div`,Hi,[j(m,{type:`primary`,size:`small`,icon:q(ve),onClick:ht},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:添加子任务`)),1)]),_:1},8,[`icon`])])])):u(``,!0)])])),E(`div`,Ui,[g.value?(H(),W(r,{key:1},[E(`details`,{class:P([`wb-simple__override`,{"has-content":!!(h.value.simpleOverride&&h.value.simpleOverride.trim())}])},[E(`summary`,Yi,[j(p,{class:`wb-simple__override-caret`},{default:U(()=>[j(q(S))]),_:1}),E(`span`,null,b(q(Y)(`@WORKBENCH:覆盖预置提示词(可选)`)),1),h.value.simpleOverride&&h.value.simpleOverride.trim()?(H(),W(`span`,{key:0,class:`wb-simple__override-tag`,title:q(Y)(`@WORKBENCH:已填写覆盖内容`)},b(q(Y)(`@WORKBENCH:已填写`)),9,Xi)):u(``,!0),Le(Ie(h.value))===`running`&&Ie(h.value)?(H(),W(`button`,{key:1,class:`wb-simple__stop`,disabled:pt(Ie(h.value).id),onClick:l[24]||=J(e=>Dt(Ie(h.value)),[`stop`])},b(q(Y)(`@WORKBENCH:停止`)),9,Zi)):u(``,!0)]),de(E(`textarea`,{class:`wb-textarea`,"onUpdate:modelValue":l[25]||=e=>h.value.simpleOverride=e,placeholder:q(Y)(`@WORKBENCH:留空则使用上方选定的「预置提示词」模板;可用变量同子任务:{{task.title}} {{task.desc}} {{repo.path}} {{branch}}`),rows:`6`},null,8,Qi),[[c,h.value.simpleOverride]])],2),Z(`${h.value.id}__simple`)?(H(),o(An,{key:0,job:Z(`${h.value.id}__simple`)},null,8,[`job`])):u(``,!0)],64)):(H(),W(r,{key:0},[x.value?(H(),W(r,{key:1},[E(`div`,Gi,[de(E(`input`,{class:`wb-input`,"onUpdate:modelValue":l[14]||=e=>x.value.title=e,placeholder:q(Y)(`@WORKBENCH:子任务标题`),onClick:l[15]||=J(()=>{},[`stop`]),onPaste:l[16]||=e=>Rt(e,{kind:`sub`,task:h.value,sub:x.value})},null,40,Ki),[[c,x.value.title]]),N.value.has(x.value.id)?(H(),W(`span`,{key:0,class:`wb-sub-item__dirty`,title:q(Y)(`@WORKBENCH:有未保存的更改`)},b(q(Y)(`@WORKBENCH:未保存`)),9,qi)):u(``,!0)]),de(E(`textarea`,{class:`wb-textarea wb-textarea--sm`,"onUpdate:modelValue":l[17]||=e=>x.value.desc=e,placeholder:q(Y)(`@WORKBENCH:子任务描述 / 独立提示词覆盖`),rows:`3`,onPaste:l[18]||=e=>Rt(e,{kind:`sub`,task:h.value,sub:x.value})},null,40,Ji),[[c,x.value.desc]]),Z(x.value.id)?(H(),o(An,{key:0,job:Z(x.value.id)},null,8,[`job`])):u(``,!0),j(Wt,{attachments:x.value.attachments||[],"is-image":Gt,"human-size":Kt,"is-uploading":At(`sub-`+x.value.id),"is-paste-hover":$.value===x.value.id,"max-count":9,"on-pick":()=>Ht({kind:`sub`,task:h.value,sub:x.value}),"on-remove":e=>Vt({kind:`sub`,task:h.value,sub:x.value},e),onPaste:l[19]||=e=>Rt(e,{kind:`sub`,task:h.value,sub:x.value}),onDrop:l[20]||=J(e=>zt(e,{kind:`sub`,task:h.value,sub:x.value}),[`prevent`]),onDragover:l[21]||=J(e=>$.value=x.value.id,[`prevent`]),onDragenter:l[22]||=J(e=>$.value=x.value.id,[`prevent`]),onDragleave:l[23]||=e=>$.value=$.value===x.value.id?null:$.value},null,8,[`attachments`,`is-uploading`,`is-paste-hover`,`on-pick`,`on-remove`])],64)):(H(),W(`div`,Wi,[E(`p`,null,b(h.value.subtasks.length===0?q(Y)(`@WORKBENCH:手动添加子任务,或让 AI 帮你自动拆分`):q(Y)(`@WORKBENCH:左侧选择子任务查看详情`)),1)]))],64))])],2)],64)):(H(),W(`div`,$r,[E(`p`,null,b(q(Y)(`@WORKBENCH:左侧选择任务,或新建一个任务开始`)),1)]))])]),j(C,{modelValue:d.value,"onUpdate:modelValue":l[26]||=e=>d.value=e,title:q(Y)(`@WORKBENCH:执行日志`),width:`1080px`,"close-on-click-modal":!1,top:`6vh`,class:`wb-logs-dialog`},{default:U(()=>[j(cr)]),_:1},8,[`modelValue`,`title`]),j(C,{modelValue:G.visible,"onUpdate:modelValue":l[30]||=e=>G.visible=e,title:G.editing?q(Y)(`@WORKBENCH:编辑提示词`):q(Y)(`@WORKBENCH:新建提示词`),width:`640px`},{footer:U(()=>[j(m,{onClick:l[29]||=e=>G.visible=!1},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:取消`)),1)]),_:1}),j(m,{type:`primary`,onClick:it},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:保存`)),1)]),_:1})]),default:U(()=>[j(k,{"label-position":`top`},{default:U(()=>[j(D,{label:q(Y)(`@WORKBENCH:名称`)},{default:U(()=>[j(w,{modelValue:G.name,"onUpdate:modelValue":l[27]||=e=>G.name=e,placeholder:q(Y)(`@WORKBENCH:如:代码审查 / 写测试`)},null,8,[`modelValue`,`placeholder`])]),_:1},8,[`label`]),j(D,null,{default:U(()=>[E(`div`,$i,[j(m,{type:`primary`,plain:``,loading:G.aiLoading,onClick:tt},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:AI 生成项目架构说明`)),1)]),_:1},8,[`loading`]),j(m,{onClick:nt},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:编辑指令`)),1)]),_:1})])]),_:1}),j(D,{label:q(Y)(`@WORKBENCH:内容`)},{default:U(()=>[j(w,{modelValue:G.content,"onUpdate:modelValue":l[28]||=e=>G.content=e,type:`textarea`,rows:10,placeholder:q(Y)(`@WORKBENCH:可用变量:`)+`{{task.title}} {{task.desc}} {{sub.title}} {{sub.desc}} {{repo.path}} {{branch}}`},null,8,[`modelValue`,`placeholder`])]),_:1},8,[`label`])]),_:1})]),_:1},8,[`modelValue`,`title`]),j(C,{modelValue:K.visible,"onUpdate:modelValue":l[33]||=e=>K.visible=e,title:q(Y)(`@WORKBENCH:编辑生成指令`),width:`720px`,"append-to-body":``},{footer:U(()=>[j(m,{onClick:l[32]||=e=>K.visible=!1},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:取消`)),1)]),_:1}),j(m,{type:`primary`,loading:K.saving,onClick:rt},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:保存`)),1)]),_:1},8,[`loading`])]),default:U(()=>[j(k,{"label-position":`top`},{default:U(()=>[j(D,{label:q(Y)(`@WORKBENCH:指令内容`)},{default:U(()=>[j(w,{modelValue:K.text,"onUpdate:modelValue":l[31]||=e=>K.text=e,type:`textarea`,rows:18,placeholder:q(Y)(`@WORKBENCH:指令内容`)},null,8,[`modelValue`,`placeholder`])]),_:1},8,[`label`])]),_:1})]),_:1},8,[`modelValue`,`title`]),j(C,{modelValue:X.visible,"onUpdate:modelValue":l[41]||=e=>X.visible=e,title:X.editing?q(Y)(`@WORKBENCH:编辑任务`):q(Y)(`@WORKBENCH:新建任务`),width:`600px`},{footer:U(()=>[j(m,{onClick:l[40]||=e=>X.visible=!1},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:取消`)),1)]),_:1}),j(m,{type:`primary`,onClick:st},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:保存`)),1)]),_:1})]),default:U(()=>[j(k,{"label-position":`top`},{default:U(()=>[j(D,{label:q(Y)(`@WORKBENCH:标题(可选)`)},{default:U(()=>[j(w,{modelValue:X.title,"onUpdate:modelValue":l[34]||=e=>X.title=e,placeholder:q(Y)(`@WORKBENCH:不填则自动命名为「无标题」,稍后可在任务列表里改名`)},null,8,[`modelValue`,`placeholder`])]),_:1},8,[`label`]),j(D,{label:q(Y)(`@WORKBENCH:类型`)},{default:U(()=>[j(M,{modelValue:X.type,"onUpdate:modelValue":l[35]||=e=>X.type=e},{default:U(()=>[j(A,{value:`complex`},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:复杂任务(需要拆分子任务)`)),1)]),_:1}),j(A,{value:`simple`},{default:U(()=>[O(b(q(Y)(`@WORKBENCH:简单任务(直接执行)`)),1)]),_:1})]),_:1},8,[`modelValue`])]),_:1},8,[`label`]),X.type===`simple`?(H(),o(D,{key:0,label:q(Y)(`@WORKBENCH:描述`)},{default:U(()=>[j(w,{modelValue:X.desc,"onUpdate:modelValue":l[36]||=e=>X.desc=e,type:`textarea`,rows:4,placeholder:q(Y)(`@WORKBENCH:把要做的事直接写在这里,执行时会把这段描述作为 prompt 喂给 Claude`)},null,8,[`modelValue`,`placeholder`])]),_:1},8,[`label`])):(H(),o(D,{key:1,label:q(Y)(`@WORKBENCH:描述`)},{default:U(()=>[j(w,{modelValue:X.desc,"onUpdate:modelValue":l[37]||=e=>X.desc=e,type:`textarea`,rows:3},null,8,[`modelValue`])]),_:1},8,[`label`])),X.type===`simple`?(H(),o(D,{key:2,label:q(Y)(`@WORKBENCH:覆盖预置提示词(可选)`)},{default:U(()=>[j(w,{modelValue:X.simpleOverride,"onUpdate:modelValue":l[38]||=e=>X.simpleOverride=e,type:`textarea`,rows:5,placeholder:q(Y)(`@WORKBENCH:留空则使用「预置提示词」下拉里选定的模板;可用变量同子任务覆盖。`)},null,8,[`modelValue`,`placeholder`])]),_:1},8,[`label`])):u(``,!0),j(D,{label:q(Y)(`@WORKBENCH:预置提示词`)},{default:U(()=>[j(ae,{modelValue:X.promptId,"onUpdate:modelValue":l[39]||=e=>X.promptId=e,clearable:``,placeholder:q(Y)(`@WORKBENCH:不绑定`),style:{width:`100%`}},{default:U(()=>[(H(!0),W(r,null,F(n.value,e=>(H(),o(R,{key:e.id,label:e.name,value:e.id},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`,`placeholder`])]),_:1},8,[`label`])]),_:1})]),_:1},8,[`modelValue`,`title`]),h.value?(H(),o(jt,{key:0,modelValue:yt.value,"onUpdate:modelValue":l[42]||=e=>yt.value=e,title:h.value.title,desc:h.value.desc,"task-id":h.value.id,"prompt-id":h.value.promptId,onConfirm:xt},null,8,[`modelValue`,`title`,`desc`,`task-id`,`prompt-id`])):u(``,!0)])}}}),[[`__scopeId`,`data-v-57e8677e`]]);export{ia as default};