@co0ontty/wand 1.21.15 → 1.21.16
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/web-ui/content/scripts.js +121 -145
- package/dist/web-ui/content/styles.css +0 -45
- package/package.json +1 -1
|
@@ -328,29 +328,81 @@
|
|
|
328
328
|
// 先驱动跨视图的运行指示器(顶部进度条/徽章计时/气泡呼吸条)
|
|
329
329
|
updateRunningIndicators(session);
|
|
330
330
|
|
|
331
|
-
//
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
// 顶部徽章计时复用。
|
|
335
|
-
var legacy = document.querySelector(".structured-status-bar");
|
|
336
|
-
if (legacy) legacy.remove();
|
|
337
|
-
|
|
331
|
+
// Status bar now lives in .composer-top-row alongside the todo-progress collapse bar
|
|
332
|
+
var topRow = document.querySelector(".composer-top-row");
|
|
333
|
+
var existing = document.querySelector(".structured-status-bar");
|
|
338
334
|
var composer = document.querySelector(".input-composer");
|
|
339
335
|
if (!session || !isStructuredSession(session)) {
|
|
336
|
+
if (existing) existing.remove();
|
|
340
337
|
if (composer) composer.classList.remove("in-flight");
|
|
341
|
-
|
|
342
|
-
|
|
338
|
+
clearInterval(_statusBarTimerId);
|
|
339
|
+
_statusBarTimerId = null;
|
|
343
340
|
return;
|
|
344
341
|
}
|
|
345
342
|
|
|
346
|
-
var isInFlight =
|
|
343
|
+
var isInFlight = session.structuredState && session.structuredState.inFlight;
|
|
344
|
+
|
|
347
345
|
if (isInFlight) {
|
|
348
|
-
if
|
|
346
|
+
// Start timer if not already running
|
|
347
|
+
if (!_statusBarTimerId) {
|
|
348
|
+
_statusBarStartTime = Date.now();
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Add glow to input composer
|
|
349
352
|
if (composer) composer.classList.add("in-flight");
|
|
353
|
+
|
|
354
|
+
if (!existing && topRow) {
|
|
355
|
+
var bar = document.createElement("div");
|
|
356
|
+
bar.className = "structured-status-bar";
|
|
357
|
+
bar.innerHTML =
|
|
358
|
+
'<span class="status-bar-dot"></span>' +
|
|
359
|
+
'<span class="status-bar-label">回复中</span>' +
|
|
360
|
+
'<span class="status-bar-timer">0.0s</span>';
|
|
361
|
+
// Append as last child of the top row so it sits to the right of the todo bar
|
|
362
|
+
topRow.appendChild(bar);
|
|
363
|
+
existing = bar;
|
|
364
|
+
} else if (existing && existing.classList.contains("completed")) {
|
|
365
|
+
// Was completed, now in-flight again — reset
|
|
366
|
+
existing.classList.remove("completed");
|
|
367
|
+
existing.style.animation = "none";
|
|
368
|
+
existing.querySelector(".status-bar-label").textContent = "回复中";
|
|
369
|
+
var dot = existing.querySelector(".status-bar-dot");
|
|
370
|
+
if (dot) dot.style.display = "";
|
|
371
|
+
_statusBarStartTime = Date.now();
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Start interval to update timer
|
|
375
|
+
if (!_statusBarTimerId) {
|
|
376
|
+
_statusBarTimerId = setInterval(function() {
|
|
377
|
+
var bar = document.querySelector(".structured-status-bar:not(.completed)");
|
|
378
|
+
if (!bar) { clearInterval(_statusBarTimerId); _statusBarTimerId = null; return; }
|
|
379
|
+
var elapsed = ((Date.now() - _statusBarStartTime) / 1000).toFixed(1);
|
|
380
|
+
var timerEl = bar.querySelector(".status-bar-timer");
|
|
381
|
+
if (timerEl) timerEl.textContent = elapsed + "s";
|
|
382
|
+
}, 100);
|
|
383
|
+
}
|
|
350
384
|
} else {
|
|
385
|
+
// Not in-flight: show completion or remove
|
|
386
|
+
clearInterval(_statusBarTimerId);
|
|
387
|
+
_statusBarTimerId = null;
|
|
388
|
+
|
|
389
|
+
// Remove glow from input composer
|
|
351
390
|
if (composer) composer.classList.remove("in-flight");
|
|
352
|
-
|
|
353
|
-
if (
|
|
391
|
+
|
|
392
|
+
if (existing && !existing.classList.contains("completed")) {
|
|
393
|
+
// Just finished — transition to completed state
|
|
394
|
+
var elapsed = _statusBarStartTime ? ((Date.now() - _statusBarStartTime) / 1000).toFixed(1) : "0.0";
|
|
395
|
+
existing.classList.add("completed");
|
|
396
|
+
existing.querySelector(".status-bar-label").textContent = "完成";
|
|
397
|
+
existing.querySelector(".status-bar-timer").textContent = elapsed + "s";
|
|
398
|
+
var dot = existing.querySelector(".status-bar-dot");
|
|
399
|
+
if (dot) dot.style.display = "none";
|
|
400
|
+
_statusBarStartTime = 0;
|
|
401
|
+
// Remove after animation ends
|
|
402
|
+
setTimeout(function() {
|
|
403
|
+
if (existing.parentNode) existing.remove();
|
|
404
|
+
}, 3000);
|
|
405
|
+
}
|
|
354
406
|
}
|
|
355
407
|
}
|
|
356
408
|
|
|
@@ -1373,12 +1425,10 @@
|
|
|
1373
1425
|
'<div class="todo-progress-header" id="todo-progress-toggle">' +
|
|
1374
1426
|
'<div class="todo-progress-left">' +
|
|
1375
1427
|
'<span class="todo-progress-spinner"></span>' +
|
|
1376
|
-
'<span class="todo-progress-
|
|
1377
|
-
|
|
1378
|
-
'<div class="todo-progress-right">' +
|
|
1379
|
-
'<span class="todo-progress-status" id="todo-progress-status">运行中</span>' +
|
|
1380
|
-
'<svg class="todo-progress-chevron" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>' +
|
|
1428
|
+
'<span class="todo-progress-counter" id="todo-progress-counter">0/0</span>' +
|
|
1429
|
+
'<span class="todo-progress-task" id="todo-progress-task"></span>' +
|
|
1381
1430
|
'</div>' +
|
|
1431
|
+
'<svg class="todo-progress-chevron" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>' +
|
|
1382
1432
|
'</div>' +
|
|
1383
1433
|
'<div class="todo-progress-body hidden" id="todo-progress-body">' +
|
|
1384
1434
|
'<ul class="todo-progress-list" id="todo-progress-list"></ul>' +
|
|
@@ -13981,122 +14031,77 @@
|
|
|
13981
14031
|
});
|
|
13982
14032
|
|
|
13983
14033
|
function updateTodoProgress(messages) {
|
|
13984
|
-
var
|
|
13985
|
-
|
|
13986
|
-
|
|
13987
|
-
|
|
13988
|
-
|
|
13989
|
-
|
|
13990
|
-
|
|
13991
|
-
|
|
13992
|
-
|
|
13993
|
-
|
|
13994
|
-
var lastUserText = "";
|
|
13995
|
-
if (Array.isArray(messages)) {
|
|
13996
|
-
for (var i = messages.length - 1; i >= 0; i--) {
|
|
13997
|
-
var umsg = messages[i];
|
|
13998
|
-
if (!umsg || umsg.role !== "user" || !Array.isArray(umsg.content)) continue;
|
|
13999
|
-
for (var uj = 0; uj < umsg.content.length; uj++) {
|
|
14000
|
-
var ublock = umsg.content[uj];
|
|
14001
|
-
if (ublock && ublock.type === "text" && ublock.text && ublock.text.trim()) {
|
|
14002
|
-
lastUserText = ublock.text.trim().replace(/\s+/g, " ");
|
|
14003
|
-
break;
|
|
14004
|
-
}
|
|
14034
|
+
var todos = null;
|
|
14035
|
+
// Scan all messages for latest TodoWrite tool_use
|
|
14036
|
+
for (var i = messages.length - 1; i >= 0; i--) {
|
|
14037
|
+
var msg = messages[i];
|
|
14038
|
+
if (!msg.content || !Array.isArray(msg.content)) continue;
|
|
14039
|
+
for (var j = msg.content.length - 1; j >= 0; j--) {
|
|
14040
|
+
var block = msg.content[j];
|
|
14041
|
+
if (block.type === "tool_use" && block.name === "TodoWrite" && block.input && block.input.todos) {
|
|
14042
|
+
todos = block.input.todos;
|
|
14043
|
+
break;
|
|
14005
14044
|
}
|
|
14006
|
-
if (lastUserText) break;
|
|
14007
14045
|
}
|
|
14046
|
+
if (todos) break;
|
|
14008
14047
|
}
|
|
14009
14048
|
|
|
14010
|
-
|
|
14011
|
-
if (!
|
|
14049
|
+
var container = document.getElementById("todo-progress");
|
|
14050
|
+
if (!container) return;
|
|
14051
|
+
|
|
14052
|
+
if (!todos || todos.length === 0) {
|
|
14012
14053
|
container.classList.add("hidden");
|
|
14013
14054
|
return;
|
|
14014
14055
|
}
|
|
14015
|
-
container.classList.remove("hidden");
|
|
14016
14056
|
|
|
14017
|
-
|
|
14018
|
-
var sig = computeRunningSignal(session);
|
|
14019
|
-
var isStructured = isStructuredSession(session);
|
|
14020
|
-
var isRunning = isStructured ? !!sig.inFlight : !!sig.ptyRunning;
|
|
14021
|
-
var statusText = isRunning
|
|
14022
|
-
? (isStructured ? "运行中" : "正在运行")
|
|
14023
|
-
: "已完成";
|
|
14057
|
+
container.classList.remove("hidden");
|
|
14024
14058
|
|
|
14025
|
-
|
|
14026
|
-
var
|
|
14027
|
-
|
|
14028
|
-
|
|
14029
|
-
|
|
14030
|
-
|
|
14031
|
-
|
|
14032
|
-
|
|
14033
|
-
|
|
14034
|
-
todos = tblock.input.todos;
|
|
14035
|
-
break;
|
|
14036
|
-
}
|
|
14059
|
+
var completed = 0;
|
|
14060
|
+
var inProgress = 0;
|
|
14061
|
+
var activeTask = "";
|
|
14062
|
+
for (var k = 0; k < todos.length; k++) {
|
|
14063
|
+
if (todos[k].status === "completed") completed++;
|
|
14064
|
+
if (todos[k].status === "in_progress") {
|
|
14065
|
+
inProgress++;
|
|
14066
|
+
if (!activeTask) {
|
|
14067
|
+
activeTask = todos[k].activeForm || todos[k].content || "";
|
|
14037
14068
|
}
|
|
14038
|
-
if (todos) break;
|
|
14039
14069
|
}
|
|
14040
14070
|
}
|
|
14041
14071
|
|
|
14042
|
-
|
|
14043
|
-
var
|
|
14044
|
-
var
|
|
14045
|
-
if (
|
|
14046
|
-
|
|
14047
|
-
|
|
14048
|
-
|
|
14049
|
-
|
|
14050
|
-
|
|
14051
|
-
}
|
|
14052
|
-
allTodosDone = completedCount === todos.length;
|
|
14053
|
-
if (isRunning && !allTodosDone) {
|
|
14054
|
-
var stepIdx = Math.max(1, completedCount + (inProgressCount > 0 ? 1 : 0));
|
|
14055
|
-
stepLabel = " · 第 " + stepIdx + "/" + todos.length + " 步";
|
|
14056
|
-
}
|
|
14072
|
+
// 显示当前执行步骤 = 已完成 + 正在进行(如果有)
|
|
14073
|
+
var currentStep = completed + inProgress;
|
|
14074
|
+
var allDone = completed === todos.length;
|
|
14075
|
+
if (allDone) {
|
|
14076
|
+
// Hide todo when all tasks are completed
|
|
14077
|
+
container.classList.add("hidden");
|
|
14078
|
+
return;
|
|
14079
|
+
} else {
|
|
14080
|
+
container.classList.remove("all-done");
|
|
14057
14081
|
}
|
|
14058
14082
|
|
|
14059
|
-
|
|
14060
|
-
|
|
14061
|
-
// 复用已有 .all-done 样式(隐藏 spinner + 显示绿色 ✓)
|
|
14062
|
-
container.classList.toggle("all-done", !isRunning);
|
|
14063
|
-
container.classList.toggle("has-todos", hasTodos);
|
|
14064
|
-
|
|
14065
|
-
// ── 写入 DOM ──
|
|
14066
|
-
var msgEl = document.getElementById("todo-progress-message");
|
|
14067
|
-
if (msgEl) msgEl.textContent = lastUserText;
|
|
14083
|
+
var counter = document.getElementById("todo-progress-counter");
|
|
14084
|
+
if (counter) counter.textContent = currentStep + "/" + todos.length;
|
|
14068
14085
|
|
|
14069
|
-
var
|
|
14070
|
-
if (
|
|
14086
|
+
var task = document.getElementById("todo-progress-task");
|
|
14087
|
+
if (task) task.textContent = activeTask;
|
|
14071
14088
|
|
|
14072
|
-
//
|
|
14089
|
+
// Render expanded list
|
|
14073
14090
|
var list = document.getElementById("todo-progress-list");
|
|
14074
14091
|
if (list) {
|
|
14075
|
-
|
|
14076
|
-
|
|
14077
|
-
|
|
14078
|
-
var
|
|
14079
|
-
|
|
14080
|
-
|
|
14081
|
-
|
|
14082
|
-
|
|
14083
|
-
|
|
14084
|
-
|
|
14085
|
-
|
|
14086
|
-
'<span class="todo-item-icon ' + iconClass + '">' + icon + '</span>' +
|
|
14087
|
-
'<span>' + escapeHtml(t.content || "") + '</span>' +
|
|
14088
|
-
'</li>';
|
|
14089
|
-
}
|
|
14090
|
-
list.innerHTML = html;
|
|
14092
|
+
var html = "";
|
|
14093
|
+
for (var m = 0; m < todos.length; m++) {
|
|
14094
|
+
var t = todos[m];
|
|
14095
|
+
var st = t.status || "pending";
|
|
14096
|
+
var itemClass = st === "in_progress" ? "active" : st === "completed" ? "done" : "";
|
|
14097
|
+
var iconClass = st === "in_progress" ? "active" : st === "completed" ? "done" : "pending";
|
|
14098
|
+
var icon = st === "completed" ? "✓" : st === "in_progress" ? "›" : "○";
|
|
14099
|
+
html += '<li class="todo-progress-item ' + itemClass + '">' +
|
|
14100
|
+
'<span class="todo-item-icon ' + iconClass + '">' + icon + '</span>' +
|
|
14101
|
+
'<span>' + escapeHtml(t.content || "") + '</span>' +
|
|
14102
|
+
'</li>';
|
|
14091
14103
|
}
|
|
14092
|
-
|
|
14093
|
-
|
|
14094
|
-
// 没有 todos 时强制收起 body(没东西可展开)
|
|
14095
|
-
if (!hasTodos) {
|
|
14096
|
-
todoExpanded = false;
|
|
14097
|
-
container.classList.remove("expanded");
|
|
14098
|
-
var body = document.getElementById("todo-progress-body");
|
|
14099
|
-
if (body) body.classList.add("hidden");
|
|
14104
|
+
list.innerHTML = html;
|
|
14100
14105
|
}
|
|
14101
14106
|
|
|
14102
14107
|
// Sync todo progress to native notification
|
|
@@ -16479,9 +16484,8 @@
|
|
|
16479
16484
|
var sessionLabel = session.summary || session.command || sessionId;
|
|
16480
16485
|
var sessionStatus = session.status || "running";
|
|
16481
16486
|
|
|
16482
|
-
//
|
|
16483
|
-
|
|
16484
|
-
if (sessionStatus === "archived") {
|
|
16487
|
+
// Clear notification for inactive sessions
|
|
16488
|
+
if (sessionStatus === "idle" || sessionStatus === "archived" || sessionStatus === "exited") {
|
|
16485
16489
|
clearSessionProgressNative(sessionId);
|
|
16486
16490
|
return;
|
|
16487
16491
|
}
|
|
@@ -16548,37 +16552,9 @@
|
|
|
16548
16552
|
currentTask = state.currentTask.title;
|
|
16549
16553
|
}
|
|
16550
16554
|
|
|
16551
|
-
// ── 与 web 通知条同源的 statusLabel / stepLabel / isRunning ──
|
|
16552
|
-
// 复用 computeRunningSignal & isStructuredSession,确保胶囊文字和顶部
|
|
16553
|
-
// 通知条永远保持一致。
|
|
16554
|
-
var sig = computeRunningSignal(session);
|
|
16555
|
-
var isStructured = isStructuredSession(session);
|
|
16556
|
-
var isRunning = isStructured ? !!sig.inFlight : !!sig.ptyRunning;
|
|
16557
|
-
var statusLabel = isRunning
|
|
16558
|
-
? (isStructured ? "运行中" : "正在运行")
|
|
16559
|
-
: "已完成";
|
|
16560
|
-
|
|
16561
|
-
var stepLabel = "";
|
|
16562
|
-
if (todos && todos.length > 0) {
|
|
16563
|
-
var completedCount = 0;
|
|
16564
|
-
var inProgressCount = 0;
|
|
16565
|
-
for (var sk = 0; sk < todos.length; sk++) {
|
|
16566
|
-
if (todos[sk].status === "completed") completedCount++;
|
|
16567
|
-
if (todos[sk].status === "in_progress") inProgressCount++;
|
|
16568
|
-
}
|
|
16569
|
-
var allTodosDone = completedCount === todos.length;
|
|
16570
|
-
if (isRunning && !allTodosDone) {
|
|
16571
|
-
var stepIdx = Math.max(1, completedCount + (inProgressCount > 0 ? 1 : 0));
|
|
16572
|
-
stepLabel = "第 " + stepIdx + "/" + todos.length + " 步";
|
|
16573
|
-
}
|
|
16574
|
-
}
|
|
16575
|
-
|
|
16576
16555
|
var data = {
|
|
16577
16556
|
sessionLabel: sessionLabel,
|
|
16578
16557
|
status: sessionStatus,
|
|
16579
|
-
isRunning: isRunning,
|
|
16580
|
-
statusLabel: statusLabel,
|
|
16581
|
-
stepLabel: stepLabel,
|
|
16582
16558
|
currentTask: currentTask,
|
|
16583
16559
|
latestUserText: latestUserText,
|
|
16584
16560
|
latestAssistantText: latestAssistantText,
|
|
@@ -5390,38 +5390,6 @@
|
|
|
5390
5390
|
text-overflow: ellipsis;
|
|
5391
5391
|
white-space: nowrap;
|
|
5392
5392
|
}
|
|
5393
|
-
/* 左侧:用户最新发出的消息 */
|
|
5394
|
-
.todo-progress-message {
|
|
5395
|
-
flex: 1;
|
|
5396
|
-
min-width: 0;
|
|
5397
|
-
font-size: 0.75rem;
|
|
5398
|
-
font-weight: 500;
|
|
5399
|
-
color: var(--text-primary);
|
|
5400
|
-
overflow: hidden;
|
|
5401
|
-
text-overflow: ellipsis;
|
|
5402
|
-
white-space: nowrap;
|
|
5403
|
-
}
|
|
5404
|
-
/* 右侧:状态文字 + 折叠箭头 */
|
|
5405
|
-
.todo-progress-right {
|
|
5406
|
-
display: flex;
|
|
5407
|
-
align-items: center;
|
|
5408
|
-
gap: 6px;
|
|
5409
|
-
flex-shrink: 0;
|
|
5410
|
-
min-width: 0;
|
|
5411
|
-
}
|
|
5412
|
-
.todo-progress-status {
|
|
5413
|
-
font-size: 0.75rem;
|
|
5414
|
-
font-weight: 500;
|
|
5415
|
-
color: var(--text-secondary);
|
|
5416
|
-
white-space: nowrap;
|
|
5417
|
-
letter-spacing: 0.01em;
|
|
5418
|
-
}
|
|
5419
|
-
.todo-progress.is-running .todo-progress-status {
|
|
5420
|
-
color: var(--accent);
|
|
5421
|
-
}
|
|
5422
|
-
.todo-progress.all-done .todo-progress-status {
|
|
5423
|
-
color: #4a7a4f;
|
|
5424
|
-
}
|
|
5425
5393
|
.todo-progress-chevron {
|
|
5426
5394
|
color: var(--text-muted);
|
|
5427
5395
|
flex-shrink: 0;
|
|
@@ -5430,16 +5398,6 @@
|
|
|
5430
5398
|
.todo-progress.expanded .todo-progress-chevron {
|
|
5431
5399
|
transform: rotate(180deg);
|
|
5432
5400
|
}
|
|
5433
|
-
/* 没有 todo 列表时,没什么可展开的——隐藏箭头并去掉指针手势 */
|
|
5434
|
-
.todo-progress:not(.has-todos) .todo-progress-chevron {
|
|
5435
|
-
display: none;
|
|
5436
|
-
}
|
|
5437
|
-
.todo-progress:not(.has-todos) .todo-progress-header {
|
|
5438
|
-
cursor: default;
|
|
5439
|
-
}
|
|
5440
|
-
.todo-progress:not(.has-todos) .todo-progress-header:hover {
|
|
5441
|
-
background: transparent;
|
|
5442
|
-
}
|
|
5443
5401
|
.todo-progress-body {
|
|
5444
5402
|
border-top: 1px solid var(--border-subtle);
|
|
5445
5403
|
padding: 6px 10px 8px;
|
|
@@ -8580,9 +8538,6 @@
|
|
|
8580
8538
|
.todo-progress-header { padding: 3px 6px; gap: 4px; }
|
|
8581
8539
|
.todo-progress-counter { font-size: 0.5625rem; }
|
|
8582
8540
|
.todo-progress-task { font-size: 0.5625rem; }
|
|
8583
|
-
.todo-progress-message { font-size: 0.625rem; }
|
|
8584
|
-
.todo-progress-status { font-size: 0.5625rem; }
|
|
8585
|
-
.todo-progress-right { gap: 4px; }
|
|
8586
8541
|
.todo-progress-chevron { width: 12px; height: 12px; }
|
|
8587
8542
|
.todo-progress-body { padding: 4px 6px; }
|
|
8588
8543
|
|