@co0ontty/wand 1.1.2 → 1.1.3
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/claude-pty-bridge.js +4 -2
- package/dist/cli.js +2 -2
- package/dist/process-manager.d.ts +4 -0
- package/dist/process-manager.js +23 -1
- package/dist/server.js +57 -27
- package/dist/web-ui/content/scripts.js +111 -16
- package/dist/web-ui/content/styles.css +97 -0
- package/package.json +1 -1
|
@@ -434,11 +434,13 @@ export class ClaudePtyBridge extends EventEmitter {
|
|
|
434
434
|
return (/\bdo you want to\b/i.test(normalized) ||
|
|
435
435
|
/\bgrant\b.*\bpermission\b/i.test(normalized) ||
|
|
436
436
|
/\bhaven't granted\b/i.test(normalized) ||
|
|
437
|
-
/\benter to confirm\b/i.test(normalized)
|
|
437
|
+
/\benter to confirm\b/i.test(normalized) ||
|
|
438
|
+
/\bwould you like to proceed\b/i.test(normalized) ||
|
|
439
|
+
/❯/.test(normalized));
|
|
438
440
|
}
|
|
439
441
|
extractPromptText(normalized) {
|
|
440
442
|
// Return a snippet around the permission prompt
|
|
441
|
-
const match = normalized.match(/.{0,100}(?:do you want to|permission|grant|enter to confirm).{0,100}/i);
|
|
443
|
+
const match = normalized.match(/.{0,100}(?:do you want to|permission|grant|enter to confirm|would you like to proceed|❯).{0,100}/i);
|
|
442
444
|
return match?.[0] ?? normalized.slice(-100);
|
|
443
445
|
}
|
|
444
446
|
extractPermissionTarget(normalized) {
|
package/dist/cli.js
CHANGED
|
@@ -6,7 +6,7 @@ import { ensureDatabaseFile, resolveDatabasePath } from "./storage.js";
|
|
|
6
6
|
async function main() {
|
|
7
7
|
const args = process.argv.slice(2);
|
|
8
8
|
const command = args[0] || "help";
|
|
9
|
-
const configPath = resolveConfigPath(readFlagValue(args, "--config"));
|
|
9
|
+
const configPath = resolveConfigPath(readFlagValue(args, "-c") || readFlagValue(args, "--config"));
|
|
10
10
|
switch (command) {
|
|
11
11
|
case "init": {
|
|
12
12
|
await ensureRequiredFiles(configPath);
|
|
@@ -63,7 +63,7 @@ Commands:
|
|
|
63
63
|
wand config:set Update a simple config value
|
|
64
64
|
|
|
65
65
|
Options:
|
|
66
|
-
--config <path>
|
|
66
|
+
-c, --config <path> Use a custom config file (default: ~/.wand/config.json)
|
|
67
67
|
`);
|
|
68
68
|
}
|
|
69
69
|
async function ensureRequiredFiles(configPath) {
|
|
@@ -52,6 +52,10 @@ export declare class ProcessManager extends EventEmitter {
|
|
|
52
52
|
private claudeHistoryCache;
|
|
53
53
|
private static readonly HISTORY_CACHE_TTL_MS;
|
|
54
54
|
listClaudeHistorySessions(): ClaudeHistorySession[];
|
|
55
|
+
deleteClaudeHistoryFiles(sessions: {
|
|
56
|
+
claudeSessionId: string;
|
|
57
|
+
cwd: string;
|
|
58
|
+
}[]): number;
|
|
55
59
|
get(id: string): SessionSnapshot | null;
|
|
56
60
|
sendInput(id: string, input: string, view?: "chat" | "terminal", shortcutKey?: string): SessionSnapshot;
|
|
57
61
|
/** Emit a task event for a session, debounced to avoid flooding */
|
package/dist/process-manager.js
CHANGED
|
@@ -40,7 +40,8 @@ const PROMPT_PATTERNS = [
|
|
|
40
40
|
/\bwould you like to\b/i,
|
|
41
41
|
/\bshall i\b/i,
|
|
42
42
|
/\bcan i\b/i,
|
|
43
|
-
/\bgrant\b.*\bpermission\b/i
|
|
43
|
+
/\bgrant\b.*\bpermission\b/i,
|
|
44
|
+
/❯/
|
|
44
45
|
];
|
|
45
46
|
const REAL_CONVERSATION_MIN_LINES = 2;
|
|
46
47
|
const REAL_CONVERSATION_MIN_MESSAGES = 2;
|
|
@@ -1135,6 +1136,27 @@ export class ProcessManager extends EventEmitter {
|
|
|
1135
1136
|
this.claudeHistoryCache = { data: allSessions, expiresAt: now + ProcessManager.HISTORY_CACHE_TTL_MS };
|
|
1136
1137
|
return allSessions;
|
|
1137
1138
|
}
|
|
1139
|
+
deleteClaudeHistoryFiles(sessions) {
|
|
1140
|
+
let deleted = 0;
|
|
1141
|
+
for (const { claudeSessionId, cwd } of sessions) {
|
|
1142
|
+
if (!UUID_V4_PATTERN.test(claudeSessionId))
|
|
1143
|
+
continue;
|
|
1144
|
+
const jsonlPath = path.join(getClaudeProjectDir(cwd), `${claudeSessionId}.jsonl`);
|
|
1145
|
+
try {
|
|
1146
|
+
if (existsSync(jsonlPath)) {
|
|
1147
|
+
unlinkSync(jsonlPath);
|
|
1148
|
+
deleted++;
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
catch {
|
|
1152
|
+
// Best-effort — Claude cache cleanup is non-critical
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
if (deleted > 0) {
|
|
1156
|
+
this.claudeHistoryCache = null;
|
|
1157
|
+
}
|
|
1158
|
+
return deleted;
|
|
1159
|
+
}
|
|
1138
1160
|
get(id) {
|
|
1139
1161
|
this.archiveExpiredSessions();
|
|
1140
1162
|
const record = this.sessions.get(id);
|
package/dist/server.js
CHANGED
|
@@ -255,6 +255,16 @@ function getHiddenClaudeSessionIds(storage) {
|
|
|
255
255
|
function saveHiddenClaudeSessionIds(storage, hidden) {
|
|
256
256
|
storage.setConfigValue(HIDDEN_CLAUDE_SESSIONS_KEY, JSON.stringify(Array.from(hidden)));
|
|
257
257
|
}
|
|
258
|
+
function removeFromHiddenClaudeSessionIds(storage, idsToRemove) {
|
|
259
|
+
const hidden = getHiddenClaudeSessionIds(storage);
|
|
260
|
+
let changed = false;
|
|
261
|
+
for (const id of idsToRemove) {
|
|
262
|
+
if (hidden.delete(id))
|
|
263
|
+
changed = true;
|
|
264
|
+
}
|
|
265
|
+
if (changed)
|
|
266
|
+
saveHiddenClaudeSessionIds(storage, hidden);
|
|
267
|
+
}
|
|
258
268
|
const MAX_RECENT_PATHS = 10;
|
|
259
269
|
// ── File language detection ──
|
|
260
270
|
function getLanguageFromExt(ext, filePath) {
|
|
@@ -508,10 +518,18 @@ export async function startServer(config, configPath) {
|
|
|
508
518
|
res.status(400).json({ error: "会话 ID 不能为空。" });
|
|
509
519
|
return;
|
|
510
520
|
}
|
|
511
|
-
const
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
521
|
+
const session = processes.listClaudeHistorySessions()
|
|
522
|
+
.find((s) => s.claudeSessionId === claudeSessionId);
|
|
523
|
+
if (session) {
|
|
524
|
+
processes.deleteClaudeHistoryFiles([{ claudeSessionId, cwd: session.cwd }]);
|
|
525
|
+
removeFromHiddenClaudeSessionIds(storage, [claudeSessionId]);
|
|
526
|
+
}
|
|
527
|
+
else {
|
|
528
|
+
const hidden = getHiddenClaudeSessionIds(storage);
|
|
529
|
+
if (!hidden.has(claudeSessionId)) {
|
|
530
|
+
hidden.add(claudeSessionId);
|
|
531
|
+
saveHiddenClaudeSessionIds(storage, hidden);
|
|
532
|
+
}
|
|
515
533
|
}
|
|
516
534
|
res.json({ ok: true });
|
|
517
535
|
});
|
|
@@ -523,22 +541,15 @@ export async function startServer(config, configPath) {
|
|
|
523
541
|
}
|
|
524
542
|
try {
|
|
525
543
|
const sessions = processes.listClaudeHistorySessions();
|
|
526
|
-
const
|
|
527
|
-
let added = 0;
|
|
544
|
+
const toDelete = [];
|
|
528
545
|
for (const session of sessions) {
|
|
529
|
-
if (
|
|
530
|
-
|
|
531
|
-
}
|
|
532
|
-
if (hidden.has(session.claudeSessionId)) {
|
|
533
|
-
continue;
|
|
546
|
+
if (session.claudeSessionId && session.cwd === cwd) {
|
|
547
|
+
toDelete.push({ claudeSessionId: session.claudeSessionId, cwd: session.cwd });
|
|
534
548
|
}
|
|
535
|
-
hidden.add(session.claudeSessionId);
|
|
536
|
-
added += 1;
|
|
537
549
|
}
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
}
|
|
541
|
-
res.json({ ok: true, deleted: added });
|
|
550
|
+
const deleted = processes.deleteClaudeHistoryFiles(toDelete);
|
|
551
|
+
removeFromHiddenClaudeSessionIds(storage, toDelete.map((s) => s.claudeSessionId));
|
|
552
|
+
res.json({ ok: true, deleted });
|
|
542
553
|
}
|
|
543
554
|
catch (error) {
|
|
544
555
|
res.status(500).json({ error: getErrorMessage(error, "无法删除该目录下的历史会话。") });
|
|
@@ -553,19 +564,38 @@ export async function startServer(config, configPath) {
|
|
|
553
564
|
return;
|
|
554
565
|
}
|
|
555
566
|
try {
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
for (const
|
|
559
|
-
if (
|
|
560
|
-
|
|
567
|
+
const allSessions = processes.listClaudeHistorySessions();
|
|
568
|
+
const sessionMap = new Map();
|
|
569
|
+
for (const s of allSessions) {
|
|
570
|
+
if (s.claudeSessionId)
|
|
571
|
+
sessionMap.set(s.claudeSessionId, s.cwd);
|
|
572
|
+
}
|
|
573
|
+
const toDelete = [];
|
|
574
|
+
const toHide = [];
|
|
575
|
+
for (const id of claudeSessionIds) {
|
|
576
|
+
const cwd = sessionMap.get(id);
|
|
577
|
+
if (cwd) {
|
|
578
|
+
toDelete.push({ claudeSessionId: id, cwd });
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
toHide.push(id);
|
|
561
582
|
}
|
|
562
|
-
hidden.add(claudeSessionId);
|
|
563
|
-
added += 1;
|
|
564
583
|
}
|
|
565
|
-
|
|
566
|
-
|
|
584
|
+
const deleted = processes.deleteClaudeHistoryFiles(toDelete);
|
|
585
|
+
removeFromHiddenClaudeSessionIds(storage, toDelete.map((s) => s.claudeSessionId));
|
|
586
|
+
if (toHide.length > 0) {
|
|
587
|
+
const hidden = getHiddenClaudeSessionIds(storage);
|
|
588
|
+
let added = 0;
|
|
589
|
+
for (const id of toHide) {
|
|
590
|
+
if (!hidden.has(id)) {
|
|
591
|
+
hidden.add(id);
|
|
592
|
+
added++;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
if (added > 0)
|
|
596
|
+
saveHiddenClaudeSessionIds(storage, hidden);
|
|
567
597
|
}
|
|
568
|
-
res.json({ ok: true, deleted:
|
|
598
|
+
res.json({ ok: true, deleted: deleted + toHide.length });
|
|
569
599
|
}
|
|
570
600
|
catch (error) {
|
|
571
601
|
res.status(500).json({ error: getErrorMessage(error, "无法批量删除历史会话。") });
|
|
@@ -494,9 +494,14 @@
|
|
|
494
494
|
'<button class="blank-chat-tool-btn" id="welcome-tool-claude" type="button">' +
|
|
495
495
|
'<span class="tool-icon">🤖</span>新建终端会话' +
|
|
496
496
|
'</button>' +
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
'
|
|
497
|
+
'</div>' +
|
|
498
|
+
'<div class="blank-chat-cwd-wrap">' +
|
|
499
|
+
'<div class="blank-chat-cwd" id="blank-chat-cwd" role="button" tabindex="0" title="点击切换工作目录">' +
|
|
500
|
+
'<span class="blank-chat-cwd-icon">📁</span>' +
|
|
501
|
+
'<span class="blank-chat-cwd-path" id="blank-chat-cwd-path">' + escapeHtml(state.workingDir || (state.config && state.config.defaultCwd ? state.config.defaultCwd : "/tmp")) + '</span>' +
|
|
502
|
+
'<span class="blank-chat-cwd-arrow" id="blank-chat-cwd-arrow">▼</span>' +
|
|
503
|
+
'</div>' +
|
|
504
|
+
'<div class="blank-chat-cwd-dropdown hidden" id="blank-chat-cwd-dropdown"></div>' +
|
|
500
505
|
'</div>' +
|
|
501
506
|
'</div>' +
|
|
502
507
|
'</div>' +
|
|
@@ -1648,10 +1653,10 @@
|
|
|
1648
1653
|
'<div class="field">' +
|
|
1649
1654
|
'<label class="field-label" for="cwd">工作目录</label>' +
|
|
1650
1655
|
'<div class="suggestions-wrap">' +
|
|
1651
|
-
'<input id="cwd" type="text" class="field-input" autocomplete="off" placeholder="
|
|
1656
|
+
'<input id="cwd" type="text" class="field-input" autocomplete="off" placeholder="' + escapeHtml(state.workingDir || (state.config && state.config.defaultCwd ? state.config.defaultCwd : "/tmp")) + '" />' +
|
|
1652
1657
|
'<div id="cwd-suggestions" class="suggestions hidden"></div>' +
|
|
1653
1658
|
'</div>' +
|
|
1654
|
-
'<p class="field-hint"
|
|
1659
|
+
'<p class="field-hint">留空则使用上方目录,支持路径自动补全。</p>' +
|
|
1655
1660
|
'<div id="recent-paths-bubbles" class="recent-paths-bubbles"></div>' +
|
|
1656
1661
|
'</div>' +
|
|
1657
1662
|
'<button id="run-button" class="btn btn-primary btn-block">启动会话</button>' +
|
|
@@ -1810,10 +1815,7 @@
|
|
|
1810
1815
|
quickStartSession();
|
|
1811
1816
|
});
|
|
1812
1817
|
}
|
|
1813
|
-
|
|
1814
|
-
if (welcomeFolderBtn) {
|
|
1815
|
-
welcomeFolderBtn.addEventListener("click", openFolderPickerWithInitialPath);
|
|
1816
|
-
}
|
|
1818
|
+
initBlankChatCwd();
|
|
1817
1819
|
|
|
1818
1820
|
var sessionsList = document.getElementById("sessions-list");
|
|
1819
1821
|
if (sessionsList) {
|
|
@@ -2403,11 +2405,7 @@
|
|
|
2403
2405
|
renderBreadcrumb(initialPath);
|
|
2404
2406
|
}
|
|
2405
2407
|
|
|
2406
|
-
// Welcome screen folder button
|
|
2407
|
-
var welcomeFolderBtn = document.getElementById("welcome-tool-folder");
|
|
2408
|
-
if (welcomeFolderBtn) {
|
|
2409
|
-
welcomeFolderBtn.addEventListener("click", openFolderPickerWithInitialPath);
|
|
2410
|
-
}
|
|
2408
|
+
// Welcome screen folder button (legacy, now handled by initBlankChatCwd)
|
|
2411
2409
|
|
|
2412
2410
|
if (closeFolderPicker && folderPickerModal) {
|
|
2413
2411
|
closeFolderPicker.addEventListener("click", function() {
|
|
@@ -2504,7 +2502,12 @@
|
|
|
2504
2502
|
}
|
|
2505
2503
|
if (_swipeState) return;
|
|
2506
2504
|
if (item.dataset.sessionId) {
|
|
2507
|
-
|
|
2505
|
+
var clickedSession = state.sessions.find(function(s) { return s.id === item.dataset.sessionId; });
|
|
2506
|
+
if (clickedSession && clickedSession.status !== "running") {
|
|
2507
|
+
resumeSessionFromList(item.dataset.sessionId);
|
|
2508
|
+
} else {
|
|
2509
|
+
selectSession(item.dataset.sessionId);
|
|
2510
|
+
}
|
|
2508
2511
|
closeSessionsDrawer();
|
|
2509
2512
|
}
|
|
2510
2513
|
}
|
|
@@ -2524,7 +2527,12 @@
|
|
|
2524
2527
|
return;
|
|
2525
2528
|
}
|
|
2526
2529
|
if (item.dataset.sessionId) {
|
|
2527
|
-
|
|
2530
|
+
var keySession = state.sessions.find(function(s) { return s.id === item.dataset.sessionId; });
|
|
2531
|
+
if (keySession && keySession.status !== "running") {
|
|
2532
|
+
resumeSessionFromList(item.dataset.sessionId);
|
|
2533
|
+
} else {
|
|
2534
|
+
selectSession(item.dataset.sessionId);
|
|
2535
|
+
}
|
|
2528
2536
|
closeSessionsDrawer();
|
|
2529
2537
|
}
|
|
2530
2538
|
}
|
|
@@ -3951,6 +3959,93 @@
|
|
|
3951
3959
|
});
|
|
3952
3960
|
}
|
|
3953
3961
|
|
|
3962
|
+
// Blank-chat CWD inline display + dropdown
|
|
3963
|
+
function initBlankChatCwd() {
|
|
3964
|
+
var cwdEl = document.getElementById("blank-chat-cwd");
|
|
3965
|
+
if (!cwdEl) return;
|
|
3966
|
+
cwdEl.addEventListener("click", toggleBlankChatCwdDropdown);
|
|
3967
|
+
cwdEl.addEventListener("keydown", function(e) {
|
|
3968
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
3969
|
+
e.preventDefault();
|
|
3970
|
+
toggleBlankChatCwdDropdown();
|
|
3971
|
+
}
|
|
3972
|
+
});
|
|
3973
|
+
document.addEventListener("click", function(e) {
|
|
3974
|
+
var dropdown = document.getElementById("blank-chat-cwd-dropdown");
|
|
3975
|
+
if (!dropdown || dropdown.classList.contains("hidden")) return;
|
|
3976
|
+
if (!e.target.closest(".blank-chat-cwd-wrap")) {
|
|
3977
|
+
dropdown.classList.add("hidden");
|
|
3978
|
+
var arrow = document.getElementById("blank-chat-cwd-arrow");
|
|
3979
|
+
if (arrow) arrow.textContent = "▼";
|
|
3980
|
+
}
|
|
3981
|
+
});
|
|
3982
|
+
}
|
|
3983
|
+
|
|
3984
|
+
function toggleBlankChatCwdDropdown() {
|
|
3985
|
+
var dropdown = document.getElementById("blank-chat-cwd-dropdown");
|
|
3986
|
+
var arrow = document.getElementById("blank-chat-cwd-arrow");
|
|
3987
|
+
if (!dropdown) return;
|
|
3988
|
+
var isHidden = dropdown.classList.contains("hidden");
|
|
3989
|
+
if (isHidden) {
|
|
3990
|
+
loadBlankChatCwdDropdown(dropdown);
|
|
3991
|
+
dropdown.classList.remove("hidden");
|
|
3992
|
+
if (arrow) arrow.textContent = "▲";
|
|
3993
|
+
} else {
|
|
3994
|
+
dropdown.classList.add("hidden");
|
|
3995
|
+
if (arrow) arrow.textContent = "▼";
|
|
3996
|
+
}
|
|
3997
|
+
}
|
|
3998
|
+
|
|
3999
|
+
function loadBlankChatCwdDropdown(dropdown) {
|
|
4000
|
+
var defaultCwd = state.config && state.config.defaultCwd ? state.config.defaultCwd : "/tmp";
|
|
4001
|
+
dropdown.innerHTML = '<div class="blank-chat-cwd-loading">加载中...</div>';
|
|
4002
|
+
fetch("/api/recent-paths", { credentials: "same-origin" })
|
|
4003
|
+
.then(function(res) { return res.json(); })
|
|
4004
|
+
.then(function(items) {
|
|
4005
|
+
var html = "";
|
|
4006
|
+
// Default directory always first
|
|
4007
|
+
var currentDir = state.workingDir || defaultCwd;
|
|
4008
|
+
html += '<div class="blank-chat-cwd-item' + (currentDir === defaultCwd ? " active" : "") + '" data-path="' + escapeHtml(defaultCwd) + '">' +
|
|
4009
|
+
'<span class="blank-chat-cwd-item-label">默认</span>' +
|
|
4010
|
+
'<span class="blank-chat-cwd-item-path">' + escapeHtml(defaultCwd) + '</span>' +
|
|
4011
|
+
'</div>';
|
|
4012
|
+
// Recent paths (exclude default to avoid duplicate)
|
|
4013
|
+
if (items && items.length) {
|
|
4014
|
+
var seen = {};
|
|
4015
|
+
seen[defaultCwd] = true;
|
|
4016
|
+
items.forEach(function(item) {
|
|
4017
|
+
if (seen[item.path]) return;
|
|
4018
|
+
seen[item.path] = true;
|
|
4019
|
+
html += '<div class="blank-chat-cwd-item' + (currentDir === item.path ? " active" : "") + '" data-path="' + escapeHtml(item.path) + '">' +
|
|
4020
|
+
'<span class="blank-chat-cwd-item-path">' + escapeHtml(item.path) + '</span>' +
|
|
4021
|
+
'</div>';
|
|
4022
|
+
});
|
|
4023
|
+
}
|
|
4024
|
+
dropdown.innerHTML = html;
|
|
4025
|
+
dropdown.querySelectorAll(".blank-chat-cwd-item").forEach(function(el) {
|
|
4026
|
+
el.addEventListener("click", function(e) {
|
|
4027
|
+
e.stopPropagation();
|
|
4028
|
+
var path = el.dataset.path;
|
|
4029
|
+
state.workingDir = path;
|
|
4030
|
+
try { localStorage.setItem("wand-working-dir", path); } catch(e) {}
|
|
4031
|
+
var pathEl = document.getElementById("blank-chat-cwd-path");
|
|
4032
|
+
if (pathEl) pathEl.textContent = path;
|
|
4033
|
+
dropdown.classList.add("hidden");
|
|
4034
|
+
var arrow = document.getElementById("blank-chat-cwd-arrow");
|
|
4035
|
+
if (arrow) arrow.textContent = "▼";
|
|
4036
|
+
// Update folder picker input if exists
|
|
4037
|
+
var fpInput = document.getElementById("folder-picker-input");
|
|
4038
|
+
if (fpInput) fpInput.value = path;
|
|
4039
|
+
});
|
|
4040
|
+
});
|
|
4041
|
+
})
|
|
4042
|
+
.catch(function() {
|
|
4043
|
+
dropdown.innerHTML = '<div class="blank-chat-cwd-item" data-path="' + escapeHtml(defaultCwd) + '">' +
|
|
4044
|
+
'<span class="blank-chat-cwd-item-path">' + escapeHtml(defaultCwd) + '</span>' +
|
|
4045
|
+
'</div>';
|
|
4046
|
+
});
|
|
4047
|
+
}
|
|
4048
|
+
|
|
3954
4049
|
function loadRecentPathBubbles() {
|
|
3955
4050
|
var container = document.getElementById("recent-paths-bubbles");
|
|
3956
4051
|
if (!container) return;
|
|
@@ -5670,6 +5670,103 @@
|
|
|
5670
5670
|
.blank-chat-tool-btn .tool-icon {
|
|
5671
5671
|
font-size: 1.125rem;
|
|
5672
5672
|
}
|
|
5673
|
+
/* Blank-chat CWD inline selector */
|
|
5674
|
+
.blank-chat-cwd-wrap {
|
|
5675
|
+
position: relative;
|
|
5676
|
+
display: flex;
|
|
5677
|
+
flex-direction: column;
|
|
5678
|
+
align-items: center;
|
|
5679
|
+
margin-top: 8px;
|
|
5680
|
+
}
|
|
5681
|
+
.blank-chat-cwd {
|
|
5682
|
+
display: inline-flex;
|
|
5683
|
+
align-items: center;
|
|
5684
|
+
gap: 4px;
|
|
5685
|
+
cursor: pointer;
|
|
5686
|
+
font-size: 0.75rem;
|
|
5687
|
+
color: var(--text-muted);
|
|
5688
|
+
padding: 4px 8px;
|
|
5689
|
+
border-radius: var(--radius-sm);
|
|
5690
|
+
transition: color var(--transition-fast), background var(--transition-fast);
|
|
5691
|
+
user-select: none;
|
|
5692
|
+
}
|
|
5693
|
+
.blank-chat-cwd:hover {
|
|
5694
|
+
color: var(--accent);
|
|
5695
|
+
background: var(--accent-muted);
|
|
5696
|
+
}
|
|
5697
|
+
.blank-chat-cwd-icon {
|
|
5698
|
+
font-size: 0.8125rem;
|
|
5699
|
+
}
|
|
5700
|
+
.blank-chat-cwd-path {
|
|
5701
|
+
font-family: var(--font-mono);
|
|
5702
|
+
max-width: 280px;
|
|
5703
|
+
overflow: hidden;
|
|
5704
|
+
text-overflow: ellipsis;
|
|
5705
|
+
white-space: nowrap;
|
|
5706
|
+
}
|
|
5707
|
+
.blank-chat-cwd-arrow {
|
|
5708
|
+
font-size: 0.625rem;
|
|
5709
|
+
opacity: 0.6;
|
|
5710
|
+
transition: transform var(--transition-fast);
|
|
5711
|
+
}
|
|
5712
|
+
.blank-chat-cwd-dropdown {
|
|
5713
|
+
position: absolute;
|
|
5714
|
+
top: 100%;
|
|
5715
|
+
left: 50%;
|
|
5716
|
+
transform: translateX(-50%);
|
|
5717
|
+
min-width: 260px;
|
|
5718
|
+
max-width: 400px;
|
|
5719
|
+
max-height: 240px;
|
|
5720
|
+
overflow-y: auto;
|
|
5721
|
+
background: var(--bg-primary);
|
|
5722
|
+
border: 1px solid var(--border-default);
|
|
5723
|
+
border-radius: var(--radius-md);
|
|
5724
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
|
|
5725
|
+
z-index: 50;
|
|
5726
|
+
margin-top: 4px;
|
|
5727
|
+
padding: 4px;
|
|
5728
|
+
}
|
|
5729
|
+
.blank-chat-cwd-item {
|
|
5730
|
+
display: flex;
|
|
5731
|
+
align-items: center;
|
|
5732
|
+
gap: 6px;
|
|
5733
|
+
padding: 6px 10px;
|
|
5734
|
+
border-radius: var(--radius-sm);
|
|
5735
|
+
cursor: pointer;
|
|
5736
|
+
font-size: 0.75rem;
|
|
5737
|
+
color: var(--text-secondary);
|
|
5738
|
+
transition: background var(--transition-fast);
|
|
5739
|
+
}
|
|
5740
|
+
.blank-chat-cwd-item:hover {
|
|
5741
|
+
background: var(--accent-muted);
|
|
5742
|
+
color: var(--accent);
|
|
5743
|
+
}
|
|
5744
|
+
.blank-chat-cwd-item.active {
|
|
5745
|
+
background: var(--accent-muted);
|
|
5746
|
+
color: var(--accent);
|
|
5747
|
+
font-weight: 500;
|
|
5748
|
+
}
|
|
5749
|
+
.blank-chat-cwd-item-label {
|
|
5750
|
+
font-size: 0.625rem;
|
|
5751
|
+
background: var(--accent-muted);
|
|
5752
|
+
color: var(--accent);
|
|
5753
|
+
padding: 1px 5px;
|
|
5754
|
+
border-radius: 3px;
|
|
5755
|
+
font-weight: 500;
|
|
5756
|
+
white-space: nowrap;
|
|
5757
|
+
}
|
|
5758
|
+
.blank-chat-cwd-item-path {
|
|
5759
|
+
font-family: var(--font-mono);
|
|
5760
|
+
overflow: hidden;
|
|
5761
|
+
text-overflow: ellipsis;
|
|
5762
|
+
white-space: nowrap;
|
|
5763
|
+
}
|
|
5764
|
+
.blank-chat-cwd-loading {
|
|
5765
|
+
padding: 8px 10px;
|
|
5766
|
+
font-size: 0.75rem;
|
|
5767
|
+
color: var(--text-muted);
|
|
5768
|
+
text-align: center;
|
|
5769
|
+
}
|
|
5673
5770
|
.blank-chat-hint {
|
|
5674
5771
|
font-size: 0.8125rem;
|
|
5675
5772
|
color: var(--text-muted);
|