@co0ontty/wand 1.5.7 → 1.6.0
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/process-manager.js
CHANGED
|
@@ -397,6 +397,24 @@ function getLatestClaudeTaskId(excludeIds) {
|
|
|
397
397
|
return null;
|
|
398
398
|
}
|
|
399
399
|
}
|
|
400
|
+
/** Derive a short summary for a session from user messages or current task. */
|
|
401
|
+
function deriveSessionSummary(messages, currentTaskTitle) {
|
|
402
|
+
// Prefer first user message as summary
|
|
403
|
+
for (const msg of messages) {
|
|
404
|
+
if (msg.role !== "user")
|
|
405
|
+
continue;
|
|
406
|
+
for (const block of msg.content) {
|
|
407
|
+
if (block.type === "text" && block.text.trim()) {
|
|
408
|
+
return block.text.trim().slice(0, 120);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
break; // only check the first user turn
|
|
412
|
+
}
|
|
413
|
+
// Fallback to current task title
|
|
414
|
+
if (currentTaskTitle)
|
|
415
|
+
return currentTaskTitle.slice(0, 120);
|
|
416
|
+
return undefined;
|
|
417
|
+
}
|
|
400
418
|
export class ProcessManager extends EventEmitter {
|
|
401
419
|
config;
|
|
402
420
|
storage;
|
|
@@ -1102,7 +1120,8 @@ export class ProcessManager extends EventEmitter {
|
|
|
1102
1120
|
resumedToSessionId: record.resumedToSessionId ?? undefined,
|
|
1103
1121
|
autoRecovered: record.autoRecovered ?? false,
|
|
1104
1122
|
autoApprovePermissions: record.autoApprovePermissions || undefined,
|
|
1105
|
-
approvalStats: record.approvalStats.total > 0 ? record.approvalStats : undefined
|
|
1123
|
+
approvalStats: record.approvalStats.total > 0 ? record.approvalStats : undefined,
|
|
1124
|
+
summary: deriveSessionSummary(messages, record.currentTask?.title ?? null),
|
|
1106
1125
|
};
|
|
1107
1126
|
}
|
|
1108
1127
|
isPermissionBlocked(record) {
|
|
@@ -4,6 +4,23 @@ const STREAM_EMIT_DEBOUNCE_MS = 16;
|
|
|
4
4
|
function isRunningAsRoot() {
|
|
5
5
|
return process.getuid?.() === 0 || process.geteuid?.() === 0;
|
|
6
6
|
}
|
|
7
|
+
/** Enrich a snapshot with a derived summary from the first user message. */
|
|
8
|
+
function withSummary(snapshot) {
|
|
9
|
+
if (snapshot.summary)
|
|
10
|
+
return snapshot;
|
|
11
|
+
const messages = snapshot.messages ?? [];
|
|
12
|
+
for (const msg of messages) {
|
|
13
|
+
if (msg.role !== "user")
|
|
14
|
+
continue;
|
|
15
|
+
for (const block of msg.content) {
|
|
16
|
+
if (block.type === "text" && block.text.trim()) {
|
|
17
|
+
return { ...snapshot, summary: block.text.trim().slice(0, 120) };
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
return snapshot;
|
|
23
|
+
}
|
|
7
24
|
/** Should we auto-approve permissions for this mode? */
|
|
8
25
|
function shouldAutoApproveForMode(mode) {
|
|
9
26
|
return mode === "full-access" || mode === "managed" || mode === "auto-edit";
|
|
@@ -46,10 +63,13 @@ export class StructuredSessionManager {
|
|
|
46
63
|
this.emitEvent = emitEvent;
|
|
47
64
|
}
|
|
48
65
|
list() {
|
|
49
|
-
return Array.from(this.sessions.values())
|
|
66
|
+
return Array.from(this.sessions.values())
|
|
67
|
+
.map(withSummary)
|
|
68
|
+
.sort((a, b) => b.startedAt.localeCompare(a.startedAt));
|
|
50
69
|
}
|
|
51
70
|
get(id) {
|
|
52
|
-
|
|
71
|
+
const s = this.sessions.get(id);
|
|
72
|
+
return s ? withSummary(s) : null;
|
|
53
73
|
}
|
|
54
74
|
createSession(options) {
|
|
55
75
|
const id = randomUUID();
|
package/dist/types.d.ts
CHANGED
|
@@ -189,6 +189,8 @@ export interface SessionSnapshot {
|
|
|
189
189
|
file: number;
|
|
190
190
|
total: number;
|
|
191
191
|
};
|
|
192
|
+
/** 会话摘要:从首条用户消息或当前任务提取 */
|
|
193
|
+
summary?: string;
|
|
192
194
|
}
|
|
193
195
|
export type SessionLifecycleState = "initializing" | "running" | "idle" | "thinking" | "waiting-input" | "archived";
|
|
194
196
|
export interface SessionLifecycle {
|
|
@@ -678,7 +678,6 @@
|
|
|
678
678
|
'</div>' +
|
|
679
679
|
'<div class="todo-progress-body hidden" id="todo-progress-body">' +
|
|
680
680
|
'<ul class="todo-progress-list" id="todo-progress-list"></ul>' +
|
|
681
|
-
'<div id="recent-actions" class="recent-actions"></div>' +
|
|
682
681
|
'</div>' +
|
|
683
682
|
'</div>' +
|
|
684
683
|
'<div class="input-composer">' +
|
|
@@ -1816,7 +1815,9 @@
|
|
|
1816
1815
|
'<div class="session-item-row">' +
|
|
1817
1816
|
checkbox +
|
|
1818
1817
|
'<div class="session-main">' +
|
|
1819
|
-
|
|
1818
|
+
(session.summary
|
|
1819
|
+
? '<div class="session-title">' + escapeHtml(session.summary) + '</div>'
|
|
1820
|
+
: '<div class="session-command">' + escapeHtml(session.resumedFromSessionId ? session.command.replace(/\s+--resume\s+\S+/, '') : session.command) + '</div>') +
|
|
1820
1821
|
'<div class="session-meta">' +
|
|
1821
1822
|
modeBadge +
|
|
1822
1823
|
'<span>' + escapeHtml(modeName) + '</span>' +
|
|
@@ -8375,40 +8376,6 @@
|
|
|
8375
8376
|
list.innerHTML = html;
|
|
8376
8377
|
}
|
|
8377
8378
|
|
|
8378
|
-
// Extract recent important actions for key points summary
|
|
8379
|
-
var recentActions = [];
|
|
8380
|
-
var actionTools = ["Write", "Edit", "Bash", "WebFetch", "WebSearch"];
|
|
8381
|
-
var msgCount = messages.length;
|
|
8382
|
-
for (var ai = 0; ai < msgCount && recentActions.length < 5; ai++) {
|
|
8383
|
-
var m = messages[ai];
|
|
8384
|
-
if (!m.content || !Array.isArray(m.content)) continue;
|
|
8385
|
-
for (var bi = 0; bi < m.content.length && recentActions.length < 5; bi++) {
|
|
8386
|
-
var blk = m.content[bi];
|
|
8387
|
-
if (blk.type !== "tool_use") continue;
|
|
8388
|
-
var toolName = blk.name || "";
|
|
8389
|
-
if (actionTools.indexOf(toolName) === -1) continue;
|
|
8390
|
-
var desc = blk.description || generateInputSummary(toolName, blk.input) || toolName;
|
|
8391
|
-
if (desc && desc.length > 50) desc = desc.slice(0, 47) + "...";
|
|
8392
|
-
var icon = getToolIcon(toolName);
|
|
8393
|
-
recentActions.push({ icon: icon, text: desc });
|
|
8394
|
-
}
|
|
8395
|
-
}
|
|
8396
|
-
|
|
8397
|
-
var actionsEl = document.getElementById("recent-actions");
|
|
8398
|
-
if (actionsEl) {
|
|
8399
|
-
if (recentActions.length > 0) {
|
|
8400
|
-
var actionsHtml = '<div class="recent-actions-label">最近操作</div>';
|
|
8401
|
-
actionsHtml += '<div class="recent-actions-list">';
|
|
8402
|
-
for (var ri = 0; ri < recentActions.length; ri++) {
|
|
8403
|
-
var a = recentActions[ri];
|
|
8404
|
-
actionsHtml += '<span class="recent-action-pill">' + a.icon + ' ' + escapeHtml(a.text) + '</span>';
|
|
8405
|
-
}
|
|
8406
|
-
actionsHtml += '</div>';
|
|
8407
|
-
actionsEl.innerHTML = actionsHtml;
|
|
8408
|
-
} else {
|
|
8409
|
-
actionsEl.innerHTML = '';
|
|
8410
|
-
}
|
|
8411
|
-
}
|
|
8412
8379
|
}
|
|
8413
8380
|
|
|
8414
8381
|
function updateQueueCounter() {
|
|
@@ -8944,6 +8911,67 @@
|
|
|
8944
8911
|
return messages;
|
|
8945
8912
|
}
|
|
8946
8913
|
|
|
8914
|
+
// ── 像素风猫咪头像 ──
|
|
8915
|
+
var PIXEL_AVATAR = (function() {
|
|
8916
|
+
var _ = "transparent";
|
|
8917
|
+
function buildSvg(grid, size) {
|
|
8918
|
+
var s = size || 3;
|
|
8919
|
+
var w = grid[0].length * s;
|
|
8920
|
+
var h = grid.length * s;
|
|
8921
|
+
var rects = "";
|
|
8922
|
+
for (var y = 0; y < grid.length; y++) {
|
|
8923
|
+
for (var x = 0; x < grid[y].length; x++) {
|
|
8924
|
+
if (grid[y][x] !== _) {
|
|
8925
|
+
rects += '<rect x="' + (x * s) + '" y="' + (y * s) + '" width="' + s + '" height="' + s + '" fill="' + grid[y][x] + '"/>';
|
|
8926
|
+
}
|
|
8927
|
+
}
|
|
8928
|
+
}
|
|
8929
|
+
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ' + w + ' ' + h + '" class="pixel-avatar-svg">' + rects + '</svg>';
|
|
8930
|
+
}
|
|
8931
|
+
// 加菲猫 (勤劳初二 / AI) — 橙色系
|
|
8932
|
+
var o = "#F0923A", d = "#C46A1A", w = "#FFFFFF", k = "#2D2D2D", p = "#F28B9A", n = "#E87D5A";
|
|
8933
|
+
var garfield = [
|
|
8934
|
+
[_,d,_,_,_,_,_,_,d,_],
|
|
8935
|
+
[d,o,d,_,_,_,_,d,o,d],
|
|
8936
|
+
[d,o,o,o,o,o,o,o,o,d],
|
|
8937
|
+
[o,o,w,k,o,o,w,k,o,o],
|
|
8938
|
+
[o,o,w,w,o,o,w,w,o,o],
|
|
8939
|
+
[o,o,o,o,p,p,o,o,o,o],
|
|
8940
|
+
[o,d,o,n,o,o,n,o,d,o],
|
|
8941
|
+
[_,o,o,o,o,o,o,o,o,_],
|
|
8942
|
+
[_,_,o,d,o,o,d,o,_,_],
|
|
8943
|
+
[_,_,_,o,_,_,o,_,_,_],
|
|
8944
|
+
];
|
|
8945
|
+
// 美短 (赛博虎妞 / 用户) — 灰色系
|
|
8946
|
+
var g = "#9EAAB8", dg = "#6B7B8D", lg = "#C5CED8", gn = "#7EC88B";
|
|
8947
|
+
var shorthair = [
|
|
8948
|
+
[_,dg,_,_,_,_,_,_,dg,_],
|
|
8949
|
+
[dg,g,dg,_,_,_,_,dg,g,dg],
|
|
8950
|
+
[dg,g,g,g,g,g,g,g,g,dg],
|
|
8951
|
+
[g,g,w,gn,g,g,w,gn,g,g],
|
|
8952
|
+
[g,g,w,w,g,g,w,w,g,g],
|
|
8953
|
+
[g,g,g,g,p,p,g,g,g,g],
|
|
8954
|
+
[g,dg,g,lg,g,g,lg,g,dg,g],
|
|
8955
|
+
[_,g,g,g,g,g,g,g,g,_],
|
|
8956
|
+
[_,_,g,dg,g,g,dg,g,_,_],
|
|
8957
|
+
[_,_,_,g,_,_,g,_,_,_],
|
|
8958
|
+
];
|
|
8959
|
+
return {
|
|
8960
|
+
assistant: buildSvg(garfield),
|
|
8961
|
+
user: buildSvg(shorthair)
|
|
8962
|
+
};
|
|
8963
|
+
})();
|
|
8964
|
+
|
|
8965
|
+
function chatAvatar(role) {
|
|
8966
|
+
var isUser = role === "user";
|
|
8967
|
+
var svg = isUser ? PIXEL_AVATAR.user : PIXEL_AVATAR.assistant;
|
|
8968
|
+
var name = isUser ? "赛博虎妞" : "勤劳初二";
|
|
8969
|
+
return '<div class="chat-message-avatar ' + role + '">' +
|
|
8970
|
+
'<div class="pixel-avatar">' + svg + '</div>' +
|
|
8971
|
+
'<span class="avatar-name">' + name + '</span>' +
|
|
8972
|
+
'</div>';
|
|
8973
|
+
}
|
|
8974
|
+
|
|
8947
8975
|
function renderChatMessage(msg, roundUsage) {
|
|
8948
8976
|
// Thinking card (deep thought) — from PTY parsing
|
|
8949
8977
|
if (msg.role === "thinking") {
|
|
@@ -8972,7 +9000,7 @@
|
|
|
8972
9000
|
}
|
|
8973
9001
|
|
|
8974
9002
|
// Legacy string content (from PTY parsing)
|
|
8975
|
-
var avatar = msg.role
|
|
9003
|
+
var avatar = chatAvatar(msg.role);
|
|
8976
9004
|
var bubbleContent = msg.role === "assistant" ? renderMarkdown(msg.content) : escapeHtml(msg.content);
|
|
8977
9005
|
return '<div class="chat-message ' + msg.role + '">' +
|
|
8978
9006
|
avatar +
|
|
@@ -9117,7 +9145,7 @@
|
|
|
9117
9145
|
|
|
9118
9146
|
function renderStructuredMessage(msg, roundUsage) {
|
|
9119
9147
|
var role = msg.role;
|
|
9120
|
-
var avatar = role
|
|
9148
|
+
var avatar = chatAvatar(role);
|
|
9121
9149
|
|
|
9122
9150
|
if (!msg.content || msg.content.length === 0) {
|
|
9123
9151
|
if (role === "assistant") {
|
|
@@ -1162,6 +1162,17 @@
|
|
|
1162
1162
|
letter-spacing: -0.01em;
|
|
1163
1163
|
}
|
|
1164
1164
|
|
|
1165
|
+
.session-title {
|
|
1166
|
+
font-weight: 600;
|
|
1167
|
+
font-size: 0.8125rem;
|
|
1168
|
+
white-space: nowrap;
|
|
1169
|
+
overflow: hidden;
|
|
1170
|
+
text-overflow: ellipsis;
|
|
1171
|
+
color: var(--text-primary);
|
|
1172
|
+
letter-spacing: -0.01em;
|
|
1173
|
+
line-height: 1.3;
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1165
1176
|
/* ===== 会话元信息 ===== */
|
|
1166
1177
|
.session-meta {
|
|
1167
1178
|
display: flex;
|
|
@@ -2292,16 +2303,51 @@
|
|
|
2292
2303
|
}
|
|
2293
2304
|
|
|
2294
2305
|
/* ===== 消息头像 ===== */
|
|
2295
|
-
.chat-message
|
|
2296
|
-
display:
|
|
2306
|
+
.chat-message-avatar {
|
|
2307
|
+
display: flex;
|
|
2308
|
+
align-items: center;
|
|
2309
|
+
gap: 6px;
|
|
2310
|
+
padding: 0 2px 4px 2px;
|
|
2297
2311
|
}
|
|
2298
2312
|
|
|
2299
|
-
.chat-message.assistant
|
|
2300
|
-
|
|
2313
|
+
.chat-message-avatar.assistant {
|
|
2314
|
+
flex-direction: row;
|
|
2315
|
+
}
|
|
2316
|
+
|
|
2317
|
+
.chat-message-avatar.user {
|
|
2318
|
+
flex-direction: row-reverse;
|
|
2319
|
+
}
|
|
2320
|
+
|
|
2321
|
+
.pixel-avatar {
|
|
2322
|
+
width: 24px;
|
|
2323
|
+
height: 24px;
|
|
2324
|
+
flex-shrink: 0;
|
|
2325
|
+
border-radius: 6px;
|
|
2326
|
+
overflow: hidden;
|
|
2327
|
+
background: var(--bg-tertiary);
|
|
2328
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
|
|
2329
|
+
}
|
|
2330
|
+
|
|
2331
|
+
.pixel-avatar-svg {
|
|
2332
|
+
display: block;
|
|
2333
|
+
width: 100%;
|
|
2334
|
+
height: 100%;
|
|
2335
|
+
image-rendering: pixelated;
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2338
|
+
.avatar-name {
|
|
2339
|
+
font-size: 0.7rem;
|
|
2301
2340
|
font-weight: 600;
|
|
2302
|
-
color: var(--accent);
|
|
2303
|
-
padding: 0 2px 4px 2px;
|
|
2304
2341
|
letter-spacing: 0.03em;
|
|
2342
|
+
line-height: 1;
|
|
2343
|
+
}
|
|
2344
|
+
|
|
2345
|
+
.chat-message.assistant .avatar-name {
|
|
2346
|
+
color: var(--accent);
|
|
2347
|
+
}
|
|
2348
|
+
|
|
2349
|
+
.chat-message.user .avatar-name {
|
|
2350
|
+
color: var(--text-tertiary);
|
|
2305
2351
|
}
|
|
2306
2352
|
|
|
2307
2353
|
/* ===== 消息气泡 ===== */
|
|
@@ -3904,39 +3950,6 @@
|
|
|
3904
3950
|
.todo-item-icon.active { color: var(--accent); }
|
|
3905
3951
|
.todo-item-icon.done { color: #4a7a4f; }
|
|
3906
3952
|
|
|
3907
|
-
/* Recent actions key points section */
|
|
3908
|
-
.recent-actions {
|
|
3909
|
-
margin-top: 8px;
|
|
3910
|
-
padding-top: 8px;
|
|
3911
|
-
border-top: 1px solid var(--border-subtle);
|
|
3912
|
-
}
|
|
3913
|
-
.recent-actions-label {
|
|
3914
|
-
font-size: 0.6875rem;
|
|
3915
|
-
font-weight: 600;
|
|
3916
|
-
color: var(--text-muted);
|
|
3917
|
-
text-transform: uppercase;
|
|
3918
|
-
letter-spacing: 0.03em;
|
|
3919
|
-
margin-bottom: 6px;
|
|
3920
|
-
}
|
|
3921
|
-
.recent-actions-list {
|
|
3922
|
-
display: flex;
|
|
3923
|
-
flex-wrap: wrap;
|
|
3924
|
-
gap: 4px;
|
|
3925
|
-
}
|
|
3926
|
-
.recent-action-pill {
|
|
3927
|
-
display: inline-flex;
|
|
3928
|
-
align-items: center;
|
|
3929
|
-
gap: 3px;
|
|
3930
|
-
padding: 3px 8px;
|
|
3931
|
-
font-size: 0.6875rem;
|
|
3932
|
-
color: var(--text-secondary);
|
|
3933
|
-
background: rgba(79, 122, 88, 0.08);
|
|
3934
|
-
border-radius: 10px;
|
|
3935
|
-
white-space: nowrap;
|
|
3936
|
-
max-width: 220px;
|
|
3937
|
-
overflow: hidden;
|
|
3938
|
-
text-overflow: ellipsis;
|
|
3939
|
-
}
|
|
3940
3953
|
|
|
3941
3954
|
@keyframes spin {
|
|
3942
3955
|
to { transform: rotate(360deg); }
|