coding-tool-x 3.7.6 → 3.7.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 (44) hide show
  1. package/dist/web/assets/{Analytics-wCRLv26m.js → Analytics-BE5H9JGG.js} +1 -1
  2. package/dist/web/assets/{ConfigTemplates-aa1blEHh.js → ConfigTemplates-z118k1BE.js} +1 -1
  3. package/dist/web/assets/{Home-eIxO50-k.js → Home-CBhtmOIN.js} +1 -1
  4. package/dist/web/assets/{PluginManager-BAwGFNjN.js → PluginManager-CGhfZ3t8.js} +1 -1
  5. package/dist/web/assets/ProjectList-BMPLJtgQ.js +1 -0
  6. package/dist/web/assets/ProjectList-VeMNXfgO.css +1 -0
  7. package/dist/web/assets/SessionList-C4chCPxK.css +1 -0
  8. package/dist/web/assets/SessionList-D9e7wGF1.js +1 -0
  9. package/dist/web/assets/{SkillManager-Bhzs1O5S.js → SkillManager-DJpdUmnk.js} +1 -1
  10. package/dist/web/assets/{WorkspaceManager-CLdX-pTT.js → WorkspaceManager-C0Ud_V7v.js} +1 -1
  11. package/dist/web/assets/index-CeTaG4IX.js +2 -0
  12. package/dist/web/assets/index-S8wrU2Nf.css +1 -0
  13. package/dist/web/index.html +2 -2
  14. package/package.json +1 -1
  15. package/src/commands/daemon.js +3 -1
  16. package/src/commands/port-config.js +0 -2
  17. package/src/commands/switch.js +1 -5
  18. package/src/commands/ui.js +4 -3
  19. package/src/commands/workspace.js +35 -3
  20. package/src/config/loader.js +76 -5
  21. package/src/index.js +11 -0
  22. package/src/server/api/config.js +0 -3
  23. package/src/server/api/omp-channels.js +29 -9
  24. package/src/server/api/omp-config.js +6 -8
  25. package/src/server/api/settings.js +0 -2
  26. package/src/server/api/workspaces.js +39 -1
  27. package/src/server/services/dashboard-snapshot-worker.js +1 -0
  28. package/src/server/services/https-cert.js +3 -2
  29. package/src/server/services/model-detector.js +106 -26
  30. package/src/server/services/omp-auth-providers.js +1 -0
  31. package/src/server/services/omp-config.js +22 -0
  32. package/src/server/services/omp-settings-manager.js +31 -16
  33. package/src/server/services/session-snapshots.js +1 -0
  34. package/src/server/services/sessions.js +35 -19
  35. package/src/server/services/web-build.js +2 -1
  36. package/src/server/services/workspace-service.js +204 -98
  37. package/src/utils/cli-flags.js +7 -0
  38. package/src/utils/session.js +10 -4
  39. package/dist/web/assets/ProjectList-CRiAEixW.js +0 -1
  40. package/dist/web/assets/ProjectList-Dw2omgOH.css +0 -1
  41. package/dist/web/assets/SessionList-BQ0FW6Gd.js +0 -1
  42. package/dist/web/assets/SessionList-kYJ6-Ies.css +0 -1
  43. package/dist/web/assets/index-B_nFqixU.css +0 -1
  44. package/dist/web/assets/index-ClMNA9Hf.js +0 -2
@@ -1,5 +1,6 @@
1
1
  // 多项目工作区服务
2
2
  const fs = require('fs');
3
+ const os = require('os');
3
4
  const path = require('path');
4
5
  const { execFileSync } = require('child_process');
5
6
  const { PATHS } = require('../../config/paths');
@@ -46,6 +47,190 @@ function resolveCurrentBranch(repoPath) {
46
47
  }
47
48
  }
48
49
 
50
+ function getGitErrorMessage(error) {
51
+ const stderr = error && error.stderr ? error.stderr.toString().trim() : '';
52
+ return stderr || (error && error.message) || String(error);
53
+ }
54
+
55
+ function normalizeString(value) {
56
+ return typeof value === 'string' ? value.trim() : '';
57
+ }
58
+
59
+ function normalizeBranchMode(projectConfig = {}) {
60
+ const branchMode = normalizeString(projectConfig.branchMode);
61
+ if (branchMode === 'new' || branchMode === 'existing') {
62
+ return branchMode;
63
+ }
64
+ return normalizeString(projectConfig.baseBranch) ? 'new' : 'existing';
65
+ }
66
+
67
+ function normalizeGitBranchRef(branchName) {
68
+ return normalizeString(branchName).replace(/^refs\/heads\//, '');
69
+ }
70
+
71
+ function parseGitWorktrees(output) {
72
+ const worktrees = [];
73
+ const lines = output.split('\n');
74
+ let current = {};
75
+
76
+ for (const line of lines) {
77
+ if (line.startsWith('worktree ')) {
78
+ if (current.path) {
79
+ worktrees.push(current);
80
+ }
81
+ current = { path: line.substring(9) };
82
+ } else if (line.startsWith('branch ')) {
83
+ current.branch = line.substring(7);
84
+ } else if (line.startsWith('HEAD ')) {
85
+ current.head = line.substring(5);
86
+ }
87
+ }
88
+
89
+ if (current.path) {
90
+ worktrees.push(current);
91
+ }
92
+
93
+ return worktrees;
94
+ }
95
+
96
+ function listGitWorktrees(repoPath) {
97
+ const output = runGitCommand(['worktree', 'list', '--porcelain'], {
98
+ cwd: repoPath
99
+ });
100
+ return parseGitWorktrees(output);
101
+ }
102
+
103
+ function hasGitRef(repoPath, ref) {
104
+ try {
105
+ runGitCommand(['show-ref', '--verify', '--quiet', ref], {
106
+ cwd: repoPath,
107
+ stdio: 'ignore'
108
+ });
109
+ return true;
110
+ } catch (_) {
111
+ return false;
112
+ }
113
+ }
114
+
115
+ function findWorktreeForBranch(repoPath, branchName) {
116
+ const normalizedBranch = normalizeGitBranchRef(branchName);
117
+ const refName = `refs/heads/${normalizedBranch}`;
118
+ return listGitWorktrees(repoPath).find(wt => wt.branch === refName);
119
+ }
120
+
121
+ function pullBaseBranch(worktreePath, baseBranch) {
122
+ try {
123
+ runGitCommand(['pull', '--ff-only'], { cwd: worktreePath });
124
+ } catch (error) {
125
+ try {
126
+ runGitCommand(['remote', 'get-url', 'origin'], { cwd: worktreePath });
127
+ } catch (_) {
128
+ return;
129
+ }
130
+ const normalizedBaseBranch = normalizeGitBranchRef(baseBranch);
131
+ runGitCommand(['pull', '--ff-only', 'origin', normalizedBaseBranch], {
132
+ cwd: worktreePath
133
+ });
134
+ }
135
+ }
136
+
137
+ function removeTemporaryWorktree(repoPath, tempWorktreePath) {
138
+ try {
139
+ runGitCommand(['worktree', 'remove', tempWorktreePath, '--force'], {
140
+ cwd: repoPath
141
+ });
142
+ } catch (error) {
143
+ console.warn(`移除临时 worktree 失败: ${tempWorktreePath}`, error.message);
144
+ } finally {
145
+ if (fs.existsSync(tempWorktreePath)) {
146
+ fs.rmSync(tempWorktreePath, { recursive: true, force: true });
147
+ }
148
+ }
149
+ }
150
+
151
+ function updateBaseBranch(repoPath, baseBranch) {
152
+ const normalizedBaseBranch = normalizeGitBranchRef(baseBranch);
153
+ if (!normalizedBaseBranch) {
154
+ return null;
155
+ }
156
+
157
+ runGitCommand(['fetch', '--all', '--prune'], { cwd: repoPath });
158
+
159
+ const localRef = `refs/heads/${normalizedBaseBranch}`;
160
+ const remoteRef = `refs/remotes/origin/${normalizedBaseBranch}`;
161
+ const hasLocalBranch = hasGitRef(repoPath, localRef);
162
+ const hasRemoteBranch = hasGitRef(repoPath, remoteRef);
163
+ if (!hasLocalBranch && !hasRemoteBranch) {
164
+ throw new Error(`基础分支不存在: ${normalizedBaseBranch}`);
165
+ }
166
+
167
+ const existingWorktree = hasLocalBranch ? findWorktreeForBranch(repoPath, normalizedBaseBranch) : null;
168
+ if (existingWorktree) {
169
+ pullBaseBranch(existingWorktree.path, normalizedBaseBranch);
170
+ return normalizedBaseBranch;
171
+ }
172
+
173
+ const tempParent = fs.mkdtempSync(path.join(os.tmpdir(), 'ctx-base-'));
174
+ const tempWorktreePath = path.join(tempParent, 'worktree');
175
+ try {
176
+ if (hasLocalBranch) {
177
+ runGitCommand(['worktree', 'add', tempWorktreePath, normalizedBaseBranch], {
178
+ cwd: repoPath
179
+ });
180
+ } else {
181
+ runGitCommand(['worktree', 'add', tempWorktreePath, '-b', normalizedBaseBranch, `origin/${normalizedBaseBranch}`], {
182
+ cwd: repoPath
183
+ });
184
+ }
185
+ pullBaseBranch(tempWorktreePath, normalizedBaseBranch);
186
+ return normalizedBaseBranch;
187
+ } finally {
188
+ removeTemporaryWorktree(repoPath, tempWorktreePath);
189
+ if (fs.existsSync(tempParent)) {
190
+ fs.rmSync(tempParent, { recursive: true, force: true });
191
+ }
192
+ }
193
+ }
194
+
195
+ function createGitWorktree({ sourcePath, worktreePath, branch, baseBranch, branchMode, actionLabel }) {
196
+ let targetBranch = normalizeString(branch);
197
+ if (!targetBranch) {
198
+ try {
199
+ targetBranch = resolveCurrentBranch(sourcePath);
200
+ } catch (e) {
201
+ targetBranch = 'main';
202
+ }
203
+ }
204
+
205
+ const resolvedBranchMode = branchMode === 'new' ? 'new' : 'existing';
206
+
207
+ if (resolvedBranchMode === 'new') {
208
+ const worktreeArgs = ['worktree', 'add', worktreePath, '-b', targetBranch];
209
+ const updatedBaseBranch = updateBaseBranch(sourcePath, baseBranch);
210
+ if (updatedBaseBranch) {
211
+ worktreeArgs.push(updatedBaseBranch);
212
+ }
213
+
214
+ try {
215
+ runGitCommand(worktreeArgs, { cwd: sourcePath });
216
+ return { branch: targetBranch, path: worktreePath };
217
+ } catch (error) {
218
+ throw new Error(`创建 worktree 失败: ${getGitErrorMessage(error)}`);
219
+ }
220
+ }
221
+
222
+ try {
223
+ // Existing branches may already be checked out in another worktree.
224
+ // `-f` makes that explicit instead of relying on a version-dependent retry.
225
+ runGitCommand(['worktree', 'add', '-f', worktreePath, targetBranch], {
226
+ cwd: sourcePath
227
+ });
228
+ return { branch: targetBranch, path: worktreePath };
229
+ } catch (error) {
230
+ throw new Error(`创建 worktree 失败: ${getGitErrorMessage(error)}`);
231
+ }
232
+ }
233
+
49
234
  /**
50
235
  * 生成唯一工作区 ID
51
236
  */
@@ -147,31 +332,7 @@ function getGitWorktrees(repoPath) {
147
332
  if (!isGitRepo(repoPath)) {
148
333
  return [];
149
334
  }
150
- const output = runGitCommand(['worktree', 'list', '--porcelain'], {
151
- cwd: repoPath
152
- });
153
-
154
- const worktrees = [];
155
- const lines = output.split('\n');
156
- let current = {};
157
-
158
- for (const line of lines) {
159
- if (line.startsWith('worktree ')) {
160
- if (current.path) {
161
- worktrees.push(current);
162
- }
163
- current = { path: line.substring(9) };
164
- } else if (line.startsWith('branch ')) {
165
- current.branch = line.substring(7);
166
- } else if (line.startsWith('HEAD ')) {
167
- current.head = line.substring(5);
168
- }
169
- }
170
-
171
- if (current.path) {
172
- worktrees.push(current);
173
- }
174
-
335
+ const worktrees = listGitWorktrees(repoPath);
175
336
  return worktrees.filter(wt => wt.path !== repoPath); // 排除主仓库
176
337
  } catch (error) {
177
338
  console.error('获取 worktree 列表失败:', error.message);
@@ -308,48 +469,19 @@ function createWorkspace(options) {
308
469
 
309
470
  // Git 仓库且需要创建 worktree:直接在工作区目录内创建,无需额外 symlink
310
471
  if (isGit && useWorktree) {
311
- // 获取当前分支作为默认分支
312
- let targetBranch = branch;
313
- if (!targetBranch) {
314
- try {
315
- targetBranch = resolveCurrentBranch(sourcePath);
316
- } catch (e) {
317
- targetBranch = 'main';
318
- }
319
- }
320
-
321
472
  // worktree 直接创建到工作区目录内的项目路径
322
473
  const worktreePath = symlinkPath;
323
-
324
- try {
325
- // 尝试检出已有分支
326
- runGitCommand(['worktree', 'add', worktreePath, targetBranch], {
327
- cwd: sourcePath
328
- });
329
- } catch (error) {
330
- // 如果分支不存在,尝试创建新分支
331
- try {
332
- const worktreeArgs = ['worktree', 'add', worktreePath, '-b', targetBranch];
333
- if (baseBranch && baseBranch.trim()) {
334
- worktreeArgs.push(baseBranch.trim());
335
- }
336
- runGitCommand(worktreeArgs, {
337
- cwd: sourcePath
338
- });
339
- } catch (err) {
340
- if (err.message.includes('already checked out')) {
341
- throw new Error(
342
- `无法创建 worktree:分支 '${targetBranch}' 已在其他工作树中检出。\n` +
343
- `错误详情: ${err.message}\n\n` +
344
- `提示:请为此项目指定不同的分支名,或禁用 worktree 模式。`
345
- );
346
- }
347
- throw new Error(`创建 worktree 失败: ${err.message}`);
348
- }
349
- }
474
+ const createdWorktree = createGitWorktree({
475
+ sourcePath,
476
+ worktreePath,
477
+ branch,
478
+ baseBranch,
479
+ branchMode: normalizeBranchMode(proj),
480
+ actionLabel: '创建 worktree'
481
+ });
350
482
 
351
483
  targetPath = worktreePath;
352
- worktrees.push({ branch: targetBranch, path: worktreePath });
484
+ worktrees.push(createdWorktree);
353
485
  } else if (isGit) {
354
486
  // Git 仓库但不创建 worktree:symlink 指向源路径,记录已有 worktrees
355
487
  worktrees = getGitWorktrees(sourcePath);
@@ -509,44 +641,18 @@ function addProjectToWorkspace(workspaceId, projectConfig) {
509
641
 
510
642
  // Git 仓库且需要创建 worktree:直接在工作区目录内创建,无需额外 symlink
511
643
  if (isGit && useWorktree) {
512
- let targetBranch = branch;
513
- if (!targetBranch) {
514
- try {
515
- targetBranch = resolveCurrentBranch(sourcePath);
516
- } catch (e) {
517
- targetBranch = 'main';
518
- }
519
- }
520
-
521
644
  const worktreePath = symlinkPath;
522
-
523
- try {
524
- runGitCommand(['worktree', 'add', worktreePath, targetBranch], {
525
- cwd: sourcePath
526
- });
527
- } catch (error) {
528
- try {
529
- const worktreeArgs = ['worktree', 'add', worktreePath, '-b', targetBranch];
530
- if (baseBranch && baseBranch.trim()) {
531
- worktreeArgs.push(baseBranch.trim());
532
- }
533
- runGitCommand(worktreeArgs, { cwd: sourcePath });
534
- } catch (err) {
535
- if (err.message && err.message.includes('already checked out')) {
536
- throw new Error(
537
- `无法添加项目:分支 '${targetBranch}' 已在其他工作树中检出。\n` +
538
- `仓库路径: ${sourcePath}\n\n` +
539
- `解决方案:\n` +
540
- `1. 指定不同的分支名\n` +
541
- `2. 或者禁用 worktree 模式(设置 createWorktree: false)`
542
- );
543
- }
544
- throw new Error(`创建 worktree 失败: ${err.message}`);
545
- }
546
- }
645
+ const createdWorktree = createGitWorktree({
646
+ sourcePath,
647
+ worktreePath,
648
+ branch,
649
+ baseBranch,
650
+ branchMode: normalizeBranchMode(projectConfig),
651
+ actionLabel: '添加项目'
652
+ });
547
653
 
548
654
  targetPath = worktreePath;
549
- worktrees.push({ branch: targetBranch, path: worktreePath });
655
+ worktrees.push(createdWorktree);
550
656
  } else if (isGit) {
551
657
  // Git 仓库但不创建 worktree:symlink 指向源路径
552
658
  worktrees = getGitWorktrees(sourcePath);
@@ -0,0 +1,7 @@
1
+ function hasHostFlag(argv = process.argv) {
2
+ return Array.isArray(argv) && (argv.includes('--host') || argv.includes('--hosts'));
3
+ }
4
+
5
+ module.exports = {
6
+ hasHostFlag
7
+ };
@@ -2,12 +2,17 @@
2
2
  const fs = require('fs');
3
3
  const path = require('path');
4
4
  const chalk = require('chalk');
5
+ const { NATIVE_PATHS } = require('../config/paths');
6
+
7
+ function resolveProjectsDir(config = {}) {
8
+ return config.projectsDir || NATIVE_PATHS.claude.projects;
9
+ }
5
10
 
6
11
  /**
7
12
  * 获取会话目录
8
13
  */
9
14
  function getSessionsDir(config) {
10
- return path.join(config.projectsDir, config.currentProject);
15
+ return path.join(resolveProjectsDir(config), config.currentProject);
11
16
  }
12
17
 
13
18
  /**
@@ -196,7 +201,7 @@ function parseLinesWithTail(headLines, tailLines) {
196
201
  * 获取所有可用的项目
197
202
  */
198
203
  async function getAvailableProjects(config) {
199
- const projectsDir = config.projectsDir;
204
+ const projectsDir = resolveProjectsDir(config);
200
205
  if (!fs.existsSync(projectsDir)) {
201
206
  console.log(chalk.red(`项目目录不存在: ${projectsDir}`));
202
207
  return [];
@@ -204,8 +209,9 @@ async function getAvailableProjects(config) {
204
209
 
205
210
  // 获取项目列表和统计信息(包含解析后的名称)
206
211
  const { getProjectsWithStats, getProjectOrder } = require('../server/services/sessions');
207
- const projects = await getProjectsWithStats(config);
208
- const savedOrder = getProjectOrder(config);
212
+ const resolvedConfig = { ...config, projectsDir };
213
+ const projects = await getProjectsWithStats(resolvedConfig);
214
+ const savedOrder = getProjectOrder(resolvedConfig);
209
215
  const projectList = Array.isArray(projects) ? projects : [];
210
216
 
211
217
  // 按保存的顺序排列
@@ -1 +0,0 @@
1
- import{r as e,f as a,c as t,o as l,a as s,X as n,s as o,Y as r,N as i,_ as c,G as u,Z as d,p,a0 as v,W as m,a8 as f,a5 as h,w as y,h as g,K as k,F as j,$ as _,a6 as x,R as w,v as b}from"./vue-vendor-B5RqjEjQ.js";import{d as C}from"./vendors-DQA4Hw9v.js";import{_ as z,k as $,l as P,m as L,o as M,p as N,q as T}from"./index-ClMNA9Hf.js";import{a9 as D,T as I,d as R,ad as U,h as E}from"./icons-nGdSKQn2.js";import{N as K,B as q,c as V,a as F,_ as H,q as O,m as S,g as A,x as B,h as G,p as W}from"./naive-ui-CVyvdmg1.js";import"./markdown-BNJfEgCA.js";const X={class:"card-content"},Y={class:"header-row"},Z={class:"project-name"},J={class:"stats-row"},Q=z({__name:"ProjectCard",props:{project:{type:Object,required:!0}},emits:["click","delete"],setup(f,{emit:h}){const y=f,g=h,k=e(!1);function j(){g("click")}function _(){g("delete",y.project)}const x=a(()=>{var e,a;return(null==(e=y.project)?void 0:e.displayName)||(null==(a=y.project)?void 0:a.name)||""}),w=a(()=>{var e,a,t;return(null==(e=y.project)?void 0:e.path)||(null==(a=y.project)?void 0:a.fullPath)||(null==(t=y.project)?void 0:t.name)||""}),b=a(()=>{var e;return(null==(e=y.project)?void 0:e.sessionCount)||0}),C=a(()=>{var e;return null==(e=y.project)?void 0:e.lastUsed}),z=a(()=>{var e;const a=["#18a058","#2080f0","#f0a020","#d03050","#9333ea","#06b6d4"];return a[((null==(e=y.project)?void 0:e.name)||"").split("").reduce((e,a)=>e+a.charCodeAt(0),0)%a.length]});function $(e){if(!e)return"";const a=new Date(e),t=new Date-a;return t<6e4?"刚刚":t<36e5?`${Math.floor(t/6e4)}分钟前`:t<864e5?`${Math.floor(t/36e5)}小时前`:t<6048e5?`${Math.floor(t/864e5)}天前`:a.toLocaleDateString("zh-CN")}return(e,a)=>(l(),t("div",{class:"project-card",onClick:j,onMouseenter:a[0]||(a[0]=e=>k.value=!0),onMouseleave:a[1]||(a[1]=e=>k.value=!1)},[s("div",X,[s("div",Y,[n(i(K),{size:"18",color:z.value},{default:r(()=>[n(i(D))]),_:1},8,["color"]),s("span",Z,c(x.value),1),o(n(i(q),{text:"",type:"error",size:"tiny",class:"delete-btn",onClick:d(_,["stop"])},{icon:r(()=>[n(i(K),{size:"14"},{default:r(()=>[n(i(I))]),_:1})]),_:1},512),[[u,k.value]])]),n(i(V),{depth:"3",class:"project-path"},{default:r(()=>[p(c(w.value),1)]),_:1}),s("div",J,[n(i(F),{size:"tiny",bordered:!1,type:"success"},{default:r(()=>[p(c(b.value)+" 会话 ",1)]),_:1}),C.value?(l(),v(i(V),{key:0,depth:"3",class:"last-used"},{default:r(()=>[p(c($(C.value)),1)]),_:1})):m("",!0)])])],32))}},[["__scopeId","data-v-3a18e66d"]]),ee={class:"project-list-container"},ae={class:"header"},te={class:"header-text"},le={key:0,class:"status-tags",role:"status","aria-live":"polite"},se={key:0,class:"loading-container"},ne={key:1,class:"loading-container compact"},oe={key:4,class:"projects-grid"},re={class:"search-hint"},ie={style:{"margin-bottom":"16px"}},ce={key:0,style:{"max-height":"60vh","overflow-y":"auto"}},ue={class:"search-result-header"},de={class:"search-result-title"},pe=z({__name:"ProjectList",setup(o){const u=f(),d=h(),z=$(),I=a(()=>d.meta.channel||"claude"),X=e(""),Y=e([]),Z=e(null),J=e(!1),pe=e(""),ve=e(null),me=e(!1),fe=e(null),he=a(()=>{const e=X.value.toLowerCase();return Y.value.filter(a=>{const t=(a.displayName||"").toLowerCase(),l=(a.fullPath||"").toLowerCase();return t.includes(e)||l.includes(e)})}),ye=a(()=>{const e=[];return z.projectsRefreshing&&e.push({key:"refreshing",type:"info",text:z.projects.length>0?"后台刷新中":"首次生成中"}),z.projectsUsingFallback&&z.projects.length>0&&e.push({key:"fallback",type:"warning",text:"正在显示缓存数据"}),z.error&&e.push({key:"error",type:"error",text:`刷新失败:${z.error}`}),e});function ge(e){const a=d.meta.channel||"claude";u.push({name:`${a}-sessions`,params:{projectName:e}})}async function ke(){const e=Y.value.map(e=>e.name);await z.saveProjectOrder(e)}function je(e){const a=e.fullPath||e.name,t=e.sessionCount||0;M.warning({title:"删除项目",content:`确定要删除项目 "${a}" 吗?\n\n当前项目包含 ${t} 个会话,删除后所有会话数据将无法恢复!`,positiveText:"确定删除",negativeText:"取消",onPositiveClick:async()=>{try{await z.deleteProject(e.name),L.success("项目已删除")}catch(a){L.error("删除失败: "+a.message)}}})}async function _e(){try{const a="codex"===(e=I.value||"claude")?"codex":"gemini"===e?"gemini":"opencode"===e?"opencode":"omp"===e?"omp":"claude",t=await P(a);if("manual"===(null==t?void 0:t.method))return void L.warning("自动复制失败,已弹出手动复制框");L.success("基础启动命令已复制到剪贴板")}catch(a){L.error("复制失败: "+a.message)}var e}async function xe(){var e;const a=(null==(e=Z.value)?void 0:e.scrollTop)||0;await z.retryProjects(),await b(),Z.value&&(Z.value.scrollTop=a)}async function we(){if(pe.value){me.value=!0;try{const e=await N(pe.value,35,I.value);ve.value=e}catch(e){L.error("搜索失败: "+e.message)}finally{me.value=!1}}}function be(e,a){if(!a||!e)return e;const t=new RegExp(`(${a})`,"gi");return e.replace(t,'<mark style="background-color: #ffd700; padding: 2px 4px; border-radius: 2px; font-weight: 600;">$1</mark>')}function Ce(e){(e.metaKey||e.ctrlKey)&&"k"===e.key&&(e.preventDefault(),J.value=!0,b(()=>{var e;null==(e=fe.value)||e.focus()}))}return y(()=>z.projects,e=>{Y.value=[...e]},{immediate:!0}),y(J,e=>{e||(pe.value="",ve.value=null)}),y(I,e=>{z.setChannel(e),z.fetchProjects()},{immediate:!0}),g(()=>{document.addEventListener("keydown",Ce)}),k(()=>{document.removeEventListener("keydown",Ce)}),(e,a)=>{var o;return l(),t("div",ee,[s("div",ae,[s("div",te,[n(i(H),{style:{margin:"0"}},{default:r(()=>[...a[4]||(a[4]=[p("我的项目",-1)])]),_:1}),n(i(V),{depth:"3"},{default:r(()=>[...a[5]||(a[5]=[p("选择一个项目查看会话,拖拽可调整顺序",-1)])]),_:1}),ye.value.length?(l(),t("div",le,[(l(!0),t(j,null,_(ye.value,e=>(l(),v(i(F),{key:e.key,size:"small",type:e.type,bordered:!1},{default:r(()=>[p(c(e.text),1)]),_:2},1032,["type"]))),128)),i(z).projectsRefreshing||(null==(o=i(z).projectsMeta)?void 0:o.error)||i(z).error?(l(),v(i(q),{key:0,text:"",size:"tiny",loading:i(z).loading,onClick:xe},{default:r(()=>[...a[6]||(a[6]=[p(" 立即刷新 ",-1)])]),_:1},8,["loading"])):m("",!0)])):m("",!0)]),n(i(S),null,{default:r(()=>[n(i(q),{type:"primary",size:"medium",onClick:_e},{icon:r(()=>[n(i(K),null,{default:r(()=>[n(i(R))]),_:1})]),default:r(()=>[a[7]||(a[7]=p(" 新建项目 ",-1))]),_:1}),n(i(O),{value:X.value,"onUpdate:value":a[0]||(a[0]=e=>X.value=e),placeholder:"搜索项目...",clearable:"",class:"search-input"},{prefix:r(()=>[n(i(K),null,{default:r(()=>[n(i(U))]),_:1})]),_:1},8,["value"])]),_:1})]),s("div",{class:"content",ref_key:"contentEl",ref:Z},[i(z).loading&&0===i(z).projects.length&&!i(z).projectsPending?(l(),t("div",se,[n(i(A),{size:"large"},{description:r(()=>[...a[8]||(a[8]=[p(" 加载项目列表... ",-1)])]),_:1})])):i(z).projectsPending?(l(),t("div",ne,[n(i(A),{size:"small"},{description:r(()=>[...a[9]||(a[9]=[p(" 正在生成项目列表... ",-1)])]),_:1})])):i(z).error&&0===i(z).projects.length?(l(),v(i(B),{key:2,type:"error",title:"加载失败",style:{"margin-top":"20px"}},{default:r(()=>[p(c(i(z).error),1)]),_:1})):!X.value&&Y.value.length>0?(l(),v(i(C),{key:3,modelValue:Y.value,"onUpdate:modelValue":a[1]||(a[1]=e=>Y.value=e),"item-key":"name",class:"projects-grid","ghost-class":"ghost","chosen-class":"chosen","drag-class":"drag",animation:"200",onEnd:ke},{item:r(({element:e})=>[n(Q,{project:e,onClick:a=>ge(e.name),onDelete:je},null,8,["project","onClick"])]),_:1},8,["modelValue"])):X.value&&he.value.length>0?(l(),t("div",oe,[(l(!0),t(j,null,_(he.value,e=>(l(),v(Q,{key:e.name,project:e,onClick:a=>ge(e.name),onDelete:je},null,8,["project","onClick"]))),128))])):m("",!0),i(z).loading||i(z).error||i(z).projectsPending||!(!X.value&&0===i(z).projects.length||X.value&&0===he.value.length)?m("",!0):(l(),v(i(G),{key:5,description:X.value?"没有匹配的项目":"没有找到项目",style:{"margin-top":"60px"}},{icon:r(()=>[n(i(K),null,{default:r(()=>[n(i(D))]),_:1})]),_:1},8,["description"]))],512),s("div",re,[n(i(V),{depth:"3",style:{"font-size":"12px"}},{default:r(()=>[...a[10]||(a[10]=[s("kbd",null,"Cmd",-1),p(" / ",-1),s("kbd",null,"Ctrl",-1),p(" + ",-1),s("kbd",null,"K",-1),p(" 全局搜索 ",-1)])]),_:1})]),n(i(W),{show:J.value,"onUpdate:show":a[3]||(a[3]=e=>J.value=e),preset:"card",title:"全局搜索",style:w([{width:"800px","max-width":"90vw"},{marginTop:"80px"}])},{default:r(()=>[s("div",ie,[n(i(O),{ref_key:"globalSearchInputRef",ref:fe,value:pe.value,"onUpdate:value":a[2]||(a[2]=e=>pe.value=e),placeholder:"搜索所有项目的对话内容...",clearable:"",onKeyup:x(we,["enter"]),disabled:me.value},{prefix:r(()=>[n(i(K),null,{default:r(()=>[n(i(U))]),_:1})]),suffix:r(()=>[n(i(q),{text:"",onClick:we,disabled:!pe.value||me.value,loading:me.value},{default:r(()=>[...a[11]||(a[11]=[p(" 搜索 ",-1)])]),_:1},8,["disabled","loading"])]),_:1},8,["value","disabled"])]),ve.value?(l(),t("div",ce,[n(i(B),{type:"info",style:{"margin-bottom":"16px"}},{default:r(()=>[p(' 关键词 "'+c(ve.value.keyword)+'" 共找到 '+c(ve.value.totalMatches)+" 处匹配 ",1)]),_:1}),(l(!0),t(j,null,_(ve.value.sessions,e=>(l(),t("div",{key:`${e.projectName}-${e.sessionId}`,class:"search-result-item"},[s("div",ue,[s("div",de,[n(i(V),{strong:"",style:{"font-size":"15px","font-weight":"700"}},{default:r(()=>[p(c(e.projectDisplayName),1)]),_:2},1024),n(i(V),{depth:"2",style:{margin:"0 8px"}},{default:r(()=>[...a[12]||(a[12]=[p("·",-1)])]),_:1}),n(i(V),{strong:""},{default:r(()=>[p(c(e.alias?`${e.alias} (${e.sessionId.substring(0,8)})`:e.sessionId.substring(0,8)),1)]),_:2},1024),n(i(F),{size:"small",bordered:!1},{default:r(()=>[p(c(e.matchCount)+" 个匹配",1)]),_:2},1024)]),n(i(q),{size:"small",type:"primary",onClick:a=>async function(e,a){try{const{copyResult:t}=await T(e,a,I.value);"manual"===(null==t?void 0:t.method)?L.warning("自动复制失败,已弹出手动复制框"):L.success("启动命令已复制到剪贴板"),J.value=!1}catch(t){L.error("复制失败: "+t.message)}}(e.projectName,e.sessionId)},{icon:r(()=>[n(i(K),null,{default:r(()=>[n(i(E))]),_:1})]),default:r(()=>[a[13]||(a[13]=p(" 使用对话 ",-1))]),_:1},8,["onClick"])]),(l(!0),t(j,null,_(e.matches,(e,a)=>(l(),t("div",{key:a,class:"search-match"},[n(i(F),{size:"tiny",type:"user"===e.role?"info":"success",bordered:!1},{default:r(()=>[p(c("user"===e.role?"用户":"助手"),1)]),_:2},1032,["type"]),n(i(V),{depth:"3",class:"search-match-text",innerHTML:be(e.context,ve.value.keyword)},null,8,["innerHTML"])]))),128))]))),128)),0===ve.value.sessions.length?(l(),v(i(G),{key:0,description:"没有找到匹配的内容"})):m("",!0)])):m("",!0)]),_:1},8,["show"])])}}},[["__scopeId","data-v-31b9e395"]]);export{pe as default};
@@ -1 +0,0 @@
1
- .project-card[data-v-3a18e66d]{padding:12px 14px;cursor:pointer;transition:all .25s cubic-bezier(.4,0,.2,1);border-radius:8px;border:1px solid var(--border-primary);box-shadow:0 1px 3px #0000000a;background:var(--bg-primary);position:relative;overflow:hidden}.project-card[data-v-3a18e66d]:before{content:"";position:absolute;top:0;left:0;width:3px;height:100%;background:linear-gradient(180deg,#18a058,#18a05866);opacity:0;transition:opacity .25s ease}.project-card[data-v-3a18e66d]:hover{transform:translateY(-3px);box-shadow:0 8px 20px #18a0581f,0 2px 6px #0000000f;border-color:#18a05866}.project-card[data-v-3a18e66d]:hover:before{opacity:1}.card-content[data-v-3a18e66d]{display:flex;flex-direction:column;gap:6px}.header-row[data-v-3a18e66d]{display:flex;align-items:center;gap:8px}.project-name[data-v-3a18e66d]{font-size:14px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;color:var(--text-primary);letter-spacing:-.2px}.delete-btn[data-v-3a18e66d]{opacity:.7;transition:opacity .2s;padding:2px!important}.delete-btn[data-v-3a18e66d]:hover{opacity:1}.project-path[data-v-3a18e66d]{font-size:11px;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.3}.stats-row[data-v-3a18e66d]{display:flex;align-items:center;justify-content:space-between;margin-top:4px;padding-top:8px;border-top:1px dashed var(--border-primary)}.stats-row[data-v-3a18e66d] .n-tag{font-size:11px;font-weight:600;padding:0 6px;height:18px;border-radius:4px}.last-used[data-v-3a18e66d]{font-size:11px;font-weight:500}.project-list-container[data-v-31b9e395]{width:100%;height:100%;display:flex;flex-direction:column;box-sizing:border-box}.header[data-v-31b9e395]{flex-shrink:0;padding:24px 24px 20px;background:var(--gradient-bg);border-bottom:1px solid var(--border-primary);display:flex;justify-content:space-between;align-items:flex-start;gap:24px;position:relative}.header[data-v-31b9e395]:after{content:"";position:absolute;bottom:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,rgba(24,160,88,.1),transparent)}.header-text[data-v-31b9e395]{flex:1}.status-tags[data-v-31b9e395]{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:8px}.header-text[data-v-31b9e395] .n-h2{font-size:26px;font-weight:700;background:linear-gradient(135deg,#1f2937,#374151);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;letter-spacing:-.5px}[data-theme=dark] .header-text[data-v-31b9e395] .n-h2{background:linear-gradient(135deg,#f9fafb,#d1d5db);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.search-input[data-v-31b9e395]{width:320px;flex-shrink:0}.search-input[data-v-31b9e395] .n-input{border-radius:10px;background:var(--bg-primary);border:1px solid var(--border-primary);transition:all .2s ease}.search-input[data-v-31b9e395] .n-input:hover{border-color:var(--border-secondary);box-shadow:var(--shadow-sm)}.search-input[data-v-31b9e395] .n-input:focus-within{border-color:#18a058;box-shadow:0 0 0 3px #18a0581a}.content[data-v-31b9e395]{flex:1;overflow-y:auto;padding:20px 24px 24px;background:var(--gradient-bg)}.loading-container[data-v-31b9e395]{display:flex;justify-content:center;align-items:center;min-height:400px}.loading-container.compact[data-v-31b9e395]{min-height:180px}.projects-grid[data-v-31b9e395]{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.ghost[data-v-31b9e395]{opacity:.4}.chosen[data-v-31b9e395]{transform:scale(1.05);box-shadow:0 8px 24px #0003!important;cursor:move!important}.drag[data-v-31b9e395]{opacity:.8;transform:rotate(2deg);box-shadow:0 12px 32px #00000040!important}.search-hint[data-v-31b9e395]{position:fixed;bottom:24px;left:24px;padding:10px 14px;background:#ffffffe6;border:1px solid var(--border-primary);border-radius:8px;box-shadow:0 4px 12px #00000014;z-index:10;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);opacity:.8;transition:all .2s ease}[data-theme=dark] .search-hint[data-v-31b9e395]{background:#1e293bf2;border:1px solid rgba(71,85,105,.6);box-shadow:0 4px 16px #0006}.search-hint[data-v-31b9e395]:hover{opacity:1;transform:translateY(-2px);box-shadow:0 6px 16px #0000001f}[data-theme=dark] .search-hint[data-v-31b9e395]:hover{box-shadow:0 6px 20px #00000080}.search-hint kbd[data-v-31b9e395]{display:inline-block;padding:4px 8px;font-family:SF Mono,Monaco,monospace;font-size:12px;line-height:1.4;font-weight:600;color:var(--text-secondary);background:var(--bg-primary);border:1px solid var(--border-secondary);border-radius:4px;box-shadow:0 2px 0 var(--border-primary),0 1px 3px #0000001a}[data-theme=dark] .search-hint kbd[data-v-31b9e395]{background:#33415599;border:1px solid rgba(71,85,105,.8);box-shadow:0 2px #1e293bcc,0 1px 4px #0006;color:#e2e8f0}.search-result-item[data-v-31b9e395]{margin-bottom:16px;padding:12px;border:1px solid var(--border-primary);border-radius:6px;background:var(--bg-elevated)}.search-result-header[data-v-31b9e395]{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.search-result-title[data-v-31b9e395]{display:flex;align-items:center;gap:8px}.search-match[data-v-31b9e395]{display:flex;align-items:flex-start;gap:8px;margin-top:6px;padding:6px;background:var(--bg-secondary);border-radius:4px}.search-match-text[data-v-31b9e395]{flex:1;line-height:1.6}
@@ -1 +0,0 @@
1
- import{a8 as e,a5 as s,f as a,r as l,w as n,h as t,K as i,c as o,o as u,a as r,X as d,a0 as c,W as v,Y as f,N as p,p as m,_ as h,F as y,$ as g,a6 as k,L as _,Z as w,s as b,G as I,y as C,v as z}from"./vue-vendor-B5RqjEjQ.js";import{d as j}from"./vendors-DQA4Hw9v.js";import{_ as x,k as F,r as N,C as S,t as $,m as M,o as B,v as U,q as L}from"./index-ClMNA9Hf.js";import{Z as P,T,ad as A,ay as R,k as q,G as E,a3 as K,az as G,q as H,h as O,Y as V}from"./icons-nGdSKQn2.js";import{N as D,B as W,_ as Y,c as Z,a as X,G as J,q as Q,g as ee,x as se,s as ae,m as le,h as ne,p as te,k as ie}from"./naive-ui-CVyvdmg1.js";import"./markdown-BNJfEgCA.js";const oe={class:"session-list-container"},ue={class:"header"},re={class:"title-bar"},de={class:"title-section"},ce={class:"title-with-count"},ve={class:"header-actions"},fe={key:0,class:"status-tags",role:"status","aria-live":"polite"},pe={key:0,class:"loading-container"},me={key:1,class:"loading-container compact"},he=["onMouseenter","onClick"],ye={key:0,class:"drag-handle"},ge={class:"session-left"},ke={class:"session-icon"},_e={class:"session-info"},we={class:"session-header"},be={class:"session-title-row"},Ie={class:"session-title"},Ce={class:"session-meta"},ze={class:"session-right"},je={class:"session-tags-area"},xe={key:0,class:"session-actions"},Fe={key:0,style:{"max-height":"70vh","overflow-y":"auto"}},Ne={class:"search-result-header"},Se={class:"search-result-title"},$e="__full__",Me=x({__name:"SessionList",props:{projectName:{type:String,required:!0}},setup(x){const Me=x,Be=e(),Ue=s(),Le=F(),{addFavorite:Pe,removeFavorite:Te,isFavorite:Ae}=N(),Re=a(()=>Ue.meta.channel||"claude"),qe=l(Me.projectName),Ee=a(()=>qe.value||Me.projectName),Ke=l(""),Ge=l(!1),He=l(null),Oe=l(""),Ve=l(null),De=l([]),We=l(null),Ye=l(!1),Ze=l(null),Xe=l(!1),Je=l(!1),Qe=l([]),es=l(!1),ss=l(!1),as=l(null),ls=l(""),ns=l($e),ts=l(!1),is=l(!1),os=l([]),us=l(!1),rs=l(""),ds=l(""),cs=l(null),vs={group:{name:`${Re.value}-sessions`,pull:!1,put:!1},forceFallback:!0,fallbackOnBody:!1,fallbackTolerance:4,scroll:!0},fs=a(()=>{var e;return(null==(e=Le.currentProjectInfo)?void 0:e.displayName)||Me.projectName}),ps=a(()=>{var e;return(null==(e=Le.currentProjectInfo)?void 0:e.fullPath)||Ee.value}),ms=a(()=>new Set(Qe.value)),hs=a(()=>Qe.value.length),ys=a(()=>De.value.length>0&&De.value.every(e=>ms.value.has(e.sessionId))),gs=a(()=>hs.value>0&&!ys.value);async function ks(){Le.projects.length||await Le.fetchProjects();const e=Le.projects.find(e=>e.name===Me.projectName);if(e)return qe.value=e.name,e.name;const s=Le.projects.find(e=>e.displayName===Me.projectName||e.fullPath===Me.projectName);return s?(qe.value=s.name,s.name!==Me.projectName&&await Be.replace({name:`${Re.value}-sessions`,params:{projectName:s.name}}),s.name):(qe.value=Me.projectName,Me.projectName)}n(()=>Le.sessionsWithAlias,e=>{De.value=[...e];const s=new Set(e.map(e=>e.sessionId));Qe.value=Qe.value.filter(e=>s.has(e)),Je.value&&0===e.length&&js()},{immediate:!0});const _s=a(()=>{if(!Ke.value)return De.value;const e=Ke.value.toLowerCase();return De.value.filter(s=>s.sessionId.toLowerCase().includes(e)||s.alias&&s.alias.toLowerCase().includes(e)||s.firstMessage&&s.firstMessage.toLowerCase().includes(e)||s.gitBranch&&s.gitBranch.toLowerCase().includes(e))}),ws=a(()=>{const e=[];return Le.sessionsRefreshing&&e.push({key:"refreshing",type:"info",text:Le.sessions.length>0?"后台刷新中":"首次生成中"}),Le.sessionsUsingFallback&&Le.sessions.length>0&&e.push({key:"fallback",type:"warning",text:"正在显示缓存数据"}),Le.error&&e.push({key:"error",type:"error",text:`刷新失败:${Le.error}`}),e});function bs(){const e=Ue.meta.channel||"claude";Be.push({name:`${e}-projects`})}async function Is(){if(Ke.value){Xe.value=!0;try{const e=await $(Ee.value,Ke.value,35,Re.value);We.value=e,Ye.value=!0}catch(e){M.error("搜索失败: "+e.message)}finally{Xe.value=!1}}}async function Cs(){const e=De.value.map(e=>e.sessionId);await Le.saveSessionOrder(e)}function zs(){Je.value=!0,Ve.value=null}function js(){Je.value=!1,Qe.value=[],Ve.value=null}function xs(e){return ms.value.has(e)}function Fs(e,s=!xs(e)){const a=new Set(Qe.value);s?a.add(e):a.delete(e),Qe.value=Array.from(a)}function Ns(e){Qe.value=e?De.value.map(e=>e.sessionId):[]}function Ss(e){Je.value?Fs(e.sessionId):function(e){rs.value=e.sessionId,ds.value=e.alias||"",us.value=!0,z(()=>{var e;null==(e=cs.value)||e.open()})}(e)}async function $s(){if(He.value)try{const e=He.value.sessionId;Oe.value?(await Le.setAlias(e,Oe.value),M.success("别名设置成功")):(await Le.deleteAlias(e),M.success("别名已删除")),Ge.value=!1,He.value=null,Oe.value=""}catch(e){M.error("操作失败: "+e.message)}}function Ms(){ss.value=!1,as.value=null,ls.value="",ns.value=$e,os.value=[],ts.value=!1,is.value=!1}async function Bs(){var e;if(as.value)try{is.value=!0,await Le.forkSession(as.value.sessionId,{afterUserMessageNumber:ns.value===$e?null:ns.value,alias:(null==(e=ls.value)?void 0:e.trim())||void 0}),M.success("Fork 成功!"),Ms()}catch(s){M.error("Fork 失败: "+s.message)}finally{is.value=!1}}function Us(e){M.error(e)}function Ls(e){const s=new Set((e||[]).filter(Boolean));0!==s.size&&(Qe.value=Qe.value.filter(e=>!s.has(e)),rs.value&&s.has(rs.value)&&(us.value=!1,rs.value="",ds.value=""))}async function Ps(e){try{const{copyResult:s}=await L(Ee.value,e,Re.value);if("manual"===(null==s?void 0:s.method))return void M.warning("自动复制失败,已弹出手动复制框");M.success("启动命令已复制到剪贴板")}catch(s){M.error("复制失败: "+s.message)}}function Ts(){if(0===hs.value)return void M.warning("请先选择要删除的会话");const e=[...Qe.value];B.warning({title:"批量删除会话",content:`确定要删除选中的 ${e.length} 个会话吗?此操作不可恢复!`,positiveText:"确定删除",negativeText:"取消",onPositiveClick:async()=>{es.value=!0;try{const s=await Le.deleteSessions(e);if(Ls(s.deletedSessionIds),0===s.failed.length)return M.success(`已删除 ${s.deletedSessionIds.length} 个会话`),void js();Qe.value=s.failed.map(e=>e.sessionId),s.deletedSessionIds.length>0?M.warning(`已删除 ${s.deletedSessionIds.length} 个会话,${s.failed.length} 个删除失败`):M.error(`删除失败: ${s.failed[0].error.message}`)}finally{es.value=!1}}})}function As(e){if(!e)return"";return new Date(e).toLocaleString("zh-CN")}function Rs(e){if(!e)return"0 B";const s=1024;return e<s?e+" B":e<s*s?(e/s).toFixed(1)+" KB":(e/s/s).toFixed(1)+" MB"}function qs(e,s){if(!s||!e)return e;const a=new RegExp(`(${s})`,"gi");return e.replace(a,'<mark style="background-color: #ffd700; padding: 2px 4px; border-radius: 2px; font-weight: 600;">$1</mark>')}function Es(e,s=80){return e?e.length>s?e.substring(0,s)+"...":e:""}async function Ks(){var e;const s=(null==(e=Ze.value)?void 0:e.scrollTop)||0,a=await ks();await Le.retrySessions(a),await z(),Ze.value&&(Ze.value.scrollTop=s)}return n([Re,()=>Me.projectName],([e])=>{js(),Le.setChannel(e),async function(e={}){const s=await ks();await Le.fetchSessions(s,e)}()},{immediate:!0}),t(()=>{}),i(()=>{}),(e,s)=>{var a;return u(),o("div",oe,[r("div",ue,[r("div",re,[d(p(W),{size:"small",onClick:bs,class:"back-button"},{icon:f(()=>[d(p(D),{size:"18"},{default:f(()=>[d(p(P))]),_:1})]),_:1}),r("div",de,[r("div",ce,[d(p(Y),null,{default:f(()=>[m(h(fs.value),1)]),_:1}),d(p(Z),{depth:"3",class:"session-count"},{default:f(()=>[m("("+h(p(Le).sessions.length)+" 个对话)",1)]),_:1}),d(p(X),{size:"small",bordered:!1,type:"info",class:"total-size-tag"},{default:f(()=>[m(h(Rs(p(Le).totalSize)),1)]),_:1}),r("div",ve,[Je.value?(u(),o(y,{key:0},[d(p(J),{checked:ys.value,indeterminate:gs.value,disabled:0===De.value.length||es.value,"onUpdate:checked":Ns},{default:f(()=>[...s[12]||(s[12]=[m(" 全选 ",-1)])]),_:1},8,["checked","indeterminate","disabled"]),d(p(Z),{depth:"3"},{default:f(()=>[m("已选 "+h(hs.value)+" 个",1)]),_:1}),d(p(W),{size:"small",type:"error",disabled:0===hs.value,loading:es.value,onClick:Ts},{icon:f(()=>[d(p(D),null,{default:f(()=>[d(p(T))]),_:1})]),default:f(()=>[s[13]||(s[13]=m(" 删除 ",-1))]),_:1},8,["disabled","loading"]),d(p(W),{size:"small",disabled:es.value,onClick:js},{default:f(()=>[...s[14]||(s[14]=[m(" 完成 ",-1)])]),_:1},8,["disabled"])],64)):(u(),c(p(W),{key:1,size:"small",type:"error",secondary:"",onClick:zs},{icon:f(()=>[d(p(D),null,{default:f(()=>[d(p(T))]),_:1})]),default:f(()=>[s[15]||(s[15]=m(" 管理 ",-1))]),_:1}))])]),d(p(Z),{depth:"3",class:"project-path"},{default:f(()=>[m(h(ps.value),1)]),_:1}),ws.value.length?(u(),o("div",fe,[(u(!0),o(y,null,g(ws.value,e=>(u(),c(p(X),{key:e.key,size:"small",type:e.type,bordered:!1},{default:f(()=>[m(h(e.text),1)]),_:2},1032,["type"]))),128)),p(Le).sessionsRefreshing||(null==(a=p(Le).sessionsMeta)?void 0:a.error)||p(Le).error?(u(),c(p(W),{key:0,text:"",size:"tiny",loading:p(Le).loading,onClick:Ks},{default:f(()=>[...s[16]||(s[16]=[m(" 立即刷新 ",-1)])]),_:1},8,["loading"])):v("",!0)])):v("",!0)]),d(p(Q),{value:Ke.value,"onUpdate:value":s[0]||(s[0]=e=>Ke.value=e),placeholder:"搜索会话...",clearable:"",class:"search-input",onKeyup:k(Is,["enter"]),disabled:Xe.value},{prefix:f(()=>[d(p(D),null,{default:f(()=>[d(p(A))]),_:1})]),suffix:f(()=>[d(p(W),{text:"",onClick:Is,disabled:!Ke.value||Xe.value,loading:Xe.value},{default:f(()=>[...s[17]||(s[17]=[m(" 搜索 ",-1)])]),_:1},8,["disabled","loading"])]),_:1},8,["value","disabled"])])]),r("div",{class:"content",ref_key:"contentEl",ref:Ze},[p(Le).loading&&0===p(Le).sessions.length&&!p(Le).sessionsPending?(u(),o("div",pe,[d(p(ee),{size:"large"},{description:f(()=>[...s[18]||(s[18]=[m(" 加载会话列表... ",-1)])]),_:1})])):p(Le).sessionsPending?(u(),o("div",me,[d(p(ee),{size:"small"},{description:f(()=>[...s[19]||(s[19]=[m(" 正在生成会话列表... ",-1)])]),_:1})])):p(Le).error&&0===p(Le).sessions.length?(u(),c(p(se),{key:2,type:"error",title:"加载失败",style:{"margin-bottom":"16px"}},{default:f(()=>[m(h(p(Le).error),1)]),_:1})):_s.value.length>0?(u(),c(p(j),C({key:3,modelValue:De.value,"onUpdate:modelValue":s[3]||(s[3]=e=>De.value=e),"item-key":"sessionId",class:"sessions-list",handle:".drag-handle",disabled:Je.value||es.value},vs,{"ghost-class":"ghost","chosen-class":"chosen",animation:"200",onEnd:Cs}),{item:f(({element:e})=>[r("div",{class:_(["session-item",{"session-item-selected":xs(e.sessionId),"session-item-selection-mode":Je.value}]),onMouseenter:s=>Ve.value=e.sessionId,onMouseleave:s[2]||(s[2]=e=>Ve.value=null),onClick:s=>Ss(e)},[Je.value?(u(),o("div",{key:1,class:"selection-checkbox",onClick:s[1]||(s[1]=w(()=>{},["stop"]))},[d(p(J),{checked:xs(e.sessionId),"onUpdate:checked":s=>Fs(e.sessionId,s)},null,8,["checked","onUpdate:checked"])])):(u(),o("div",ye,[d(p(D),{size:"16",color:"#999"},{default:f(()=>[d(p(R))]),_:1})])),r("div",ge,[r("div",ke,[d(p(D),{size:"24",color:"#18a058"},{default:f(()=>[d(p(q))]),_:1})]),r("div",_e,[r("div",we,[r("div",be,[r("span",Ie,h(e.alias?`${e.alias} (${e.sessionId.substring(0,8)})`:e.sessionId),1),e.forkedFrom?(u(),c(p(ae),{key:0,placement:"top"},{trigger:f(()=>[d(p(X),{size:"small",type:"warning",bordered:!1,style:{"margin-left":"8px",cursor:"help"}},{icon:f(()=>[d(p(D),null,{default:f(()=>[d(p(E))]),_:1})]),default:f(()=>[s[20]||(s[20]=m(" Fork ",-1))]),_:1})]),default:f(()=>[m(" Fork 自: "+h(e.forkedFrom),1)]),_:2},1024)):v("",!0)])]),r("div",Ce,[d(p(Z),{depth:"3"},{default:f(()=>[m(h(As(e.mtime)),1)]),_:2},1024),d(p(Z),{depth:"3"},{default:f(()=>[...s[21]||(s[21]=[m("•",-1)])]),_:1}),d(p(X),{size:"small",bordered:!1},{default:f(()=>[m(h(Rs(e.size)),1)]),_:2},1024)]),e.firstMessage?(u(),c(p(Z),{key:0,depth:"3",class:"session-message"},{default:f(()=>[m(h(Es(e.firstMessage,80)),1)]),_:2},1024)):e.gitBranch||e.summary?v("",!0):(u(),c(p(Z),{key:1,depth:"3",class:"session-message session-message-empty"},{default:f(()=>[...s[22]||(s[22]=[m(" 暂未读取到对话内容 ",-1)])]),_:1}))])]),r("div",ze,[r("div",je,[e.gitBranch?(u(),c(p(X),{key:0,size:"small",type:"info",bordered:!1},{icon:f(()=>[d(p(D),null,{default:f(()=>[d(p(E))]),_:1})]),default:f(()=>[m(" "+h(e.gitBranch),1)]),_:2},1024)):v("",!0)]),Je.value?v("",!0):(u(),o("div",xe,[d(p(le),null,{default:f(()=>[b(d(p(W),{size:"small",type:"error",onClick:w(s=>{return a=e.sessionId,void B.warning({title:"删除会话",content:"确定要删除这个会话吗?此操作不可恢复!",positiveText:"确定删除",negativeText:"取消",onPositiveClick:async()=>{try{await Le.deleteSession(a),Ls([a]),M.success("会话已删除")}catch(e){M.error("删除失败: "+e.message)}}});var a},["stop"])},{icon:f(()=>[d(p(D),null,{default:f(()=>[d(p(T))]),_:1})]),default:f(()=>[s[23]||(s[23]=m(" 删除 ",-1))]),_:1},8,["onClick"]),[[I,Ve.value===e.sessionId]]),d(p(W),{size:"small",onClick:w(s=>function(e){He.value=e,Oe.value=e.alias||"",Ge.value=!0}(e),["stop"])},{icon:f(()=>[d(p(D),null,{default:f(()=>[d(p(K))]),_:1})]),default:f(()=>[s[24]||(s[24]=m(" 别名 ",-1))]),_:1},8,["onClick"]),d(p(W),{size:"small",type:p(Ae)(Re.value,Ee.value,e.sessionId)?"warning":"default",onClick:w(s=>async function(e){const s=Re.value,a=Ae(s,Ee.value,e.sessionId);try{if(a)await Te(s,Ee.value,e.sessionId),M.success("已取消收藏");else{const a={sessionId:e.sessionId,projectName:Ee.value,projectDisplayName:fs.value,projectFullPath:ps.value,alias:e.alias||"",firstMessage:e.firstMessage||"",mtime:e.mtime,size:e.size,gitBranch:e.gitBranch||"",forkedFrom:e.forkedFrom||""};await Pe(s,a),M.success("已添加到收藏")}}catch(l){M.error("操作失败: "+l.message)}}(e),["stop"])},{icon:f(()=>[d(p(D),null,{default:f(()=>[p(Ae)(Re.value,Ee.value,e.sessionId)?(u(),c(p(G),{key:0})):(u(),c(p(H),{key:1}))]),_:2},1024)]),default:f(()=>[m(" "+h(p(Ae)(Re.value,Ee.value,e.sessionId)?"已收藏":"收藏"),1)]),_:2},1032,["type","onClick"]),"opencode"!==Re.value?(u(),c(p(W),{key:0,size:"small",onClick:w(s=>async function(e){if("opencode"!==Re.value)try{const s=De.value.find(s=>s.sessionId===e);as.value=s||{sessionId:e},ls.value="",ns.value=$e,os.value=[{label:"完整会话末尾(保留全部消息)",value:$e}],ss.value=!0,ts.value=!0;const a=await U(Ee.value,e,Re.value),l=Array.isArray(null==a?void 0:a.items)?a.items:[];os.value=[{label:"完整会话末尾(保留全部消息)",value:$e},...l.map(e=>({label:`保留到第 ${e.userMessageNumber} 条用户消息这一轮 · ${e.preview}`,value:e.userMessageNumber}))]}catch(s){M.error("加载 Fork 位置失败: "+s.message),Ms()}finally{ts.value=!1}else M.warning("OpenCode 当前不支持该 Fork 操作")}(e.sessionId),["stop"])},{icon:f(()=>[d(p(D),null,{default:f(()=>[d(p(E))]),_:1})]),default:f(()=>[s[25]||(s[25]=m(" Fork ",-1))]),_:1},8,["onClick"])):v("",!0),d(p(W),{size:"small",type:"primary",onClick:w(s=>Ps(e.sessionId),["stop"])},{icon:f(()=>[d(p(D),null,{default:f(()=>[d(p(O))]),_:1})]),default:f(()=>[s[26]||(s[26]=m(" 使用对话 ",-1))]),_:1},8,["onClick"])]),_:2},1024)]))])],42,he)]),_:1},16,["modelValue","disabled"])):(u(),c(p(ne),{key:4,description:"没有找到会话",style:{"margin-top":"60px"}},{icon:f(()=>[d(p(D),null,{default:f(()=>[d(p(V))]),_:1})]),_:1}))],512),d(p(te),{show:Ge.value,"onUpdate:show":s[6]||(s[6]=e=>Ge.value=e),preset:"dialog",title:"设置别名"},{action:f(()=>[d(p(le),null,{default:f(()=>[d(p(W),{onClick:s[5]||(s[5]=e=>Ge.value=!1)},{default:f(()=>[...s[27]||(s[27]=[m("取消",-1)])]),_:1}),d(p(W),{type:"primary",onClick:$s},{default:f(()=>[...s[28]||(s[28]=[m("确定",-1)])]),_:1})]),_:1})]),default:f(()=>[d(p(Q),{value:Oe.value,"onUpdate:value":s[4]||(s[4]=e=>Oe.value=e),placeholder:"输入别名(留空删除)",onKeyup:k($s,["enter"])},null,8,["value"])]),_:1},8,["show"]),d(p(te),{show:ss.value,"onUpdate:show":s[9]||(s[9]=e=>ss.value=e),preset:"dialog",title:"Fork 对话"},{action:f(()=>[d(p(le),null,{default:f(()=>[d(p(W),{disabled:is.value,onClick:Ms},{default:f(()=>[...s[30]||(s[30]=[m("取消",-1)])]),_:1},8,["disabled"]),d(p(W),{type:"primary",loading:is.value,onClick:Bs},{default:f(()=>[...s[31]||(s[31]=[m(" 确认 Fork ",-1)])]),_:1},8,["loading"])]),_:1})]),default:f(()=>[d(p(le),{vertical:"",size:14},{default:f(()=>[d(p(Z),{depth:"3"},{default:f(()=>[...s[29]||(s[29]=[m(" 可选择保留到第几条用户消息所在轮次;会包含这条消息后 AI 的完整输出。 ",-1)])]),_:1}),d(p(ie),{value:ns.value,"onUpdate:value":s[7]||(s[7]=e=>ns.value=e),options:os.value,loading:ts.value,clearable:"",placeholder:"选择保留到哪一轮(默认完整会话)"},null,8,["value","options","loading"]),d(p(Q),{value:ls.value,"onUpdate:value":s[8]||(s[8]=e=>ls.value=e),placeholder:"输入新会话别名(可选)",maxlength:"120"},null,8,["value"])]),_:1})]),_:1},8,["show"]),d(p(te),{show:Ye.value,"onUpdate:show":s[10]||(s[10]=e=>Ye.value=e),preset:"card",title:"搜索结果",style:{width:"1200px"}},{default:f(()=>[We.value?(u(),o("div",Fe,[d(p(se),{type:"info",style:{"margin-bottom":"16px"}},{default:f(()=>[m(' 关键词 "'+h(We.value.keyword)+'" 共找到 '+h(We.value.totalMatches)+" 处匹配 ",1)]),_:1}),(u(!0),o(y,null,g(We.value.sessions,e=>(u(),o("div",{key:e.sessionId,class:"search-result-item"},[r("div",Ne,[r("div",Se,[d(p(Z),{strong:""},{default:f(()=>[m(h(e.alias?`${e.alias} (${e.sessionId.substring(0,8)})`:e.sessionId.substring(0,8)),1)]),_:2},1024),d(p(X),{size:"small",bordered:!1},{default:f(()=>[m(h(e.matchCount)+" 个匹配",1)]),_:2},1024)]),d(p(W),{size:"small",type:"primary",onClick:s=>Ps(e.sessionId)},{icon:f(()=>[d(p(D),null,{default:f(()=>[d(p(O))]),_:1})]),default:f(()=>[s[32]||(s[32]=m(" 使用对话 ",-1))]),_:1},8,["onClick"])]),(u(!0),o(y,null,g(e.matches,(e,s)=>(u(),o("div",{key:s,class:"search-match"},[d(p(X),{size:"tiny",type:"user"===e.role?"info":"success",bordered:!1},{default:f(()=>[m(h("user"===e.role?"用户":"助手"),1)]),_:2},1032,["type"]),d(p(Z),{depth:"3",class:"search-match-text",innerHTML:qs(e.context,We.value.keyword)},null,8,["innerHTML"])]))),128))]))),128)),0===We.value.sessions.length?(u(),c(p(ne),{key:0,description:"没有找到匹配的内容"})):v("",!0)])):v("",!0)]),_:1},8,["show"]),rs.value?(u(),c(S,{key:0,ref_key:"chatHistoryRef",ref:cs,show:us.value,"onUpdate:show":s[11]||(s[11]=e=>us.value=e),"project-name":Ee.value,"session-id":rs.value,"session-alias":ds.value,channel:Re.value,onError:Us},null,8,["show","project-name","session-id","session-alias","channel"])):v("",!0)])}}},[["__scopeId","data-v-1660d94f"]]);export{Me as default};
@@ -1 +0,0 @@
1
- .session-list-container[data-v-1660d94f]{width:100%;height:100%;display:flex;flex-direction:column;box-sizing:border-box}.header[data-v-1660d94f]{flex-shrink:0;padding:24px 24px 16px;background:var(--bg-primary);border-bottom:1px solid var(--border-primary)}.content[data-v-1660d94f]{flex:1;overflow-y:auto;overflow-x:hidden;padding:16px 24px 24px}.sessions-list[data-v-1660d94f]{position:relative;overflow:hidden}.back-button[data-v-1660d94f]{flex-shrink:0;margin-right:12px}.title-bar[data-v-1660d94f]{display:flex;align-items:center;gap:16px}.title-section[data-v-1660d94f]{flex:1;min-width:0}.title-with-count[data-v-1660d94f]{display:flex;align-items:center;gap:8px;margin-bottom:2px;flex-wrap:wrap}.title-section h2[data-v-1660d94f]{margin:0;font-size:20px}.session-count[data-v-1660d94f]{font-size:14px;color:#666}.total-size-tag[data-v-1660d94f]{margin-left:8px}.project-path[data-v-1660d94f]{font-size:13px;display:block;color:#666;margin-bottom:2px}.status-tags[data-v-1660d94f]{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:6px}.header-actions[data-v-1660d94f]{display:flex;align-items:center;gap:12px;margin-left:4px}.search-input[data-v-1660d94f]{width:320px;flex-shrink:0}.loading-container[data-v-1660d94f]{display:flex;justify-content:center;align-items:center;min-height:400px}.loading-container.compact[data-v-1660d94f]{min-height:180px}.session-item[data-v-1660d94f]{display:flex;align-items:center;gap:12px;padding:16px;background:var(--bg-primary);border:1px solid var(--border-primary);border-radius:8px;margin-bottom:8px;transition:all .2s;cursor:pointer}.session-item[data-v-1660d94f]:hover{border-color:#18a058;box-shadow:0 2px 8px #18a0581a}.session-item-selection-mode[data-v-1660d94f]{cursor:default}.session-item-selected[data-v-1660d94f]{border-color:#18a058;box-shadow:0 0 0 2px #18a0581f;background:#18a0580a}.drag-handle[data-v-1660d94f]{cursor:move;width:24px;height:24px;padding:4px;opacity:.4;transition:all .2s;flex-shrink:0;display:flex;align-items:center;justify-content:center}.session-item:hover .drag-handle[data-v-1660d94f]{opacity:1;background-color:#18a0581a;border-radius:4px}.selection-checkbox[data-v-1660d94f]{width:24px;min-width:24px;display:flex;align-items:center;justify-content:center}.session-left[data-v-1660d94f]{flex:1;display:flex;align-items:center;gap:16px;min-width:0}.session-icon[data-v-1660d94f]{flex-shrink:0}.session-info[data-v-1660d94f]{flex:1;min-width:0}.session-header[data-v-1660d94f]{display:flex;align-items:center;margin-bottom:6px}.session-title-row[data-v-1660d94f]{display:flex;align-items:center;gap:8px}.session-title[data-v-1660d94f]{font-size:15px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-shrink:1;min-width:0}.session-meta[data-v-1660d94f]{display:flex;align-items:center;gap:8px;margin-bottom:6px;font-size:13px}.session-message[data-v-1660d94f]{display:block;max-width:600px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px}.session-message-empty[data-v-1660d94f]{font-style:italic;opacity:.5}.session-right[data-v-1660d94f]{display:flex;flex-direction:column;justify-content:flex-start;align-items:flex-end;min-width:280px;flex-shrink:0;gap:12px}.session-tags-area[data-v-1660d94f]{min-height:24px;display:flex;align-items:flex-start;justify-content:flex-end}.session-actions[data-v-1660d94f]{display:flex;align-items:center;margin-top:auto}.ghost[data-v-1660d94f]{opacity:.4}.chosen[data-v-1660d94f]{box-shadow:0 4px 16px #00000026}.search-result-item[data-v-1660d94f]{margin-bottom:16px;padding:12px;border:1px solid var(--border-primary);border-radius:6px;background:var(--bg-elevated)}.search-result-header[data-v-1660d94f]{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.search-result-title[data-v-1660d94f]{display:flex;align-items:center;gap:8px}.search-match[data-v-1660d94f]{display:flex;align-items:flex-start;gap:8px;margin-top:6px;padding:6px;background:var(--bg-secondary);border-radius:4px}.search-match-text[data-v-1660d94f]{flex:1;line-height:1.6}