coding-tool-x 3.4.12 → 3.5.1

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.
@@ -5,7 +5,7 @@
5
5
  <link rel="icon" href="/favicon.ico">
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
7
  <title>CC-TOOL - ClaudeCode增强工作助手</title>
8
- <script type="module" crossorigin src="/assets/index-EMrm1wk-.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-B1ujw2sM.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/assets/markdown-DyTJGI4N.js">
10
10
  <link rel="modulepreload" crossorigin href="/assets/vue-vendor-3bf-fPGP.js">
11
11
  <link rel="modulepreload" crossorigin href="/assets/vendors-CKPV1OAU.js">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coding-tool-x",
3
- "version": "3.4.12",
3
+ "version": "3.5.1",
4
4
  "description": "Vibe Coding 增强工作助手 - 智能会话管理、动态渠道切换、全局搜索、实时监控",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -356,6 +356,60 @@ module.exports = (config) => {
356
356
  }
357
357
  });
358
358
 
359
+ /**
360
+ * POST /api/codex/sessions/:projectName/batch-delete
361
+ * 批量删除会话
362
+ */
363
+ router.post('/:projectName/batch-delete', (req, res) => {
364
+ try {
365
+ if (!isCodexInstalled()) {
366
+ return res.status(404).json({ error: 'Codex CLI not installed' });
367
+ }
368
+
369
+ const { sessionIds } = req.body || {};
370
+ if (!Array.isArray(sessionIds) || sessionIds.length === 0) {
371
+ return res.status(400).json({ error: 'sessionIds must be a non-empty array' });
372
+ }
373
+
374
+ const uniqueSessionIds = Array.from(new Set(
375
+ sessionIds
376
+ .filter(sessionId => typeof sessionId === 'string')
377
+ .map(sessionId => sessionId.trim())
378
+ .filter(Boolean)
379
+ ));
380
+
381
+ if (uniqueSessionIds.length === 0) {
382
+ return res.status(400).json({ error: 'sessionIds must be a non-empty array' });
383
+ }
384
+
385
+ const deletedSessionIds = [];
386
+ const failed = [];
387
+
388
+ uniqueSessionIds.forEach((sessionId) => {
389
+ try {
390
+ deleteSession(sessionId);
391
+ deletedSessionIds.push(sessionId);
392
+ } catch (err) {
393
+ failed.push({
394
+ sessionId,
395
+ error: err.message
396
+ });
397
+ }
398
+ });
399
+
400
+ res.json({
401
+ success: failed.length === 0,
402
+ requestedCount: uniqueSessionIds.length,
403
+ deletedCount: deletedSessionIds.length,
404
+ deletedSessionIds,
405
+ failed
406
+ });
407
+ } catch (err) {
408
+ console.error('[Codex API] Failed to batch delete sessions:', err);
409
+ res.status(500).json({ error: err.message });
410
+ }
411
+ });
412
+
359
413
  /**
360
414
  * POST /api/codex/sessions/:projectName/:sessionId/fork
361
415
  * Fork 一个会话
@@ -256,6 +256,60 @@ module.exports = (config) => {
256
256
  }
257
257
  });
258
258
 
259
+ /**
260
+ * POST /api/gemini/sessions/:projectHash/batch-delete
261
+ * 批量删除会话
262
+ */
263
+ router.post('/:projectHash/batch-delete', (req, res) => {
264
+ try {
265
+ if (!isGeminiInstalled()) {
266
+ return res.status(404).json({ error: 'Gemini CLI not installed' });
267
+ }
268
+
269
+ const { sessionIds } = req.body || {};
270
+ if (!Array.isArray(sessionIds) || sessionIds.length === 0) {
271
+ return res.status(400).json({ error: 'sessionIds must be a non-empty array' });
272
+ }
273
+
274
+ const uniqueSessionIds = Array.from(new Set(
275
+ sessionIds
276
+ .filter(sessionId => typeof sessionId === 'string')
277
+ .map(sessionId => sessionId.trim())
278
+ .filter(Boolean)
279
+ ));
280
+
281
+ if (uniqueSessionIds.length === 0) {
282
+ return res.status(400).json({ error: 'sessionIds must be a non-empty array' });
283
+ }
284
+
285
+ const deletedSessionIds = [];
286
+ const failed = [];
287
+
288
+ uniqueSessionIds.forEach((sessionId) => {
289
+ try {
290
+ deleteSession(sessionId);
291
+ deletedSessionIds.push(sessionId);
292
+ } catch (err) {
293
+ failed.push({
294
+ sessionId,
295
+ error: err.message
296
+ });
297
+ }
298
+ });
299
+
300
+ res.json({
301
+ success: failed.length === 0,
302
+ requestedCount: uniqueSessionIds.length,
303
+ deletedCount: deletedSessionIds.length,
304
+ deletedSessionIds,
305
+ failed
306
+ });
307
+ } catch (err) {
308
+ console.error('[Gemini API] Failed to batch delete sessions:', err);
309
+ res.status(500).json({ error: err.message });
310
+ }
311
+ });
312
+
259
313
  /**
260
314
  * POST /api/gemini/sessions/:projectHash/:sessionId/fork
261
315
  * Fork 一个会话
@@ -228,6 +228,60 @@ module.exports = (config) => {
228
228
  }
229
229
  });
230
230
 
231
+ /**
232
+ * POST /api/opencode/sessions/:projectName/batch-delete
233
+ * 批量删除会话
234
+ */
235
+ router.post('/:projectName/batch-delete', (req, res) => {
236
+ try {
237
+ if (!isOpenCodeInstalled()) {
238
+ return res.status(404).json({ error: 'OpenCode CLI not installed' });
239
+ }
240
+
241
+ const { sessionIds } = req.body || {};
242
+ if (!Array.isArray(sessionIds) || sessionIds.length === 0) {
243
+ return res.status(400).json({ error: 'sessionIds must be a non-empty array' });
244
+ }
245
+
246
+ const uniqueSessionIds = Array.from(new Set(
247
+ sessionIds
248
+ .filter(sessionId => typeof sessionId === 'string')
249
+ .map(sessionId => sessionId.trim())
250
+ .filter(Boolean)
251
+ ));
252
+
253
+ if (uniqueSessionIds.length === 0) {
254
+ return res.status(400).json({ error: 'sessionIds must be a non-empty array' });
255
+ }
256
+
257
+ const deletedSessionIds = [];
258
+ const failed = [];
259
+
260
+ uniqueSessionIds.forEach((sessionId) => {
261
+ try {
262
+ deleteSession(sessionId);
263
+ deletedSessionIds.push(sessionId);
264
+ } catch (err) {
265
+ failed.push({
266
+ sessionId,
267
+ error: err.message
268
+ });
269
+ }
270
+ });
271
+
272
+ res.json({
273
+ success: failed.length === 0,
274
+ requestedCount: uniqueSessionIds.length,
275
+ deletedCount: deletedSessionIds.length,
276
+ deletedSessionIds,
277
+ failed
278
+ });
279
+ } catch (err) {
280
+ console.error('[OpenCode API] Failed to batch delete sessions:', err);
281
+ res.status(500).json({ error: err.message });
282
+ }
283
+ });
284
+
231
285
  /**
232
286
  * POST /api/opencode/sessions/:projectName/:sessionId/fork
233
287
  * Fork 一个会话
@@ -83,6 +83,55 @@ module.exports = (config) => {
83
83
  }
84
84
  });
85
85
 
86
+ // POST /api/sessions/:projectName/batch-delete - Delete multiple sessions
87
+ router.post('/:projectName/batch-delete', (req, res) => {
88
+ try {
89
+ const { projectName } = req.params;
90
+ const { sessionIds } = req.body || {};
91
+
92
+ if (!Array.isArray(sessionIds) || sessionIds.length === 0) {
93
+ return res.status(400).json({ error: 'sessionIds must be a non-empty array' });
94
+ }
95
+
96
+ const uniqueSessionIds = Array.from(new Set(
97
+ sessionIds
98
+ .filter(sessionId => typeof sessionId === 'string')
99
+ .map(sessionId => sessionId.trim())
100
+ .filter(Boolean)
101
+ ));
102
+
103
+ if (uniqueSessionIds.length === 0) {
104
+ return res.status(400).json({ error: 'sessionIds must be a non-empty array' });
105
+ }
106
+
107
+ const deletedSessionIds = [];
108
+ const failed = [];
109
+
110
+ uniqueSessionIds.forEach((sessionId) => {
111
+ try {
112
+ deleteSession(config, projectName, sessionId);
113
+ deletedSessionIds.push(sessionId);
114
+ } catch (error) {
115
+ failed.push({
116
+ sessionId,
117
+ error: error.message
118
+ });
119
+ }
120
+ });
121
+
122
+ res.json({
123
+ success: failed.length === 0,
124
+ requestedCount: uniqueSessionIds.length,
125
+ deletedCount: deletedSessionIds.length,
126
+ deletedSessionIds,
127
+ failed
128
+ });
129
+ } catch (error) {
130
+ console.error('Error batch deleting sessions:', error);
131
+ res.status(500).json({ error: error.message });
132
+ }
133
+ });
134
+
86
135
  // POST /api/sessions/:projectName/:sessionId/fork - Fork a session
87
136
  router.post('/:projectName/:sessionId/fork', (req, res) => {
88
137
  try {
@@ -205,6 +205,7 @@ async function startServer(port, host = '127.0.0.1', options = {}) {
205
205
 
206
206
  // 初始化 Claude hooks 默认配置(自动开启任务完成通知)
207
207
  notificationHooks.initDefaultHooks();
208
+ notificationHooks.syncManagedNotificationAssets();
208
209
 
209
210
  // Claude Code 专有功能 API
210
211
  app.use('/api/commands', require('./api/commands'));
@@ -3,7 +3,7 @@ const path = require('path');
3
3
  const os = require('os');
4
4
  const http = require('http');
5
5
  const https = require('https');
6
- const { execSync } = require('child_process');
6
+ const { execSync, execFileSync } = require('child_process');
7
7
  const { PATHS, NATIVE_PATHS } = require('../../config/paths');
8
8
  const { loadUIConfig, saveUIConfig } = require('./ui-config');
9
9
  const codexSettingsManager = require('./codex-settings-manager');
@@ -422,7 +422,15 @@ function buildWindowsPopupCommand(title, message) {
422
422
  '[void]$form.ShowDialog()',
423
423
  '}'
424
424
  ].join('; ');
425
- return `powershell -NoProfile -STA -Command ${JSON.stringify(script)}`;
425
+ return script;
426
+ }
427
+
428
+ function runWindowsPowerShellCommand(command) {
429
+ // Invoke PowerShell directly so the styled popup script doesn't hit cmd.exe's 8191-char limit.
430
+ execFileSync('powershell', ['-NoProfile', '-STA', '-Command', command], {
431
+ stdio: 'ignore',
432
+ windowsHide: true
433
+ });
426
434
  }
427
435
 
428
436
  function generateNotifyScript(feishu = {}) {
@@ -434,7 +442,7 @@ const fs = require('fs')
434
442
  const os = require('os')
435
443
  const http = require('http')
436
444
  const https = require('https')
437
- const { execSync } = require('child_process')
445
+ const { execSync, execFileSync } = require('child_process')
438
446
 
439
447
  const FEISHU_ENABLED = ${feishuEnabled ? 'true' : 'false'}
440
448
  const FEISHU_WEBHOOK_URL = ${JSON.stringify(feishuEnabled ? feishu.webhookUrl : '')}
@@ -529,10 +537,13 @@ function notify(mode, message) {
529
537
  const ps = "Add-Type -AssemblyName PresentationFramework; [System.Windows.MessageBox]::Show('" +
530
538
  escapeForPowerShellSingleQuote(message) + "', '" +
531
539
  escapeForPowerShellSingleQuote(title) + "', 'OK', 'Information')"
532
- const command = 'powershell -NoProfile -STA -Command ' + JSON.stringify(ps) + ' || ' + popupCommand
533
- execSync(command, { stdio: 'ignore', windowsHide: true })
540
+ try {
541
+ runWindowsPowerShellCommand(ps)
542
+ } catch (dialogError) {
543
+ runWindowsPowerShellCommand(popupCommand)
544
+ }
534
545
  } else {
535
- execSync(popupCommand, { stdio: 'ignore', windowsHide: true })
546
+ runWindowsPowerShellCommand(popupCommand)
536
547
  }
537
548
  return
538
549
  }
@@ -832,7 +843,15 @@ function buildWindowsPopupCommand(title, message) {
832
843
  '[void]$form.ShowDialog()',
833
844
  '}'
834
845
  ].join('; ')
835
- return 'powershell -NoProfile -STA -Command ' + JSON.stringify(script)
846
+ return script
847
+ }
848
+
849
+ function runWindowsPowerShellCommand(command) {
850
+ // Invoke PowerShell directly so the styled popup script doesn't hit cmd.exe's 8191-char limit.
851
+ execFileSync('powershell', ['-NoProfile', '-STA', '-Command', command], {
852
+ stdio: 'ignore',
853
+ windowsHide: true
854
+ })
836
855
  }
837
856
  `;
838
857
  }
@@ -1476,12 +1495,78 @@ function generateSystemNotificationCommand(type, message, platformOverride = os.
1476
1495
  return `notify-send "Coding Tool" "${String(message || '').replace(/"/g, '\\"')}"`;
1477
1496
  }
1478
1497
 
1498
+ function runSystemNotification(type, message, platformOverride = os.platform()) {
1499
+ const normalizedType = normalizeType(type);
1500
+ const title = 'Coding Tool';
1501
+ const platform = platformOverride;
1502
+
1503
+ if (platform === 'darwin') {
1504
+ if (normalizedType === 'dialog') {
1505
+ const appleScript = 'display dialog "' + escapeForAppleScript(message) +
1506
+ '" with title "' + escapeForAppleScript(title) +
1507
+ '" buttons {"好的"} default button 1 with icon note';
1508
+ execSync('osascript -e ' + JSON.stringify(appleScript), { stdio: 'ignore', windowsHide: true });
1509
+ } else {
1510
+ const fallbackScript = 'display notification "' + escapeForAppleScript(message) +
1511
+ '" with title "' + escapeForAppleScript(title) + '" sound name "Glass"';
1512
+ const command = 'if command -v terminal-notifier >/dev/null 2>&1; then ' +
1513
+ 'terminal-notifier -title ' + JSON.stringify(title) +
1514
+ ' -message ' + JSON.stringify(message) +
1515
+ ' -sound Glass -activate com.apple.Terminal; ' +
1516
+ 'else osascript -e ' + JSON.stringify(fallbackScript) + '; fi';
1517
+ execSync(command, { stdio: 'ignore', windowsHide: true });
1518
+ }
1519
+ return;
1520
+ }
1521
+
1522
+ if (platform === 'win32') {
1523
+ const popupCommand = buildWindowsPopupCommand(title, message);
1524
+ if (normalizedType === 'dialog') {
1525
+ const dialogScript = "Add-Type -AssemblyName PresentationFramework; [System.Windows.MessageBox]::Show('" +
1526
+ escapeForPowerShellSingleQuote(message) + "', '" +
1527
+ escapeForPowerShellSingleQuote(title) + "', 'OK', 'Information')";
1528
+ try {
1529
+ runWindowsPowerShellCommand(dialogScript);
1530
+ } catch (dialogError) {
1531
+ runWindowsPowerShellCommand(popupCommand);
1532
+ }
1533
+ } else {
1534
+ runWindowsPowerShellCommand(popupCommand);
1535
+ }
1536
+ return;
1537
+ }
1538
+
1539
+ const escapedMessage = String(message || '').replace(/"/g, '\\"');
1540
+ if (normalizedType === 'dialog') {
1541
+ execSync(
1542
+ `zenity --info --title="Coding Tool" --text="${escapedMessage}" 2>/dev/null || notify-send "Coding Tool" "${escapedMessage}"`,
1543
+ { stdio: 'ignore', windowsHide: true }
1544
+ );
1545
+ return;
1546
+ }
1547
+
1548
+ execSync(`notify-send "Coding Tool" "${escapedMessage}"`, { stdio: 'ignore', windowsHide: true });
1549
+ }
1550
+
1551
+ function syncManagedNotificationAssets() {
1552
+ const settings = getNotificationSettings();
1553
+ const hasManagedPlatform = Object.values(settings?.platforms || {}).some((platform) => platform?.enabled === true);
1554
+
1555
+ if (hasManagedPlatform) {
1556
+ writeNotifyScript(settings.feishu || {});
1557
+ } else {
1558
+ removeNotifyScript();
1559
+ }
1560
+
1561
+ return settings;
1562
+ }
1563
+
1479
1564
  function testNotification({ type, testFeishu, webhookUrl } = {}) {
1480
1565
  if (testFeishu && webhookUrl) {
1481
1566
  return sendFeishuTest(webhookUrl);
1482
1567
  }
1483
1568
 
1484
- execSync(generateSystemNotificationCommand(type || 'notification', '这是一条测试通知'), { stdio: 'ignore', windowsHide: true });
1569
+ runSystemNotification(type || 'notification', '这是一条测试通知');
1485
1570
  }
1486
1571
 
1487
1572
  module.exports = {
@@ -1492,6 +1577,7 @@ module.exports = {
1492
1577
  saveLegacyClaudeHookSettings,
1493
1578
  testNotification,
1494
1579
  initDefaultHooks,
1580
+ syncManagedNotificationAssets,
1495
1581
  getOpenCodeManagedPluginPath,
1496
1582
  buildOpenCodePluginContent,
1497
1583
  buildCodexNotifyCommand,
@@ -1 +0,0 @@
1
- .session-list-container[data-v-05ca5429]{width:100%;height:100%;display:flex;flex-direction:column;box-sizing:border-box}.header[data-v-05ca5429]{flex-shrink:0;padding:24px 24px 16px;background:var(--bg-primary);border-bottom:1px solid var(--border-primary)}.content[data-v-05ca5429]{flex:1;overflow-y:auto;overflow-x:hidden;padding:16px 24px 24px}.sessions-list[data-v-05ca5429]{position:relative;overflow:hidden}.back-button[data-v-05ca5429]{flex-shrink:0;margin-right:12px}.title-bar[data-v-05ca5429]{display:flex;align-items:center;gap:16px}.title-section[data-v-05ca5429]{flex:1;min-width:0}.title-with-count[data-v-05ca5429]{display:flex;align-items:baseline;gap:8px;margin-bottom:2px}.title-section h2[data-v-05ca5429]{margin:0;font-size:20px}.session-count[data-v-05ca5429]{font-size:14px;color:#666}.total-size-tag[data-v-05ca5429]{margin-left:8px}.project-path[data-v-05ca5429]{font-size:13px;display:block;color:#666;margin-bottom:2px}.search-input[data-v-05ca5429]{width:320px;flex-shrink:0}.loading-container[data-v-05ca5429]{display:flex;justify-content:center;align-items:center;min-height:400px}.session-item[data-v-05ca5429]{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-05ca5429]:hover{border-color:#18a058;box-shadow:0 2px 8px #18a0581a}.drag-handle[data-v-05ca5429]{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-05ca5429]{opacity:1;background-color:#18a0581a;border-radius:4px}.session-left[data-v-05ca5429]{flex:1;display:flex;align-items:center;gap:16px;min-width:0}.session-icon[data-v-05ca5429]{flex-shrink:0}.session-info[data-v-05ca5429]{flex:1;min-width:0}.session-header[data-v-05ca5429]{display:flex;align-items:center;margin-bottom:6px}.session-title-row[data-v-05ca5429]{display:flex;align-items:center;gap:8px}.session-title[data-v-05ca5429]{font-size:15px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-shrink:1;min-width:0}.session-meta[data-v-05ca5429]{display:flex;align-items:center;gap:8px;margin-bottom:6px;font-size:13px}.session-message[data-v-05ca5429]{display:block;max-width:600px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px}.session-message-empty[data-v-05ca5429]{font-style:italic;opacity:.5}.session-right[data-v-05ca5429]{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-05ca5429]{min-height:24px;display:flex;align-items:flex-start;justify-content:flex-end}.session-actions[data-v-05ca5429]{display:flex;align-items:center;margin-top:auto}.ghost[data-v-05ca5429]{opacity:.4}.chosen[data-v-05ca5429]{box-shadow:0 4px 16px #00000026}.search-result-item[data-v-05ca5429]{margin-bottom:16px;padding:12px;border:1px solid var(--border-primary);border-radius:6px;background:var(--bg-elevated)}.search-result-header[data-v-05ca5429]{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.search-result-title[data-v-05ca5429]{display:flex;align-items:center;gap:8px}.search-match[data-v-05ca5429]{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-05ca5429]{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 t,h as n,K as o,c as i,o as r,a as u,X as c,a0 as d,W as v,Y as f,N as p,p as m,_ as h,a6 as y,s as g,Z as k,G as _,y as w,F as j,$ as C,v as I}from"./vue-vendor-3bf-fPGP.js";import{d as b}from"./vendors-CKPV1OAU.js";import{_ as x,m as z,t as N,C as F,v as B,o as M,p as L,r as $,w as S}from"./index-EMrm1wk-.js";import{X as P,d as T,ac as U,ay as E,j as K,G as O,T as R,a2 as V,az as A,p as H,h as q,V as D}from"./icons-B5Pl4lrD.js";import{N as G,B as W,_ as X,c as Y,a as Z,q as J,g as Q,x as ee,s as se,n as ae,h as le,p as te}from"./naive-ui-Bdxp09n2.js";import"./markdown-DyTJGI4N.js";const ne={class:"session-list-container"},oe={class:"header"},ie={class:"title-bar"},re={class:"title-section"},ue={class:"title-with-count"},ce={key:0,class:"loading-container"},de=["onMouseenter","onClick"],ve={class:"drag-handle"},fe={class:"session-left"},pe={class:"session-icon"},me={class:"session-info"},he={class:"session-header"},ye={class:"session-title-row"},ge={class:"session-title"},ke={class:"session-meta"},_e={class:"session-right"},we={class:"session-tags-area"},je={class:"session-actions"},Ce={key:0,style:{"max-height":"70vh","overflow-y":"auto"}},Ie={class:"search-result-header"},be={class:"search-result-title"},xe=x({__name:"SessionList",props:{projectName:{type:String,required:!0}},setup(x){const xe=x,ze=e(),Ne=s(),Fe=z(),{addFavorite:Be,removeFavorite:Me,isFavorite:Le}=N(),$e=a(()=>Ne.meta.channel||"claude"),Se=l(xe.projectName),Pe=a(()=>Se.value||xe.projectName),Te=l(""),Ue=l(!1),Ee=l(null),Ke=l(""),Oe=l(null),Re=l([]),Ve=l(null),Ae=l(!1),He=l(null),qe=l(!1),De=l(!1),Ge=l(""),We=l(""),Xe=l(null),Ye=l(!1),Ze={group:{name:`${$e.value}-sessions`,pull:!1,put:!1},forceFallback:!0,fallbackOnBody:!1,fallbackTolerance:4,scroll:!0},Je=a(()=>{var e;return(null==(e=Fe.currentProjectInfo)?void 0:e.displayName)||xe.projectName}),Qe=a(()=>{var e;return(null==(e=Fe.currentProjectInfo)?void 0:e.fullPath)||Pe.value});async function es(){const e=await async function(){Fe.projects.length||await Fe.fetchProjects();const e=Fe.projects.find(e=>e.name===xe.projectName);if(e)return Se.value=e.name,e.name;const s=Fe.projects.find(e=>e.displayName===xe.projectName||e.fullPath===xe.projectName);return s?(Se.value=s.name,s.name!==xe.projectName&&await ze.replace({name:`${$e.value}-sessions`,params:{projectName:s.name}}),s.name):(Se.value=xe.projectName,xe.projectName)}();await Fe.fetchSessions(e)}t(()=>Fe.sessionsWithAlias,e=>{Re.value=[...e]},{immediate:!0});const ss=a(()=>{if(!Te.value)return Re.value;const e=Te.value.toLowerCase();return Re.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))});function as(){const e=Ne.meta.channel||"claude";ze.push({name:`${e}-projects`})}async function ls(){if(Te.value){qe.value=!0;try{const e=await B(Pe.value,Te.value,35,$e.value);Ve.value=e,Ae.value=!0}catch(e){M.error("搜索失败: "+e.message)}finally{qe.value=!1}}}async function ts(){const e=Re.value.map(e=>e.sessionId);await Fe.saveSessionOrder(e)}async function ns(){if(Ee.value)try{const e=Ee.value.sessionId;Ke.value?(await Fe.setAlias(e,Ke.value),M.success("别名设置成功")):(await Fe.deleteAlias(e),M.success("别名已删除")),Ue.value=!1,Ee.value=null,Ke.value=""}catch(e){M.error("操作失败: "+e.message)}}function os(e){M.error(e)}async function is(e){try{const{copyResult:s}=await $(Pe.value,e,$e.value);if("manual"===(null==s?void 0:s.method))return void M.warning("自动复制失败,已弹出手动复制框");M.success("启动命令已复制到剪贴板")}catch(s){M.error("复制失败: "+s.message)}}async function rs(){Ye.value=!0;try{const e=$e.value||"claude",s=function(e){return"codex"===e?"codex":"gemini"===e?"gemini":"opencode"===e?null:"claude"}(e);if(!s)return void M.warning("OpenCode 暂不支持在此新建会话,请在 CLI 中手动创建");const a=await S(Pe.value,s),l=null==a?void 0:a.sessionId;if(!l)throw new Error("创建会话成功但未返回 sessionId");const{copyResult:t}=await $(Pe.value,l,e);if(await es(),"manual"===(null==t?void 0:t.method))return void M.warning("新会话已创建,自动复制失败,已弹出手动复制框");M.success("新会话已创建,启动命令已复制到剪贴板")}catch(e){M.error("创建会话失败: "+e.message)}finally{Ye.value=!1}}function us(e){if(!e)return"";return new Date(e).toLocaleString("zh-CN")}function cs(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 ds(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 vs(e,s=80){return e?e.length>s?e.substring(0,s)+"...":e:""}return t([$e,()=>xe.projectName],([e])=>{Fe.setChannel(e),es()},{immediate:!0}),n(()=>{}),o(()=>{}),(e,s)=>(r(),i("div",ne,[u("div",oe,[u("div",ie,[c(p(W),{size:"small",onClick:as,class:"back-button"},{icon:f(()=>[c(p(G),{size:"18"},{default:f(()=>[c(p(P))]),_:1})]),_:1}),u("div",re,[u("div",ue,[c(p(X),null,{default:f(()=>[m(h(Je.value),1)]),_:1}),c(p(Y),{depth:"3",class:"session-count"},{default:f(()=>[m("("+h(p(Fe).sessions.length)+" 个对话)",1)]),_:1}),c(p(Z),{size:"small",bordered:!1,type:"info",class:"total-size-tag"},{default:f(()=>[m(h(cs(p(Fe).totalSize)),1)]),_:1}),c(p(W),{type:"primary",size:"small",loading:Ye.value,onClick:rs,style:{"margin-left":"12px"}},{icon:f(()=>[c(p(G),null,{default:f(()=>[c(p(T))]),_:1})]),default:f(()=>[s[8]||(s[8]=m(" 新建会话 ",-1))]),_:1},8,["loading"])]),c(p(Y),{depth:"3",class:"project-path"},{default:f(()=>[m(h(Qe.value),1)]),_:1})]),c(p(J),{value:Te.value,"onUpdate:value":s[0]||(s[0]=e=>Te.value=e),placeholder:"搜索会话...",clearable:"",class:"search-input",onKeyup:y(ls,["enter"]),disabled:qe.value},{prefix:f(()=>[c(p(G),null,{default:f(()=>[c(p(U))]),_:1})]),suffix:f(()=>[c(p(W),{text:"",onClick:ls,disabled:!Te.value||qe.value,loading:qe.value},{default:f(()=>[...s[9]||(s[9]=[m(" 搜索 ",-1)])]),_:1},8,["disabled","loading"])]),_:1},8,["value","disabled"])])]),u("div",{class:"content",ref_key:"contentEl",ref:He},[p(Fe).loading?(r(),i("div",ce,[c(p(Q),{size:"large"},{description:f(()=>[...s[10]||(s[10]=[m(" 加载会话列表... ",-1)])]),_:1})])):p(Fe).error?(r(),d(p(ee),{key:1,type:"error",title:"加载失败",style:{"margin-bottom":"16px"}},{default:f(()=>[m(h(p(Fe).error),1)]),_:1})):ss.value.length>0?(r(),d(p(b),w({key:2,modelValue:Re.value,"onUpdate:modelValue":s[2]||(s[2]=e=>Re.value=e),"item-key":"sessionId",class:"sessions-list",handle:".drag-handle"},Ze,{"ghost-class":"ghost","chosen-class":"chosen",animation:"200",onEnd:ts}),{item:f(({element:e})=>[u("div",{class:"session-item",onMouseenter:s=>Oe.value=e.sessionId,onMouseleave:s[1]||(s[1]=e=>Oe.value=null),onClick:s=>function(e){Ge.value=e.sessionId,We.value=e.alias||"",De.value=!0,I(()=>{var e;null==(e=Xe.value)||e.open()})}(e)},[u("div",ve,[c(p(G),{size:"16",color:"#999"},{default:f(()=>[c(p(E))]),_:1})]),u("div",fe,[u("div",pe,[c(p(G),{size:"24",color:"#18a058"},{default:f(()=>[c(p(K))]),_:1})]),u("div",me,[u("div",he,[u("div",ye,[u("span",ge,h(e.alias?`${e.alias} (${e.sessionId.substring(0,8)})`:e.sessionId),1),e.forkedFrom?(r(),d(p(se),{key:0,placement:"top"},{trigger:f(()=>[c(p(Z),{size:"small",type:"warning",bordered:!1,style:{"margin-left":"8px",cursor:"help"}},{icon:f(()=>[c(p(G),null,{default:f(()=>[c(p(O))]),_:1})]),default:f(()=>[s[11]||(s[11]=m(" Fork ",-1))]),_:1})]),default:f(()=>[m(" Fork 自: "+h(e.forkedFrom),1)]),_:2},1024)):v("",!0)])]),u("div",ke,[c(p(Y),{depth:"3"},{default:f(()=>[m(h(us(e.mtime)),1)]),_:2},1024),c(p(Y),{depth:"3"},{default:f(()=>[...s[12]||(s[12]=[m("•",-1)])]),_:1}),c(p(Z),{size:"small",bordered:!1},{default:f(()=>[m(h(cs(e.size)),1)]),_:2},1024)]),e.firstMessage?(r(),d(p(Y),{key:0,depth:"3",class:"session-message"},{default:f(()=>[m(h(vs(e.firstMessage,80)),1)]),_:2},1024)):e.gitBranch||e.summary?v("",!0):(r(),d(p(Y),{key:1,depth:"3",class:"session-message session-message-empty"},{default:f(()=>[...s[13]||(s[13]=[m(" 暂未读取到对话内容 ",-1)])]),_:1}))])]),u("div",_e,[u("div",we,[e.gitBranch?(r(),d(p(Z),{key:0,size:"small",type:"info",bordered:!1},{icon:f(()=>[c(p(G),null,{default:f(()=>[c(p(O))]),_:1})]),default:f(()=>[m(" "+h(e.gitBranch),1)]),_:2},1024)):v("",!0)]),u("div",je,[c(p(ae),null,{default:f(()=>[g(c(p(W),{size:"small",type:"error",onClick:k(s=>{return a=e.sessionId,void L.warning({title:"删除会话",content:"确定要删除这个会话吗?此操作不可恢复!",positiveText:"确定删除",negativeText:"取消",onPositiveClick:async()=>{try{await Fe.deleteSession(a),M.success("会话已删除")}catch(e){M.error("删除失败: "+e.message)}}});var a},["stop"])},{icon:f(()=>[c(p(G),null,{default:f(()=>[c(p(R))]),_:1})]),default:f(()=>[s[14]||(s[14]=m(" 删除 ",-1))]),_:1},8,["onClick"]),[[_,Oe.value===e.sessionId]]),c(p(W),{size:"small",onClick:k(s=>function(e){Ee.value=e,Ke.value=e.alias||"",Ue.value=!0}(e),["stop"])},{icon:f(()=>[c(p(G),null,{default:f(()=>[c(p(V))]),_:1})]),default:f(()=>[s[15]||(s[15]=m(" 别名 ",-1))]),_:1},8,["onClick"]),c(p(W),{size:"small",type:p(Le)($e.value,Pe.value,e.sessionId)?"warning":"default",onClick:k(s=>async function(e){const s=$e.value,a=Le(s,Pe.value,e.sessionId);try{if(a)await Me(s,Pe.value,e.sessionId),M.success("已取消收藏");else{const a={sessionId:e.sessionId,projectName:Pe.value,projectDisplayName:Je.value,projectFullPath:Qe.value,alias:e.alias||"",firstMessage:e.firstMessage||"",mtime:e.mtime,size:e.size,gitBranch:e.gitBranch||"",forkedFrom:e.forkedFrom||""};await Be(s,a),M.success("已添加到收藏")}}catch(l){M.error("操作失败: "+l.message)}}(e),["stop"])},{icon:f(()=>[c(p(G),null,{default:f(()=>[p(Le)($e.value,Pe.value,e.sessionId)?(r(),d(p(A),{key:0})):(r(),d(p(H),{key:1}))]),_:2},1024)]),default:f(()=>[m(" "+h(p(Le)($e.value,Pe.value,e.sessionId)?"已收藏":"收藏"),1)]),_:2},1032,["type","onClick"]),"opencode"!==$e.value?(r(),d(p(W),{key:0,size:"small",onClick:k(s=>async function(e){if("opencode"!==$e.value)try{await Fe.forkSession(e),M.success("Fork 成功!")}catch(s){M.error("Fork 失败: "+s.message)}else M.warning("OpenCode 当前不支持该 Fork 操作")}(e.sessionId),["stop"])},{icon:f(()=>[c(p(G),null,{default:f(()=>[c(p(O))]),_:1})]),default:f(()=>[s[16]||(s[16]=m(" Fork ",-1))]),_:1},8,["onClick"])):v("",!0),c(p(W),{size:"small",type:"primary",onClick:k(s=>is(e.sessionId),["stop"])},{icon:f(()=>[c(p(G),null,{default:f(()=>[c(p(q))]),_:1})]),default:f(()=>[s[17]||(s[17]=m(" 使用对话 ",-1))]),_:1},8,["onClick"])]),_:2},1024)])])],40,de)]),_:1},16,["modelValue"])):(r(),d(p(le),{key:3,description:"没有找到会话",style:{"margin-top":"60px"}},{icon:f(()=>[c(p(G),null,{default:f(()=>[c(p(D))]),_:1})]),_:1}))],512),c(p(te),{show:Ue.value,"onUpdate:show":s[5]||(s[5]=e=>Ue.value=e),preset:"dialog",title:"设置别名"},{action:f(()=>[c(p(ae),null,{default:f(()=>[c(p(W),{onClick:s[4]||(s[4]=e=>Ue.value=!1)},{default:f(()=>[...s[18]||(s[18]=[m("取消",-1)])]),_:1}),c(p(W),{type:"primary",onClick:ns},{default:f(()=>[...s[19]||(s[19]=[m("确定",-1)])]),_:1})]),_:1})]),default:f(()=>[c(p(J),{value:Ke.value,"onUpdate:value":s[3]||(s[3]=e=>Ke.value=e),placeholder:"输入别名(留空删除)",onKeyup:y(ns,["enter"])},null,8,["value"])]),_:1},8,["show"]),c(p(te),{show:Ae.value,"onUpdate:show":s[6]||(s[6]=e=>Ae.value=e),preset:"card",title:"搜索结果",style:{width:"1200px"}},{default:f(()=>[Ve.value?(r(),i("div",Ce,[c(p(ee),{type:"info",style:{"margin-bottom":"16px"}},{default:f(()=>[m(' 关键词 "'+h(Ve.value.keyword)+'" 共找到 '+h(Ve.value.totalMatches)+" 处匹配 ",1)]),_:1}),(r(!0),i(j,null,C(Ve.value.sessions,e=>(r(),i("div",{key:e.sessionId,class:"search-result-item"},[u("div",Ie,[u("div",be,[c(p(Y),{strong:""},{default:f(()=>[m(h(e.alias?`${e.alias} (${e.sessionId.substring(0,8)})`:e.sessionId.substring(0,8)),1)]),_:2},1024),c(p(Z),{size:"small",bordered:!1},{default:f(()=>[m(h(e.matchCount)+" 个匹配",1)]),_:2},1024)]),c(p(W),{size:"small",type:"primary",onClick:s=>is(e.sessionId)},{icon:f(()=>[c(p(G),null,{default:f(()=>[c(p(q))]),_:1})]),default:f(()=>[s[20]||(s[20]=m(" 使用对话 ",-1))]),_:1},8,["onClick"])]),(r(!0),i(j,null,C(e.matches,(e,s)=>(r(),i("div",{key:s,class:"search-match"},[c(p(Z),{size:"tiny",type:"user"===e.role?"info":"success",bordered:!1},{default:f(()=>[m(h("user"===e.role?"用户":"助手"),1)]),_:2},1032,["type"]),c(p(Y),{depth:"3",class:"search-match-text",innerHTML:ds(e.context,Ve.value.keyword)},null,8,["innerHTML"])]))),128))]))),128)),0===Ve.value.sessions.length?(r(),d(p(le),{key:0,description:"没有找到匹配的内容"})):v("",!0)])):v("",!0)]),_:1},8,["show"]),Ge.value?(r(),d(F,{key:0,ref_key:"chatHistoryRef",ref:Xe,show:De.value,"onUpdate:show":s[7]||(s[7]=e=>De.value=e),"project-name":Pe.value,"session-id":Ge.value,"session-alias":We.value,channel:$e.value,onError:os},null,8,["show","project-name","session-id","session-alias","channel"])):v("",!0)]))}},[["__scopeId","data-v-05ca5429"]]);export{xe as default};