zen-gitsync 2.18.6 → 2.18.8

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 (43) hide show
  1. package/package.json +5 -1
  2. package/src/config.js +41 -1
  3. package/src/ui/public/assets/AgentView-BRAUZCtA.js +1 -0
  4. package/src/ui/public/assets/{AgentView-am93H7C2.css → AgentView-DZx3n-So.css} +1 -1
  5. package/src/ui/public/assets/{AppVersionBadge-D4YCHNS8.js → AppVersionBadge-Bg5lrtKb.js} +2 -2
  6. package/src/ui/public/assets/{BranchSelector-CpYCgEuj.js → BranchSelector-CxjTqAkl.js} +1 -1
  7. package/src/ui/public/assets/{CommitForm-CwOF_1gO.js → CommitForm-BWWrOvj5.js} +1 -1
  8. package/src/ui/public/assets/{CommonDialog-BUuLsgNS.js → CommonDialog-x5jfL4Lq.js} +1 -1
  9. package/src/ui/public/assets/{CopySessionButton-SgJr0xOC.js → CopySessionButton-D0wFpk8a.js} +1 -1
  10. package/src/ui/public/assets/{EditorView-DwbVdSmS.js → EditorView-DmaGiI-z.js} +1 -1
  11. package/src/ui/public/assets/{FlowExecutionViewer-CKHp0Hfi.js → FlowExecutionViewer-BkZ20jxN.js} +1 -1
  12. package/src/ui/public/assets/{FlowOrchestrationWorkspace-RgXtsQ7y.js → FlowOrchestrationWorkspace-aZBYu29g.js} +1 -1
  13. package/src/ui/public/assets/{LogList-DdbyFS8j.js → LogList-CSIbmUMK.js} +1 -1
  14. package/src/ui/public/assets/{MindmapView-ep2o8uXg.js → MindmapView-JYLp185X.js} +1 -1
  15. package/src/ui/public/assets/{MonitorView-BTNWi4QG.js → MonitorView-BS2Mh-I7.js} +1 -1
  16. package/src/ui/public/assets/{ProjectStartupButton-DWTFof63.js → ProjectStartupButton-DAEP6ZU5.js} +1 -1
  17. package/src/ui/public/assets/{RecentDirectoriesChat-Do1spWVH.js → RecentDirectoriesChat-CVFTShrU.js} +1 -1
  18. package/src/ui/public/assets/{RemoteManagerDialog-DjLVltnm.js → RemoteManagerDialog-aaNmsKpy.js} +1 -1
  19. package/src/ui/public/assets/{RemoteRepoCard-DpcEDqyo.js → RemoteRepoCard-DndI8rNZ.js} +1 -1
  20. package/src/ui/public/assets/{SourceMapView-Djj6QLgu.js → SourceMapView-BTD9-R8t.js} +1 -1
  21. package/src/ui/public/assets/{SvgIcon-Du5MOe8A.js → SvgIcon-0n6uuKFm.js} +1 -1
  22. package/src/ui/public/assets/{UserInputNode-CQWY6Jwx.js → UserInputNode-B-mDg9Wy.js} +1 -1
  23. package/src/ui/public/assets/WorkbenchView-CfSrCIbp.js +8 -0
  24. package/src/ui/public/assets/{_plugin-vue_export-helper-CDrhhAKC.js → _plugin-vue_export-helper-C3o7kvRL.js} +2 -2
  25. package/src/ui/public/assets/{agentConversations-BvuyjfgF.js → agentConversations-DpiGplZB.js} +1 -1
  26. package/src/ui/public/assets/configStore-BdL3uW2E.js +1 -0
  27. package/src/ui/public/assets/index-BS7BDFG4.js +57 -0
  28. package/src/ui/public/assets/index-DwJWiCiN.css +1 -0
  29. package/src/ui/public/assets/useOrchestrator-CS9sn7nV.js +1 -0
  30. package/src/ui/public/index.html +6 -6
  31. package/src/ui/server/routes/config.js +13 -0
  32. package/src/ui/server/routes/workbench/agentChat.js +43 -11
  33. package/src/ui/server/routes/workbench/agentChatShared.test.js +148 -57
  34. package/src/ui/server/routes/workbench/agentRoutes.js +23 -1
  35. package/src/ui/server/routes/workbench/chatPrompts.js +115 -0
  36. package/src/ui/server/routes/workbench/chatPrompts.test.js +114 -0
  37. package/src/ui/server/utils/directoryFetch.js +14 -1
  38. package/src/ui/server/utils/directoryFetch.test.js +5 -0
  39. package/src/ui/public/assets/AgentView-D-k_LYiJ.js +0 -1
  40. package/src/ui/public/assets/WorkbenchView-CQ8qLTMM.js +0 -8
  41. package/src/ui/public/assets/configStore-DojhW1P7.js +0 -1
  42. package/src/ui/public/assets/index-BuFKNHju.css +0 -1
  43. package/src/ui/public/assets/index-Z7rlN9LU.js +0 -57
@@ -0,0 +1,114 @@
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
+ // 「和 g ai 对话时固定注入的两块提示词」的拼装与取数口径。
16
+ //
17
+ // 这个能力是**纯 prompt 注入**的:没有按钮、没有状态、界面上看不出对错。
18
+ // 改 agentChat.js / runExternalTurn.js 的人(哪怕只是把一段挪个位置)会无声地把它弄掉,
19
+ // 而用户只会觉得"模型今天不太听话"。所以口径在这一层逐条钉住,注入点那条链路由
20
+ // agentChatShared.test.js 跑真实 runAgentTurn 验(见那里的"用户固定提示词"用例)。
21
+ //
22
+ // 注意:必须在 import 之前把 USERPROFILE/HOME 指到沙箱 —— chatPrompts.js 会连带
23
+ // 加载 configManager 与 orchestratorStore,它们按 home 定位 ~/.zen-gitsync。
24
+ // 本文件里的用例全部走注入口(不读真实配置),沙箱只是防"哪天有人加了真实读取"。
25
+ import { test } from 'node:test'
26
+ import assert from 'node:assert/strict'
27
+ import { mkdtempSync } from 'node:fs'
28
+ import os from 'node:os'
29
+ import path from 'node:path'
30
+
31
+ const SANDBOX = mkdtempSync(path.join(os.tmpdir(), 'zen-chat-prompts-'))
32
+ process.env.USERPROFILE = SANDBOX
33
+ process.env.HOME = SANDBOX
34
+ delete process.env.HOMEDRIVE
35
+ delete process.env.HOMEPATH
36
+
37
+ const { buildChatPromptSection, resolveChatPromptSection } = await import('./chatPrompts.js')
38
+
39
+ // ── 拼装(纯函数)─────────────────────────────────────────
40
+
41
+ test('两块都没配 → 空串(调用方据此完全跳过注入,连一节标题都不出现)', () => {
42
+ assert.equal(buildChatPromptSection({}), '')
43
+ assert.equal(buildChatPromptSection({ gaiPrompt: '', dispatchPrompt: '' }), '')
44
+ // 只有空白也算没配 —— 用户清空后留下一堆换行,不该在提示词里留一节空标题
45
+ assert.equal(buildChatPromptSection({ gaiPrompt: ' \n\n ', dispatchPrompt: '\t' }), '')
46
+ })
47
+
48
+ test('两块都在 → 各带自己的小标题,g ai 那段在前', () => {
49
+ const out = buildChatPromptSection({ gaiPrompt: '回答用中文', dispatchPrompt: '改完就提交' })
50
+ assert.match(out, /### g ai 默认提示词\n回答用中文/)
51
+ assert.match(out, /### 派发任务的提示词(与工作台派发任务时附加的是同一份)\n改完就提交/)
52
+ assert.ok(out.indexOf('回答用中文') < out.indexOf('改完就提交'), 'g ai 那段必须在前')
53
+ })
54
+
55
+ test('只配一块 → 只出那一块(另一块不留空标题)', () => {
56
+ const onlyGai = buildChatPromptSection({ gaiPrompt: '回答用中文' })
57
+ assert.match(onlyGai, /### g ai 默认提示词/)
58
+ assert.doesNotMatch(onlyGai, /### 派发任务的提示词/)
59
+
60
+ const onlyDispatch = buildChatPromptSection({ dispatchPrompt: '改完就提交' })
61
+ assert.match(onlyDispatch, /### 派发任务的提示词/)
62
+ assert.doesNotMatch(onlyDispatch, /### g ai 默认提示词/)
63
+ })
64
+
65
+ test('正文前后空白被裁掉,中间原样保留(用户排版不被破坏)', () => {
66
+ const out = buildChatPromptSection({ gaiPrompt: '\n\n第一段\n\n第二段\n\n' })
67
+ assert.match(out, /### g ai 默认提示词\n第一段\n\n第二段$/)
68
+ })
69
+
70
+ test('英文界面走英文标题(与系统提示词同一套 locale 判定)', () => {
71
+ const out = buildChatPromptSection({ gaiPrompt: 'answer in Chinese', locale: 'en-US' })
72
+ assert.match(out, /### g ai default prompt/)
73
+ assert.match(out, /Standing instructions|Settings/)
74
+ })
75
+
76
+ test('非字符串入参不炸(手改配置塞了数字 / 对象)', () => {
77
+ assert.equal(buildChatPromptSection({ gaiPrompt: 42, dispatchPrompt: {} }), '')
78
+ })
79
+
80
+ // ── 取数 ────────────────────────────────────────────────
81
+
82
+ test('两块分别来自两处:g ai 默认提示词取 config,派发提示词取 orchestrator', async () => {
83
+ const seenCwd = []
84
+ const out = await resolveChatPromptSection({
85
+ cwd: 'D:\\ws\\alpha',
86
+ loadAgentPrompt: async () => '回答用中文',
87
+ loadDispatchPrompt: async (cwd) => { seenCwd.push(cwd); return '改完就提交' },
88
+ })
89
+ assert.match(out, /回答用中文/)
90
+ assert.match(out, /改完就提交/)
91
+ assert.deepEqual(seenCwd, ['D:\\ws\\alpha'], '派发提示词必须按本轮 cwd 解析(项目级那条靠它生效)')
92
+ })
93
+
94
+ test('取数抛错一律当"没配",绝不把整轮对话打挂', async () => {
95
+ const both = await resolveChatPromptSection({
96
+ loadAgentPrompt: async () => { throw new Error('config.json 坏了') },
97
+ loadDispatchPrompt: async () => { throw new Error('orchestrator.json 坏了') },
98
+ })
99
+ assert.equal(both, '', '两边都挂 = 不注入')
100
+
101
+ // 一边挂另一边照常:坏的那份不该连累好的那份
102
+ const half = await resolveChatPromptSection({
103
+ loadAgentPrompt: async () => '回答用中文',
104
+ loadDispatchPrompt: async () => { throw new Error('orchestrator.json 坏了') },
105
+ })
106
+ assert.match(half, /回答用中文/)
107
+ assert.doesNotMatch(half, /### 派发任务的提示词/)
108
+ })
109
+
110
+ test('返回值是字符串而不是 undefined(调用方直接拼进 system,undefined 会印出字面量)', async () => {
111
+ const out = await resolveChatPromptSection({ loadAgentPrompt: async () => '', loadDispatchPrompt: async () => '' })
112
+ assert.equal(typeof out, 'string')
113
+ assert.equal(out, '')
114
+ })
@@ -27,9 +27,14 @@
27
27
  //
28
28
  // 绝不能停在交互式凭据提示上(这是批量动作,卡一个仓库就卡掉整轮刷新):
29
29
  // - GIT_TERMINAL_PROMPT=0 让 git 直接失败,而不是在终端上等人输密码
30
+ // - GCM_INTERACTIVE=never 关掉 Git Credential Manager 的 GUI 弹窗。
31
+ // ⚠️ 单靠 GIT_TERMINAL_PROMPT 挡不住 GCM:它只管「终端里问」,GCM 的
32
+ // 「Connect to GitHub」窗口由 GCM 自己决定弹不弹(2026-10-12 实测 GCM 2.9.1:
33
+ // windowsHide + 非交互 spawn 照样弹窗,fetch 挂到超时;加上这个变量后
34
+ // 1.1s 内以 'user interactivity has been disabled' 失败返回)。
30
35
  // - GIT_SSH_COMMAND 注入 BatchMode=yes,让 ssh 的 passphrase 也变成明确报错;
31
36
  // 用户自己设过 GIT_SSH_COMMAND 就不动他的(那可能是他的跳板机/密钥配置)
32
- // 两者叠加的效果是:需要认证又没存凭据的仓库会**快速失败**并回报一句人话,
37
+ // 三者叠加的效果是:需要认证又没存凭据的仓库会**快速失败**并回报一句人话,
33
38
  // 而不是留下一个永远不返回的进程。
34
39
  //
35
40
  // 不做的事:
@@ -101,12 +106,20 @@ export function firstErrorLine(text, maxLen = ERROR_LINE_MAX) {
101
106
  *
102
107
  * GIT_CONFIG_PARAMETERS 与目录状态探测保持一致(关闭路径转义,否则中文/空格
103
108
  * 路径在报错里会变成 \xxx 八进制,用户没法对着看)。
109
+ *
110
+ * GCM_INTERACTIVE 与文件头「绝不能停在交互式凭据提示上」一节对应:
111
+ * GIT_TERMINAL_PROMPT=0 只管「终端里问」,挡不住 GCM 的 GUI 弹窗(实测后台
112
+ * spawn 也会弹「Connect to GitHub」并挂住整条 fetch);这个变量关掉 GCM 的
113
+ * 全部交互(语义等价 credential.interactive=never,GCM 2.x 直接读)。
104
114
  */
105
115
  export function buildFetchEnv(baseEnv = process.env) {
106
116
  const env = {
107
117
  ...baseEnv,
108
118
  GIT_CONFIG_PARAMETERS: "'core.quotepath=false'",
109
119
  GIT_TERMINAL_PROMPT: '0',
120
+ // 无条件覆盖:这是后台批量动作,宁可「快速失败 + 一句人话」也不要任何 UI。
121
+ // 用户要登录 GCM 会在自己的前台操作(push/pull)里遇到弹窗,不靠刷新徽标。
122
+ GCM_INTERACTIVE: 'never',
110
123
  };
111
124
  if (!baseEnv.GIT_SSH_COMMAND) env.GIT_SSH_COMMAND = 'ssh -oBatchMode=yes';
112
125
  return env;
@@ -53,12 +53,17 @@ const asRemote = p => p.replace(/\\/g, '/');
53
53
  test('buildFetchEnv: 关掉交互式凭据提示,且不覆盖用户自己的 GIT_SSH_COMMAND', () => {
54
54
  const withOwn = buildFetchEnv({ PATH: '/usr/bin', GIT_SSH_COMMAND: 'ssh -i /my/key' });
55
55
  assert.equal(withOwn.GIT_TERMINAL_PROMPT, '0', '批量刷新绝不能停在终端等输密码');
56
+ assert.equal(withOwn.GCM_INTERACTIVE, 'never', 'GCM 的 GUI 弹窗不受 GIT_TERMINAL_PROMPT 约束,必须单独关(实测会弹「Connect to GitHub」并挂住整条 fetch)');
56
57
  assert.equal(withOwn.GIT_SSH_COMMAND, 'ssh -i /my/key', '用户自己的 ssh 配置不能被顶掉');
57
58
  assert.equal(withOwn.PATH, '/usr/bin', '原有环境变量要带过去');
58
59
  assert.match(withOwn.GIT_CONFIG_PARAMETERS, /core\.quotepath=false/);
59
60
 
60
61
  const injected = buildFetchEnv({ PATH: '/usr/bin' });
61
62
  assert.match(injected.GIT_SSH_COMMAND, /BatchMode=yes/, 'ssh 的 passphrase 提示也要变成明确报错');
63
+
64
+ // 后台批量动作无条件禁交互:外部哪怕传了 always 也要顶掉(否则启动自动刷新会弹窗)
65
+ const override = buildFetchEnv({ GCM_INTERACTIVE: 'always' });
66
+ assert.equal(override.GCM_INTERACTIVE, 'never');
62
67
  });
63
68
 
64
69
  test('isNotARepoMessage: 认得 git 的两种措辞', () => {
@@ -1 +0,0 @@
1
- import"./rolldown-runtime-C0FnF6B9.js";import{$r as e,$t as t,An as n,At as r,Ct as i,Dn as a,Dr as o,En as s,Fn as c,Fr as l,Gn as u,Gt as d,Ht as f,J as p,Jn as m,Jr as h,Ln as g,M as _,On as v,Pn as y,Qn as b,Sn as x,Tt as S,Vn as C,W as ee,Xn as w,Xr as T,Yt as E,_n as D,a as te,an as ne,dn as O,er as k,et as A,gn as j,i as M,j as re,kn as N,kt as ie,lr as P,lt as F,mn as I,mr as L,mt as ae,r as R,rr as z,sr as B,st as V,tt as H,ur as U,vn as W,xr as G,yr as K}from"./element-plus-J45pKUrE.js";import{a as q,r as J}from"./vendor-B3NyhlYR.js";import{n as Y,t as X}from"./_plugin-vue_export-helper-CDrhhAKC.js";import{t as oe}from"./configStore-DojhW1P7.js";import{t as se}from"./CommonDialog-BUuLsgNS.js";import{v as ce}from"./index-Z7rlN9LU.js";import{a as Z,c as le,i as ue,l as de,n as fe,o as pe,p as me,r as he,s as ge,t as _e,u as ve}from"./agentConversations-BvuyjfgF.js";import{c as ye,s as be,t as xe}from"./CopySessionButton-SgJr0xOC.js";C(),L(),O(),l();var Se={class:`marketplace-panel`},Ce={class:`mp-toolbar`},we={class:`mp-search`},Te=[`placeholder`],Ee={class:`mp-toolbar-sub`},De={class:`mp-target-hint`},Oe={class:`mp-source-filter`},ke=[`onClick`],Ae={class:`mp-body`},je={class:`mp-group-header`},Me={class:`mp-group-title`},Ne={key:0,class:`mp-group-count`},Pe={key:1,class:`mp-group-error`},Fe=[`href`,`title`],Ie={key:0,class:`mp-grid`},Le={class:`mp-card-head`},Re=[`title`],ze={key:0,class:`mp-card-metric`},Be=[`title`],Ve={class:`mp-card-meta`},He=[`title`],Ue=[`title`],We={key:2,class:`mp-tag remote`},Ge={class:`mp-card-foot`},Ke=[`href`],qe={key:1,class:`mp-installed-chip`},Je=[`disabled`,`onClick`],Ye={key:3,class:`mp-not-installable`},Xe={key:1,class:`mp-empty`},Ze={key:0,class:`mp-group installed`},Qe={class:`mp-group-header`},$e={class:`mp-group-title`},et={class:`mp-group-count`},tt={key:0,class:`mp-installed-block`},nt={class:`mp-installed-target`},rt={class:`mp-installed-list`},it=[`title`],at=[`title`],ot={key:1,class:`mp-meta-pkg`},st={key:2,class:`mp-tag warn`},ct=[`disabled`,`title`,`onClick`],lt=[`disabled`,`onClick`],ut={key:1,class:`mp-empty all`},dt={key:0,class:`mkt-form`},ft={class:`mkt-form-name`},pt=[`onUpdate:modelValue`,`placeholder`],mt={key:0,class:`mkt-field`},ht={class:`mkt-hint`},gt=X(g({__name:`MarketplacePanel`,props:{type:{}},setup(t){let r=t,l=oe(),u=G([]),m=G([]),g=G(!1),S=G(``),C=G(``),w=G([]),T=G(`project`),D=G(new Set),O=G(new Set),A=G(new Set),j=s(()=>l.currentDirectory||``),I=null;async function L(){if(!g.value){g.value=!0;try{let e=new URLSearchParams({type:r.type,cwd:j.value});C.value&&e.set(`q`,C.value),w.value.length&&e.set(`sources`,w.value.join(`,`));let t=await(await fetch(`/api/agent/marketplace/catalog?${e}`)).json();t?.success?(u.value=t.groups||[],m.value=t.installed||[]):M.error(t?.error||Y(`@MKT:加载失败`))}catch{M.error(Y(`@MKT:加载失败`))}finally{g.value=!1}}}B(S,e=>{I&&clearTimeout(I),I=setTimeout(()=>{C.value=e.trim(),L()},400)}),B(w,()=>L()),B(()=>r.type,()=>{w.value=[],C.value=``,S.value=``,L()}),B(j,()=>L()),L();let z=s(()=>{let e=j.value?j.value.split(/[\\/]/).filter(Boolean).pop():``;return T.value===`project`?e||Y(`@MKT:当前项目`):Y(`@MKT:g ai 智能体`)});function V(e){return e.stars?`${q(e.stars)} ★`:e.downloads?`${q(e.downloads)} ${Y(`@MKT:周下载`)}`:e.uses?`${q(e.uses)} ${Y(`@MKT:次使用`)}`:``}function q(e){return e>=1e3?`${(e/1e3).toFixed(e>=1e4?0:1)}k`:String(e)}function J(e){return`${e.id}`}function X(e){return D.value.has(J(e))}let ce=s(()=>{let e={project:[],global:[]};for(let t of m.value)(e[t.target]||=[]).push(t);return e}),Z=K({visible:!1,item:null,env:{},args:``});function le(e){return r.type===`mcp`&&(!!e.envKeys?.length||!!e.args?.length)}function ue(e){Z.item=e,Z.env=Object.fromEntries((e.envKeys||[]).map(e=>[e,``])),Z.args=(e.args||[]).join(` `),Z.visible=!0}function de(){let e=Z.item;if(Z.visible=!1,!e)return;let t=Object.fromEntries(Object.entries(Z.env).filter(([,e])=>e.trim()!==``)),n=Z.args.trim()?Z.args.trim().match(/(?:[^\s"]+|"[^"]*")+/g)?.map(e=>e.replace(/^"|"$/g,``))??void 0:void 0;pe(e,{env:t,...n?{args:n}:{}})}async function fe(e){if(!e.installed||await me(e)){if(le(e)){ue(e);return}await pe(e,{})}}async function pe(e,t){let n=J(e);D.value.add(n);try{let n=await fetch(`/api/agent/marketplace/install`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({type:r.type,target:T.value,cwd:j.value,item:{...e,...t}})}),i=await n.json().catch(()=>null);if(!n.ok||!i?.success){M.error(i?.error||Y(`@MKT:安装失败`));return}i.item?.warning&&M.warning(i.item.warning),i.item?.envKeys?.length?M.warning(`${Y(`@MKT:还缺环境变量`)}: ${i.item.envKeys.join(`, `)}`):M.success(Y(`@MKT:安装成功`)),await L()}catch{M.error(Y(`@MKT:安装失败`))}finally{D.value.delete(n)}}async function me(e){try{return await R.confirm(`${e.name} ${Y(`@MKT:已安装,要重新安装吗?`)}`,Y(`@MKT:重新安装`),{confirmButtonText:Y(`@MKT:重装`),cancelButtonText:Y(`@MKT:取消`),type:`warning`}),!0}catch{return!1}}async function he(e){let t=`${e.target}:${e.id}`;A.value.add(t);try{let t=await fetch(`/api/agent/marketplace/reveal`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({type:r.type,target:e.target,cwd:j.value,id:e.id})}),n=await t.json().catch(()=>null);(!t.ok||!n?.success)&&M.error(n?.error||Y(`@MKT:打开失败`))}catch{M.error(Y(`@MKT:打开失败`))}finally{A.value.delete(t)}}async function ge(e){try{await R.confirm(`${Y(`@MKT:确定卸载`)} ${e.name}?`,Y(`@MKT:卸载`),{confirmButtonText:Y(`@MKT:卸载`),cancelButtonText:Y(`@MKT:取消`),type:`warning`})}catch{return}let t=`${e.target}:${e.id}`;O.value.add(t);try{let t=new URLSearchParams({target:e.target,cwd:j.value}),n=await fetch(`/api/agent/marketplace/item/${r.type}/${encodeURIComponent(e.id)}?${t}`,{method:`DELETE`}),i=await n.json().catch(()=>null);if(!n.ok||!i?.success){M.error(i?.error||Y(`@MKT:卸载失败`));return}M.success(Y(`@MKT:已卸载`)),await L()}catch{M.error(Y(`@MKT:卸载失败`))}finally{O.value.delete(t)}}return(r,s)=>{let l=p,C=re,D=_,j=ee,M=te;return b(),n(`div`,Se,[a(`div`,Ce,[a(`div`,we,[c(l,{class:`mp-search-icon`},{default:P(()=>[c(o(d))]),_:1}),U(a(`input`,{"onUpdate:modelValue":s[0]||=e=>S.value=e,class:`mp-search-input`,type:`text`,placeholder:t.type===`skill`?o(Y)(`@MKT:搜索 Skill...`):o(Y)(`@MKT:搜索 MCP 服务...`)},null,8,Te),[[W,S.value]])]),c(D,{modelValue:T.value,"onUpdate:modelValue":s[1]||=e=>T.value=e,size:`small`,class:`mp-target`},{default:P(()=>[c(C,{value:`project`},{default:P(()=>[y(e(o(Y)(`@MKT:当前项目`)),1)]),_:1}),c(C,{value:`global`},{default:P(()=>[y(e(o(Y)(`@MKT:g ai 智能体`)),1)]),_:1})]),_:1},8,[`modelValue`]),c(j,{content:o(Y)(`@MKT:刷新`),placement:`top`,"show-after":300},{default:P(()=>[a(`button`,{class:h([`mp-refresh`,{spinning:g.value}]),onClick:L},[c(l,null,{default:P(()=>[c(o(f))]),_:1})],2)]),_:1},8,[`content`])]),a(`div`,Ee,[a(`span`,De,[y(e(o(Y)(`@MKT:安装到`))+` `,1),a(`b`,null,e(z.value),1)]),a(`div`,Oe,[(b(!0),n(x,null,k(u.value,t=>(b(),n(`button`,{key:t.id,class:h([`mp-chip`,{active:w.value.includes(t.id)}]),onClick:()=>{let e=w.value.indexOf(t.id);e>=0?w.value.splice(e,1):w.value.push(t.id)}},e(t.label),11,ke))),128)),w.value.length?(b(),n(`button`,{key:0,class:`mp-chip clear`,onClick:s[2]||=e=>w.value=[]},e(o(Y)(`@MKT:全部来源`)),1)):N(``,!0)])]),U((b(),n(`div`,Ae,[(b(!0),n(x,null,k(u.value,t=>(b(),n(`section`,{key:t.id,class:`mp-group`},[a(`header`,je,[a(`h3`,Me,e(t.label),1),t.status===`ok`?(b(),n(`span`,Ne,e(t.items.length),1)):(b(),n(`span`,Pe,[c(l,null,{default:P(()=>[c(o(ne))]),_:1}),y(` `+e(t.error||o(Y)(`@MKT:来源不可用`)),1)])),t.homepage?(b(),n(`a`,{key:2,class:`mp-group-link`,href:t.homepage,target:`_blank`,rel:`noopener noreferrer`,title:t.homepage},[c(l,null,{default:P(()=>[c(o(ie))]),_:1})],8,Fe)):N(``,!0)]),t.status===`ok`&&t.items.length?(b(),n(`div`,Ie,[(b(!0),n(x,null,k(t.items,t=>(b(),n(`article`,{key:J(t),class:`mp-card`},[a(`div`,Le,[a(`span`,{class:`mp-card-name`,title:t.name},e(t.name),9,Re),V(t)?(b(),n(`span`,ze,[c(l,null,{default:P(()=>[t.stars?(b(),v(o(E),{key:0})):(b(),v(o(ae),{key:1}))]),_:2},1024),y(` `+e(V(t)),1)])):N(``,!0)]),a(`p`,{class:`mp-card-desc`,title:t.description},e(t.description||o(Y)(`@MKT:暂无描述`)),9,Be),a(`div`,Ve,[t.package?(b(),n(`code`,{key:0,class:`mp-meta-pkg`,title:t.package},e(t.package),9,He)):t.repository?(b(),n(`span`,{key:1,class:`mp-meta-repo`,title:t.repository+(t.subpath?` · `+t.subpath:``)},[y(e(t.repository),1),t.subpath?(b(),n(x,{key:0},[y(` · `+e(t.subpath),1)],64)):N(``,!0)],8,Ue)):N(``,!0),t.transport===`remote`?(b(),n(`span`,We,e(o(Y)(`@MKT:远程服务`)),1)):N(``,!0),(b(!0),n(x,null,k((t.tags||[]).slice(0,2),t=>(b(),n(`span`,{key:t,class:`mp-tag`},e(t),1))),128))]),a(`div`,Ge,[t.upstream?(b(),n(`a`,{key:0,class:`mp-card-link`,href:t.upstream,target:`_blank`,rel:`noopener noreferrer`},e(o(Y)(`@MKT:查看来源`)),9,Ke)):N(``,!0),s[6]||=a(`span`,{class:`mp-foot-spacer`},null,-1),t.installed?(b(),n(`span`,qe,[c(l,null,{default:P(()=>[c(o(H))]),_:1}),y(e(o(Y)(`@MKT:已安装`)),1)])):t.installable===!1?(b(),n(`span`,Ye,e(o(Y)(`@MKT:暂不支持一键安装`)),1)):(b(),n(`button`,{key:2,class:`mp-install-btn`,disabled:X(t),onClick:e=>fe(t)},e(X(t)?o(Y)(`@MKT:安装中...`):o(Y)(`@MKT:安装`)),9,Je))])]))),128))])):t.status===`ok`?(b(),n(`div`,Xe,e(o(Y)(`@MKT:该来源暂无结果`)),1)):N(``,!0)]))),128)),m.value.length?(b(),n(`section`,Ze,[a(`header`,Qe,[a(`h3`,$e,e(o(Y)(`@MKT:已安装`)),1),a(`span`,et,e(m.value.length),1)]),(b(),n(x,null,k([`project`,`global`],t=>a(`div`,{key:t},[ce.value[t]?.length?(b(),n(`div`,tt,[a(`div`,nt,e(t===`project`?o(Y)(`@MKT:当前项目`):o(Y)(`@MKT:g ai 智能体`)),1),a(`div`,rt,[(b(!0),n(x,null,k(ce.value[t],r=>(b(),n(`div`,{key:t+r.id,class:`mp-installed-row`},[a(`span`,{class:`mp-installed-name`,title:r.name},e(r.name),9,it),r.id&&r.id!==r.name?(b(),n(`code`,{key:0,class:`mp-installed-id`,title:r.dir||r.file||r.id},e(r.id),9,at)):N(``,!0),r.package?(b(),n(`code`,ot,e(r.package),1)):N(``,!0),r.requiredEnv?.length?(b(),n(`span`,st,e(o(Y)(`@MKT:待配置`))+`: `+e(r.requiredEnv.join(`, `)),1)):N(``,!0),s[7]||=a(`span`,{class:`mp-foot-spacer`},null,-1),a(`button`,{class:`mp-reveal-btn`,disabled:A.value.has(t+r.id),title:r.dir||r.file||``,onClick:e=>he(r)},[c(l,null,{default:P(()=>[c(o(i))]),_:1}),y(` `+e(o(Y)(`@MKT:打开文件夹`)),1)],8,ct),a(`button`,{class:`mp-remove-btn`,disabled:O.value.has(t+r.id),onClick:e=>ge(r)},[c(l,null,{default:P(()=>[c(o(F))]),_:1}),y(` `+e(O.value.has(t+r.id)?o(Y)(`@MKT:卸载中...`):o(Y)(`@MKT:卸载`)),1)],8,lt)]))),128))])])):N(``,!0)])),64))])):N(``,!0),!g.value&&!u.value.length?(b(),n(`div`,ut,e(o(Y)(`@MKT:加载失败`)),1)):N(``,!0)])),[[M,g.value]]),c(se,{modelValue:Z.visible,"onUpdate:modelValue":s[5]||=e=>Z.visible=e,title:o(Y)(`@MKT:配置 MCP`),width:`460px`,type:`flex`,"close-on-click-modal":!1,"append-to-body":``},{footer:P(()=>[a(`button`,{class:`mkt-cancel`,onClick:s[4]||=e=>Z.visible=!1},e(o(Y)(`@MKT:取消`)),1),a(`button`,{class:`mkt-confirm`,onClick:de},e(o(Y)(`@MKT:安装`)),1)]),default:P(()=>[Z.item?(b(),n(`div`,dt,[a(`p`,ft,e(Z.item.name),1),(b(!0),n(x,null,k(Object.keys(Z.env),t=>(b(),n(`div`,{key:t,class:`mkt-field`},[a(`label`,null,e(t),1),U(a(`input`,{"onUpdate:modelValue":e=>Z.env[t]=e,type:`text`,autocomplete:`off`,placeholder:o(Y)(`@MKT:环境变量值`),spellcheck:`false`},null,8,pt),[[W,Z.env[t]]])]))),128)),Z.item.args?.length?(b(),n(`div`,mt,[a(`label`,null,e(o(Y)(`@MKT:启动参数`)),1),U(a(`input`,{"onUpdate:modelValue":s[3]||=e=>Z.args=e,type:`text`,autocomplete:`off`,spellcheck:`false`},null,512),[[W,Z.args]]),a(`p`,ht,e(o(Y)(`@MKT:参数提示`)),1)])):N(``,!0)])):N(``,!0)]),_:1},8,[`modelValue`,`title`])])}}}),[[`__scopeId`,`data-v-536d7952`]]);async function Q(e,t){let n=await fetch(e,{headers:{"Content-Type":`application/json`},...t}),r={};try{r=await n.json()}catch{}if(!n.ok||r.success===!1)throw Error(r.error||`请求失败 (${n.status})`);return r}async function _t(){let e=await Q(`/api/schedules`);return Array.isArray(e.tasks)?e.tasks:[]}async function vt(e){return(await Q(`/api/schedules`,{method:`POST`,body:JSON.stringify(e)})).task}async function yt(e,t){return(await Q(`/api/schedules/${encodeURIComponent(e)}`,{method:`PUT`,body:JSON.stringify(t)})).task}async function bt(e){await Q(`/api/schedules/${encodeURIComponent(e)}`,{method:`DELETE`})}async function xt(e){await Q(`/api/schedules/${encodeURIComponent(e)}/run`,{method:`POST`})}async function St(e){await Q(`/api/schedules/${encodeURIComponent(e)}/stop`,{method:`POST`})}function Ct(e){if(typeof EventSource>`u`)return()=>{};let t=new EventSource(`/api/schedules/events`);return t.onmessage=t=>{try{e(JSON.parse(t.data))}catch{}},()=>t.close()}var wt=e=>/^\d+$/.test(e)?Number(e):null;function Tt(e){let t=String(e||``).trim(),n=t.split(/\s+/);if(n.length!==5)return{kind:`custom`,raw:t};let[r,i,a,o,s]=n,c=wt(r),l=wt(i);if(t===`* * * * *`)return{kind:`every-minute`,raw:t};let u=r.match(/^\*\/(\d+)$/);if(u&&i===`*`&&a===`*`&&o===`*`&&s===`*`)return{kind:`every-n-minutes`,n:Number(u[1]),raw:t};if(c!==null&&i===`*`&&a===`*`&&o===`*`&&s===`*`)return{kind:`hourly`,minute:c,raw:t};if(c!==null&&l!==null&&a===`*`&&o===`*`&&s===`*`)return{kind:`daily`,hour:l,minute:c,raw:t};let d=wt(s);if(c!==null&&l!==null&&a===`*`&&o===`*`&&d!==null)return{kind:`weekly`,weekday:d%7,hour:l,minute:c,raw:t};let f=wt(a);return c!==null&&l!==null&&f!==null&&o===`*`&&s===`*`?{kind:`monthly`,day:f,hour:l,minute:c,raw:t}:{kind:`custom`,raw:t}}var $=e=>String(e).padStart(2,`0`),Et=e=>new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime();function Dt(e,t=new Date){if(!e)return{kind:`none`};let n=new Date(e);if(Number.isNaN(n.getTime()))return{kind:`none`};let r=`${$(n.getHours())}:${$(n.getMinutes())}`,i=Math.round((Et(n)-Et(t))/864e5);return i<0?{kind:`date`,date:`${n.getMonth()+1}-${$(n.getDate())}`,time:r}:i===0?{kind:`today`,time:r}:i===1?{kind:`tomorrow`,time:r}:i<7?{kind:`weekday`,weekday:n.getDay(),time:r}:{kind:`date`,date:`${n.getMonth()+1}-${$(n.getDate())}`,time:r}}function Ot(e){switch(e){case`ok`:return`ok`;case`error`:case`timed-out`:return`error`;case`skipped-busy`:case`missed`:case`cancelled`:return`skipped`;default:return`pending`}}function kt(e){let t=Number(e);if(!Number.isFinite(t)||t<0)return``;if(t<1e3)return`<1s`;let n=Math.round(t/1e3);if(n<60)return`${n}s`;let r=Math.floor(n/60);return r<60?`${r}m${$(n%60)}s`:`${Math.floor(r/60)}h${$(r%60)}m`}function At(e){let t=Math.min(59,Math.max(0,Math.floor(e.minute))),n=Math.min(23,Math.max(0,Math.floor(e.hour))),r=(Math.floor(e.weekday)%7+7)%7;switch(e.freq){case`minutes`:return`*/${Math.min(59,Math.max(1,Math.floor(e.everyMinutes??30)))} * * * *`;case`hourly`:return`${t} * * * *`;case`daily`:return`${t} ${n} * * *`;case`weekly`:return`${t} ${n} * * ${r}`;case`custom`:return String(e.custom||``).trim()}}C(),l(),L(),O();var jt={class:`schedule-panel`},Mt={class:`schedule-toolbar`},Nt={class:`schedule-summary`},Pt={key:0,class:`schedule-error`},Ft={key:1,class:`schedule-loading`},It={key:2,class:`schedule-empty`},Lt={class:`schedule-empty-title`},Rt={class:`schedule-empty-desc`},zt={key:3,class:`schedule-list`},Bt={class:`schedule-card-body`},Vt={class:`schedule-card-head`},Ht={class:`schedule-name`},Ut={key:0,class:`schedule-running`},Wt=[`aria-checked`,`aria-label`,`onClick`],Gt={class:`schedule-card-sub`},Kt={class:`schedule-desc`},qt=[`onClick`],Jt={class:`schedule-card-side`},Yt={class:`schedule-actions`},Xt=[`disabled`,`onClick`],Zt=[`disabled`,`onClick`],Qt=[`onClick`],$t=[`onClick`],en={class:`sch-form`},tn={class:`sch-field`},nn={class:`sch-field-label`},rn=[`placeholder`],an={class:`sch-field`},on={class:`sch-field-label`},sn={class:`sch-freq-row`},cn=[`value`],ln={class:`sch-inline-label`},un=[`value`],dn={class:`sch-inline-label`},fn=[`value`],pn=[`value`],mn=[`value`],hn={class:`sch-inline-label`},gn=[`value`],_n={class:`sch-inline-label`},vn=[`placeholder`],yn={class:`sch-hint`},bn={class:`sch-field`},xn={class:`sch-field-label`},Sn=[`placeholder`],Cn={class:`sch-field`},wn={class:`sch-field-label`},Tn=[`placeholder`],En={class:`sch-field`},Dn={class:`sch-field-label`},On={class:`sch-radio-row`},kn={class:`sch-radio`},An={class:`sch-radio`},jn={class:`sch-radio`},Mn={key:0,class:`sch-form-error`},Nn={class:`sch-form-footer`},Pn=[`disabled`],Fn={class:`sch-confirm-text`},In={class:`sch-form-footer`},Ln=X(g({__name:`SchedulePanel`,emits:[`open-session`],setup(t,{emit:r}){let i=r,l=oe(),u=G([]),d=G(!0),f=G(``),p=G({}),g=null,_=null;async function v(){try{u.value=await _t(),f.value=``}catch(e){f.value=e?.message||String(e)}finally{d.value=!1}}function y(){_===null&&(_=window.setTimeout(()=>{_=null,v()},150))}w(async()=>{await v(),g=Ct(e=>{[`tasks_changed`,`task_started`,`task_finished`,`hello`].includes(e.type)&&y()})}),m(()=>{g?.(),_!==null&&window.clearTimeout(_)});let S=s(()=>{let e=u.value.filter(e=>e.enabled).length,t=u.value.length-e;return u.value.length?Y(`@SCHED:{on} 个启用 · {off} 个停用`,{on:e,off:t}):``}),C=[`@SCHED:周日`,`@SCHED:周一`,`@SCHED:周二`,`@SCHED:周三`,`@SCHED:周四`,`@SCHED:周五`,`@SCHED:周六`];function ee(e){let t=Tt(e.schedule);switch(t.kind){case`every-minute`:return Y(`@SCHED:每分钟`);case`every-n-minutes`:return Y(`@SCHED:每 {n} 分钟`,{n:t.n});case`hourly`:return Y(`@SCHED:每小时第 {minute} 分钟`,{minute:t.minute});case`daily`:return Y(`@SCHED:每天 {time}`,{time:`${String(t.hour).padStart(2,`0`)}:${String(t.minute).padStart(2,`0`)}`});case`weekly`:return Y(`@SCHED:每周 {weekday} {time}`,{weekday:Y(C[t.weekday]),time:`${String(t.hour).padStart(2,`0`)}:${String(t.minute).padStart(2,`0`)}`});case`monthly`:return Y(`@SCHED:每月 {day} 日 {time}`,{day:t.day,time:`${String(t.hour).padStart(2,`0`)}:${String(t.minute).padStart(2,`0`)}`});default:return t.raw}}function T(e){if(!e.enabled)return Y(`@SCHED:已停用`);if(e.running)return Y(`@SCHED:运行中...`);let t=Dt(e.nextRunAt);switch(t.kind){case`none`:return``;case`today`:return Y(`@SCHED:下次 今天 {time}`,{time:t.time});case`tomorrow`:return Y(`@SCHED:下次 明天 {time}`,{time:t.time});case`weekday`:return Y(`@SCHED:下次 {weekday} {time}`,{weekday:Y(C[t.weekday]),time:t.time});case`date`:return Y(`@SCHED:下次 {date} {time}`,{date:t.date,time:t.time})}}function E(e){let t=e.lastRun;if(!t)return Y(`@SCHED:还没执行过`);switch(t.status){case`ok`:return Y(`@SCHED:成功`);case`error`:return Y(`@SCHED:失败`);case`timed-out`:return Y(`@SCHED:超时中止`);case`skipped-busy`:return Y(`@SCHED:已跳过(会话忙)`);case`missed`:return Y(`@SCHED:已错过(未运行)`);case`cancelled`:return Y(`@SCHED:已停止`);default:return t.status}}function te(e){let t=e.lastRun;if(!t)return Y(`@SCHED:还没执行过`);let n=kt(t.durationMs),r=Y(`@SCHED:上次 {status}`,{status:E(e)});return n?`${r} · ${n}`:r}function ne(e){return e.lastRun?`is-${Ot(e.lastRun.status)}`:`is-muted`}async function O(e,t){if(!p.value[e.id]){p.value={...p.value,[e.id]:!0};try{await t(),await v()}catch(e){M.error(e?.message||String(e))}finally{let t={...p.value};delete t[e.id],p.value=t}}}function A(e){return O(e,()=>yt(e.id,{enabled:!e.enabled}))}function re(e){return O(e,()=>xt(e.id))}function ie(e){return O(e,()=>St(e.id))}let F=G(!1),L=G(null);function ae(e){L.value=e,F.value=!0}async function R(){let e=L.value;if(e)try{await bt(e.id),F.value=!1,await v()}catch(e){M.error(e?.message||String(e))}}let z=G(!1),B=G(``),V=G(``),H=G(!1),K=G({name:``,freq:`daily`,everyMinutes:30,minute:0,hour:9,weekday:1,custom:``,cwd:``,prompt:``,onMissed:`run`,enabled:!0}),q=s(()=>[{value:`minutes`,label:Y(`@SCHED:每 N 分钟`)},{value:`hourly`,label:Y(`@SCHED:每小时`)},{value:`daily`,label:Y(`@SCHED:每天`)},{value:`weekly`,label:Y(`@SCHED:每周`)},{value:`custom`,label:Y(`@SCHED:自定义 cron`)}]),J=s(()=>At({freq:K.value.freq,everyMinutes:K.value.everyMinutes,minute:K.value.minute,hour:K.value.hour,weekday:K.value.weekday,custom:K.value.custom}));function X(){K.value={name:``,freq:`daily`,everyMinutes:30,minute:0,hour:9,weekday:1,custom:``,cwd:l.currentDirectory||``,prompt:``,onMissed:`run`,enabled:!0},V.value=``}function ce(){B.value=``,X(),z.value=!0}function Z(e){B.value=e.id;let t=Tt(e.schedule),n={name:e.name,freq:`custom`,everyMinutes:30,minute:0,hour:9,weekday:1,custom:e.schedule,cwd:e.cwd,prompt:e.prompt,onMissed:e.onMissed===`skip`?`skip`:`run`,enabled:e.enabled};switch(t.kind){case`every-n-minutes`:n.freq=`minutes`,n.everyMinutes=t.n;break;case`hourly`:n.freq=`hourly`,n.minute=t.minute;break;case`daily`:n.freq=`daily`,n.minute=t.minute,n.hour=t.hour;break;case`weekly`:n.freq=`weekly`,n.minute=t.minute,n.hour=t.hour,n.weekday=t.weekday;break;default:n.freq=`custom`}K.value=n,V.value=``,z.value=!0}async function le(){let e=K.value;if(!e.name.trim()){V.value=Y(`@SCHED:任务名不能为空`);return}if(!e.prompt.trim()){V.value=Y(`@SCHED:提示词不能为空`);return}let t=J.value;if(!t){V.value=Y(`@SCHED:cron 表达式不能为空`);return}let n={name:e.name.trim(),schedule:t,cwd:e.cwd.trim(),prompt:e.prompt.trim(),enabled:e.enabled,onMissed:e.onMissed};H.value=!0;try{B.value?await yt(B.value,n):await vt(n),z.value=!1,await v()}catch(e){V.value=e?.message||String(e)}finally{H.value=!1}}return(t,r)=>(b(),n(`div`,jt,[a(`div`,Mt,[a(`span`,Nt,e(S.value),1),a(`button`,{type:`button`,class:`sch-btn sch-btn-primary`,onClick:ce},e(o(Y)(`@SCHED:新建任务`)),1)]),f.value?(b(),n(`div`,Pt,e(o(Y)(`@SCHED:操作失败:{error}`,{error:f.value})),1)):N(``,!0),d.value?(b(),n(`div`,Ft,e(o(Y)(`@SCHED:加载中...`)),1)):u.value.length?(b(),n(`div`,zt,[(b(!0),n(x,null,k(u.value,t=>(b(),n(`article`,{key:t.id,class:h([`schedule-card`,{"is-disabled":!t.enabled,"is-running":!!t.running}])},[a(`div`,Bt,[a(`div`,Vt,[a(`span`,Ht,e(t.name),1),t.running?(b(),n(`span`,Ut,e(o(Y)(`@SCHED:运行中`)),1)):N(``,!0),a(`button`,{type:`button`,class:h([`sch-switch`,{on:t.enabled}]),role:`switch`,"aria-checked":t.enabled,"aria-label":t.enabled?o(Y)(`@SCHED:停用`):o(Y)(`@SCHED:启用`),onClick:e=>A(t)},[...r[17]||=[a(`span`,{class:`sch-switch-knob`},null,-1)]],10,Wt)]),a(`div`,Gt,[a(`span`,Kt,e(ee(t)),1),r[18]||=a(`span`,{class:`schedule-sep`},`·`,-1),a(`span`,{class:h([`schedule-last`,ne(t)])},e(te(t)),3),t.sessionId?(b(),n(`button`,{key:0,type:`button`,class:`sch-link`,onClick:e=>i(`open-session`,t.sessionId)},e(o(Y)(`@SCHED:查看会话`)),9,qt)):N(``,!0)])]),a(`div`,Jt,[a(`div`,{class:h([`schedule-next`,{"is-muted":!t.enabled}])},e(T(t)),3),a(`div`,Yt,[t.running?(b(),n(`button`,{key:0,type:`button`,class:`sch-btn`,disabled:!!p.value[t.id],onClick:e=>ie(t)},e(o(Y)(`@SCHED:停止`)),9,Xt)):(b(),n(`button`,{key:1,type:`button`,class:`sch-btn`,disabled:!!p.value[t.id],onClick:e=>re(t)},e(o(Y)(`@SCHED:运行`)),9,Zt)),a(`button`,{type:`button`,class:`sch-btn`,onClick:e=>Z(t)},e(o(Y)(`@SCHED:编辑`)),9,Qt),a(`button`,{type:`button`,class:`sch-btn sch-btn-danger`,onClick:e=>ae(t)},e(o(Y)(`@SCHED:删除`)),9,$t)])])],2))),128))])):(b(),n(`div`,It,[a(`p`,Lt,e(o(Y)(`@SCHED:还没有定时任务`)),1),a(`p`,Rt,e(o(Y)(`@SCHED:让 g ai 在指定时间自动做事:定时拉代码、定时巡检、定时汇总。也可以在对话里直接说「每天 9 点帮我…」,让 g ai 来创建。`)),1)])),c(se,{modelValue:z.value,"onUpdate:modelValue":r[14]||=e=>z.value=e,title:B.value?o(Y)(`@SCHED:编辑任务`):o(Y)(`@SCHED:新建任务`),"close-on-click-modal":!1,"append-to-body":!0,size:`medium`,width:`560px`,"z-index":3e6,"custom-class":`schedule-dialog`},{default:P(()=>[a(`div`,en,[a(`label`,tn,[a(`span`,nn,e(o(Y)(`@SCHED:任务名`)),1),U(a(`input`,{"onUpdate:modelValue":r[0]||=e=>K.value.name=e,class:`sch-input`,type:`text`,placeholder:o(Y)(`@SCHED:如:每日拉代码`)},null,8,rn),[[W,K.value.name]])]),a(`div`,an,[a(`span`,on,e(o(Y)(`@SCHED:执行计划`)),1),a(`div`,sn,[U(a(`select`,{"onUpdate:modelValue":r[1]||=e=>K.value.freq=e,class:`sch-input sch-select`},[(b(!0),n(x,null,k(q.value,t=>(b(),n(`option`,{key:t.value,value:t.value},e(t.label),9,cn))),128))],512),[[D,K.value.freq]]),K.value.freq===`minutes`?(b(),n(x,{key:0},[a(`span`,ln,e(o(Y)(`@SCHED:每`)),1),U(a(`select`,{"onUpdate:modelValue":r[2]||=e=>K.value.everyMinutes=e,class:`sch-input sch-select sch-select-sm`},[(b(),n(x,null,k([5,10,15,20,30,60],t=>a(`option`,{key:t,value:t},e(t),9,un)),64))],512),[[D,K.value.everyMinutes,void 0,{number:!0}]]),a(`span`,dn,e(o(Y)(`@SCHED:分钟`)),1)],64)):K.value.freq===`daily`||K.value.freq===`weekly`?(b(),n(x,{key:1},[K.value.freq===`weekly`?U((b(),n(`select`,{key:0,"onUpdate:modelValue":r[3]||=e=>K.value.weekday=e,class:`sch-input sch-select sch-select-sm`},[(b(),n(x,null,k(C,(t,n)=>a(`option`,{key:n,value:n},e(o(Y)(t)),9,fn)),64))],512)),[[D,K.value.weekday,void 0,{number:!0}]]):N(``,!0),U(a(`select`,{"onUpdate:modelValue":r[4]||=e=>K.value.hour=e,class:`sch-input sch-select sch-select-sm`},[(b(),n(x,null,k(24,t=>a(`option`,{key:t-1,value:t-1},e(String(t-1).padStart(2,`0`)),9,pn)),64))],512),[[D,K.value.hour,void 0,{number:!0}]]),r[19]||=a(`span`,{class:`sch-inline-label`},`:`,-1),U(a(`select`,{"onUpdate:modelValue":r[5]||=e=>K.value.minute=e,class:`sch-input sch-select sch-select-sm`},[(b(),n(x,null,k(60,t=>a(`option`,{key:t-1,value:t-1},e(String(t-1).padStart(2,`0`)),9,mn)),64))],512),[[D,K.value.minute,void 0,{number:!0}]])],64)):K.value.freq===`hourly`?(b(),n(x,{key:2},[a(`span`,hn,e(o(Y)(`@SCHED:第`)),1),U(a(`select`,{"onUpdate:modelValue":r[6]||=e=>K.value.minute=e,class:`sch-input sch-select sch-select-sm`},[(b(),n(x,null,k(60,t=>a(`option`,{key:t-1,value:t-1},e(String(t-1).padStart(2,`0`)),9,gn)),64))],512),[[D,K.value.minute,void 0,{number:!0}]]),a(`span`,_n,e(o(Y)(`@SCHED:分钟`)),1)],64)):U((b(),n(`input`,{key:3,"onUpdate:modelValue":r[7]||=e=>K.value.custom=e,class:`sch-input sch-input-cron`,type:`text`,spellcheck:`false`,placeholder:o(Y)(`@SCHED:如:0 9 * * 1-5`)},null,8,vn)),[[W,K.value.custom]])]),a(`span`,yn,e(o(Y)(`@SCHED:cron:{cron}(分 时 日 月 周,本地时间)`,{cron:J.value||`—`})),1)]),a(`label`,bn,[a(`span`,xn,e(o(Y)(`@SCHED:项目目录`)),1),U(a(`input`,{"onUpdate:modelValue":r[8]||=e=>K.value.cwd=e,class:`sch-input`,type:`text`,spellcheck:`false`,placeholder:o(Y)(`@SCHED:任务在该目录下执行(默认当前项目)`)},null,8,Sn),[[W,K.value.cwd]])]),a(`label`,Cn,[a(`span`,wn,e(o(Y)(`@SCHED:提示词`)),1),U(a(`textarea`,{"onUpdate:modelValue":r[9]||=e=>K.value.prompt=e,class:`sch-input sch-textarea`,rows:`4`,placeholder:o(Y)(`@SCHED:到点后发给 g ai 的完整指令,例如:检查所有仓库远端更新,有变更就 pull;写成一次自足的请求(未来那一轮没有现在的上下文)`)},null,8,Tn),[[W,K.value.prompt]])]),a(`div`,En,[a(`span`,Dn,e(o(Y)(`@SCHED:错过补偿`)),1),a(`div`,On,[a(`label`,kn,[U(a(`input`,{"onUpdate:modelValue":r[10]||=e=>K.value.onMissed=e,type:`radio`,value:`run`},null,512),[[j,K.value.onMissed]]),a(`span`,null,e(o(Y)(`@SCHED:补跑一次(g ui 重新运行后)`)),1)]),a(`label`,An,[U(a(`input`,{"onUpdate:modelValue":r[11]||=e=>K.value.onMissed=e,type:`radio`,value:`skip`},null,512),[[j,K.value.onMissed]]),a(`span`,null,e(o(Y)(`@SCHED:跳过`)),1)]),a(`label`,jn,[U(a(`input`,{"onUpdate:modelValue":r[12]||=e=>K.value.enabled=e,type:`checkbox`},null,512),[[I,K.value.enabled]]),a(`span`,null,e(o(Y)(`@SCHED:创建后启用`)),1)])])]),V.value?(b(),n(`p`,Mn,e(V.value),1)):N(``,!0)]),a(`div`,Nn,[a(`button`,{type:`button`,class:`sch-btn`,onClick:r[13]||=e=>z.value=!1},e(o(Y)(`@SCHED:取消`)),1),a(`button`,{type:`button`,class:`sch-btn sch-btn-primary`,disabled:H.value,onClick:le},e(H.value?o(Y)(`@SCHED:保存中...`):o(Y)(`@SCHED:保存`)),9,Pn)])]),_:1},8,[`modelValue`,`title`]),c(se,{modelValue:F.value,"onUpdate:modelValue":r[16]||=e=>F.value=e,title:o(Y)(`@SCHED:删除任务`),"close-on-click-modal":!1,"append-to-body":!0,size:`small`,width:`400px`,"z-index":3e6,"custom-class":`schedule-dialog-confirm`},{default:P(()=>[a(`p`,Fn,e(o(Y)(`@SCHED:确定删除「{name}」吗?已产生的会话会保留,但任务不再执行。`,{name:L.value?.name||``})),1),a(`div`,In,[a(`button`,{type:`button`,class:`sch-btn`,onClick:r[15]||=e=>F.value=!1},e(o(Y)(`@SCHED:取消`)),1),a(`button`,{type:`button`,class:`sch-btn sch-btn-danger`,onClick:R},e(o(Y)(`@SCHED:删除`)),1)])]),_:1},8,[`modelValue`,`title`])]))}}),[[`__scopeId`,`data-v-75be84e5`]]);C(),L(),l();var Rn={class:`agent-chat-area`},zn={class:`agent-tabs`,role:`tablist`},Bn=[`aria-selected`,`onClick`],Vn={class:`agent-tab-body`},Hn={key:0,class:`agent-chat-pane`},Un={key:0,class:`agent-list-page`},Wn={key:0,class:`agent-page-bar`},Gn=[`title`,`aria-label`],Kn={class:`agent-page-title`},qn={key:0,class:`chat-loading`},Jn=X(g({__name:`AgentView`,setup(i){let l=oe(),d=G(null),{narrow:f}=ye(d),m=G(`chat`),g=G(`chat`),_=s(()=>g.value===`mcp`?`mcp`:`skill`),y=s(()=>[{id:`chat`,label:Y(`@AGENT:对话`),icon:A},{id:`schedule`,label:Y(`@AGENT:定时任务`),icon:t},{id:`skill`,label:Y(`@AGENT:Skill 广场`),icon:S},{id:`mcp`,label:Y(`@AGENT:MCP 广场`),icon:V}]),{sessions:C,sessionsLoading:ee,currentSessionId:w,messages:E,isStreaming:D,sessionLoading:te,loadSessions:ne,loadSession:O,deleteSession:j,renameSession:M,newSession:re,sendMessage:ie,retryTurn:F,questionPanel:I,answeringQuestion:L,answerQuestion:ae,isSessionGenerating:R,currentEngine:H,pendingEngine:U,isEngineLocked:W,pickEngine:K,stop:X,inputContextUsage:se,queuedMessages:Se,queuePaused:Ce,removeQueuedMessage:we,flushQueued:Te}=ve(),Ee=s(()=>W.value?H.value:U.value);function De(e){W.value||K(e)}let Oe=s(()=>{let e=l.theme;return e===`dark`||e===`auto`&&window.matchMedia(`(prefers-color-scheme: dark)`).matches?`dark`:`light`}),ke=s(()=>le(C.value,R)),Ae=Z(),je=s(()=>ke.value.find(e=>e.id===w.value)?.title||Y(`@AGENT:对话`)),Me={"--welcome-avatar":`url("${_e}")`},Ne=s(()=>ce(l.agentPresetPrompts));async function Pe(e){await ie(e.text,e.files),await u(),ze()}async function Fe(e){await ie(e.prompt),await u(),ze()}let Ie=pe(),Le=G(null),Re=ge();function ze(e=!0){Le.value?.scrollToBottom(e)}B(()=>E.value.length,()=>{u(()=>ze(!1))});function Be(e){O(e),m.value=`chat`}function Ve(e){e&&(g.value=`chat`,Be(e))}function He(){re(),m.value=`chat`}let Ue=G(280),We=G(!1);function Ge(e){We.value=!0;let t=e.clientX,n=Ue.value,r=e=>{let r=e.clientX-t,i=Math.max(200,Math.min(500,n+r));Ue.value=i},i=()=>{We.value=!1,document.removeEventListener(`mousemove`,r),document.removeEventListener(`mouseup`,i)};document.addEventListener(`mousemove`,r),document.addEventListener(`mouseup`,i)}return B(f,e=>{e||(m.value=`chat`)}),B(()=>[l.currentDirectory,D.value],async([e,t],n)=>{let r=!n||e!==n[0],i=!!n&&n[1]===!0&&!t;(r||i)&&await ne(),w.value&&!D.value&&!C.value.some(e=>e.sessionId===w.value)&&re()},{immediate:!0}),(t,i)=>(b(),n(`div`,{ref_key:`rootRef`,ref:d,class:`agent-view`},[g.value===`chat`&&!o(f)?(b(),n(x,{key:0},[a(`aside`,{class:`agent-sidebar`,style:T({width:Ue.value+`px`})},[c(o(J),{class:`agent-conversations`,items:ke.value,"active-id":o(w),loading:o(ee),labels:o(Ae),onSelect:Be,onNew:He,onRename:o(M),onDelete:o(j)},null,8,[`items`,`active-id`,`loading`,`labels`,`onRename`,`onDelete`])],4),a(`div`,{class:h([`sidebar-resizer`,{active:We.value}]),onMousedown:Ge},null,34)],64)):N(``,!0),a(`main`,Rn,[a(`nav`,zn,[(b(!0),n(x,null,k(y.value,t=>(b(),n(`button`,{key:t.id,type:`button`,class:h([`agent-tab`,{active:g.value===t.id}]),role:`tab`,"aria-selected":g.value===t.id,onClick:e=>g.value=t.id},[c(o(p),null,{default:P(()=>[(b(),v(z(t.icon)))]),_:2},1024),a(`span`,null,e(t.label),1)],10,Bn))),128)),g.value===`chat`?(b(),v(be,{key:0,class:`agent-engine`,engine:Ee.value,locked:o(W),onSelect:De},null,8,[`engine`,`locked`])):N(``,!0),g.value===`chat`?(b(),v(xe,{key:1,class:`agent-copy`,messages:o(E),title:je.value,engine:o(me)(Ee.value)},null,8,[`messages`,`title`,`engine`])):N(``,!0)]),a(`div`,Vn,[g.value===`chat`?(b(),n(`div`,Hn,[o(f)&&m.value===`list`?(b(),n(`div`,Un,[c(o(J),{class:`agent-conversations`,items:ke.value,"active-id":o(w),loading:o(ee),labels:o(Ae),onSelect:Be,onNew:He,onRename:o(M),onDelete:o(j)},null,8,[`items`,`active-id`,`loading`,`labels`,`onRename`,`onDelete`])])):(b(),n(x,{key:1},[o(f)?(b(),n(`div`,Wn,[a(`button`,{type:`button`,class:`agent-page-back`,title:o(Y)(`@AGENT:返回会话列表`),"aria-label":o(Y)(`@AGENT:返回会话列表`),onClick:i[0]||=e=>m.value=`list`},[...i[1]||=[a(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[a(`line`,{x1:`19`,y1:`12`,x2:`5`,y2:`12`}),a(`polyline`,{points:`12 19 5 12 12 5`})],-1)]],8,Gn),a(`span`,Kn,e(je.value),1)])):N(``,!0),a(`div`,{class:`agent-chat-host`,style:Me},[o(te)?(b(),n(`div`,qn,[c(o(p),{class:`is-loading`,size:32},{default:P(()=>[c(o(r))]),_:1}),a(`span`,null,e(o(Y)(`@AGENT:加载会话中...`)),1)])):(b(),v(o(q),{key:1,ref_key:`chatContainerRef`,ref:Le,messages:o(E),"preset-questions":Ne.value,"welcome-title":o(Y)(`@AGENT:智能体助手`),"welcome-description":o(Y)(`@AGENT:我可以帮你阅读代码、执行命令、修改文件。选择下方话题或直接输入你的问题。`),"assistant-name":o(fe),"assistant-avatar":o(_e),theme:Oe.value,generating:o(D),"allow-queue":!0,queued:o(Se),"queue-paused":o(Ce),"queue-labels":o(Re),"upload-config":{accept:o(de)},"context-usage":o(se),placeholder:o(D)?o(Y)(`@AGENT:生成中,发送后会排队,等本轮跑完自动接上…`):o(Y)(`@AGENT:输入消息,Enter 发送`),question:o(I),"question-submitting":o(L),"question-labels":o(Ie),"plan-config":{labels:{title:o(Y)(`@AGENT:计划`),raw:o(Y)(`@AGENT:原始参数`)}},"message-rail-config":o(ue),"message-meta-config":o(he),onSend:Pe,onSelect:Fe,onStop:o(X),onUnqueue:o(we),onFlushQueued:o(Te),onAnswer:o(ae),onRetry:o(F)},null,8,[`messages`,`preset-questions`,`welcome-title`,`welcome-description`,`assistant-name`,`assistant-avatar`,`theme`,`generating`,`queued`,`queue-paused`,`queue-labels`,`upload-config`,`context-usage`,`placeholder`,`question`,`question-submitting`,`question-labels`,`plan-config`,`message-rail-config`,`message-meta-config`,`onStop`,`onUnqueue`,`onFlushQueued`,`onAnswer`,`onRetry`]))])],64))])):g.value===`schedule`?(b(),v(Ln,{key:1,onOpenSession:Ve})):(b(),v(gt,{key:2,type:_.value},null,8,[`type`]))])])],512))}}),[[`__scopeId`,`data-v-df7b54d8`]]);export{Jn as default};