cli-link 0.0.6 → 0.0.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.
- package/README.md +56 -14
- package/dist/client/assets/History-D2xDopni.js +4 -0
- package/dist/client/assets/ImageViewer-DuegU_fC.js +1 -0
- package/dist/client/assets/MarkdownRenderer-CsyizEL3.js +1 -0
- package/dist/client/assets/{PageTopBar-C8j-5s_3.js → PageTopBar-CQwjO6Af.js} +1 -1
- package/dist/client/assets/Session-B0s5zBGg.js +7 -0
- package/dist/client/assets/Settings-CfHFmJdV.js +1 -0
- package/dist/client/assets/Workspace-Cfl0mbNE.js +4 -0
- package/dist/client/assets/WorkspaceLinkedText-DCVYd9x-.js +2 -0
- package/dist/client/assets/c-BIGW1oBm.js +1 -0
- package/dist/client/assets/cpp-DIPi6g--.js +1 -0
- package/dist/client/assets/csharp-DSvCPggb.js +1 -0
- package/dist/client/assets/dart-bE4Kk8sk.js +1 -0
- package/dist/client/assets/dotenv-Da5cRb03.js +1 -0
- package/dist/client/assets/go-C27-OAKa.js +1 -0
- package/dist/client/assets/graphql-pNE0_Gx8.js +1 -0
- package/dist/client/assets/groovy-gcz8RCvz.js +1 -0
- package/dist/client/assets/index-BCg3ymV3.css +1 -0
- package/dist/client/assets/index-CrJqHlc8.js +2 -0
- package/dist/client/assets/java-VnEXKtx_.js +148 -0
- package/dist/client/assets/jsx-g9-lgVsj.js +1 -0
- package/dist/client/assets/kotlin-BdnUsdx6.js +1 -0
- package/dist/client/assets/less-B1dDrJ26.js +1 -0
- package/dist/client/assets/lua-BaeVxFsk.js +1 -0
- package/dist/client/assets/makefile-CHLpvVh8.js +1 -0
- package/dist/client/assets/php-BcCyJq-p.js +1 -0
- package/dist/client/assets/properties-DTPjHERo.js +1 -0
- package/dist/client/assets/ruby-BwImf3Ka.js +1 -0
- package/dist/client/assets/rust-B1yitclQ.js +1 -0
- package/dist/client/assets/scss-lMagJa-5.js +1 -0
- package/dist/client/assets/sql-CRqJ_cUM.js +1 -0
- package/dist/client/assets/svelte-B4a9v_or.js +1 -0
- package/dist/client/assets/swift-D82vCrfD.js +1 -0
- package/dist/client/assets/toml-vGWfd6FD.js +1 -0
- package/dist/client/assets/{vendor-icons-CNN4EKVi.js → vendor-icons-CMXJHDEv.js} +125 -65
- package/dist/client/assets/vendor-markdown--d-T3AbU.js +37 -0
- package/dist/client/assets/{vendor-motion-n6Lx6G4a.js → vendor-motion-D0ZmPdi9.js} +1 -1
- package/dist/client/assets/{vendor-react-DSV5aFEg.js → vendor-react-CcDXZHn_.js} +1 -1
- package/dist/client/assets/{vendor-virtual-CcftJrIC.js → vendor-virtual-DJI7OicV.js} +1 -1
- package/dist/client/assets/vue-DBXACu8K.js +1 -0
- package/dist/client/assets/workspace-return-FrQUv7g3.js +1 -0
- package/dist/client/index.html +4 -4
- package/dist/server/cli-manager.js +151 -26
- package/dist/server/codex-history.js +119 -17
- package/dist/server/index.js +906 -57
- package/dist/server/store.js +369 -27
- package/package.json +3 -3
- package/dist/client/assets/History-BxJVDFpN.js +0 -3
- package/dist/client/assets/MarkdownRenderer-BO-KS_L1.js +0 -1
- package/dist/client/assets/Session-CQFXA2Sr.js +0 -11
- package/dist/client/assets/Settings-DYmjRmoN.js +0 -1
- package/dist/client/assets/Workspace-D8kv9euM.js +0 -8
- package/dist/client/assets/WorkspaceLinkedText-DQyPLk-X.js +0 -2
- package/dist/client/assets/code-highlight-CEcsuMpw.js +0 -1
- package/dist/client/assets/index-BXT2BylN.css +0 -1
- package/dist/client/assets/index-DOgH1Kf3.js +0 -2
- package/dist/client/assets/vendor-markdown-BDwu-Ux6.js +0 -35
package/dist/server/store.js
CHANGED
|
@@ -33,6 +33,17 @@ function buildHistoryTitle(messages) {
|
|
|
33
33
|
const userMessage = messages.find(m => m.type === 'user_message' || m.type === 'user');
|
|
34
34
|
return userMessage ? cleanHistoryTitle(userMessage.content) : '会话记录';
|
|
35
35
|
}
|
|
36
|
+
function normalizePromptHistoryText(content) {
|
|
37
|
+
if (typeof content !== 'string')
|
|
38
|
+
return null;
|
|
39
|
+
const text = content.trim();
|
|
40
|
+
if (!text)
|
|
41
|
+
return null;
|
|
42
|
+
const key = text.replace(/\s+/g, ' ').toLowerCase();
|
|
43
|
+
if (!key)
|
|
44
|
+
return null;
|
|
45
|
+
return { text, key };
|
|
46
|
+
}
|
|
36
47
|
function normalizeWorkDir(workDir) {
|
|
37
48
|
if (typeof workDir !== 'string')
|
|
38
49
|
return null;
|
|
@@ -124,7 +135,20 @@ export function initDb(dbPath) {
|
|
|
124
135
|
created_at INTEGER NOT NULL
|
|
125
136
|
);
|
|
126
137
|
|
|
138
|
+
CREATE TABLE IF NOT EXISTS prompt_history (
|
|
139
|
+
id TEXT PRIMARY KEY,
|
|
140
|
+
work_dir TEXT,
|
|
141
|
+
text TEXT NOT NULL,
|
|
142
|
+
normalized_text TEXT NOT NULL,
|
|
143
|
+
session_id TEXT,
|
|
144
|
+
message_id TEXT,
|
|
145
|
+
use_count INTEGER NOT NULL DEFAULT 1,
|
|
146
|
+
last_used_at INTEGER NOT NULL,
|
|
147
|
+
created_at INTEGER NOT NULL
|
|
148
|
+
);
|
|
149
|
+
|
|
127
150
|
CREATE INDEX IF NOT EXISTS idx_messages_session_seq ON messages(session_id, seq);
|
|
151
|
+
CREATE INDEX IF NOT EXISTS idx_messages_session_id ON messages(session_id, id);
|
|
128
152
|
`);
|
|
129
153
|
// Migrate: add 'details' column if it doesn't exist (for existing databases)
|
|
130
154
|
const columns = db.prepare(`PRAGMA table_info(messages)`).all();
|
|
@@ -147,7 +171,11 @@ export function initDb(dbPath) {
|
|
|
147
171
|
}
|
|
148
172
|
db.exec(`CREATE INDEX IF NOT EXISTS idx_history_tasks_work_dir_created ON history_tasks(work_dir, created_at DESC)`);
|
|
149
173
|
db.exec(`CREATE INDEX IF NOT EXISTS idx_workdir_history_last_used ON workdir_history(last_used_at DESC)`);
|
|
174
|
+
db.exec(`CREATE INDEX IF NOT EXISTS idx_prompt_history_work_dir_last_used ON prompt_history(work_dir, last_used_at DESC)`);
|
|
175
|
+
db.exec(`CREATE INDEX IF NOT EXISTS idx_prompt_history_last_used ON prompt_history(last_used_at DESC)`);
|
|
176
|
+
db.exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_prompt_history_work_dir_norm ON prompt_history(work_dir, normalized_text)`);
|
|
150
177
|
backfillHistoryTaskSummaries();
|
|
178
|
+
backfillPromptHistoryFromMessages();
|
|
151
179
|
console.log(`[Store] Database initialized at ${path}`);
|
|
152
180
|
}
|
|
153
181
|
function backfillHistoryTaskSummaries() {
|
|
@@ -475,6 +503,105 @@ export function getRecentWorkDirs(limit = 12) {
|
|
|
475
503
|
}
|
|
476
504
|
return existing;
|
|
477
505
|
}
|
|
506
|
+
// --- Prompt History ---
|
|
507
|
+
export function recordPromptHistory(input) {
|
|
508
|
+
const normalizedText = normalizePromptHistoryText(input.text);
|
|
509
|
+
if (!normalizedText)
|
|
510
|
+
return null;
|
|
511
|
+
const workDir = normalizeWorkDir(input.workDir);
|
|
512
|
+
const now = Date.now();
|
|
513
|
+
const existing = workDir
|
|
514
|
+
? db.prepare(`SELECT * FROM prompt_history WHERE work_dir = ? AND normalized_text = ?`)
|
|
515
|
+
.get(workDir, normalizedText.key)
|
|
516
|
+
: db.prepare(`SELECT * FROM prompt_history WHERE work_dir IS NULL AND normalized_text = ?`)
|
|
517
|
+
.get(normalizedText.key);
|
|
518
|
+
if (existing) {
|
|
519
|
+
db.prepare(`UPDATE prompt_history
|
|
520
|
+
SET text = ?, session_id = ?, message_id = ?, use_count = use_count + 1, last_used_at = ?
|
|
521
|
+
WHERE id = ?`).run(normalizedText.text, input.sessionId || null, input.messageId || null, now, existing.id);
|
|
522
|
+
return {
|
|
523
|
+
...existing,
|
|
524
|
+
text: normalizedText.text,
|
|
525
|
+
session_id: input.sessionId || null,
|
|
526
|
+
message_id: input.messageId || null,
|
|
527
|
+
use_count: existing.use_count + 1,
|
|
528
|
+
last_used_at: now,
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
const item = {
|
|
532
|
+
id: randomUUID(),
|
|
533
|
+
work_dir: workDir,
|
|
534
|
+
text: normalizedText.text,
|
|
535
|
+
normalized_text: normalizedText.key,
|
|
536
|
+
session_id: input.sessionId || null,
|
|
537
|
+
message_id: input.messageId || null,
|
|
538
|
+
use_count: 1,
|
|
539
|
+
last_used_at: now,
|
|
540
|
+
created_at: now,
|
|
541
|
+
};
|
|
542
|
+
db.prepare(`INSERT INTO prompt_history (id, work_dir, text, normalized_text, session_id, message_id, use_count, last_used_at, created_at)
|
|
543
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(item.id, item.work_dir || null, item.text, item.normalized_text, item.session_id || null, item.message_id || null, item.use_count, item.last_used_at, item.created_at);
|
|
544
|
+
return item;
|
|
545
|
+
}
|
|
546
|
+
export function getPromptHistory(options = {}) {
|
|
547
|
+
const limit = Math.max(1, Math.min(100, Math.floor(options.limit || 50)));
|
|
548
|
+
const workDir = normalizeWorkDir(options.workDir);
|
|
549
|
+
const query = normalizePromptHistoryText(options.query || '')?.key || '';
|
|
550
|
+
const like = `%${query}%`;
|
|
551
|
+
if (workDir && query) {
|
|
552
|
+
return db.prepare(`SELECT * FROM prompt_history
|
|
553
|
+
WHERE work_dir = ? AND normalized_text LIKE ?
|
|
554
|
+
ORDER BY last_used_at DESC
|
|
555
|
+
LIMIT ?`).all(workDir, like, limit);
|
|
556
|
+
}
|
|
557
|
+
if (workDir) {
|
|
558
|
+
return db.prepare(`SELECT * FROM prompt_history
|
|
559
|
+
WHERE work_dir = ?
|
|
560
|
+
ORDER BY last_used_at DESC
|
|
561
|
+
LIMIT ?`).all(workDir, limit);
|
|
562
|
+
}
|
|
563
|
+
if (query) {
|
|
564
|
+
return db.prepare(`SELECT * FROM prompt_history
|
|
565
|
+
WHERE normalized_text LIKE ?
|
|
566
|
+
ORDER BY last_used_at DESC
|
|
567
|
+
LIMIT ?`).all(like, limit);
|
|
568
|
+
}
|
|
569
|
+
return db.prepare(`SELECT * FROM prompt_history
|
|
570
|
+
ORDER BY last_used_at DESC
|
|
571
|
+
LIMIT ?`).all(limit);
|
|
572
|
+
}
|
|
573
|
+
export function deletePromptHistory(id, workDir) {
|
|
574
|
+
const normalizedWorkDir = normalizeWorkDir(workDir);
|
|
575
|
+
const result = normalizedWorkDir
|
|
576
|
+
? db.prepare(`DELETE FROM prompt_history WHERE id = ? AND work_dir = ?`).run(id, normalizedWorkDir)
|
|
577
|
+
: db.prepare(`DELETE FROM prompt_history WHERE id = ?`).run(id);
|
|
578
|
+
return result.changes > 0;
|
|
579
|
+
}
|
|
580
|
+
function backfillPromptHistoryFromMessages() {
|
|
581
|
+
const existing = db.prepare(`SELECT COUNT(*) AS count FROM prompt_history`).get();
|
|
582
|
+
if (existing.count > 0)
|
|
583
|
+
return;
|
|
584
|
+
const rows = db.prepare(`SELECT m.id AS message_id, m.session_id, m.content, s.cli_config
|
|
585
|
+
FROM messages m
|
|
586
|
+
LEFT JOIN sessions s ON s.id = m.session_id
|
|
587
|
+
WHERE m.type IN ('user_message', 'user') AND TRIM(m.content) != ''
|
|
588
|
+
ORDER BY m.seq ASC
|
|
589
|
+
LIMIT 10000`).all();
|
|
590
|
+
if (rows.length === 0)
|
|
591
|
+
return;
|
|
592
|
+
const backfill = db.transaction((items) => {
|
|
593
|
+
for (const item of items) {
|
|
594
|
+
recordPromptHistory({
|
|
595
|
+
text: item.content,
|
|
596
|
+
workDir: getWorkDirFromSessionConfig(item.cli_config),
|
|
597
|
+
sessionId: item.session_id,
|
|
598
|
+
messageId: item.message_id,
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
});
|
|
602
|
+
backfill(rows);
|
|
603
|
+
console.log(`[Store] Backfilled ${rows.length} user messages into prompt history`);
|
|
604
|
+
}
|
|
478
605
|
// --- Migration (from client localStorage) ---
|
|
479
606
|
export function importLocalData(messages, historyTasks, workDir) {
|
|
480
607
|
const current = getCurrentSession();
|
|
@@ -496,7 +623,18 @@ export function importLocalData(messages, historyTasks, workDir) {
|
|
|
496
623
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
497
624
|
const insertMany = db.transaction((msgs) => {
|
|
498
625
|
for (const msg of msgs) {
|
|
499
|
-
|
|
626
|
+
const id = String(msg.id || randomUUID());
|
|
627
|
+
const type = String(msg.type || 'system');
|
|
628
|
+
const content = String(msg.content || '');
|
|
629
|
+
insertStmt.run(id, type, content, String(msg.time || new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hourCycle: 'h23' })), msg.status || null, msg.toolName || null, msg.toolDetails || null, msg.permission ? JSON.stringify(msg.permission) : null, sessionId);
|
|
630
|
+
if (type === 'user_message' || type === 'user') {
|
|
631
|
+
recordPromptHistory({
|
|
632
|
+
text: content,
|
|
633
|
+
workDir: importWorkDir,
|
|
634
|
+
sessionId,
|
|
635
|
+
messageId: id,
|
|
636
|
+
});
|
|
637
|
+
}
|
|
500
638
|
}
|
|
501
639
|
});
|
|
502
640
|
insertMany(messages);
|
|
@@ -517,10 +655,76 @@ export function importLocalData(messages, historyTasks, workDir) {
|
|
|
517
655
|
}
|
|
518
656
|
console.log(`[Store] Imported ${messages.length} messages and ${historyTasks.length} history tasks`);
|
|
519
657
|
}
|
|
658
|
+
function jsonOrNull(value) {
|
|
659
|
+
if (value == null)
|
|
660
|
+
return null;
|
|
661
|
+
try {
|
|
662
|
+
return JSON.stringify(value);
|
|
663
|
+
}
|
|
664
|
+
catch {
|
|
665
|
+
return String(value);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
function textOrNull(value) {
|
|
669
|
+
if (value == null)
|
|
670
|
+
return null;
|
|
671
|
+
const text = String(value);
|
|
672
|
+
return text.length > 0 ? text : null;
|
|
673
|
+
}
|
|
674
|
+
function getImportedSessionTiming(session) {
|
|
675
|
+
const startedAt = Number.isFinite(session.startedAt) && session.startedAt > 0 ? session.startedAt : Date.now();
|
|
676
|
+
const endedAt = Number.isFinite(session.endedAt) && session.endedAt > 0 ? session.endedAt : startedAt;
|
|
677
|
+
const createdAt = Number.isFinite(session.createdAt) && session.createdAt > 0 ? session.createdAt : endedAt;
|
|
678
|
+
const diffSec = Math.max(0, Math.round((endedAt - startedAt) / 1000));
|
|
679
|
+
const duration = diffSec > 0
|
|
680
|
+
? diffSec >= 60
|
|
681
|
+
? `${Math.floor(diffSec / 60)}m ${String(diffSec % 60).padStart(2, '0')}s`
|
|
682
|
+
: `${diffSec}s`
|
|
683
|
+
: null;
|
|
684
|
+
return { startedAt, endedAt, createdAt, duration };
|
|
685
|
+
}
|
|
686
|
+
function importedMessageSignature(message) {
|
|
687
|
+
return [
|
|
688
|
+
message.type || '',
|
|
689
|
+
message.time || '',
|
|
690
|
+
message.toolUseId || '',
|
|
691
|
+
message.toolName || '',
|
|
692
|
+
message.content || '',
|
|
693
|
+
].join('\u001f');
|
|
694
|
+
}
|
|
695
|
+
function storedMessageSignature(message) {
|
|
696
|
+
return importedMessageSignature({
|
|
697
|
+
type: message.type,
|
|
698
|
+
content: message.content,
|
|
699
|
+
time: message.time,
|
|
700
|
+
toolName: message.toolName || undefined,
|
|
701
|
+
toolUseId: message.toolUseId || undefined,
|
|
702
|
+
});
|
|
703
|
+
}
|
|
704
|
+
function codexSpecialKeyFromDetails(details, type) {
|
|
705
|
+
if (type !== 'system')
|
|
706
|
+
return null;
|
|
707
|
+
const parsed = typeof details === 'string' ? parseConfig(details) : details;
|
|
708
|
+
if (!parsed || typeof parsed !== 'object')
|
|
709
|
+
return null;
|
|
710
|
+
const record = parsed;
|
|
711
|
+
const subtype = record.subtype;
|
|
712
|
+
const sessionId = record.session_id;
|
|
713
|
+
if ((subtype === 'init' || subtype === 'result') && typeof sessionId === 'string' && sessionId) {
|
|
714
|
+
return `${subtype}:${sessionId}`;
|
|
715
|
+
}
|
|
716
|
+
return null;
|
|
717
|
+
}
|
|
718
|
+
function putFirst(map, key, value) {
|
|
719
|
+
if (key == null || map.has(key))
|
|
720
|
+
return;
|
|
721
|
+
map.set(key, value);
|
|
722
|
+
}
|
|
520
723
|
export function importCodexSessions(sessions) {
|
|
521
724
|
const result = {
|
|
522
725
|
scanned: sessions.length,
|
|
523
726
|
imported: 0,
|
|
727
|
+
updated: 0,
|
|
524
728
|
skipped: 0,
|
|
525
729
|
failed: 0,
|
|
526
730
|
messagesImported: 0,
|
|
@@ -529,60 +733,198 @@ export function importCodexSessions(sessions) {
|
|
|
529
733
|
if (sessions.length === 0) {
|
|
530
734
|
return result;
|
|
531
735
|
}
|
|
532
|
-
const
|
|
533
|
-
const
|
|
736
|
+
const getSession = db.prepare(`SELECT * FROM sessions WHERE id = ?`);
|
|
737
|
+
const getTaskById = db.prepare(`SELECT * FROM history_tasks WHERE id = ?`);
|
|
738
|
+
const getTaskBySession = db.prepare(`SELECT * FROM history_tasks WHERE session_id = ? ORDER BY created_at DESC LIMIT 1`);
|
|
739
|
+
const getMessagesBySession = db.prepare(`SELECT * FROM messages WHERE session_id = ? ORDER BY seq ASC`);
|
|
534
740
|
const insertSession = db.prepare(`INSERT INTO sessions (id, status, cli_config, started_at, last_seq) VALUES (?, ?, ?, ?, 0)`);
|
|
741
|
+
const updateSession = db.prepare(`UPDATE sessions SET cli_config = ?, started_at = ? WHERE id = ?`);
|
|
535
742
|
const insertMessage = db.prepare(`INSERT INTO messages (id, type, content, time, status, toolName, toolDetails, toolUseId, toolResult, permission, details, session_id)
|
|
536
743
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
744
|
+
const updateMessage = db.prepare(`UPDATE messages
|
|
745
|
+
SET id = ?, type = ?, content = ?, time = ?, status = ?, toolName = ?, toolDetails = ?, toolUseId = ?, toolResult = ?, permission = ?, details = ?
|
|
746
|
+
WHERE seq = ?`);
|
|
747
|
+
const getMaxSeq = db.prepare(`SELECT MAX(seq) AS seq FROM messages WHERE session_id = ?`);
|
|
537
748
|
const updateLastSeq = db.prepare(`UPDATE sessions SET last_seq = ? WHERE id = ?`);
|
|
538
749
|
const insertTask = db.prepare(`INSERT INTO history_tasks (id, session_id, work_dir, status, title, confirm_count, tool_count, duration, start_time, end_time, created_at)
|
|
539
750
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
751
|
+
const updateTask = db.prepare(`UPDATE history_tasks
|
|
752
|
+
SET session_id = ?, work_dir = ?, status = ?, title = ?, confirm_count = ?, tool_count = ?, duration = ?, start_time = ?, end_time = ?, created_at = ?
|
|
753
|
+
WHERE id = ?`);
|
|
540
754
|
const importOne = db.transaction((session) => {
|
|
541
755
|
const workDir = normalizeWorkDir(session.workDir);
|
|
542
756
|
const messages = session.messages || [];
|
|
543
757
|
const confirmCount = messages.filter(m => m.type === 'confirm_request' || m.type === 'confirm').length;
|
|
544
758
|
const toolCount = messages.filter(m => m.type === 'tool_call' || m.type === 'tool').length;
|
|
545
|
-
const
|
|
546
|
-
const
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
759
|
+
const { startedAt, endedAt, createdAt, duration } = getImportedSessionTiming(session);
|
|
760
|
+
const existingSession = getSession.get(session.sessionId);
|
|
761
|
+
const createdSession = !existingSession;
|
|
762
|
+
let changed = false;
|
|
763
|
+
if (existingSession) {
|
|
764
|
+
const mergedConfig = { ...parseConfig(existingSession.cli_config), ...(session.cliConfig || {}) };
|
|
765
|
+
const nextConfig = JSON.stringify(mergedConfig);
|
|
766
|
+
const nextStartedAt = existingSession.started_at > 0 ? Math.min(existingSession.started_at, startedAt) : startedAt;
|
|
767
|
+
if ((existingSession.cli_config || null) !== nextConfig || existingSession.started_at !== nextStartedAt) {
|
|
768
|
+
updateSession.run(nextConfig, nextStartedAt, session.sessionId);
|
|
769
|
+
changed = true;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
else {
|
|
773
|
+
insertSession.run(session.sessionId, 'archived', JSON.stringify(session.cliConfig || {}), startedAt);
|
|
774
|
+
changed = true;
|
|
775
|
+
}
|
|
776
|
+
const existingMessages = getMessagesBySession.all(session.sessionId);
|
|
777
|
+
const byId = new Map();
|
|
778
|
+
const bySpecial = new Map();
|
|
779
|
+
const byToolUseId = new Map();
|
|
780
|
+
const bySignature = new Map();
|
|
781
|
+
const rememberMessage = (message) => {
|
|
782
|
+
putFirst(byId, message.id, message);
|
|
783
|
+
putFirst(bySpecial, codexSpecialKeyFromDetails(message.details, message.type), message);
|
|
784
|
+
if (message.type === 'tool_call' || message.type === 'tool') {
|
|
785
|
+
putFirst(byToolUseId, message.toolUseId, message);
|
|
786
|
+
}
|
|
787
|
+
putFirst(bySignature, storedMessageSignature(message), message);
|
|
788
|
+
};
|
|
789
|
+
for (const message of existingMessages)
|
|
790
|
+
rememberMessage(message);
|
|
791
|
+
let insertedMessages = 0;
|
|
792
|
+
let updatedMessages = 0;
|
|
556
793
|
for (const message of messages) {
|
|
557
|
-
|
|
558
|
-
|
|
794
|
+
if (!message.id || !message.type)
|
|
795
|
+
continue;
|
|
796
|
+
const next = {
|
|
797
|
+
id: message.id,
|
|
798
|
+
type: message.type,
|
|
799
|
+
content: message.content || '',
|
|
800
|
+
time: message.time || '',
|
|
801
|
+
status: textOrNull(message.status),
|
|
802
|
+
toolName: textOrNull(message.toolName),
|
|
803
|
+
toolDetails: textOrNull(message.toolDetails),
|
|
804
|
+
toolUseId: textOrNull(message.toolUseId),
|
|
805
|
+
toolResult: textOrNull(message.toolResult),
|
|
806
|
+
permission: jsonOrNull(message.permission),
|
|
807
|
+
details: jsonOrNull(message.details),
|
|
808
|
+
};
|
|
809
|
+
const specialKey = codexSpecialKeyFromDetails(message.details, message.type);
|
|
810
|
+
const signature = importedMessageSignature(message);
|
|
811
|
+
const existing = byId.get(next.id)
|
|
812
|
+
|| (next.toolUseId && (next.type === 'tool_call' || next.type === 'tool') ? byToolUseId.get(next.toolUseId) : undefined)
|
|
813
|
+
|| (specialKey ? bySpecial.get(specialKey) : undefined)
|
|
814
|
+
|| bySignature.get(signature);
|
|
815
|
+
if (existing) {
|
|
816
|
+
const differs = existing.id !== next.id
|
|
817
|
+
|| existing.type !== next.type
|
|
818
|
+
|| existing.content !== next.content
|
|
819
|
+
|| existing.time !== next.time
|
|
820
|
+
|| (existing.status || null) !== next.status
|
|
821
|
+
|| (existing.toolName || null) !== next.toolName
|
|
822
|
+
|| (existing.toolDetails || null) !== next.toolDetails
|
|
823
|
+
|| (existing.toolUseId || null) !== next.toolUseId
|
|
824
|
+
|| (existing.toolResult || null) !== next.toolResult
|
|
825
|
+
|| (existing.permission || null) !== next.permission
|
|
826
|
+
|| (existing.details || null) !== next.details;
|
|
827
|
+
if (differs) {
|
|
828
|
+
updateMessage.run(next.id, next.type, next.content, next.time, next.status, next.toolName, next.toolDetails, next.toolUseId, next.toolResult, next.permission, next.details, existing.seq);
|
|
829
|
+
updatedMessages += 1;
|
|
830
|
+
changed = true;
|
|
831
|
+
rememberMessage({
|
|
832
|
+
...existing,
|
|
833
|
+
...next,
|
|
834
|
+
status: next.status || undefined,
|
|
835
|
+
toolName: next.toolName || undefined,
|
|
836
|
+
toolDetails: next.toolDetails || undefined,
|
|
837
|
+
toolUseId: next.toolUseId || undefined,
|
|
838
|
+
toolResult: next.toolResult || undefined,
|
|
839
|
+
permission: next.permission || undefined,
|
|
840
|
+
details: next.details || undefined,
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
continue;
|
|
844
|
+
}
|
|
845
|
+
const inserted = insertMessage.run(next.id, next.type, next.content, next.time, next.status, next.toolName, next.toolDetails, next.toolUseId, next.toolResult, next.permission, next.details, session.sessionId);
|
|
846
|
+
insertedMessages += 1;
|
|
847
|
+
changed = true;
|
|
848
|
+
if (next.type === 'user_message' || next.type === 'user') {
|
|
849
|
+
recordPromptHistory({
|
|
850
|
+
text: next.content,
|
|
851
|
+
workDir,
|
|
852
|
+
sessionId: session.sessionId,
|
|
853
|
+
messageId: next.id,
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
rememberMessage({
|
|
857
|
+
seq: Number(inserted.lastInsertRowid),
|
|
858
|
+
id: next.id,
|
|
859
|
+
type: next.type,
|
|
860
|
+
content: next.content,
|
|
861
|
+
time: next.time,
|
|
862
|
+
status: next.status || undefined,
|
|
863
|
+
toolName: next.toolName || undefined,
|
|
864
|
+
toolDetails: next.toolDetails || undefined,
|
|
865
|
+
toolUseId: next.toolUseId || undefined,
|
|
866
|
+
toolResult: next.toolResult || undefined,
|
|
867
|
+
permission: next.permission || undefined,
|
|
868
|
+
details: next.details || undefined,
|
|
869
|
+
session_id: session.sessionId,
|
|
870
|
+
});
|
|
871
|
+
}
|
|
872
|
+
if (insertedMessages > 0 || updatedMessages > 0) {
|
|
873
|
+
const row = getMaxSeq.get(session.sessionId);
|
|
874
|
+
if (row?.seq)
|
|
875
|
+
updateLastSeq.run(row.seq, session.sessionId);
|
|
876
|
+
}
|
|
877
|
+
const refreshedSession = (existingSession ? getSession.get(session.sessionId) : null);
|
|
878
|
+
const isActiveSession = (refreshedSession || existingSession)?.status !== 'archived' && !!(refreshedSession || existingSession);
|
|
879
|
+
const existingTask = (getTaskById.get(session.taskId) || getTaskBySession.get(session.sessionId));
|
|
880
|
+
const taskStatus = session.status || 'completed';
|
|
881
|
+
const taskTitle = session.title || 'Codex 会话记录';
|
|
882
|
+
if (existingTask) {
|
|
883
|
+
const taskDiffers = existingTask.session_id !== session.sessionId
|
|
884
|
+
|| (existingTask.work_dir || null) !== (workDir || null)
|
|
885
|
+
|| existingTask.status !== taskStatus
|
|
886
|
+
|| existingTask.title !== taskTitle
|
|
887
|
+
|| existingTask.confirm_count !== confirmCount
|
|
888
|
+
|| existingTask.tool_count !== toolCount
|
|
889
|
+
|| (existingTask.duration || null) !== duration
|
|
890
|
+
|| existingTask.start_time !== startedAt
|
|
891
|
+
|| existingTask.end_time !== endedAt
|
|
892
|
+
|| existingTask.created_at !== createdAt;
|
|
893
|
+
if (taskDiffers) {
|
|
894
|
+
updateTask.run(session.sessionId, workDir, taskStatus, taskTitle, confirmCount, toolCount, duration, startedAt, endedAt, createdAt, existingTask.id);
|
|
895
|
+
changed = true;
|
|
896
|
+
}
|
|
559
897
|
}
|
|
560
|
-
if (
|
|
561
|
-
|
|
898
|
+
else if (!isActiveSession) {
|
|
899
|
+
insertTask.run(session.taskId, session.sessionId, workDir, taskStatus, taskTitle, confirmCount, toolCount, duration, startedAt, endedAt, createdAt);
|
|
900
|
+
changed = true;
|
|
562
901
|
}
|
|
563
|
-
|
|
564
|
-
return messages.length;
|
|
902
|
+
return { createdSession, changed, insertedMessages };
|
|
565
903
|
});
|
|
566
904
|
for (const session of sessions) {
|
|
567
905
|
try {
|
|
568
|
-
if (!session.sessionId || !session.taskId || session.messages.length === 0) {
|
|
906
|
+
if (!session.sessionId || !session.taskId || !session.messages || session.messages.length === 0) {
|
|
569
907
|
result.skipped += 1;
|
|
570
908
|
continue;
|
|
571
909
|
}
|
|
572
|
-
|
|
910
|
+
const imported = importOne(session);
|
|
911
|
+
if (imported.createdSession) {
|
|
912
|
+
result.imported += 1;
|
|
913
|
+
}
|
|
914
|
+
else if (imported.changed) {
|
|
915
|
+
result.updated += 1;
|
|
916
|
+
}
|
|
917
|
+
else {
|
|
573
918
|
result.skipped += 1;
|
|
574
|
-
continue;
|
|
575
919
|
}
|
|
576
|
-
|
|
577
|
-
result.imported += 1;
|
|
578
|
-
result.messagesImported += importedMessages;
|
|
920
|
+
result.messagesImported += imported.insertedMessages;
|
|
579
921
|
}
|
|
580
922
|
catch (err) {
|
|
581
923
|
result.failed += 1;
|
|
582
924
|
result.errors.push(`${session.sessionId || 'unknown'}: ${err?.message || 'import failed'}`);
|
|
583
925
|
}
|
|
584
926
|
}
|
|
585
|
-
console.log(`[Store] Synced Codex history: imported=${result.imported}, skipped=${result.skipped}, failed=${result.failed}`);
|
|
927
|
+
console.log(`[Store] Synced Codex history: imported=${result.imported}, updated=${result.updated}, skipped=${result.skipped}, failed=${result.failed}`);
|
|
586
928
|
return result;
|
|
587
929
|
}
|
|
588
930
|
// --- Cleanup ---
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cli-link",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"cli-link": "bin/agentpilot.js"
|
|
@@ -62,10 +62,10 @@
|
|
|
62
62
|
"react-dom": "18.2.0",
|
|
63
63
|
"react-markdown": "^9.0.1",
|
|
64
64
|
"react-router-dom": "6.23.0",
|
|
65
|
-
"rehype-highlight": "^7.0.2",
|
|
66
65
|
"remark-gfm": "^4.0.0",
|
|
67
|
-
"
|
|
66
|
+
"shiki": "^4.2.0",
|
|
68
67
|
"tailwind-merge": "2.3.0",
|
|
68
|
+
"tailwindcss": "^3.4.3",
|
|
69
69
|
"tsx": "^4.7.0",
|
|
70
70
|
"typescript": "^5.4.0",
|
|
71
71
|
"vite": "^5.2.0"
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{u as oe,h as xe,r as m,j as e}from"./vendor-react-DSV5aFEg.js";import{u as ce,s as N,g as me,c as g}from"./index-DOgH1Kf3.js";import{g as ue,M as C,W as ge}from"./WorkspaceLinkedText-DQyPLk-X.js";import{P as pe}from"./PageTopBar-C8j-5s_3.js";import{C as ye,X as K,L as O,j as he,g as L,q as H,r as R,s as fe,B as be,m as _,n as D,c as F,o as je,p as ke}from"./vendor-icons-CNN4EKVi.js";import{A as Ne,m as q}from"./vendor-motion-n6Lx6G4a.js";function G(r){if(/^```/.test(r.trim()))return r;try{const s=JSON.parse(r);return"```json\n"+JSON.stringify(s,null,2)+"\n```"}catch{}return r.split(`
|
|
2
|
-
`).map(s=>{const n=s.trim();if(!n)return s;try{const i=JSON.parse(n);return"```json\n"+JSON.stringify(i,null,2)+"\n```"}catch{return s}}).join(`
|
|
3
|
-
`)}function V(r){const l=Date.now()-r,s=Math.floor(l/6e4);if(s<1)return"刚刚";if(s<60)return`${s}分钟前`;const n=Math.floor(s/60);if(n<24)return`${n}小时前`;const i=Math.floor(n/24);return i===1?"昨天":i<7?`${i}天前`:new Date(r).toLocaleDateString("zh-CN",{month:"short",day:"numeric"})}function we(r){return r.split(/[\\/]/).filter(Boolean).pop()||r}const ze=()=>{var A;const r=oe(),{cliConfig:t}=ce(),[l,s]=xe(),n=l.get("filter")||"all",i=l.get("detail"),[c,p]=m.useState([]),[d,u]=m.useState(!0),[b,h]=m.useState(""),[j,$]=m.useState(null),[I,k]=m.useState(""),[re,B]=m.useState(null),[P,w]=m.useState(""),v=m.useRef(null),T=m.useCallback(async()=>{try{const a=await N.fetchHistory();p(x=>a.map(y=>{const f=x.find(de=>de.id===y.id);return f!=null&&f.messagesLoaded?{...y,messagesLoaded:!0,messages:f.messages}:y}))}catch(a){console.error("[History] Failed to fetch:",a)}finally{u(!1)}},[]);m.useEffect(()=>{T()},[T]),m.useEffect(()=>{h(""),k(""),$(null),w(""),v.current=null},[i]),m.useEffect(()=>{const x=me().onMessage(y=>{y.type==="history_changed"&&T()});return()=>{x()}},[T]);const U=c.filter(a=>n==="all"?!0:n==="running"?a.status==="running"||a.status==="confirm":a.status===n),o=c.find(a=>a.id===i),W=o!=null&&o.messagesLoaded?ue(o.messages):[],M=(t==null?void 0:t.workDir)||((A=c.find(a=>a.workDir))==null?void 0:A.workDir)||"",te=M?we(M):"未选择工作目录";m.useEffect(()=>{if(!i||!o||o.messagesLoaded||v.current===i)return;let a=!1;return v.current=i,B(i),w(""),N.fetchHistoryTask(i).then(x=>{if(!a){if(!x){w("会话记录不存在或已被删除");return}p(y=>y.map(f=>f.id===x.id?x:f))}}).catch(x=>{a||(console.error("[History] Failed to fetch detail:",x),w(x instanceof Error?x.message:"加载会话记录失败"))}).finally(()=>{a||(B(null),v.current=null)}),()=>{a=!0}},[i,o==null?void 0:o.id,o==null?void 0:o.messagesLoaded]);const ae=a=>{s(x=>(x.set("filter",a),x.delete("detail"),x))},se=a=>{s(x=>(x.set("detail",a),x))},S=()=>{s(a=>(a.delete("detail"),a))},ne=async(a,x)=>{x.stopPropagation();try{await N.deleteHistoryTask(a),p(y=>y.filter(f=>f.id!==a)),i===a&&S()}catch(y){console.error("[History] Failed to delete:",y)}},le=async()=>{try{await N.clearHistory(),p([])}catch(a){console.error("[History] Failed to clear:",a)}},z=async()=>{if(!o||j)return;const a=b.trim();if(a){if(!o.canResume){k("该会话记录缺少可恢复的 CLI 会话 ID,无法继续追问");return}$(o.id),k("");try{await N.resumeHistoryTask(o.id,a),h(""),r("/session")}catch(x){k(x instanceof Error?x.message:"恢复会话记录失败")}finally{$(null)}}},ie=[{id:"all",label:"全部",count:c.length},{id:"running",label:"进行中",count:c.filter(a=>a.status==="running"||a.status==="confirm").length},{id:"completed",label:"已完成",count:c.filter(a=>a.status==="completed").length},{id:"failed",label:"失败",count:c.filter(a=>a.status==="failed").length}];return e.jsxs("div",{className:"flex flex-col h-full bg-gray-50 dark:bg-gray-950 relative",children:[e.jsx(pe,{title:"会话记录",meta:e.jsx("span",{className:"text-[10px] text-gray-500 dark:text-gray-400 truncate max-w-[120px] flex-shrink-0",title:M,children:te}),actions:c.length>0?e.jsx("button",{onClick:le,className:"text-xs text-gray-400 hover:text-red-500 transition-colors flex-shrink-0",children:"清空"}):void 0,bottom:e.jsx("div",{className:"flex px-2 overflow-x-auto hide-scrollbar",children:ie.map(a=>e.jsxs("button",{onClick:()=>ae(a.id),className:g("flex items-center gap-1.5 px-4 py-2.5 border-b-2 text-sm font-medium whitespace-nowrap transition-colors",n===a.id?"border-primary-600 text-primary-600 dark:text-primary-400":"border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300"),children:[a.label,e.jsx("span",{className:g("text-[10px] px-1.5 py-0.5 rounded-full",n===a.id?"bg-primary-100 text-primary-700 dark:bg-primary-900 dark:text-primary-300":"bg-gray-100 text-gray-500 dark:bg-gray-800 dark:text-gray-400"),children:a.count})]},a.id))})}),e.jsx("div",{className:"flex-1 overflow-y-auto p-4 space-y-3",children:U.length>0?U.map(a=>e.jsx(Re,{task:a,onClick:()=>se(a.id),onDelete:x=>ne(a.id,x)},a.id)):e.jsxs("div",{className:"flex flex-col items-center justify-center h-full text-gray-400 dark:text-gray-600 gap-3",children:[e.jsx(ye,{className:"w-12 h-12 opacity-20"}),e.jsx("p",{className:"text-sm",children:"暂无相关会话"})]})}),e.jsx(Ne,{children:i&&o&&e.jsxs(e.Fragment,{children:[e.jsx(q.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},onClick:S,className:"absolute inset-0 bg-black/40 z-40"}),e.jsxs(q.div,{initial:{y:"100%"},animate:{y:0},exit:{y:"100%"},transition:{type:"spring",damping:25,stiffness:200},className:"absolute bottom-0 left-0 right-0 h-[85%] bg-white dark:bg-gray-900 rounded-t-2xl z-50 flex flex-col shadow-xl",children:[e.jsx("div",{className:"flex justify-center pt-3 pb-2 flex-shrink-0",onClick:S,children:e.jsx("div",{className:"w-12 h-1.5 bg-gray-300 dark:bg-gray-600 rounded-full"})}),e.jsxs("div",{className:"px-5 pb-4 border-b border-gray-100 dark:border-gray-800 flex-shrink-0",children:[e.jsxs("div",{className:"flex justify-between items-start gap-4 mb-3",children:[e.jsx("h2",{className:"text-base font-medium text-gray-900 dark:text-gray-100 leading-snug",children:o.title}),e.jsx("button",{onClick:S,className:"p-1 text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-full flex-shrink-0",children:e.jsx(K,{className:"w-5 h-5"})})]}),e.jsxs("div",{className:"flex items-center gap-3 text-sm",children:[e.jsx(ee,{status:o.status}),o.duration&&e.jsxs("span",{className:"text-gray-500 dark:text-gray-400",children:["耗时 ",o.duration]}),e.jsx("span",{className:"text-gray-400 dark:text-gray-500",children:V(o.startTime)})]})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-5 bg-gray-50 dark:bg-gray-950",children:[e.jsx("div",{className:"text-center text-xs text-gray-400 dark:text-gray-600 mb-4",children:"完整消息流"}),re===o.id?e.jsxs("div",{className:"flex flex-col items-center justify-center mt-10 gap-2 text-gray-400 dark:text-gray-600",children:[e.jsx(O,{className:"w-5 h-5 animate-spin"}),e.jsx("div",{className:"text-sm",children:"正在加载会话详情"})]}):P?e.jsx("div",{className:"text-center text-sm text-red-500 dark:text-red-400 mt-8",children:P}):W.length>0?e.jsx("div",{className:"space-y-4",children:W.map(a=>e.jsx(ve,{message:a},a.id))}):o.messagesLoaded?e.jsx("div",{className:"text-center text-sm text-gray-400 dark:text-gray-600 mt-8",children:"无消息记录"}):e.jsx("div",{className:"text-center text-sm text-gray-400 dark:text-gray-600 mt-8",children:"点击后加载消息记录"})]}),e.jsx("div",{className:"border-t border-gray-100 dark:border-gray-800 bg-white dark:bg-gray-900 p-3 pb-safe flex-shrink-0",children:o.canResume?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-end gap-2",children:[e.jsx("textarea",{value:b,onChange:a=>{h(a.target.value),k(""),a.currentTarget.style.height="auto",a.currentTarget.style.height=`${Math.min(a.currentTarget.scrollHeight,96)}px`},onKeyDown:a=>{a.key==="Enter"&&(a.metaKey||a.ctrlKey)&&(a.preventDefault(),z())},placeholder:"基于这段会话继续追问…",rows:1,disabled:j===o.id,className:"flex-1 min-h-[42px] max-h-24 resize-none rounded-2xl border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800 px-4 py-2.5 text-sm text-gray-800 dark:text-gray-200 placeholder:text-gray-400 dark:placeholder:text-gray-600 outline-none focus:border-primary-400 focus:bg-white dark:focus:bg-gray-800 focus:ring-[3px] focus:ring-primary-100 dark:focus:ring-primary-900 hide-scrollbar"}),e.jsx("button",{type:"button",onClick:z,disabled:!b.trim()||j===o.id,className:g("p-2.5 rounded-full flex-shrink-0 transition-all duration-200 shadow-sm active:scale-95",b.trim()&&j!==o.id?"bg-primary-600 text-white hover:bg-primary-700":"bg-gray-200 dark:bg-gray-700 text-gray-400 dark:text-gray-500 shadow-none"),title:"继续追问",children:j===o.id?e.jsx(O,{className:"w-4 h-4 animate-spin"}):e.jsx(he,{className:"w-4 h-4"})})]}),I&&e.jsx("div",{className:"mt-2 text-xs text-red-500 dark:text-red-400 px-1",children:I})]}):e.jsx("div",{className:"rounded-xl border border-gray-200 dark:border-gray-800 bg-gray-50 dark:bg-gray-950 px-3 py-2 text-xs text-gray-500 dark:text-gray-400",children:"该会话记录缺少底层 CLI 会话 ID,无法继续追问。"})})]})]})})]})},ve=({message:r})=>{switch(r.type){case"system_group":return e.jsx(Ee,{group:r});case"tool_group":return e.jsx(Me,{group:r});case"user":return e.jsx("div",{className:"flex justify-end",children:e.jsx("div",{className:"bg-primary-600 text-white rounded-2xl rounded-tr-sm px-4 py-2.5 max-w-[85%] shadow-sm",children:e.jsx("p",{className:"text-[15px] leading-relaxed whitespace-pre-wrap",children:e.jsx(ge,{linkClassName:"text-white decoration-white/70",children:r.content})})})});case"ai":return e.jsx("div",{className:"flex justify-start",children:e.jsx("div",{className:"bg-white dark:bg-gray-800 border border-gray-100 dark:border-gray-700 text-gray-800 dark:text-gray-200 rounded-2xl rounded-tl-md px-3.5 py-3 max-w-[88%] shadow-sm markdown-body overflow-hidden min-w-0",children:e.jsx(C,{children:r.content})})});case"tool":return e.jsx($e,{message:r});case"confirm":return e.jsx("div",{className:"flex justify-start",children:e.jsxs("div",{className:g("border rounded-xl px-4 py-2.5 max-w-[85%] shadow-sm",r.status==="approved"?"bg-green-50 dark:bg-green-950 border-green-200 dark:border-green-800":"bg-red-50 dark:bg-red-950 border-red-200 dark:border-red-800"),children:[e.jsxs("div",{className:"flex items-center gap-1.5 mb-1",children:[r.status==="approved"?e.jsx(R,{className:"w-3.5 h-3.5 text-green-600"}):e.jsx(H,{className:"w-3.5 h-3.5 text-red-600"}),e.jsx("span",{className:g("text-xs font-medium",r.status==="approved"?"text-green-700 dark:text-green-400":"text-red-700 dark:text-red-400"),children:r.status==="approved"?"已批准":"已拒绝"})]}),e.jsx("p",{className:"text-sm text-gray-700 dark:text-gray-300",children:r.content})]})});case"system":{const t=r.details;if(t&&Object.keys(t).length>0){const l=t.subtype==="result",s=[];if(t.model&&s.push({label:"模型",value:t.model}),t.costUsd!=null&&s.push({label:"费用",value:`$${Number(t.costUsd).toFixed(4)}`}),t.durationMs!=null){const n=Math.round(Number(t.durationMs)/1e3);s.push({label:"耗时",value:n>=60?`${Math.floor(n/60)}m${n%60}s`:`${n}s`})}return t.numTurns!=null&&s.push({label:"轮次",value:String(t.numTurns)}),e.jsx("div",{className:"flex justify-start",children:e.jsxs("div",{className:`px-3 py-2 rounded-xl border max-w-[85%] ${l?"bg-green-50/80 dark:bg-green-950/40 border-green-200/60 dark:border-green-800/40":"bg-gray-50 dark:bg-gray-800/80 border-gray-200 dark:border-gray-700"}`,children:[e.jsxs("div",{className:"flex items-center gap-1.5 mb-1",children:[e.jsx("span",{className:`text-xs font-medium ${l?"text-green-700 dark:text-green-300":"text-gray-500 dark:text-gray-400"}`,children:r.content}),e.jsx("span",{className:"text-[10px] text-gray-400 dark:text-gray-500",children:r.time})]}),s.length>0&&e.jsx("div",{className:"flex flex-wrap gap-1.5",children:s.map((n,i)=>e.jsxs("span",{className:"inline-flex items-center gap-1 text-[10px] px-1.5 py-0.5 rounded-full font-medium bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300",children:[e.jsx("span",{className:"opacity-60",children:n.label}),e.jsx("span",{className:"font-semibold",children:n.value})]},i))})]})})}return e.jsx("div",{className:"flex justify-start",children:e.jsx("span",{className:"text-xs text-gray-400 dark:text-gray-600 bg-gray-100 dark:bg-gray-800 px-2 py-1 rounded-full",children:r.content})})}case"thinking":return e.jsx(Le,{message:r});case"error":return e.jsx("div",{className:"flex justify-start",children:e.jsxs("div",{className:"bg-red-50 dark:bg-red-950 border border-red-100 dark:border-red-800 text-red-800 dark:text-red-300 rounded-xl px-4 py-2.5 max-w-[85%] shadow-sm flex items-start gap-2",children:[e.jsx(H,{className:"w-4 h-4 mt-0.5 flex-shrink-0"}),e.jsx("p",{className:"text-sm leading-relaxed",children:r.content})]})});default:return null}};function Te(r){const t=(r.toolName||r.content||"").toLowerCase();return["readfile","writefile","read","write","edit","multiedit"].includes(t)}function E(r){return r.toolName&&r.toolName!=="result"?r.toolName:r.content||"tool"}function Se(r){return X(r).join("、")||"工具调用"}function X(r){return Array.from(new Set(r.map(E).filter(Boolean)))}function Ce(r){if(r.some(t=>t.status==="failed"))return"failed";if(r.some(t=>t.status==="running"))return"running";if(r.some(t=>t.status==="success"))return"success"}function He(r){const t=r.filter(i=>i.status==="running").length,l=r.filter(i=>i.status==="failed").length,s=r.filter(i=>i.status==="success").length,n=[`${r.length} 个`];return t&&n.push(`${t} 运行中`),l&&n.push(`${l} 失败`),s&&!t&&!l&&n.push("已完成"),n.join(" · ")}function Q(r,t="w-4 h-4 text-primary-600 dark:text-primary-400"){return Te(r)?e.jsx(je,{className:t}):e.jsx(F,{className:t})}function Y({status:r,className:t="w-3.5 h-3.5"}){return r==="running"?e.jsx(ke,{className:g(t,"text-primary-500 animate-pulse")}):r==="success"?e.jsx(R,{className:g(t,"text-green-600")}):r==="failed"?e.jsx(H,{className:g(t,"text-red-600")}):null}function De({status:r}){return e.jsx("span",{className:g("w-1.5 h-1.5 rounded-full flex-shrink-0",r==="running"?"bg-primary-500 animate-pulse":r==="failed"?"bg-red-500":r==="success"?"bg-green-500":"bg-gray-300 dark:bg-gray-600")})}const Z=({message:r,compact:t=!1})=>{const l="max-h-32";return e.jsxs(e.Fragment,{children:[r.toolDetails&&e.jsxs("div",{children:[e.jsx("div",{className:"text-[10px] font-medium text-primary-600 dark:text-primary-400 uppercase tracking-wider mb-0.5",children:"输入"}),e.jsx("div",{className:g("text-xs text-gray-600 dark:text-gray-400 bg-white/50 dark:bg-gray-900/50 p-2 rounded-lg border border-primary-50 dark:border-gray-700 overflow-y-auto",l),children:e.jsx(C,{children:G(r.toolDetails)})})]}),r.toolResult&&e.jsxs("div",{children:[e.jsx("div",{className:"text-[10px] font-medium text-primary-600 dark:text-primary-400 uppercase tracking-wider mb-0.5",children:"输出"}),e.jsx("div",{className:g("text-xs p-2 rounded-lg overflow-y-auto",l,r.status==="failed"?"text-red-700 dark:text-red-300 bg-red-50/50 dark:bg-red-950/50 border border-red-100 dark:border-red-900":"text-gray-600 dark:text-gray-400 bg-white/50 dark:bg-gray-900/50 border border-primary-50 dark:border-gray-700"),children:e.jsx(C,{children:G(r.toolResult)})})]})]})},$e=({message:r})=>e.jsx("div",{className:"flex justify-start",children:e.jsxs("div",{className:"bg-primary-50 dark:bg-primary-950 border border-primary-100 dark:border-primary-900 rounded-xl px-3 py-2 max-w-[85%] flex flex-col gap-1.5",children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[Q(r),e.jsx("span",{className:"text-sm text-primary-800 dark:text-primary-300 break-words min-w-0",children:r.content}),e.jsx("span",{className:"ml-auto flex-shrink-0",children:e.jsx(Y,{status:r.status})})]}),e.jsx(Z,{message:r})]})}),Me=({group:r})=>{const[t,l]=m.useState(!1),[s,n]=m.useState({}),i=Ce(r.messages),c=Se(r.messages),p=m.useCallback(d=>{n(u=>({...u,[d]:!u[d]}))},[]);return e.jsx("div",{className:"flex justify-start",children:e.jsxs("div",{className:"max-w-[85%] rounded-xl border border-primary-100 dark:border-gray-700 bg-primary-50/90 dark:bg-gray-800 overflow-hidden",children:[e.jsxs("button",{type:"button",onClick:()=>l(!t),className:"w-full px-3 py-2 flex items-center gap-2 text-left min-w-0 hover:bg-primary-100/60 dark:hover:bg-gray-700 transition-colors",children:[t?e.jsx(D,{className:"w-3.5 h-3.5 text-primary-500 flex-shrink-0"}):e.jsx(L,{className:"w-3.5 h-3.5 text-primary-500 flex-shrink-0"}),e.jsx(F,{className:"w-3.5 h-3.5 text-primary-600 dark:text-primary-400 flex-shrink-0"}),e.jsx("span",{className:"text-xs font-semibold text-primary-800 dark:text-primary-300 flex-shrink-0",children:"工具调用"}),e.jsx("span",{className:g("text-[10px] px-1.5 py-0.5 rounded-full flex-shrink-0",i==="failed"?"bg-red-100 text-red-700 dark:bg-red-950 dark:text-red-300":i==="running"?"bg-primary-100 text-primary-700 dark:bg-primary-950 dark:text-primary-300":"bg-green-100 text-green-700 dark:bg-green-950 dark:text-green-300"),children:He(r.messages)}),e.jsx("span",{className:"text-[10px] text-gray-400 dark:text-gray-500 flex-shrink-0",children:r.time}),e.jsx("span",{className:"min-w-0 truncate text-xs text-gray-600 dark:text-gray-400",title:c,children:c})]}),!t&&e.jsx("div",{className:"px-3 pb-2 flex flex-wrap gap-1.5",children:X(r.messages).map(d=>{const u=r.messages.find(b=>E(b)===d);return e.jsxs("span",{className:"inline-flex max-w-full min-w-0 items-center gap-1.5 text-[10px] px-1.5 py-0.5 rounded-full bg-white/70 dark:bg-gray-900/50 text-gray-600 dark:text-gray-300 border border-primary-100/60 dark:border-gray-700",title:d,children:[e.jsx(De,{status:u==null?void 0:u.status}),e.jsx("span",{className:"truncate text-left",children:d})]},d)})}),t&&e.jsx("div",{className:"border-t border-primary-100/80 dark:border-gray-700 divide-y divide-primary-100/70 dark:divide-gray-700",children:r.messages.map(d=>{const u=E(d),b=d.content&&d.content!==u,h=!!(d.toolDetails||d.toolResult),j=!!s[d.id];return e.jsxs("div",{className:"px-3 py-2 flex flex-col gap-1.5 min-w-0",children:[e.jsxs("button",{type:"button",onClick:()=>h&&p(d.id),className:g("w-full flex flex-col gap-1 min-w-0 text-left",h&&"cursor-pointer hover:text-primary-900 dark:hover:text-primary-200"),children:[e.jsxs("div",{className:"w-full flex items-start gap-2 min-w-0",children:[Q(d,"w-3.5 h-3.5 text-primary-600 dark:text-primary-400 flex-shrink-0 mt-0.5"),e.jsx("span",{className:"min-w-0 flex-1 truncate text-xs font-semibold text-primary-800 dark:text-primary-300",title:u,children:u}),e.jsxs("span",{className:"ml-auto flex items-center gap-1.5 flex-shrink-0",children:[e.jsx("span",{className:"text-[10px] text-gray-400 dark:text-gray-500 flex-shrink-0",children:d.time}),h&&e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded-full bg-white/70 dark:bg-gray-900/50 text-gray-500 dark:text-gray-400 border border-primary-100/60 dark:border-gray-700",children:d.toolDetails&&d.toolResult?"输入/输出":d.toolDetails?"输入":"输出"}),e.jsx(Y,{status:d.status,className:"w-3 h-3"}),h&&(j?e.jsx(_,{className:"w-3 h-3 text-primary-500"}):e.jsx(D,{className:"w-3 h-3 text-primary-500"}))]})]}),b&&e.jsx("span",{className:"w-full pl-5 pr-1 text-xs text-gray-500 dark:text-gray-400 truncate min-w-0",children:d.content})]}),h&&j&&e.jsx(Z,{message:d,compact:!0})]},d.id)})})]})})};function J(r){const t=r.details;if(!t)return[];const l=[];if(t.model&&l.push({label:"模型",value:t.model}),t.costUsd!=null&&l.push({label:"费用",value:`$${Number(t.costUsd).toFixed(4)}`}),t.durationMs!=null){const s=Math.round(Number(t.durationMs)/1e3);l.push({label:"耗时",value:s>=60?`${Math.floor(s/60)}m${s%60}s`:`${s}s`})}if(t.numTurns!=null&&l.push({label:"轮次",value:String(t.numTurns)}),t.inputTokens!=null||t.outputTokens!=null){const s=t.inputTokens?Number(t.inputTokens).toLocaleString():"0",n=t.outputTokens?Number(t.outputTokens).toLocaleString():"0";l.push({label:"Token",value:`${s} → ${n}`})}return l}const Ee=({group:r})=>{const[t,l]=m.useState(!1),s=r.messages.length>1,n=r.messages[r.messages.length-1],i=J(n);return e.jsx("div",{className:"flex justify-start",children:e.jsxs("div",{className:"max-w-[85%] rounded-xl border border-gray-200 dark:border-gray-800 bg-gray-50/90 dark:bg-gray-900/80 overflow-hidden",children:[e.jsxs("button",{type:"button",onClick:()=>s&&l(!t),className:g("w-full px-3 py-2 flex items-center gap-2 text-left min-w-0",s&&"hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"),children:[s?t?e.jsx(D,{className:"w-3.5 h-3.5 text-gray-400 flex-shrink-0"}):e.jsx(L,{className:"w-3.5 h-3.5 text-gray-400 flex-shrink-0"}):e.jsx(F,{className:"w-3.5 h-3.5 text-gray-400 flex-shrink-0"}),e.jsx("span",{className:"text-xs font-semibold text-gray-600 dark:text-gray-300 flex-shrink-0",children:"系统消息"}),s&&e.jsxs("span",{className:"text-[10px] px-1.5 py-0.5 rounded-full bg-gray-200/70 dark:bg-gray-800 text-gray-500 dark:text-gray-400 flex-shrink-0",children:[r.messages.length," 条"]}),e.jsx("span",{className:"text-[10px] text-gray-400 dark:text-gray-500 flex-shrink-0",children:r.time}),e.jsx("span",{className:"text-xs text-gray-500 dark:text-gray-400 truncate min-w-0",children:r.content})]}),!t&&i.length>0&&e.jsx("div",{className:"px-3 pb-2 flex flex-wrap gap-1.5",children:i.map((c,p)=>e.jsxs("span",{className:"inline-flex items-center gap-1 text-[10px] px-1.5 py-0.5 rounded-full font-medium bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 max-w-full",children:[e.jsx("span",{className:"opacity-60 flex-shrink-0",children:c.label}),e.jsx("span",{className:"font-semibold truncate",children:c.value})]},`${c.label}-${p}`))}),t&&s&&e.jsx("div",{className:"border-t border-gray-200/80 dark:border-gray-800 divide-y divide-gray-200/70 dark:divide-gray-800",children:r.messages.map(c=>{const p=J(c);return e.jsxs("div",{className:"px-3 py-2 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx("span",{className:"text-xs text-gray-600 dark:text-gray-300 truncate min-w-0",children:c.content}),e.jsx("span",{className:"text-[10px] text-gray-400 dark:text-gray-500 flex-shrink-0",children:c.time})]}),p.length>0&&e.jsx("div",{className:"mt-1.5 flex flex-wrap gap-1.5",children:p.map((d,u)=>e.jsxs("span",{className:"inline-flex items-center gap-1 text-[10px] px-1.5 py-0.5 rounded-full font-medium bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 max-w-full",children:[e.jsx("span",{className:"opacity-60 flex-shrink-0",children:d.label}),e.jsx("span",{className:"font-semibold truncate",children:d.value})]},`${d.label}-${u}`))})]},c.id)})})]})})},Le=({message:r})=>{const[t,l]=m.useState(!1);return e.jsx("div",{className:"flex justify-start",children:e.jsxs("div",{className:"bg-indigo-50/80 dark:bg-indigo-950/40 border border-indigo-200/60 dark:border-indigo-800/40 rounded-xl px-3 py-2 max-w-[85%] cursor-pointer hover:bg-indigo-100/60 dark:hover:bg-indigo-950/60 transition-colors",onClick:()=>l(!t),children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(be,{className:"w-3.5 h-3.5 text-indigo-500 dark:text-indigo-400"}),e.jsx("span",{className:"text-xs font-medium text-indigo-600 dark:text-indigo-400",children:t?"思考过程":"思考中..."}),e.jsxs("span",{className:"text-[10px] text-indigo-400 dark:text-indigo-500",children:["(",r.content.length," 字)"]}),t?e.jsx(_,{className:"w-3 h-3 text-indigo-400"}):e.jsx(D,{className:"w-3 h-3 text-indigo-400"})]}),t&&e.jsx("div",{className:"mt-2 text-sm text-indigo-800/80 dark:text-indigo-200/80 markdown-body-sm prose-sm",children:e.jsx(C,{children:r.content})})]})})},Re=({task:r,onClick:t,onDelete:l})=>e.jsxs("div",{onClick:t,className:"bg-white dark:bg-gray-900 p-4 rounded-xl border border-gray-100 dark:border-gray-800 shadow-sm active:scale-[0.98] transition-transform cursor-pointer group",children:[e.jsxs("div",{className:"flex justify-between items-start mb-2",children:[e.jsx(ee,{status:r.status}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-gray-400 dark:text-gray-500",children:V(r.startTime)}),e.jsx("button",{onClick:l,className:"p-0.5 text-gray-300 dark:text-gray-600 hover:text-red-400 opacity-0 group-hover:opacity-100 transition-all",children:e.jsx(K,{className:"w-3.5 h-3.5"})})]})]}),e.jsx("p",{className:"text-sm text-gray-800 dark:text-gray-200 font-medium line-clamp-2 mb-3 leading-relaxed",children:r.title}),e.jsxs("div",{className:"flex items-center justify-between text-xs text-gray-500 dark:text-gray-400",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("span",{children:[r.confirmCount," 次确认"]}),e.jsx("span",{children:"·"}),e.jsxs("span",{children:[r.toolCount," 个工具调用"]}),r.duration&&e.jsxs(e.Fragment,{children:[e.jsx("span",{children:"·"}),e.jsx("span",{children:r.duration})]})]}),e.jsx(L,{className:"w-4 h-4 text-gray-300 dark:text-gray-600"})]})]}),ee=({status:r})=>{switch(r){case"running":return e.jsxs("div",{className:"flex items-center gap-1.5 text-primary-600 dark:text-primary-400",children:[e.jsx("div",{className:"w-2 h-2 rounded-full bg-primary-600 dark:bg-primary-400 animate-pulse"}),e.jsx("span",{className:"text-xs font-medium",children:"进行中"})]});case"confirm":return e.jsxs("div",{className:"flex items-center gap-1.5 text-orange-600 dark:text-orange-400",children:[e.jsx(fe,{className:"w-3.5 h-3.5"}),e.jsx("span",{className:"text-xs font-medium",children:"等待确认"})]});case"completed":return e.jsxs("div",{className:"flex items-center gap-1.5 text-green-600",children:[e.jsx(R,{className:"w-3.5 h-3.5"}),e.jsx("span",{className:"text-xs font-medium",children:"已完成"})]});case"failed":return e.jsxs("div",{className:"flex items-center gap-1.5 text-red-600",children:[e.jsx(H,{className:"w-3.5 h-3.5"}),e.jsx("span",{className:"text-xs font-medium",children:"失败"})]})}};export{ze as History};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{u as x,r as f,j as m}from"./vendor-react-DSV5aFEg.js";import{u as k}from"./index-DOgH1Kf3.js";import{c as H}from"./code-highlight-CEcsuMpw.js";import{p as d,s as M}from"./WorkspaceLinkedText-DQyPLk-X.js";import{r as j,M as w,a as K}from"./vendor-markdown-BDwu-Ux6.js";import"./vendor-icons-CNN4EKVi.js";const P=[K];function R(t){return function(){return function(n){h(n,t)}}}function W(t){return(t==null?void 0:t.type)==="element"&&["a","code","pre"].includes(t.tagName)}function h(t,o){if(!(t!=null&&t.children)||W(t))return;const r=[];let n=!1;for(const e of t.children){if((e==null?void 0:e.type)==="text"&&typeof e.value=="string"){const c=M(e.value,o);if(c.length===1&&c[0].type==="text"){r.push(e);continue}n=!0;for(const i of c)i.type==="text"?r.push({type:"text",value:i.text}):r.push({type:"element",tagName:"a",properties:{href:i.target.href,title:`打开 ${i.target.path}:${i.target.line}`},children:[{type:"text",value:i.text}]});continue}h(e,o),r.push(e)}n&&(t.children=r)}function $(t){return t.startsWith("/workspace?")}function S({children:t,enableWorkspaceLinks:o=!0}){const r=x(),{cliConfig:n}=k(),e=n==null?void 0:n.workDir,c=f.useMemo(()=>{const s=[[j,H]];return o&&s.push(R(e)),s},[o,e]),i=f.useMemo(()=>({a({href:s,children:g,node:N,...l}){const a=typeof s=="string"?d(s,e):null,p=(a==null?void 0:a.href)||(typeof s=="string"&&$(s)?s:""),y=p||s;return m.jsx("a",{...l,href:y,title:a?`打开 ${a.path}:${a.line}`:l.title,onClick:u=>{!p||u.button!==0||u.metaKey||u.ctrlKey||u.shiftKey||u.altKey||(u.preventDefault(),r(p))},children:g})}}),[r,e]);return m.jsx(w,{remarkPlugins:P,rehypePlugins:c,components:i,children:t})}export{S as default};
|