@co0ontty/wand 1.4.0 → 1.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.
- package/dist/config.js +3 -2
- package/dist/process-manager.js +7 -0
- package/dist/server.js +6 -7
- package/dist/structured-session-manager.d.ts +3 -2
- package/dist/structured-session-manager.js +12 -5
- package/dist/types.d.ts +2 -2
- package/dist/web-ui/content/scripts.js +74 -55
- package/dist/web-ui/content/styles.css +124 -72
- package/dist/web-ui/index.js +1 -1
- package/package.json +4 -4
package/dist/config.js
CHANGED
|
@@ -15,7 +15,7 @@ export const defaultConfig = () => ({
|
|
|
15
15
|
startupCommands: [],
|
|
16
16
|
allowedCommandPrefixes: [],
|
|
17
17
|
shortcutLogMaxBytes: 10 * 1024 * 1024,
|
|
18
|
-
|
|
18
|
+
language: "",
|
|
19
19
|
commandPresets: [
|
|
20
20
|
{
|
|
21
21
|
label: "Claude",
|
|
@@ -107,7 +107,8 @@ function mergeWithDefaults(input) {
|
|
|
107
107
|
command: normalizePresetCommand(preset.command),
|
|
108
108
|
mode: isExecutionMode(preset.mode) ? preset.mode : undefined
|
|
109
109
|
}))
|
|
110
|
-
: defaults.commandPresets
|
|
110
|
+
: defaults.commandPresets,
|
|
111
|
+
language: typeof input.language === "string" ? input.language.trim() : defaults.language,
|
|
111
112
|
};
|
|
112
113
|
}
|
|
113
114
|
export function isExecutionMode(value) {
|
package/dist/process-manager.js
CHANGED
|
@@ -1559,6 +1559,13 @@ export class ProcessManager extends EventEmitter {
|
|
|
1559
1559
|
const escaped = autonomousPrompt.replace(/'/g, "'\\''");
|
|
1560
1560
|
result += ` --append-system-prompt '${escaped}'`;
|
|
1561
1561
|
}
|
|
1562
|
+
// Append language preference if configured
|
|
1563
|
+
const language = this.config.language?.trim();
|
|
1564
|
+
if (language) {
|
|
1565
|
+
const langPrompt = `Please respond in ${language}. Use ${language} for all your explanations, comments, and conversational text.`;
|
|
1566
|
+
const escaped = langPrompt.replace(/'/g, "'\\''");
|
|
1567
|
+
result += ` --append-system-prompt '${escaped}'`;
|
|
1568
|
+
}
|
|
1562
1569
|
return result;
|
|
1563
1570
|
}
|
|
1564
1571
|
}
|
package/dist/server.js
CHANGED
|
@@ -253,14 +253,14 @@ export async function startServer(config, configPath) {
|
|
|
253
253
|
const configDir = resolveConfigDir(configPath);
|
|
254
254
|
const avatarSeed = await ensureAvatarSeed(configDir);
|
|
255
255
|
const processes = new ProcessManager(config, storage, configDir);
|
|
256
|
-
const structuredSessions = new StructuredSessionManager(storage);
|
|
256
|
+
const structuredSessions = new StructuredSessionManager(storage, config);
|
|
257
257
|
const useHttps = config.https === true;
|
|
258
258
|
const protocol = useHttps ? "https" : "http";
|
|
259
259
|
const nodeModulesDir = path.join(RUNTIME_ROOT_DIR, "node_modules");
|
|
260
260
|
app.use(express.json({ limit: "1mb" }));
|
|
261
|
-
app.use("/vendor/xterm", express.static(path.join(nodeModulesDir, "xterm")));
|
|
261
|
+
app.use("/vendor/xterm", express.static(path.join(nodeModulesDir, "@xterm", "xterm")));
|
|
262
262
|
app.use("/vendor/xterm-addon-fit", express.static(path.join(nodeModulesDir, "@xterm", "addon-fit")));
|
|
263
|
-
app.use("/vendor/xterm-addon-serialize", express.static(path.join(nodeModulesDir, "xterm
|
|
263
|
+
app.use("/vendor/xterm-addon-serialize", express.static(path.join(nodeModulesDir, "@xterm", "addon-serialize")));
|
|
264
264
|
// ── Web UI and PWA endpoints ──
|
|
265
265
|
app.get("/", (_req, res) => {
|
|
266
266
|
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
|
@@ -336,7 +336,6 @@ export async function startServer(config, configPath) {
|
|
|
336
336
|
defaultCwd: config.defaultCwd,
|
|
337
337
|
commandPresets: config.commandPresets,
|
|
338
338
|
structuredRunners: [{ label: "Claude Structured", runner: "claude-cli-print" }],
|
|
339
|
-
experimentalDomTerminal: config.experimentalDomTerminal ?? false,
|
|
340
339
|
updateAvailable: cachedUpdateInfo?.updateAvailable ?? false,
|
|
341
340
|
latestVersion: cachedUpdateInfo?.latest ?? null,
|
|
342
341
|
currentVersion: PKG_VERSION,
|
|
@@ -360,7 +359,7 @@ export async function startServer(config, configPath) {
|
|
|
360
359
|
});
|
|
361
360
|
app.post("/api/settings/config", async (req, res) => {
|
|
362
361
|
const body = req.body;
|
|
363
|
-
const allowedFields = ["host", "port", "https", "defaultMode", "defaultCwd", "shell", "
|
|
362
|
+
const allowedFields = ["host", "port", "https", "defaultMode", "defaultCwd", "shell", "language"];
|
|
364
363
|
let changed = false;
|
|
365
364
|
for (const field of allowedFields) {
|
|
366
365
|
if (field in body && body[field] !== undefined) {
|
|
@@ -391,8 +390,8 @@ export async function startServer(config, configPath) {
|
|
|
391
390
|
else if (field === "shell") {
|
|
392
391
|
config.shell = String(body.shell);
|
|
393
392
|
}
|
|
394
|
-
else if (field === "
|
|
395
|
-
config.
|
|
393
|
+
else if (field === "language") {
|
|
394
|
+
config.language = typeof body.language === "string" ? body.language.trim() : "";
|
|
396
395
|
}
|
|
397
396
|
changed = true;
|
|
398
397
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WandStorage } from "./storage.js";
|
|
2
|
-
import { ExecutionMode, SessionRunner, SessionSnapshot } from "./types.js";
|
|
2
|
+
import { ExecutionMode, SessionRunner, SessionSnapshot, WandConfig } from "./types.js";
|
|
3
3
|
import { ProcessEvent } from "./ws-broadcast.js";
|
|
4
4
|
interface CreateStructuredSessionOptions {
|
|
5
5
|
cwd: string;
|
|
@@ -9,10 +9,11 @@ interface CreateStructuredSessionOptions {
|
|
|
9
9
|
}
|
|
10
10
|
export declare class StructuredSessionManager {
|
|
11
11
|
private readonly storage;
|
|
12
|
+
private readonly config;
|
|
12
13
|
private readonly sessions;
|
|
13
14
|
private readonly pendingChildren;
|
|
14
15
|
private emitEvent;
|
|
15
|
-
constructor(storage: WandStorage);
|
|
16
|
+
constructor(storage: WandStorage, config: WandConfig);
|
|
16
17
|
setEventEmitter(emitEvent: (event: ProcessEvent) => void): void;
|
|
17
18
|
list(): SessionSnapshot[];
|
|
18
19
|
get(id: string): SessionSnapshot | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
|
-
const STREAM_EMIT_DEBOUNCE_MS =
|
|
3
|
+
const STREAM_EMIT_DEBOUNCE_MS = 16;
|
|
4
4
|
function isRunningAsRoot() {
|
|
5
5
|
return process.getuid?.() === 0 || process.geteuid?.() === 0;
|
|
6
6
|
}
|
|
@@ -10,11 +10,13 @@ function shouldAutoApproveForMode(mode) {
|
|
|
10
10
|
}
|
|
11
11
|
export class StructuredSessionManager {
|
|
12
12
|
storage;
|
|
13
|
+
config;
|
|
13
14
|
sessions = new Map();
|
|
14
15
|
pendingChildren = new Map();
|
|
15
16
|
emitEvent = null;
|
|
16
|
-
constructor(storage) {
|
|
17
|
+
constructor(storage, config) {
|
|
17
18
|
this.storage = storage;
|
|
19
|
+
this.config = config;
|
|
18
20
|
for (const snapshot of this.storage.loadSessions()) {
|
|
19
21
|
if ((snapshot.sessionKind ?? "pty") !== "structured")
|
|
20
22
|
continue;
|
|
@@ -369,6 +371,11 @@ export class StructuredSessionManager {
|
|
|
369
371
|
if (session.mode === "managed") {
|
|
370
372
|
args.push("--append-system-prompt", "You are running in a fully managed, autonomous mode. The user may not be available to respond to questions or confirmations in a timely manner. You MUST make all decisions independently — choose the best approach yourself instead of asking the user for preferences, confirmations, or clarifications. If multiple approaches are viable, pick the one you judge most appropriate and proceed. Never block on user input unless the task is fundamentally ambiguous and cannot be reasonably inferred. Be decisive and self-directed.");
|
|
371
373
|
}
|
|
374
|
+
// Append language preference if configured
|
|
375
|
+
const language = this.config.language?.trim();
|
|
376
|
+
if (language) {
|
|
377
|
+
args.push("--append-system-prompt", `Please respond in ${language}. Use ${language} for all your explanations, comments, and conversational text.`);
|
|
378
|
+
}
|
|
372
379
|
if (session.claudeSessionId) {
|
|
373
380
|
args.push("--resume", session.claudeSessionId);
|
|
374
381
|
}
|
|
@@ -456,9 +463,9 @@ export class StructuredSessionManager {
|
|
|
456
463
|
if (extracted.content.length > 0) {
|
|
457
464
|
turnState.blocks.push(...extracted.content);
|
|
458
465
|
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
466
|
+
// NOTE: usage from streaming "assistant" events contains partial/incremental
|
|
467
|
+
// token counts (e.g. output_tokens=1 during streaming) and is NOT accurate.
|
|
468
|
+
// We only use the authoritative usage from the final "result" event.
|
|
462
469
|
syncSnapshot();
|
|
463
470
|
scheduleEmit();
|
|
464
471
|
return;
|
package/dist/types.d.ts
CHANGED
|
@@ -45,8 +45,8 @@ export interface WandConfig {
|
|
|
45
45
|
commandPresets: CommandPreset[];
|
|
46
46
|
/** Max total size (bytes) for shortcut interaction logs per session (default: 10 MB). Set 0 to disable logging. */
|
|
47
47
|
shortcutLogMaxBytes?: number;
|
|
48
|
-
/**
|
|
49
|
-
|
|
48
|
+
/** Preferred response language for Claude (e.g. "中文", "English"). Empty string means no override. */
|
|
49
|
+
language?: string;
|
|
50
50
|
}
|
|
51
51
|
export interface CommandRequest {
|
|
52
52
|
command: string;
|
|
@@ -821,11 +821,21 @@
|
|
|
821
821
|
'<label class="field-label" for="cfg-shell">Shell</label>' +
|
|
822
822
|
'<input id="cfg-shell" type="text" class="field-input" placeholder="/bin/bash" />' +
|
|
823
823
|
'</div>' +
|
|
824
|
-
'<div class="field
|
|
825
|
-
'<label class="field-label" for="cfg-
|
|
826
|
-
'<
|
|
824
|
+
'<div class="field">' +
|
|
825
|
+
'<label class="field-label" for="cfg-language">回复语言</label>' +
|
|
826
|
+
'<select id="cfg-language" class="field-input">' +
|
|
827
|
+
'<option value="">自动(不指定)</option>' +
|
|
828
|
+
'<option value="中文">中文</option>' +
|
|
829
|
+
'<option value="English">English</option>' +
|
|
830
|
+
'<option value="日本語">日本語</option>' +
|
|
831
|
+
'<option value="한국어">한국어</option>' +
|
|
832
|
+
'<option value="Español">Español</option>' +
|
|
833
|
+
'<option value="Français">Français</option>' +
|
|
834
|
+
'<option value="Deutsch">Deutsch</option>' +
|
|
835
|
+
'<option value="Русский">Русский</option>' +
|
|
836
|
+
'</select>' +
|
|
837
|
+
'<p class="hint" style="margin-top:4px;margin-bottom:0;">设置后,Claude 将尽量使用指定语言回复。</p>' +
|
|
827
838
|
'</div>' +
|
|
828
|
-
'<p class="hint" style="margin-top:-8px;margin-bottom:8px;">移动端使用 DOM 渲染终端,支持原生文本选择与复制。保存后刷新页面生效。</p>' +
|
|
829
839
|
'<button id="save-config-button" class="btn btn-primary btn-block">保存配置</button>' +
|
|
830
840
|
'<p id="config-message" class="hint hidden"></p>' +
|
|
831
841
|
'</div>' +
|
|
@@ -1916,21 +1926,23 @@
|
|
|
1916
1926
|
var statusSpan = el.querySelector(".inline-tool-status");
|
|
1917
1927
|
if (statusSpan) {
|
|
1918
1928
|
if (el.dataset.status === "error") {
|
|
1919
|
-
statusSpan.textContent = "
|
|
1929
|
+
statusSpan.textContent = "✗";
|
|
1920
1930
|
} else if (el.dataset.status === "done") {
|
|
1921
|
-
statusSpan.textContent =
|
|
1931
|
+
statusSpan.textContent = "✓";
|
|
1922
1932
|
}
|
|
1923
1933
|
}
|
|
1924
1934
|
};
|
|
1925
1935
|
// Toggle function for terminal tool blocks
|
|
1926
1936
|
window.__terminalExpand = function(el) {
|
|
1927
|
-
var
|
|
1937
|
+
var container = el.closest(".inline-terminal");
|
|
1938
|
+
if (!container) return;
|
|
1939
|
+
var body = container.querySelector(".term-body");
|
|
1928
1940
|
if (body) {
|
|
1929
1941
|
var isHidden = body.style.display === "none";
|
|
1930
1942
|
body.style.display = isHidden ? "block" : "none";
|
|
1931
|
-
|
|
1943
|
+
container.dataset.expanded = isHidden ? "true" : "false";
|
|
1932
1944
|
var toggleIcon = el.querySelector(".term-toggle-icon");
|
|
1933
|
-
if (toggleIcon) toggleIcon.textContent = isHidden ? "▼" : "
|
|
1945
|
+
if (toggleIcon) toggleIcon.textContent = isHidden ? "▼" : "▶";
|
|
1934
1946
|
}
|
|
1935
1947
|
};
|
|
1936
1948
|
// Update streaming thinking content (called from WebSocket handler)
|
|
@@ -4196,8 +4208,8 @@
|
|
|
4196
4208
|
if (modeEl) modeEl.value = cfg.defaultMode || "default";
|
|
4197
4209
|
if (cwdEl) cwdEl.value = cfg.defaultCwd || "";
|
|
4198
4210
|
if (shellEl) shellEl.value = cfg.shell || "";
|
|
4199
|
-
var
|
|
4200
|
-
if (
|
|
4211
|
+
var langEl = document.getElementById("cfg-language");
|
|
4212
|
+
if (langEl) langEl.value = cfg.language || "";
|
|
4201
4213
|
|
|
4202
4214
|
// Cert status
|
|
4203
4215
|
var certStatus = document.getElementById("cert-status");
|
|
@@ -4235,7 +4247,7 @@
|
|
|
4235
4247
|
defaultMode: (document.getElementById("cfg-mode") || {}).value,
|
|
4236
4248
|
defaultCwd: (document.getElementById("cfg-cwd") || {}).value,
|
|
4237
4249
|
shell: (document.getElementById("cfg-shell") || {}).value,
|
|
4238
|
-
|
|
4250
|
+
language: (document.getElementById("cfg-language") || {}).value || "",
|
|
4239
4251
|
};
|
|
4240
4252
|
|
|
4241
4253
|
fetch("/api/settings/config", {
|
|
@@ -7357,7 +7369,8 @@
|
|
|
7357
7369
|
switch (msg.type) {
|
|
7358
7370
|
case 'output':
|
|
7359
7371
|
// Update session output (for terminal display and local message parsing)
|
|
7360
|
-
|
|
7372
|
+
// NOTE: For structured sessions, output may be "" during streaming — check messages too
|
|
7373
|
+
if (msg.data && (msg.data.output || msg.data.messages) && msg.sessionId) {
|
|
7361
7374
|
var snapshot = { id: msg.sessionId, output: msg.data.output };
|
|
7362
7375
|
if (Object.prototype.hasOwnProperty.call(msg.data, 'permissionBlocked')) {
|
|
7363
7376
|
snapshot.permissionBlocked = !!msg.data.permissionBlocked;
|
|
@@ -7381,7 +7394,12 @@
|
|
|
7381
7394
|
}
|
|
7382
7395
|
}
|
|
7383
7396
|
updateTaskDisplay();
|
|
7384
|
-
|
|
7397
|
+
// Structured sessions: render immediately for responsiveness
|
|
7398
|
+
if (msg.data.sessionKind === 'structured') {
|
|
7399
|
+
renderChat();
|
|
7400
|
+
} else {
|
|
7401
|
+
scheduleChatRender();
|
|
7402
|
+
}
|
|
7385
7403
|
}
|
|
7386
7404
|
|
|
7387
7405
|
}
|
|
@@ -8446,10 +8464,8 @@
|
|
|
8446
8464
|
// ===== Terminal copy button for mobile =====
|
|
8447
8465
|
// ===== Mobile DOM terminal view =====
|
|
8448
8466
|
function initMobileDomTerminal(container) {
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
// Gated by experimental config flag
|
|
8452
|
-
if (!state.config || !state.config.experimentalDomTerminal) return;
|
|
8467
|
+
// DOM terminal feature removed — always return
|
|
8468
|
+
return;
|
|
8453
8469
|
|
|
8454
8470
|
// Create DOM view container
|
|
8455
8471
|
var domView = document.createElement("div");
|
|
@@ -8848,7 +8864,7 @@
|
|
|
8848
8864
|
if (msg.role === "thinking") {
|
|
8849
8865
|
return '<div class="chat-message thinking">' +
|
|
8850
8866
|
'<div class="thinking-inline thinking-pty collapsed" data-thinking="" onclick="__thinkingToggle(this)">' +
|
|
8851
|
-
'<span class="thinking-inline-icon"
|
|
8867
|
+
'<span class="thinking-inline-icon">⦿</span>' +
|
|
8852
8868
|
'<span class="thinking-inline-preview">' + escapeHtml(msg.content) + '</span>' +
|
|
8853
8869
|
'<span class="thinking-inline-action">展开</span>' +
|
|
8854
8870
|
'</div>' +
|
|
@@ -8859,7 +8875,7 @@
|
|
|
8859
8875
|
if (msg.role === "prompt") {
|
|
8860
8876
|
return '<div class="chat-message prompt">' +
|
|
8861
8877
|
'<div class="prompt-card">' +
|
|
8862
|
-
'<div class="prompt-icon"
|
|
8878
|
+
'<div class="prompt-icon">→</div>' +
|
|
8863
8879
|
'<div class="prompt-content">试试:<span class="prompt-text">' + escapeHtml(msg.content) + '</span></div>' +
|
|
8864
8880
|
'</div>' +
|
|
8865
8881
|
'</div>';
|
|
@@ -8871,7 +8887,7 @@
|
|
|
8871
8887
|
}
|
|
8872
8888
|
|
|
8873
8889
|
// Legacy string content (from PTY parsing)
|
|
8874
|
-
var avatar = msg.role === "assistant" ? '<div class="chat-message-avatar"
|
|
8890
|
+
var avatar = msg.role === "assistant" ? '<div class="chat-message-avatar">赛博虎妞</div>' : "";
|
|
8875
8891
|
var bubbleContent = msg.role === "assistant" ? renderMarkdown(msg.content) : escapeHtml(msg.content);
|
|
8876
8892
|
return '<div class="chat-message ' + msg.role + '">' +
|
|
8877
8893
|
avatar +
|
|
@@ -8924,7 +8940,7 @@
|
|
|
8924
8940
|
|
|
8925
8941
|
function renderStructuredMessage(msg) {
|
|
8926
8942
|
var role = msg.role;
|
|
8927
|
-
var avatar = role === "assistant" ? '<div class="chat-message-avatar"
|
|
8943
|
+
var avatar = role === "assistant" ? '<div class="chat-message-avatar">赛博虎妞</div>' : "";
|
|
8928
8944
|
|
|
8929
8945
|
if (!msg.content || msg.content.length === 0) {
|
|
8930
8946
|
if (role === "assistant") {
|
|
@@ -8951,7 +8967,7 @@
|
|
|
8951
8967
|
} catch (e) {
|
|
8952
8968
|
return '<div class="chat-message ' + role + '">' +
|
|
8953
8969
|
avatar +
|
|
8954
|
-
'<div class="chat-message-
|
|
8970
|
+
'<div class="chat-message-content"><div class="render-error">消息渲染失败</div></div>' +
|
|
8955
8971
|
'</div>';
|
|
8956
8972
|
}
|
|
8957
8973
|
|
|
@@ -8970,7 +8986,7 @@
|
|
|
8970
8986
|
|
|
8971
8987
|
return '<div class="chat-message ' + role + '">' +
|
|
8972
8988
|
avatar +
|
|
8973
|
-
'<div class="chat-message-
|
|
8989
|
+
'<div class="chat-message-content">' + blocksHtml + '</div>' +
|
|
8974
8990
|
usageHtml +
|
|
8975
8991
|
'</div>';
|
|
8976
8992
|
}
|
|
@@ -8991,13 +9007,13 @@
|
|
|
8991
9007
|
if (isStreaming) {
|
|
8992
9008
|
return '<div class="thinking-inline thinking-streaming" data-thinking="">' +
|
|
8993
9009
|
'<div class="thinking-streaming-inner">' +
|
|
8994
|
-
'<span class="thinking-streaming-icon spinning"
|
|
9010
|
+
'<span class="thinking-streaming-icon spinning">⦿</span>' +
|
|
8995
9011
|
'<div class="thinking-streaming-text"></div>' +
|
|
8996
9012
|
'</div>' +
|
|
8997
9013
|
'</div>';
|
|
8998
9014
|
}
|
|
8999
9015
|
return '<div class="thinking-inline collapsed" data-thinking="' + escapeHtml(thinkingText) + '" onclick="__thinkingToggle(this)">' +
|
|
9000
|
-
'<span class="thinking-inline-icon"
|
|
9016
|
+
'<span class="thinking-inline-icon">⦿</span>' +
|
|
9001
9017
|
'<span class="thinking-inline-preview">' + escapeHtml(preview) + '</span>' +
|
|
9002
9018
|
'<span class="thinking-inline-action">展开</span>' +
|
|
9003
9019
|
'</div>';
|
|
@@ -9025,7 +9041,7 @@
|
|
|
9025
9041
|
|
|
9026
9042
|
var isError = toolResult && toolResult.is_error;
|
|
9027
9043
|
var hasResult = resultContent.length > 0;
|
|
9028
|
-
var statusIcon = isError ? "
|
|
9044
|
+
var statusIcon = isError ? "✗" : (hasResult ? "✓" : "…");
|
|
9029
9045
|
|
|
9030
9046
|
// Build the inline preview line
|
|
9031
9047
|
var icon = "";
|
|
@@ -9090,7 +9106,7 @@
|
|
|
9090
9106
|
var fullResult = resultContent;
|
|
9091
9107
|
|
|
9092
9108
|
var expandedHtml = "";
|
|
9093
|
-
var shouldExpand =
|
|
9109
|
+
var shouldExpand = false; // All inline tools collapsed by default
|
|
9094
9110
|
if (hasResult) {
|
|
9095
9111
|
expandedHtml = '<div class="inline-tool-expanded" style="display: ' + (shouldExpand ? 'block' : 'none') + ';">' +
|
|
9096
9112
|
'<div class="inline-tool-result">' + formatInlineResult(resultContent, toolName) + '</div>' +
|
|
@@ -9104,7 +9120,7 @@
|
|
|
9104
9120
|
|
|
9105
9121
|
var extraInfoHtml = meta ? '<span class="inline-tool-meta">' + escapeHtml(meta) + '</span>' : '';
|
|
9106
9122
|
var extraClass = isError ? 'inline-tool-error-inline' : '';
|
|
9107
|
-
if (
|
|
9123
|
+
if (shouldExpand) extraClass += ' inline-tool-open';
|
|
9108
9124
|
|
|
9109
9125
|
return '<div class="inline-tool ' + extraClass + '" ' +
|
|
9110
9126
|
'data-result="' + escapeHtml(fullResult) + '" ' +
|
|
@@ -9161,13 +9177,16 @@
|
|
|
9161
9177
|
exitCodeHtml = '<div class="term-exit ' + codeClass + '">exit ' + exitCode + '</div>';
|
|
9162
9178
|
}
|
|
9163
9179
|
|
|
9164
|
-
|
|
9180
|
+
// Show command preview in header (truncate long commands)
|
|
9181
|
+
var cmdPreview = command.length > 80 ? command.slice(0, 77) + "…" : command;
|
|
9182
|
+
|
|
9183
|
+
return '<div class="inline-terminal" data-expanded="false">' +
|
|
9165
9184
|
'<div class="term-header" onclick="__terminalExpand(this)">' +
|
|
9166
9185
|
statusDot +
|
|
9167
|
-
'<span class="term-
|
|
9168
|
-
'<span class="term-toggle-icon"
|
|
9186
|
+
'<span class="term-cmd-preview"><span class="term-prompt">$</span> ' + escapeHtml(cmdPreview) + '</span>' +
|
|
9187
|
+
'<span class="term-toggle-icon">▶</span>' +
|
|
9169
9188
|
'</div>' +
|
|
9170
|
-
'<div class="term-body">' +
|
|
9189
|
+
'<div class="term-body" style="display:none;">' +
|
|
9171
9190
|
'<div class="term-command"><span class="term-prompt">$</span> ' + cmdDisplay + '</div>' +
|
|
9172
9191
|
(outputHtml ? '<div class="term-output">' + outputHtml + '</div>' : '') +
|
|
9173
9192
|
exitCodeHtml +
|
|
@@ -9230,15 +9249,15 @@
|
|
|
9230
9249
|
if (isError) {
|
|
9231
9250
|
statusClass = "diff-error";
|
|
9232
9251
|
statusText = toolResultText.indexOf("haven't granted") !== -1 || toolResultText.indexOf("permission") !== -1
|
|
9233
|
-
? "
|
|
9234
|
-
: "
|
|
9252
|
+
? "等待授权"
|
|
9253
|
+
: "失败";
|
|
9235
9254
|
} else {
|
|
9236
9255
|
statusClass = "diff-success";
|
|
9237
|
-
statusText = "
|
|
9256
|
+
statusText = "已修改";
|
|
9238
9257
|
}
|
|
9239
9258
|
} else {
|
|
9240
9259
|
statusClass = "diff-pending";
|
|
9241
|
-
statusText = "
|
|
9260
|
+
statusText = "执行中";
|
|
9242
9261
|
}
|
|
9243
9262
|
|
|
9244
9263
|
// If only one column has content, show full width
|
|
@@ -9247,7 +9266,7 @@
|
|
|
9247
9266
|
|
|
9248
9267
|
return '<div class="inline-diff" data-tool-name="' + escapeHtml(toolName) + '">' +
|
|
9249
9268
|
'<div class="diff-header">' +
|
|
9250
|
-
'<span class="diff-file-icon"
|
|
9269
|
+
'<span class="diff-file-icon"></span>' +
|
|
9251
9270
|
'<span class="diff-file-name">' + escapeHtml(fileName) + '</span>' +
|
|
9252
9271
|
'<span class="diff-path">' + escapeHtml(path) + '</span>' +
|
|
9253
9272
|
'<span class="diff-status ' + statusClass + '">' + statusText + '</span>' +
|
|
@@ -9306,7 +9325,7 @@
|
|
|
9306
9325
|
}
|
|
9307
9326
|
return '<div class="tool-use-card ask-user" data-tool-use-id="' + escapeHtml(toolId) + '">' +
|
|
9308
9327
|
'<div class="tool-use-header" data-tool-toggle onclick="__tcToggle(event,this)">' +
|
|
9309
|
-
'<span class="tool-use-icon"
|
|
9328
|
+
'<span class="tool-use-icon">?</span>' +
|
|
9310
9329
|
'<span class="tool-use-name">提问</span>' +
|
|
9311
9330
|
'</div>' +
|
|
9312
9331
|
'<div class="tool-use-body ask-user-body">' +
|
|
@@ -9397,23 +9416,23 @@
|
|
|
9397
9416
|
|
|
9398
9417
|
function getToolIcon(toolName) {
|
|
9399
9418
|
var icons = {
|
|
9400
|
-
"Read": "
|
|
9401
|
-
"Write": "
|
|
9402
|
-
"Edit": "
|
|
9403
|
-
"MultiEdit": "
|
|
9404
|
-
"Bash": "
|
|
9405
|
-
"Grep": "
|
|
9406
|
-
"Glob": "
|
|
9407
|
-
"WebFetch": "
|
|
9408
|
-
"WebSearch": "
|
|
9409
|
-
"Task": "
|
|
9410
|
-
"TodoWrite": "
|
|
9411
|
-
"TodoRead": "
|
|
9412
|
-
"NotebookEdit": "
|
|
9413
|
-
"Agent": "
|
|
9414
|
-
"Exit": "
|
|
9419
|
+
"Read": "R",
|
|
9420
|
+
"Write": "W",
|
|
9421
|
+
"Edit": "E",
|
|
9422
|
+
"MultiEdit": "E",
|
|
9423
|
+
"Bash": "$",
|
|
9424
|
+
"Grep": "G",
|
|
9425
|
+
"Glob": "F",
|
|
9426
|
+
"WebFetch": "⇣",
|
|
9427
|
+
"WebSearch": "⇢",
|
|
9428
|
+
"Task": "T",
|
|
9429
|
+
"TodoWrite": "☐",
|
|
9430
|
+
"TodoRead": "☑",
|
|
9431
|
+
"NotebookEdit": "N",
|
|
9432
|
+
"Agent": "A",
|
|
9433
|
+
"Exit": "×"
|
|
9415
9434
|
};
|
|
9416
|
-
return icons[toolName] || "
|
|
9435
|
+
return icons[toolName] || "·";
|
|
9417
9436
|
}
|
|
9418
9437
|
|
|
9419
9438
|
function generateInputSummary(toolName, input) {
|
|
@@ -2231,6 +2231,7 @@
|
|
|
2231
2231
|
|
|
2232
2232
|
.chat-message.assistant {
|
|
2233
2233
|
align-self: flex-start;
|
|
2234
|
+
max-width: 95%;
|
|
2234
2235
|
}
|
|
2235
2236
|
|
|
2236
2237
|
.chat-message.system-info {
|
|
@@ -2296,9 +2297,11 @@
|
|
|
2296
2297
|
}
|
|
2297
2298
|
|
|
2298
2299
|
.chat-message.assistant .chat-message-avatar {
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2300
|
+
font-size: 0.75rem;
|
|
2301
|
+
font-weight: 600;
|
|
2302
|
+
color: var(--accent);
|
|
2303
|
+
padding: 0 2px 4px 2px;
|
|
2304
|
+
letter-spacing: 0.03em;
|
|
2302
2305
|
}
|
|
2303
2306
|
|
|
2304
2307
|
/* ===== 消息气泡 ===== */
|
|
@@ -2351,23 +2354,44 @@
|
|
|
2351
2354
|
box-shadow: var(--shadow-md);
|
|
2352
2355
|
}
|
|
2353
2356
|
|
|
2357
|
+
/* ===== 结构化消息内容(无气泡包裹) ===== */
|
|
2358
|
+
.chat-message-content {
|
|
2359
|
+
display: flex;
|
|
2360
|
+
flex-direction: column;
|
|
2361
|
+
gap: 2px;
|
|
2362
|
+
max-width: 100%;
|
|
2363
|
+
font-size: 0.875rem;
|
|
2364
|
+
line-height: var(--line-height-relaxed);
|
|
2365
|
+
word-wrap: break-word;
|
|
2366
|
+
color: var(--text-primary);
|
|
2367
|
+
}
|
|
2368
|
+
|
|
2369
|
+
.chat-message-content > .thinking-inline,
|
|
2370
|
+
.chat-message-content > .inline-tool,
|
|
2371
|
+
.chat-message-content > .terminal-tool,
|
|
2372
|
+
.chat-message-content > .diff-tool,
|
|
2373
|
+
.chat-message-content > .tool-use-card {
|
|
2374
|
+
margin: 1px 0;
|
|
2375
|
+
}
|
|
2376
|
+
|
|
2354
2377
|
/* ===== 消息使用量信息 ===== */
|
|
2355
2378
|
.message-usage {
|
|
2356
|
-
margin-top:
|
|
2357
|
-
padding-top:
|
|
2358
|
-
border-top: 1px
|
|
2379
|
+
margin-top: 8px;
|
|
2380
|
+
padding-top: 6px;
|
|
2381
|
+
border-top: 1px solid var(--border-subtle);
|
|
2359
2382
|
font-family: var(--font-mono);
|
|
2360
|
-
font-size: 0.
|
|
2361
|
-
color: var(--text-
|
|
2383
|
+
font-size: 0.625rem;
|
|
2384
|
+
color: var(--text-muted);
|
|
2362
2385
|
display: flex;
|
|
2363
|
-
gap:
|
|
2386
|
+
gap: 10px;
|
|
2364
2387
|
align-items: center;
|
|
2365
2388
|
flex-wrap: wrap;
|
|
2389
|
+
opacity: 0.5;
|
|
2366
2390
|
}
|
|
2367
2391
|
|
|
2368
2392
|
.message-usage::before {
|
|
2369
|
-
content: '
|
|
2370
|
-
color: var(--
|
|
2393
|
+
content: '·';
|
|
2394
|
+
color: var(--text-muted);
|
|
2371
2395
|
font-size: 0.625rem;
|
|
2372
2396
|
}
|
|
2373
2397
|
|
|
@@ -2488,9 +2512,9 @@
|
|
|
2488
2512
|
|
|
2489
2513
|
/* Tool Use Card */
|
|
2490
2514
|
.tool-use-card {
|
|
2491
|
-
margin:
|
|
2515
|
+
margin: 3px 0;
|
|
2492
2516
|
border: 1px solid var(--border-subtle);
|
|
2493
|
-
border-radius:
|
|
2517
|
+
border-radius: 8px;
|
|
2494
2518
|
overflow: hidden;
|
|
2495
2519
|
width: 100%;
|
|
2496
2520
|
box-sizing: border-box;
|
|
@@ -2498,9 +2522,8 @@
|
|
|
2498
2522
|
transition: all 0.3s var(--ease-out-expo);
|
|
2499
2523
|
}
|
|
2500
2524
|
.tool-use-card:hover {
|
|
2501
|
-
border-color: rgba(79, 122, 88, 0.
|
|
2502
|
-
|
|
2503
|
-
box-shadow: -4px 4px 16px rgba(79, 122, 88, 0.08);
|
|
2525
|
+
border-color: rgba(79, 122, 88, 0.25);
|
|
2526
|
+
box-shadow: 0 2px 8px rgba(79, 122, 88, 0.06);
|
|
2504
2527
|
}
|
|
2505
2528
|
.tool-use-card.loading {
|
|
2506
2529
|
border-color: rgba(79, 122, 88, 0.4);
|
|
@@ -2515,8 +2538,8 @@
|
|
|
2515
2538
|
display: flex;
|
|
2516
2539
|
align-items: center;
|
|
2517
2540
|
gap: 8px;
|
|
2518
|
-
padding:
|
|
2519
|
-
background: rgba(79, 122, 88, 0.
|
|
2541
|
+
padding: 8px 12px;
|
|
2542
|
+
background: rgba(79, 122, 88, 0.04);
|
|
2520
2543
|
cursor: pointer;
|
|
2521
2544
|
font-size: 0.8125rem;
|
|
2522
2545
|
user-select: none;
|
|
@@ -2524,7 +2547,7 @@
|
|
|
2524
2547
|
-webkit-tap-highlight-color: transparent;
|
|
2525
2548
|
touch-action: manipulation;
|
|
2526
2549
|
transition: all 0.2s var(--ease-out-expo);
|
|
2527
|
-
min-height:
|
|
2550
|
+
min-height: 36px;
|
|
2528
2551
|
flex-wrap: nowrap;
|
|
2529
2552
|
}
|
|
2530
2553
|
.tool-use-header:hover {
|
|
@@ -2543,12 +2566,18 @@
|
|
|
2543
2566
|
background: rgba(178, 79, 69, 0.1);
|
|
2544
2567
|
}
|
|
2545
2568
|
.tool-use-icon {
|
|
2546
|
-
font-size:
|
|
2569
|
+
font-size: 0.6875rem;
|
|
2570
|
+
font-family: var(--font-mono);
|
|
2571
|
+
font-weight: 600;
|
|
2547
2572
|
flex-shrink: 0;
|
|
2548
2573
|
display: flex;
|
|
2549
2574
|
align-items: center;
|
|
2550
2575
|
justify-content: center;
|
|
2551
|
-
min-width:
|
|
2576
|
+
min-width: 18px;
|
|
2577
|
+
height: 18px;
|
|
2578
|
+
border-radius: 4px;
|
|
2579
|
+
background: rgba(79, 122, 88, 0.1);
|
|
2580
|
+
color: var(--success);
|
|
2552
2581
|
}
|
|
2553
2582
|
.tool-use-spinner {
|
|
2554
2583
|
display: inline-block;
|
|
@@ -2745,22 +2774,22 @@
|
|
|
2745
2774
|
.thinking-inline {
|
|
2746
2775
|
display: flex;
|
|
2747
2776
|
align-items: baseline;
|
|
2748
|
-
gap:
|
|
2749
|
-
margin:
|
|
2750
|
-
padding:
|
|
2751
|
-
border-radius:
|
|
2752
|
-
background: rgba(138, 108, 178, 0.
|
|
2777
|
+
gap: 5px;
|
|
2778
|
+
margin: 2px 0;
|
|
2779
|
+
padding: 3px 8px;
|
|
2780
|
+
border-radius: 6px;
|
|
2781
|
+
background: rgba(138, 108, 178, 0.04);
|
|
2753
2782
|
cursor: pointer;
|
|
2754
|
-
font-size: 0.
|
|
2755
|
-
line-height: 1.
|
|
2756
|
-
color: rgba(138, 108, 178, 0.
|
|
2783
|
+
font-size: 0.75rem;
|
|
2784
|
+
line-height: 1.4;
|
|
2785
|
+
color: rgba(138, 108, 178, 0.55);
|
|
2757
2786
|
transition: background var(--transition-fast), color var(--transition-fast);
|
|
2758
2787
|
word-break: break-word;
|
|
2759
2788
|
overflow-wrap: break-word;
|
|
2760
2789
|
}
|
|
2761
2790
|
.thinking-inline:hover {
|
|
2762
|
-
background: rgba(138, 108, 178, 0.
|
|
2763
|
-
color: rgba(138, 108, 178, 0.
|
|
2791
|
+
background: rgba(138, 108, 178, 0.08);
|
|
2792
|
+
color: rgba(138, 108, 178, 0.8);
|
|
2764
2793
|
}
|
|
2765
2794
|
.thinking-inline.expanded {
|
|
2766
2795
|
color: var(--text-secondary);
|
|
@@ -2771,7 +2800,7 @@
|
|
|
2771
2800
|
}
|
|
2772
2801
|
.thinking-inline-icon {
|
|
2773
2802
|
flex-shrink: 0;
|
|
2774
|
-
font-size: 0.
|
|
2803
|
+
font-size: 0.625rem;
|
|
2775
2804
|
}
|
|
2776
2805
|
.thinking-inline-preview {
|
|
2777
2806
|
flex: 1;
|
|
@@ -2786,42 +2815,42 @@
|
|
|
2786
2815
|
}
|
|
2787
2816
|
.thinking-inline-action {
|
|
2788
2817
|
flex-shrink: 0;
|
|
2789
|
-
font-size: 0.
|
|
2790
|
-
color: rgba(138, 108, 178, 0.
|
|
2791
|
-
padding:
|
|
2818
|
+
font-size: 0.625rem;
|
|
2819
|
+
color: rgba(138, 108, 178, 0.4);
|
|
2820
|
+
padding: 0 4px;
|
|
2792
2821
|
border-radius: 3px;
|
|
2793
|
-
background: rgba(138, 108, 178, 0.
|
|
2822
|
+
background: rgba(138, 108, 178, 0.08);
|
|
2794
2823
|
margin-left: auto;
|
|
2795
2824
|
}
|
|
2796
2825
|
.thinking-inline:hover .thinking-inline-action {
|
|
2797
|
-
color: rgba(138, 108, 178, 0.
|
|
2826
|
+
color: rgba(138, 108, 178, 0.7);
|
|
2798
2827
|
}
|
|
2799
2828
|
.thinking-inline.thinking-pty {
|
|
2800
|
-
background: rgba(138, 108, 178, 0.
|
|
2829
|
+
background: rgba(138, 108, 178, 0.03);
|
|
2801
2830
|
}
|
|
2802
2831
|
|
|
2803
2832
|
/* Streaming thinking: 3-line scrollable area during thinking */
|
|
2804
2833
|
.thinking-streaming {
|
|
2805
2834
|
display: flex;
|
|
2806
2835
|
align-items: flex-start;
|
|
2807
|
-
gap:
|
|
2808
|
-
margin:
|
|
2809
|
-
padding:
|
|
2810
|
-
border-radius:
|
|
2811
|
-
background: rgba(138, 108, 178, 0.
|
|
2836
|
+
gap: 5px;
|
|
2837
|
+
margin: 2px 0;
|
|
2838
|
+
padding: 3px 8px;
|
|
2839
|
+
border-radius: 6px;
|
|
2840
|
+
background: rgba(138, 108, 178, 0.04);
|
|
2812
2841
|
cursor: default;
|
|
2813
|
-
font-size: 0.
|
|
2814
|
-
line-height: 1.
|
|
2815
|
-
color: rgba(138, 108, 178, 0.
|
|
2842
|
+
font-size: 0.75rem;
|
|
2843
|
+
line-height: 1.4;
|
|
2844
|
+
color: rgba(138, 108, 178, 0.55);
|
|
2816
2845
|
}
|
|
2817
2846
|
.thinking-streaming-inner {
|
|
2818
2847
|
display: flex;
|
|
2819
2848
|
align-items: flex-start;
|
|
2820
|
-
gap:
|
|
2849
|
+
gap: 5px;
|
|
2821
2850
|
width: 100%;
|
|
2822
2851
|
}
|
|
2823
2852
|
.thinking-streaming-icon {
|
|
2824
|
-
font-size: 0.
|
|
2853
|
+
font-size: 0.625rem;
|
|
2825
2854
|
flex-shrink: 0;
|
|
2826
2855
|
margin-top: 1px;
|
|
2827
2856
|
}
|
|
@@ -2851,33 +2880,38 @@
|
|
|
2851
2880
|
.inline-tool {
|
|
2852
2881
|
display: flex;
|
|
2853
2882
|
flex-direction: column;
|
|
2854
|
-
margin:
|
|
2855
|
-
border-radius:
|
|
2883
|
+
margin: 1px 0;
|
|
2884
|
+
border-radius: 6px;
|
|
2856
2885
|
cursor: pointer;
|
|
2857
2886
|
transition: background var(--transition-fast);
|
|
2858
2887
|
}
|
|
2859
2888
|
.inline-tool-row {
|
|
2860
2889
|
display: flex;
|
|
2861
2890
|
align-items: center;
|
|
2862
|
-
gap:
|
|
2863
|
-
padding:
|
|
2864
|
-
font-size: 0.
|
|
2891
|
+
gap: 5px;
|
|
2892
|
+
padding: 2px 6px;
|
|
2893
|
+
font-size: 0.6875rem;
|
|
2865
2894
|
color: var(--text-muted);
|
|
2866
2895
|
font-family: var(--font-mono);
|
|
2867
|
-
line-height: 1.
|
|
2896
|
+
line-height: 1.4;
|
|
2897
|
+
opacity: 0.7;
|
|
2868
2898
|
}
|
|
2869
2899
|
.inline-tool:hover .inline-tool-row {
|
|
2870
|
-
|
|
2871
|
-
|
|
2900
|
+
opacity: 1;
|
|
2901
|
+
background: rgba(0, 0, 0, 0.02);
|
|
2902
|
+
border-radius: 6px;
|
|
2872
2903
|
}
|
|
2873
2904
|
.inline-tool-status {
|
|
2874
|
-
font-size: 0.
|
|
2905
|
+
font-size: 0.625rem;
|
|
2875
2906
|
flex-shrink: 0;
|
|
2876
2907
|
}
|
|
2877
2908
|
.inline-tool-icon {
|
|
2878
2909
|
flex-shrink: 0;
|
|
2879
2910
|
color: var(--text-muted);
|
|
2880
|
-
margin: 0
|
|
2911
|
+
margin: 0 1px;
|
|
2912
|
+
opacity: 0.6;
|
|
2913
|
+
width: 12px;
|
|
2914
|
+
height: 12px;
|
|
2881
2915
|
}
|
|
2882
2916
|
.inline-tool-title {
|
|
2883
2917
|
flex: 1;
|
|
@@ -2885,13 +2919,13 @@
|
|
|
2885
2919
|
overflow: hidden;
|
|
2886
2920
|
text-overflow: ellipsis;
|
|
2887
2921
|
white-space: nowrap;
|
|
2888
|
-
color: var(--text-
|
|
2922
|
+
color: var(--text-muted);
|
|
2889
2923
|
}
|
|
2890
2924
|
.inline-tool-meta {
|
|
2891
2925
|
flex-shrink: 0;
|
|
2892
|
-
font-size: 0.
|
|
2926
|
+
font-size: 0.625rem;
|
|
2893
2927
|
color: var(--text-muted);
|
|
2894
|
-
opacity: 0.
|
|
2928
|
+
opacity: 0.5;
|
|
2895
2929
|
max-width: 200px;
|
|
2896
2930
|
overflow: hidden;
|
|
2897
2931
|
text-overflow: ellipsis;
|
|
@@ -2958,9 +2992,9 @@
|
|
|
2958
2992
|
|
|
2959
2993
|
/* ── Inline Terminal Display (Bash) ── */
|
|
2960
2994
|
.inline-terminal {
|
|
2961
|
-
margin:
|
|
2995
|
+
margin: 3px 0;
|
|
2962
2996
|
border: 1px solid rgba(255, 255, 255, 0.06);
|
|
2963
|
-
border-radius:
|
|
2997
|
+
border-radius: 8px;
|
|
2964
2998
|
background: #1a1714;
|
|
2965
2999
|
overflow: hidden;
|
|
2966
3000
|
}
|
|
@@ -2968,12 +3002,15 @@
|
|
|
2968
3002
|
display: flex;
|
|
2969
3003
|
align-items: center;
|
|
2970
3004
|
gap: 6px;
|
|
2971
|
-
padding:
|
|
3005
|
+
padding: 5px 10px;
|
|
2972
3006
|
background: rgba(255, 255, 255, 0.03);
|
|
2973
3007
|
font-size: 0.75rem;
|
|
2974
3008
|
cursor: pointer;
|
|
2975
3009
|
user-select: none;
|
|
2976
3010
|
}
|
|
3011
|
+
.term-header:hover {
|
|
3012
|
+
background: rgba(255, 255, 255, 0.05);
|
|
3013
|
+
}
|
|
2977
3014
|
.term-status-dot {
|
|
2978
3015
|
width: 6px;
|
|
2979
3016
|
height: 6px;
|
|
@@ -2988,6 +3025,22 @@
|
|
|
2988
3025
|
0%, 100% { opacity: 1; }
|
|
2989
3026
|
50% { opacity: 0.4; }
|
|
2990
3027
|
}
|
|
3028
|
+
.term-cmd-preview {
|
|
3029
|
+
flex: 1;
|
|
3030
|
+
min-width: 0;
|
|
3031
|
+
font-family: var(--font-mono);
|
|
3032
|
+
font-size: 0.6875rem;
|
|
3033
|
+
color: rgba(255, 255, 255, 0.45);
|
|
3034
|
+
overflow: hidden;
|
|
3035
|
+
text-overflow: ellipsis;
|
|
3036
|
+
white-space: nowrap;
|
|
3037
|
+
}
|
|
3038
|
+
.term-cmd-preview .term-prompt {
|
|
3039
|
+
color: rgba(110, 224, 154, 0.6);
|
|
3040
|
+
font-weight: 500;
|
|
3041
|
+
margin-right: 4px;
|
|
3042
|
+
font-size: 0.6875rem;
|
|
3043
|
+
}
|
|
2991
3044
|
.term-title {
|
|
2992
3045
|
flex: 1;
|
|
2993
3046
|
font-family: var(--font-mono);
|
|
@@ -2995,8 +3048,8 @@
|
|
|
2995
3048
|
color: rgba(255, 255, 255, 0.3);
|
|
2996
3049
|
}
|
|
2997
3050
|
.term-toggle-icon {
|
|
2998
|
-
font-size: 0.
|
|
2999
|
-
color: rgba(255, 255, 255, 0.
|
|
3051
|
+
font-size: 0.5rem;
|
|
3052
|
+
color: rgba(255, 255, 255, 0.25);
|
|
3000
3053
|
transition: transform var(--transition-fast);
|
|
3001
3054
|
}
|
|
3002
3055
|
.term-body {
|
|
@@ -3040,9 +3093,9 @@
|
|
|
3040
3093
|
|
|
3041
3094
|
/* ── Inline Diff Display (Edit, Write, MultiEdit) ── */
|
|
3042
3095
|
.inline-diff {
|
|
3043
|
-
margin:
|
|
3044
|
-
border: 1px solid rgba(0, 0, 0, 0.
|
|
3045
|
-
border-radius:
|
|
3096
|
+
margin: 3px 0;
|
|
3097
|
+
border: 1px solid rgba(0, 0, 0, 0.06);
|
|
3098
|
+
border-radius: 8px;
|
|
3046
3099
|
overflow: hidden;
|
|
3047
3100
|
background: var(--bg-secondary);
|
|
3048
3101
|
}
|
|
@@ -3055,8 +3108,7 @@
|
|
|
3055
3108
|
font-size: 0.75rem;
|
|
3056
3109
|
}
|
|
3057
3110
|
.diff-file-icon {
|
|
3058
|
-
|
|
3059
|
-
font-size: 0.875rem;
|
|
3111
|
+
display: none;
|
|
3060
3112
|
}
|
|
3061
3113
|
.diff-file-name {
|
|
3062
3114
|
font-family: var(--font-mono);
|
|
@@ -5480,7 +5532,7 @@
|
|
|
5480
5532
|
.btn-sm { min-height: 32px; }
|
|
5481
5533
|
|
|
5482
5534
|
.chat-message-bubble { padding: 8px 10px; font-size: 0.75rem; }
|
|
5483
|
-
.chat-message-avatar {
|
|
5535
|
+
.chat-message-avatar { font-size: 0.6875rem; }
|
|
5484
5536
|
|
|
5485
5537
|
/* 模态框移动端优化 */
|
|
5486
5538
|
.modal-backdrop {
|
package/dist/web-ui/index.js
CHANGED
|
@@ -37,7 +37,7 @@ ${cssStyles}
|
|
|
37
37
|
<div id="app"></div>
|
|
38
38
|
${scriptOpen} src="/vendor/xterm/lib/xterm.js">${scriptClose}
|
|
39
39
|
${scriptOpen} src="/vendor/xterm-addon-fit/lib/addon-fit.js">${scriptClose}
|
|
40
|
-
${scriptOpen} src="/vendor/xterm-addon-serialize/lib/
|
|
40
|
+
${scriptOpen} src="/vendor/xterm-addon-serialize/lib/addon-serialize.js">${scriptClose}
|
|
41
41
|
${scriptOpen}>
|
|
42
42
|
${scriptContent}
|
|
43
43
|
${scriptClose}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@co0ontty/wand",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "A web terminal for local CLI tools like Claude.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -35,12 +35,12 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@types/cookie": "^0.6.0",
|
|
37
37
|
"@xterm/addon-fit": "^0.11.0",
|
|
38
|
+
"@xterm/addon-serialize": "^0.14.0",
|
|
39
|
+
"@xterm/xterm": "^5.5.0",
|
|
38
40
|
"express": "^4.21.2",
|
|
39
41
|
"node-pty": "^1.1.0",
|
|
40
42
|
"puppeteer": "^24.40.0",
|
|
41
|
-
"ws": "^8.19.0"
|
|
42
|
-
"xterm": "^5.3.0",
|
|
43
|
-
"xterm-addon-serialize": "^0.11.0"
|
|
43
|
+
"ws": "^8.19.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/express": "^4.17.21",
|