coding-tool-x 3.7.5 → 3.7.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/web/assets/{Analytics-DnnufrQi.js → Analytics-B6FzPvdJ.js} +1 -1
- package/dist/web/assets/{ConfigTemplates-BTVhMSfe.js → ConfigTemplates-DXVnqR5c.js} +1 -1
- package/dist/web/assets/{Home-D03PEREx.js → Home-FHJB7hYI.js} +1 -1
- package/dist/web/assets/{PluginManager-BiMqEiyQ.js → PluginManager-D8RToURX.js} +1 -1
- package/dist/web/assets/ProjectList-Cdz4jnOg.js +1 -0
- package/dist/web/assets/ProjectList-VeMNXfgO.css +1 -0
- package/dist/web/assets/SessionList-C4chCPxK.css +1 -0
- package/dist/web/assets/SessionList-XYydFlQg.js +1 -0
- package/dist/web/assets/{SkillManager-DAy8k5CL.js → SkillManager-Bu9p7mMb.js} +1 -1
- package/dist/web/assets/{WorkspaceManager-Bs2D6R9j.js → WorkspaceManager-Bx0Gj3Mk.js} +1 -1
- package/dist/web/assets/index-DxkAvn4g.js +2 -0
- package/dist/web/assets/index-S8wrU2Nf.css +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/src/commands/daemon.js +3 -1
- package/src/commands/port-config.js +0 -2
- package/src/commands/switch.js +1 -5
- package/src/commands/ui.js +4 -3
- package/src/commands/workspace.js +35 -3
- package/src/config/loader.js +76 -5
- package/src/index.js +11 -0
- package/src/server/api/config.js +0 -3
- package/src/server/api/omp-channels.js +50 -7
- package/src/server/api/settings.js +0 -2
- package/src/server/api/workspaces.js +39 -1
- package/src/server/services/dashboard-snapshot-worker.js +2 -1
- package/src/server/services/https-cert.js +3 -2
- package/src/server/services/native-oauth-adapters.js +2 -1
- package/src/server/services/omp-auth-provider-worker.js +29 -0
- package/src/server/services/omp-auth-providers.js +138 -11
- package/src/server/services/omp-config.js +7 -4
- package/src/server/services/omp-sessions.js +18 -14
- package/src/server/services/plugins-service.js +2 -1
- package/src/server/services/project-snapshots.js +8 -1
- package/src/server/services/session-snapshots.js +10 -1
- package/src/server/services/sessions.js +35 -19
- package/src/server/services/snapshot-cache.js +47 -3
- package/src/server/services/web-build.js +2 -1
- package/src/server/services/workspace-service.js +204 -98
- package/src/utils/cli-flags.js +7 -0
- package/src/utils/session.js +10 -4
- package/dist/web/assets/ProjectList-C6BA3V49.js +0 -1
- package/dist/web/assets/ProjectList-DQ5ZCJO2.css +0 -1
- package/dist/web/assets/SessionList--9Bl6EhV.css +0 -1
- package/dist/web/assets/SessionList-DChG04jz.js +0 -1
- package/dist/web/assets/index-DnDBHGCC.js +0 -2
- package/dist/web/assets/index-U3TOywtB.css +0 -1
|
@@ -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
|
|
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
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
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(
|
|
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
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
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(
|
|
655
|
+
worktrees.push(createdWorktree);
|
|
550
656
|
} else if (isGit) {
|
|
551
657
|
// Git 仓库但不创建 worktree:symlink 指向源路径
|
|
552
658
|
worktrees = getGitWorktrees(sourcePath);
|
package/src/utils/session.js
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
208
|
-
const
|
|
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 s,a as l,X as n,s as o,Y as r,N as c,_ as i,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 _,F as k,$ as j,a6 as w,R as x,v as C}from"./vue-vendor-B5RqjEjQ.js";import{d as b}from"./vendors-DQA4Hw9v.js";import{_ as $,k as z,l as L,m as N,o as P,p as M,q as D}from"./index-DnDBHGCC.js";import{a9 as I,T,d as E,ad as K,h as U}from"./icons-nGdSKQn2.js";import{N as R,B as q,c as V,a as H,_ as O,q as S,m as A,g as B,x as F,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=$({__name:"ProjectCard",props:{project:{type:Object,required:!0}},emits:["click","delete"],setup(f,{emit:h}){const y=f,g=h,_=e(!1);function k(){g("click")}function j(){g("delete",y.project)}const w=a(()=>{var e,a;return(null==(e=y.project)?void 0:e.displayName)||(null==(a=y.project)?void 0:a.name)||""}),x=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)||""}),C=a(()=>{var e;return(null==(e=y.project)?void 0:e.sessionCount)||0}),b=a(()=>{var e;return null==(e=y.project)?void 0:e.lastUsed}),$=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 z(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)=>(s(),t("div",{class:"project-card",onClick:k,onMouseenter:a[0]||(a[0]=e=>_.value=!0),onMouseleave:a[1]||(a[1]=e=>_.value=!1)},[l("div",X,[l("div",Y,[n(c(R),{size:"18",color:$.value},{default:r(()=>[n(c(I))]),_:1},8,["color"]),l("span",Z,i(w.value),1),o(n(c(q),{text:"",type:"error",size:"tiny",class:"delete-btn",onClick:d(j,["stop"])},{icon:r(()=>[n(c(R),{size:"14"},{default:r(()=>[n(c(T))]),_:1})]),_:1},512),[[u,_.value]])]),n(c(V),{depth:"3",class:"project-path"},{default:r(()=>[p(i(x.value),1)]),_:1}),l("div",J,[n(c(H),{size:"tiny",bordered:!1,type:"success"},{default:r(()=>[p(i(C.value)+" 会话 ",1)]),_:1}),b.value?(s(),v(c(V),{key:0,depth:"3",class:"last-used"},{default:r(()=>[p(i(z(b.value)),1)]),_:1})):m("",!0)])])],32))}},[["__scopeId","data-v-3a18e66d"]]),ee={class:"project-list-container"},ae={class:"header"},te={class:"header-text"},se={key:0,class:"loading-container"},le={key:3,class:"projects-grid"},ne={class:"search-hint"},oe={style:{"margin-bottom":"16px"}},re={key:0,style:{"max-height":"60vh","overflow-y":"auto"}},ce={class:"search-result-header"},ie={class:"search-result-title"},ue=$({__name:"ProjectList",setup(o){const u=f(),d=h(),$=z(),T=a(()=>d.meta.channel||"claude"),X=e(""),Y=e([]),Z=e(null),J=e(!1),ue=e(""),de=e(null),pe=e(!1),ve=e(null),me=a(()=>{const e=X.value.toLowerCase();return Y.value.filter(a=>{const t=(a.displayName||"").toLowerCase(),s=(a.fullPath||"").toLowerCase();return t.includes(e)||s.includes(e)})});function fe(e){const a=d.meta.channel||"claude";u.push({name:`${a}-sessions`,params:{projectName:e}})}async function he(){const e=Y.value.map(e=>e.name);await $.saveProjectOrder(e)}function ye(e){const a=e.fullPath||e.name,t=e.sessionCount||0;P.warning({title:"删除项目",content:`确定要删除项目 "${a}" 吗?\n\n当前项目包含 ${t} 个会话,删除后所有会话数据将无法恢复!`,positiveText:"确定删除",negativeText:"取消",onPositiveClick:async()=>{try{await $.deleteProject(e.name),N.success("项目已删除")}catch(a){N.error("删除失败: "+a.message)}}})}async function ge(){try{const a="codex"===(e=T.value||"claude")?"codex":"gemini"===e?"gemini":"opencode"===e?"opencode":"omp"===e?"omp":"claude",t=await L(a);if("manual"===(null==t?void 0:t.method))return void N.warning("自动复制失败,已弹出手动复制框");N.success("基础启动命令已复制到剪贴板")}catch(a){N.error("复制失败: "+a.message)}var e}async function _e(){if(ue.value){pe.value=!0;try{const e=await M(ue.value,35,T.value);de.value=e}catch(e){N.error("搜索失败: "+e.message)}finally{pe.value=!1}}}function ke(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 je(e){(e.metaKey||e.ctrlKey)&&"k"===e.key&&(e.preventDefault(),J.value=!0,C(()=>{var e;null==(e=ve.value)||e.focus()}))}return y(()=>$.projects,e=>{Y.value=[...e]},{immediate:!0}),y(J,e=>{e||(ue.value="",de.value=null)}),y(T,e=>{$.setChannel(e),$.fetchProjects()},{immediate:!0}),g(()=>{document.addEventListener("keydown",je)}),_(()=>{document.removeEventListener("keydown",je)}),(e,a)=>(s(),t("div",ee,[l("div",ae,[l("div",te,[n(c(O),{style:{margin:"0"}},{default:r(()=>[...a[4]||(a[4]=[p("我的项目",-1)])]),_:1}),n(c(V),{depth:"3"},{default:r(()=>[...a[5]||(a[5]=[p("选择一个项目查看会话,拖拽可调整顺序",-1)])]),_:1})]),n(c(A),null,{default:r(()=>[n(c(q),{type:"primary",size:"medium",onClick:ge},{icon:r(()=>[n(c(R),null,{default:r(()=>[n(c(E))]),_:1})]),default:r(()=>[a[6]||(a[6]=p(" 新建项目 ",-1))]),_:1}),n(c(S),{value:X.value,"onUpdate:value":a[0]||(a[0]=e=>X.value=e),placeholder:"搜索项目...",clearable:"",class:"search-input"},{prefix:r(()=>[n(c(R),null,{default:r(()=>[n(c(K))]),_:1})]),_:1},8,["value"])]),_:1})]),l("div",{class:"content",ref_key:"contentEl",ref:Z},[c($).loading?(s(),t("div",se,[n(c(B),{size:"large"},{description:r(()=>[...a[7]||(a[7]=[p(" 加载项目列表... ",-1)])]),_:1})])):c($).error?(s(),v(c(F),{key:1,type:"error",title:"加载失败",style:{"margin-top":"20px"}},{default:r(()=>[p(i(c($).error),1)]),_:1})):X.value?(s(),t("div",le,[(s(!0),t(k,null,j(me.value,e=>(s(),v(Q,{key:e.name,project:e,onClick:a=>fe(e.name),onDelete:ye},null,8,["project","onClick"]))),128))])):(s(),v(c(b),{key:2,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:he},{item:r(({element:e})=>[n(Q,{project:e,onClick:a=>fe(e.name),onDelete:ye},null,8,["project","onClick"])]),_:1},8,["modelValue"])),c($).loading||c($).error||0!==c($).projects.length?m("",!0):(s(),v(c(G),{key:4,description:"没有找到项目",style:{"margin-top":"60px"}},{icon:r(()=>[n(c(R),null,{default:r(()=>[n(c(I))]),_:1})]),_:1}))],512),l("div",ne,[n(c(V),{depth:"3",style:{"font-size":"12px"}},{default:r(()=>[...a[8]||(a[8]=[l("kbd",null,"Cmd",-1),p(" / ",-1),l("kbd",null,"Ctrl",-1),p(" + ",-1),l("kbd",null,"K",-1),p(" 全局搜索 ",-1)])]),_:1})]),n(c(W),{show:J.value,"onUpdate:show":a[3]||(a[3]=e=>J.value=e),preset:"card",title:"全局搜索",style:x([{width:"800px","max-width":"90vw"},{marginTop:"80px"}])},{default:r(()=>[l("div",oe,[n(c(S),{ref_key:"globalSearchInputRef",ref:ve,value:ue.value,"onUpdate:value":a[2]||(a[2]=e=>ue.value=e),placeholder:"搜索所有项目的对话内容...",clearable:"",onKeyup:w(_e,["enter"]),disabled:pe.value},{prefix:r(()=>[n(c(R),null,{default:r(()=>[n(c(K))]),_:1})]),suffix:r(()=>[n(c(q),{text:"",onClick:_e,disabled:!ue.value||pe.value,loading:pe.value},{default:r(()=>[...a[9]||(a[9]=[p(" 搜索 ",-1)])]),_:1},8,["disabled","loading"])]),_:1},8,["value","disabled"])]),de.value?(s(),t("div",re,[n(c(F),{type:"info",style:{"margin-bottom":"16px"}},{default:r(()=>[p(' 关键词 "'+i(de.value.keyword)+'" 共找到 '+i(de.value.totalMatches)+" 处匹配 ",1)]),_:1}),(s(!0),t(k,null,j(de.value.sessions,e=>(s(),t("div",{key:`${e.projectName}-${e.sessionId}`,class:"search-result-item"},[l("div",ce,[l("div",ie,[n(c(V),{strong:"",style:{"font-size":"15px","font-weight":"700"}},{default:r(()=>[p(i(e.projectDisplayName),1)]),_:2},1024),n(c(V),{depth:"2",style:{margin:"0 8px"}},{default:r(()=>[...a[10]||(a[10]=[p("·",-1)])]),_:1}),n(c(V),{strong:""},{default:r(()=>[p(i(e.alias?`${e.alias} (${e.sessionId.substring(0,8)})`:e.sessionId.substring(0,8)),1)]),_:2},1024),n(c(H),{size:"small",bordered:!1},{default:r(()=>[p(i(e.matchCount)+" 个匹配",1)]),_:2},1024)]),n(c(q),{size:"small",type:"primary",onClick:a=>async function(e,a){try{const{copyResult:t}=await D(e,a,T.value);"manual"===(null==t?void 0:t.method)?N.warning("自动复制失败,已弹出手动复制框"):N.success("启动命令已复制到剪贴板"),J.value=!1}catch(t){N.error("复制失败: "+t.message)}}(e.projectName,e.sessionId)},{icon:r(()=>[n(c(R),null,{default:r(()=>[n(c(U))]),_:1})]),default:r(()=>[a[11]||(a[11]=p(" 使用对话 ",-1))]),_:1},8,["onClick"])]),(s(!0),t(k,null,j(e.matches,(e,a)=>(s(),t("div",{key:a,class:"search-match"},[n(c(H),{size:"tiny",type:"user"===e.role?"info":"success",bordered:!1},{default:r(()=>[p(i("user"===e.role?"用户":"助手"),1)]),_:2},1032,["type"]),n(c(V),{depth:"3",class:"search-match-text",innerHTML:ke(e.context,de.value.keyword)},null,8,["innerHTML"])]))),128))]))),128)),0===de.value.sessions.length?(s(),v(c(G),{key:0,description:"没有找到匹配的内容"})):m("",!0)])):m("",!0)]),_:1},8,["show"])]))}},[["__scopeId","data-v-f9fdf45c"]]);export{ue 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-f9fdf45c]{width:100%;height:100%;display:flex;flex-direction:column;box-sizing:border-box}.header[data-v-f9fdf45c]{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-f9fdf45c]: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-f9fdf45c]{flex:1}.header-text[data-v-f9fdf45c] .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-f9fdf45c] .n-h2{background:linear-gradient(135deg,#f9fafb,#d1d5db);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.search-input[data-v-f9fdf45c]{width:320px;flex-shrink:0}.search-input[data-v-f9fdf45c] .n-input{border-radius:10px;background:var(--bg-primary);border:1px solid var(--border-primary);transition:all .2s ease}.search-input[data-v-f9fdf45c] .n-input:hover{border-color:var(--border-secondary);box-shadow:var(--shadow-sm)}.search-input[data-v-f9fdf45c] .n-input:focus-within{border-color:#18a058;box-shadow:0 0 0 3px #18a0581a}.content[data-v-f9fdf45c]{flex:1;overflow-y:auto;padding:20px 24px 24px;background:var(--gradient-bg)}.loading-container[data-v-f9fdf45c]{display:flex;justify-content:center;align-items:center;min-height:400px}.projects-grid[data-v-f9fdf45c]{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.ghost[data-v-f9fdf45c]{opacity:.4}.chosen[data-v-f9fdf45c]{transform:scale(1.05);box-shadow:0 8px 24px #0003!important;cursor:move!important}.drag[data-v-f9fdf45c]{opacity:.8;transform:rotate(2deg);box-shadow:0 12px 32px #00000040!important}.search-hint[data-v-f9fdf45c]{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-f9fdf45c]{background:#1e293bf2;border:1px solid rgba(71,85,105,.6);box-shadow:0 4px 16px #0006}.search-hint[data-v-f9fdf45c]:hover{opacity:1;transform:translateY(-2px);box-shadow:0 6px 16px #0000001f}[data-theme=dark] .search-hint[data-v-f9fdf45c]:hover{box-shadow:0 6px 20px #00000080}.search-hint kbd[data-v-f9fdf45c]{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-f9fdf45c]{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-f9fdf45c]{margin-bottom:16px;padding:12px;border:1px solid var(--border-primary);border-radius:6px;background:var(--bg-elevated)}.search-result-header[data-v-f9fdf45c]{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.search-result-title[data-v-f9fdf45c]{display:flex;align-items:center;gap:8px}.search-match[data-v-f9fdf45c]{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-f9fdf45c]{flex:1;line-height:1.6}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.session-list-container[data-v-84cf7ac0]{width:100%;height:100%;display:flex;flex-direction:column;box-sizing:border-box}.header[data-v-84cf7ac0]{flex-shrink:0;padding:24px 24px 16px;background:var(--bg-primary);border-bottom:1px solid var(--border-primary)}.content[data-v-84cf7ac0]{flex:1;overflow-y:auto;overflow-x:hidden;padding:16px 24px 24px}.sessions-list[data-v-84cf7ac0]{position:relative;overflow:hidden}.back-button[data-v-84cf7ac0]{flex-shrink:0;margin-right:12px}.title-bar[data-v-84cf7ac0]{display:flex;align-items:center;gap:16px}.title-section[data-v-84cf7ac0]{flex:1;min-width:0}.title-with-count[data-v-84cf7ac0]{display:flex;align-items:center;gap:8px;margin-bottom:2px;flex-wrap:wrap}.title-section h2[data-v-84cf7ac0]{margin:0;font-size:20px}.session-count[data-v-84cf7ac0]{font-size:14px;color:#666}.total-size-tag[data-v-84cf7ac0]{margin-left:8px}.project-path[data-v-84cf7ac0]{font-size:13px;display:block;color:#666;margin-bottom:2px}.header-actions[data-v-84cf7ac0]{display:flex;align-items:center;gap:12px;margin-left:4px}.search-input[data-v-84cf7ac0]{width:320px;flex-shrink:0}.loading-container[data-v-84cf7ac0]{display:flex;justify-content:center;align-items:center;min-height:400px}.session-item[data-v-84cf7ac0]{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-84cf7ac0]:hover{border-color:#18a058;box-shadow:0 2px 8px #18a0581a}.session-item-selection-mode[data-v-84cf7ac0]{cursor:default}.session-item-selected[data-v-84cf7ac0]{border-color:#18a058;box-shadow:0 0 0 2px #18a0581f;background:#18a0580a}.drag-handle[data-v-84cf7ac0]{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-84cf7ac0]{opacity:1;background-color:#18a0581a;border-radius:4px}.selection-checkbox[data-v-84cf7ac0]{width:24px;min-width:24px;display:flex;align-items:center;justify-content:center}.session-left[data-v-84cf7ac0]{flex:1;display:flex;align-items:center;gap:16px;min-width:0}.session-icon[data-v-84cf7ac0]{flex-shrink:0}.session-info[data-v-84cf7ac0]{flex:1;min-width:0}.session-header[data-v-84cf7ac0]{display:flex;align-items:center;margin-bottom:6px}.session-title-row[data-v-84cf7ac0]{display:flex;align-items:center;gap:8px}.session-title[data-v-84cf7ac0]{font-size:15px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-shrink:1;min-width:0}.session-meta[data-v-84cf7ac0]{display:flex;align-items:center;gap:8px;margin-bottom:6px;font-size:13px}.session-message[data-v-84cf7ac0]{display:block;max-width:600px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px}.session-message-empty[data-v-84cf7ac0]{font-style:italic;opacity:.5}.session-right[data-v-84cf7ac0]{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-84cf7ac0]{min-height:24px;display:flex;align-items:flex-start;justify-content:flex-end}.session-actions[data-v-84cf7ac0]{display:flex;align-items:center;margin-top:auto}.ghost[data-v-84cf7ac0]{opacity:.4}.chosen[data-v-84cf7ac0]{box-shadow:0 4px 16px #00000026}.search-result-item[data-v-84cf7ac0]{margin-bottom:16px;padding:12px;border:1px solid var(--border-primary);border-radius:6px;background:var(--bg-elevated)}.search-result-header[data-v-84cf7ac0]{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.search-result-title[data-v-84cf7ac0]{display:flex;align-items:center;gap:8px}.search-match[data-v-84cf7ac0]{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-84cf7ac0]{flex:1;line-height:1.6}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a8 as e,a5 as a,f as s,r as l,w as t,h as n,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,a6 as g,L as k,Z as _,s as w,G as b,y as I,$ as C,v as j}from"./vue-vendor-B5RqjEjQ.js";import{d as z}from"./vendors-DQA4Hw9v.js";import{_ as x,k as N,r as F,C as S,t as $,m as M,o as B,v as U,q as L}from"./index-DnDBHGCC.js";import{Z as P,T,ad as A,ay as q,k as E,G as K,a3 as G,az as H,q as O,h as R,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 ae,s as se,m as le,h as te,p as ne,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:"loading-container"},pe=["onMouseenter","onClick"],me={key:0,class:"drag-handle"},he={class:"session-left"},ye={class:"session-icon"},ge={class:"session-info"},ke={class:"session-header"},_e={class:"session-title-row"},we={class:"session-title"},be={class:"session-meta"},Ie={class:"session-right"},Ce={class:"session-tags-area"},je={key:0,class:"session-actions"},ze={key:0,style:{"max-height":"70vh","overflow-y":"auto"}},xe={class:"search-result-header"},Ne={class:"search-result-title"},Fe="__full__",Se=x({__name:"SessionList",props:{projectName:{type:String,required:!0}},setup(x){const Se=x,$e=e(),Me=a(),Be=N(),{addFavorite:Ue,removeFavorite:Le,isFavorite:Pe}=F(),Te=s(()=>Me.meta.channel||"claude"),Ae=l(Se.projectName),qe=s(()=>Ae.value||Se.projectName),Ee=l(""),Ke=l(!1),Ge=l(null),He=l(""),Oe=l(null),Re=l([]),Ve=l(null),De=l(!1),We=l(null),Ye=l(!1),Ze=l(!1),Xe=l([]),Je=l(!1),Qe=l(!1),ea=l(null),aa=l(""),sa=l(Fe),la=l(!1),ta=l(!1),na=l([]),ia=l(!1),oa=l(""),ua=l(""),ra=l(null),da={group:{name:`${Te.value}-sessions`,pull:!1,put:!1},forceFallback:!0,fallbackOnBody:!1,fallbackTolerance:4,scroll:!0},ca=s(()=>{var e;return(null==(e=Be.currentProjectInfo)?void 0:e.displayName)||Se.projectName}),va=s(()=>{var e;return(null==(e=Be.currentProjectInfo)?void 0:e.fullPath)||qe.value}),fa=s(()=>new Set(Xe.value)),pa=s(()=>Xe.value.length),ma=s(()=>Re.value.length>0&&Re.value.every(e=>fa.value.has(e.sessionId))),ha=s(()=>pa.value>0&&!ma.value);async function ya(e={}){const a=await async function(){Be.projects.length||await Be.fetchProjects();const e=Be.projects.find(e=>e.name===Se.projectName);if(e)return Ae.value=e.name,e.name;const a=Be.projects.find(e=>e.displayName===Se.projectName||e.fullPath===Se.projectName);return a?(Ae.value=a.name,a.name!==Se.projectName&&await $e.replace({name:`${Te.value}-sessions`,params:{projectName:a.name}}),a.name):(Ae.value=Se.projectName,Se.projectName)}();await Be.fetchSessions(a,e)}t(()=>Be.sessionsWithAlias,e=>{Re.value=[...e];const a=new Set(e.map(e=>e.sessionId));Xe.value=Xe.value.filter(e=>a.has(e)),Ze.value&&0===e.length&&Ia()},{immediate:!0});const ga=s(()=>{if(!Ee.value)return Re.value;const e=Ee.value.toLowerCase();return Re.value.filter(a=>a.sessionId.toLowerCase().includes(e)||a.alias&&a.alias.toLowerCase().includes(e)||a.firstMessage&&a.firstMessage.toLowerCase().includes(e)||a.gitBranch&&a.gitBranch.toLowerCase().includes(e))});function ka(){const e=Me.meta.channel||"claude";$e.push({name:`${e}-projects`})}async function _a(){if(Ee.value){Ye.value=!0;try{const e=await $(qe.value,Ee.value,35,Te.value);Ve.value=e,De.value=!0}catch(e){M.error("搜索失败: "+e.message)}finally{Ye.value=!1}}}async function wa(){const e=Re.value.map(e=>e.sessionId);await Be.saveSessionOrder(e)}function ba(){Ze.value=!0,Oe.value=null}function Ia(){Ze.value=!1,Xe.value=[],Oe.value=null}function Ca(e){return fa.value.has(e)}function ja(e,a=!Ca(e)){const s=new Set(Xe.value);a?s.add(e):s.delete(e),Xe.value=Array.from(s)}function za(e){Xe.value=e?Re.value.map(e=>e.sessionId):[]}function xa(e){Ze.value?ja(e.sessionId):function(e){oa.value=e.sessionId,ua.value=e.alias||"",ia.value=!0,j(()=>{var e;null==(e=ra.value)||e.open()})}(e)}async function Na(){if(Ge.value)try{const e=Ge.value.sessionId;He.value?(await Be.setAlias(e,He.value),M.success("别名设置成功")):(await Be.deleteAlias(e),M.success("别名已删除")),Ke.value=!1,Ge.value=null,He.value=""}catch(e){M.error("操作失败: "+e.message)}}function Fa(){Qe.value=!1,ea.value=null,aa.value="",sa.value=Fe,na.value=[],la.value=!1,ta.value=!1}async function Sa(){var e;if(ea.value)try{ta.value=!0,await Be.forkSession(ea.value.sessionId,{afterUserMessageNumber:sa.value===Fe?null:sa.value,alias:(null==(e=aa.value)?void 0:e.trim())||void 0}),M.success("Fork 成功!"),Fa()}catch(a){M.error("Fork 失败: "+a.message)}finally{ta.value=!1}}function $a(e){M.error(e)}function Ma(e){const a=new Set((e||[]).filter(Boolean));0!==a.size&&(Xe.value=Xe.value.filter(e=>!a.has(e)),oa.value&&a.has(oa.value)&&(ia.value=!1,oa.value="",ua.value=""))}async function Ba(e){try{const{copyResult:a}=await L(qe.value,e,Te.value);if("manual"===(null==a?void 0:a.method))return void M.warning("自动复制失败,已弹出手动复制框");M.success("启动命令已复制到剪贴板")}catch(a){M.error("复制失败: "+a.message)}}function Ua(){if(0===pa.value)return void M.warning("请先选择要删除的会话");const e=[...Xe.value];B.warning({title:"批量删除会话",content:`确定要删除选中的 ${e.length} 个会话吗?此操作不可恢复!`,positiveText:"确定删除",negativeText:"取消",onPositiveClick:async()=>{Je.value=!0;try{const a=await Be.deleteSessions(e);if(Ma(a.deletedSessionIds),0===a.failed.length)return M.success(`已删除 ${a.deletedSessionIds.length} 个会话`),void Ia();Xe.value=a.failed.map(e=>e.sessionId),a.deletedSessionIds.length>0?M.warning(`已删除 ${a.deletedSessionIds.length} 个会话,${a.failed.length} 个删除失败`):M.error(`删除失败: ${a.failed[0].error.message}`)}finally{Je.value=!1}}})}function La(e){if(!e)return"";return new Date(e).toLocaleString("zh-CN")}function Pa(e){if(!e)return"0 B";const a=1024;return e<a?e+" B":e<a*a?(e/a).toFixed(1)+" KB":(e/a/a).toFixed(1)+" MB"}function Ta(e,a){if(!a||!e)return e;const s=new RegExp(`(${a})`,"gi");return e.replace(s,'<mark style="background-color: #ffd700; padding: 2px 4px; border-radius: 2px; font-weight: 600;">$1</mark>')}function Aa(e,a=80){return e?e.length>a?e.substring(0,a)+"...":e:""}return t([Te,()=>Se.projectName],([e])=>{Ia(),Be.setChannel(e),ya()},{immediate:!0}),n(()=>{}),i(()=>{}),(e,a)=>(u(),o("div",oe,[r("div",ue,[r("div",re,[d(p(W),{size:"small",onClick:ka,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(ca.value),1)]),_:1}),d(p(Z),{depth:"3",class:"session-count"},{default:f(()=>[m("("+h(p(Be).sessions.length)+" 个对话)",1)]),_:1}),d(p(X),{size:"small",bordered:!1,type:"info",class:"total-size-tag"},{default:f(()=>[m(h(Pa(p(Be).totalSize)),1)]),_:1}),r("div",ve,[Ze.value?(u(),o(y,{key:0},[d(p(J),{checked:ma.value,indeterminate:ha.value,disabled:0===Re.value.length||Je.value,"onUpdate:checked":za},{default:f(()=>[...a[12]||(a[12]=[m(" 全选 ",-1)])]),_:1},8,["checked","indeterminate","disabled"]),d(p(Z),{depth:"3"},{default:f(()=>[m("已选 "+h(pa.value)+" 个",1)]),_:1}),d(p(W),{size:"small",type:"error",disabled:0===pa.value,loading:Je.value,onClick:Ua},{icon:f(()=>[d(p(D),null,{default:f(()=>[d(p(T))]),_:1})]),default:f(()=>[a[13]||(a[13]=m(" 删除 ",-1))]),_:1},8,["disabled","loading"]),d(p(W),{size:"small",disabled:Je.value,onClick:Ia},{default:f(()=>[...a[14]||(a[14]=[m(" 完成 ",-1)])]),_:1},8,["disabled"])],64)):(u(),c(p(W),{key:1,size:"small",type:"error",secondary:"",onClick:ba},{icon:f(()=>[d(p(D),null,{default:f(()=>[d(p(T))]),_:1})]),default:f(()=>[a[15]||(a[15]=m(" 管理 ",-1))]),_:1}))])]),d(p(Z),{depth:"3",class:"project-path"},{default:f(()=>[m(h(va.value),1)]),_:1})]),d(p(Q),{value:Ee.value,"onUpdate:value":a[0]||(a[0]=e=>Ee.value=e),placeholder:"搜索会话...",clearable:"",class:"search-input",onKeyup:g(_a,["enter"]),disabled:Ye.value},{prefix:f(()=>[d(p(D),null,{default:f(()=>[d(p(A))]),_:1})]),suffix:f(()=>[d(p(W),{text:"",onClick:_a,disabled:!Ee.value||Ye.value,loading:Ye.value},{default:f(()=>[...a[16]||(a[16]=[m(" 搜索 ",-1)])]),_:1},8,["disabled","loading"])]),_:1},8,["value","disabled"])])]),r("div",{class:"content",ref_key:"contentEl",ref:We},[p(Be).loading?(u(),o("div",fe,[d(p(ee),{size:"large"},{description:f(()=>[...a[17]||(a[17]=[m(" 加载会话列表... ",-1)])]),_:1})])):p(Be).error?(u(),c(p(ae),{key:1,type:"error",title:"加载失败",style:{"margin-bottom":"16px"}},{default:f(()=>[m(h(p(Be).error),1)]),_:1})):ga.value.length>0?(u(),c(p(z),I({key:2,modelValue:Re.value,"onUpdate:modelValue":a[3]||(a[3]=e=>Re.value=e),"item-key":"sessionId",class:"sessions-list",handle:".drag-handle",disabled:Ze.value||Je.value},da,{"ghost-class":"ghost","chosen-class":"chosen",animation:"200",onEnd:wa}),{item:f(({element:e})=>[r("div",{class:k(["session-item",{"session-item-selected":Ca(e.sessionId),"session-item-selection-mode":Ze.value}]),onMouseenter:a=>Oe.value=e.sessionId,onMouseleave:a[2]||(a[2]=e=>Oe.value=null),onClick:a=>xa(e)},[Ze.value?(u(),o("div",{key:1,class:"selection-checkbox",onClick:a[1]||(a[1]=_(()=>{},["stop"]))},[d(p(J),{checked:Ca(e.sessionId),"onUpdate:checked":a=>ja(e.sessionId,a)},null,8,["checked","onUpdate:checked"])])):(u(),o("div",me,[d(p(D),{size:"16",color:"#999"},{default:f(()=>[d(p(q))]),_:1})])),r("div",he,[r("div",ye,[d(p(D),{size:"24",color:"#18a058"},{default:f(()=>[d(p(E))]),_:1})]),r("div",ge,[r("div",ke,[r("div",_e,[r("span",we,h(e.alias?`${e.alias} (${e.sessionId.substring(0,8)})`:e.sessionId),1),e.forkedFrom?(u(),c(p(se),{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(K))]),_:1})]),default:f(()=>[a[18]||(a[18]=m(" Fork ",-1))]),_:1})]),default:f(()=>[m(" Fork 自: "+h(e.forkedFrom),1)]),_:2},1024)):v("",!0)])]),r("div",be,[d(p(Z),{depth:"3"},{default:f(()=>[m(h(La(e.mtime)),1)]),_:2},1024),d(p(Z),{depth:"3"},{default:f(()=>[...a[19]||(a[19]=[m("•",-1)])]),_:1}),d(p(X),{size:"small",bordered:!1},{default:f(()=>[m(h(Pa(e.size)),1)]),_:2},1024)]),e.firstMessage?(u(),c(p(Z),{key:0,depth:"3",class:"session-message"},{default:f(()=>[m(h(Aa(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(()=>[...a[20]||(a[20]=[m(" 暂未读取到对话内容 ",-1)])]),_:1}))])]),r("div",Ie,[r("div",Ce,[e.gitBranch?(u(),c(p(X),{key:0,size:"small",type:"info",bordered:!1},{icon:f(()=>[d(p(D),null,{default:f(()=>[d(p(K))]),_:1})]),default:f(()=>[m(" "+h(e.gitBranch),1)]),_:2},1024)):v("",!0)]),Ze.value?v("",!0):(u(),o("div",je,[d(p(le),null,{default:f(()=>[w(d(p(W),{size:"small",type:"error",onClick:_(a=>{return s=e.sessionId,void B.warning({title:"删除会话",content:"确定要删除这个会话吗?此操作不可恢复!",positiveText:"确定删除",negativeText:"取消",onPositiveClick:async()=>{try{await Be.deleteSession(s),Ma([s]),M.success("会话已删除")}catch(e){M.error("删除失败: "+e.message)}}});var s},["stop"])},{icon:f(()=>[d(p(D),null,{default:f(()=>[d(p(T))]),_:1})]),default:f(()=>[a[21]||(a[21]=m(" 删除 ",-1))]),_:1},8,["onClick"]),[[b,Oe.value===e.sessionId]]),d(p(W),{size:"small",onClick:_(a=>function(e){Ge.value=e,He.value=e.alias||"",Ke.value=!0}(e),["stop"])},{icon:f(()=>[d(p(D),null,{default:f(()=>[d(p(G))]),_:1})]),default:f(()=>[a[22]||(a[22]=m(" 别名 ",-1))]),_:1},8,["onClick"]),d(p(W),{size:"small",type:p(Pe)(Te.value,qe.value,e.sessionId)?"warning":"default",onClick:_(a=>async function(e){const a=Te.value,s=Pe(a,qe.value,e.sessionId);try{if(s)await Le(a,qe.value,e.sessionId),M.success("已取消收藏");else{const s={sessionId:e.sessionId,projectName:qe.value,projectDisplayName:ca.value,projectFullPath:va.value,alias:e.alias||"",firstMessage:e.firstMessage||"",mtime:e.mtime,size:e.size,gitBranch:e.gitBranch||"",forkedFrom:e.forkedFrom||""};await Ue(a,s),M.success("已添加到收藏")}}catch(l){M.error("操作失败: "+l.message)}}(e),["stop"])},{icon:f(()=>[d(p(D),null,{default:f(()=>[p(Pe)(Te.value,qe.value,e.sessionId)?(u(),c(p(H),{key:0})):(u(),c(p(O),{key:1}))]),_:2},1024)]),default:f(()=>[m(" "+h(p(Pe)(Te.value,qe.value,e.sessionId)?"已收藏":"收藏"),1)]),_:2},1032,["type","onClick"]),"opencode"!==Te.value?(u(),c(p(W),{key:0,size:"small",onClick:_(a=>async function(e){if("opencode"!==Te.value)try{const a=Re.value.find(a=>a.sessionId===e);ea.value=a||{sessionId:e},aa.value="",sa.value=Fe,na.value=[{label:"完整会话末尾(保留全部消息)",value:Fe}],Qe.value=!0,la.value=!0;const s=await U(qe.value,e,Te.value),l=Array.isArray(null==s?void 0:s.items)?s.items:[];na.value=[{label:"完整会话末尾(保留全部消息)",value:Fe},...l.map(e=>({label:`保留到第 ${e.userMessageNumber} 条用户消息这一轮 · ${e.preview}`,value:e.userMessageNumber}))]}catch(a){M.error("加载 Fork 位置失败: "+a.message),Fa()}finally{la.value=!1}else M.warning("OpenCode 当前不支持该 Fork 操作")}(e.sessionId),["stop"])},{icon:f(()=>[d(p(D),null,{default:f(()=>[d(p(K))]),_:1})]),default:f(()=>[a[23]||(a[23]=m(" Fork ",-1))]),_:1},8,["onClick"])):v("",!0),d(p(W),{size:"small",type:"primary",onClick:_(a=>Ba(e.sessionId),["stop"])},{icon:f(()=>[d(p(D),null,{default:f(()=>[d(p(R))]),_:1})]),default:f(()=>[a[24]||(a[24]=m(" 使用对话 ",-1))]),_:1},8,["onClick"])]),_:2},1024)]))])],42,pe)]),_:1},16,["modelValue","disabled"])):(u(),c(p(te),{key:3,description:"没有找到会话",style:{"margin-top":"60px"}},{icon:f(()=>[d(p(D),null,{default:f(()=>[d(p(V))]),_:1})]),_:1}))],512),d(p(ne),{show:Ke.value,"onUpdate:show":a[6]||(a[6]=e=>Ke.value=e),preset:"dialog",title:"设置别名"},{action:f(()=>[d(p(le),null,{default:f(()=>[d(p(W),{onClick:a[5]||(a[5]=e=>Ke.value=!1)},{default:f(()=>[...a[25]||(a[25]=[m("取消",-1)])]),_:1}),d(p(W),{type:"primary",onClick:Na},{default:f(()=>[...a[26]||(a[26]=[m("确定",-1)])]),_:1})]),_:1})]),default:f(()=>[d(p(Q),{value:He.value,"onUpdate:value":a[4]||(a[4]=e=>He.value=e),placeholder:"输入别名(留空删除)",onKeyup:g(Na,["enter"])},null,8,["value"])]),_:1},8,["show"]),d(p(ne),{show:Qe.value,"onUpdate:show":a[9]||(a[9]=e=>Qe.value=e),preset:"dialog",title:"Fork 对话"},{action:f(()=>[d(p(le),null,{default:f(()=>[d(p(W),{disabled:ta.value,onClick:Fa},{default:f(()=>[...a[28]||(a[28]=[m("取消",-1)])]),_:1},8,["disabled"]),d(p(W),{type:"primary",loading:ta.value,onClick:Sa},{default:f(()=>[...a[29]||(a[29]=[m(" 确认 Fork ",-1)])]),_:1},8,["loading"])]),_:1})]),default:f(()=>[d(p(le),{vertical:"",size:14},{default:f(()=>[d(p(Z),{depth:"3"},{default:f(()=>[...a[27]||(a[27]=[m(" 可选择保留到第几条用户消息所在轮次;会包含这条消息后 AI 的完整输出。 ",-1)])]),_:1}),d(p(ie),{value:sa.value,"onUpdate:value":a[7]||(a[7]=e=>sa.value=e),options:na.value,loading:la.value,clearable:"",placeholder:"选择保留到哪一轮(默认完整会话)"},null,8,["value","options","loading"]),d(p(Q),{value:aa.value,"onUpdate:value":a[8]||(a[8]=e=>aa.value=e),placeholder:"输入新会话别名(可选)",maxlength:"120"},null,8,["value"])]),_:1})]),_:1},8,["show"]),d(p(ne),{show:De.value,"onUpdate:show":a[10]||(a[10]=e=>De.value=e),preset:"card",title:"搜索结果",style:{width:"1200px"}},{default:f(()=>[Ve.value?(u(),o("div",ze,[d(p(ae),{type:"info",style:{"margin-bottom":"16px"}},{default:f(()=>[m(' 关键词 "'+h(Ve.value.keyword)+'" 共找到 '+h(Ve.value.totalMatches)+" 处匹配 ",1)]),_:1}),(u(!0),o(y,null,C(Ve.value.sessions,e=>(u(),o("div",{key:e.sessionId,class:"search-result-item"},[r("div",xe,[r("div",Ne,[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:a=>Ba(e.sessionId)},{icon:f(()=>[d(p(D),null,{default:f(()=>[d(p(R))]),_:1})]),default:f(()=>[a[30]||(a[30]=m(" 使用对话 ",-1))]),_:1},8,["onClick"])]),(u(!0),o(y,null,C(e.matches,(e,a)=>(u(),o("div",{key:a,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:Ta(e.context,Ve.value.keyword)},null,8,["innerHTML"])]))),128))]))),128)),0===Ve.value.sessions.length?(u(),c(p(te),{key:0,description:"没有找到匹配的内容"})):v("",!0)])):v("",!0)]),_:1},8,["show"]),oa.value?(u(),c(S,{key:0,ref_key:"chatHistoryRef",ref:ra,show:ia.value,"onUpdate:show":a[11]||(a[11]=e=>ia.value=e),"project-name":qe.value,"session-id":oa.value,"session-alias":ua.value,channel:Te.value,onError:$a},null,8,["show","project-name","session-id","session-alias","channel"])):v("",!0)]))}},[["__scopeId","data-v-84cf7ac0"]]);export{Se as default};
|