evolclaw-web 1.1.0 → 1.2.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/index.js +9 -9
- package/dist/process-utils.js +20 -12
- package/dist/server.js +75 -14
- package/dist/sources/aid.js +20 -1
- package/dist/sources/monitor.js +96 -0
- package/dist/sources/session.js +10 -1
- package/dist/sources/system.js +2 -2
- package/dist/static/app.js +632 -120
- package/dist/static/index.html +31 -2
- package/dist/static/style.css +176 -10
- package/package.json +2 -2
- package/dist/sources/control.js +0 -58
package/dist/static/index.html
CHANGED
|
@@ -32,11 +32,11 @@
|
|
|
32
32
|
<button class="tab" data-view="cache">Cache</button>
|
|
33
33
|
<button class="tab" data-view="system">System</button>
|
|
34
34
|
<button class="tab" data-view="usage">Usage</button>
|
|
35
|
+
<button class="tab" data-view="monitor">Monitor</button>
|
|
35
36
|
|
|
36
37
|
</nav>
|
|
37
|
-
<span id="today-cost" class="today-cost"></span>
|
|
38
38
|
<span style="flex:1"></span>
|
|
39
|
-
2026-06-
|
|
39
|
+
2026-06-12 22:54
|
|
40
40
|
<span id="conn-status" class="conn-status">连接中…</span>
|
|
41
41
|
<button id="theme-btn" class="theme-btn" title="切换主题">🌗</button>
|
|
42
42
|
<button id="logout-btn" class="logout-btn" title="退出配对">退出</button>
|
|
@@ -139,6 +139,35 @@
|
|
|
139
139
|
</div>
|
|
140
140
|
</section>
|
|
141
141
|
|
|
142
|
+
<section id="view-monitor" class="view">
|
|
143
|
+
<div class="mon-layout">
|
|
144
|
+
<div class="mon-toolbar">
|
|
145
|
+
<span class="mon-toolbar-label">时间范围</span>
|
|
146
|
+
<div class="mon-range-tabs">
|
|
147
|
+
<button class="mon-range active" data-range="2m">2 分钟</button>
|
|
148
|
+
<button class="mon-range" data-range="10m">10 分钟</button>
|
|
149
|
+
<button class="mon-range" data-range="1h">1 小时</button>
|
|
150
|
+
</div>
|
|
151
|
+
<span style="flex:1"></span>
|
|
152
|
+
<span class="mon-legend">
|
|
153
|
+
<span class="mon-legend-item"><i class="lg-dot lg-proc"></i>evolclaw 进程</span>
|
|
154
|
+
<span class="mon-legend-item"><i class="lg-dot lg-sys"></i>整机系统</span>
|
|
155
|
+
</span>
|
|
156
|
+
</div>
|
|
157
|
+
<div id="mon-cards" class="usage-cards"></div>
|
|
158
|
+
<div class="mon-row2">
|
|
159
|
+
<div id="mon-cpu-chart" class="mon-chart"></div>
|
|
160
|
+
<div id="mon-mem-chart" class="mon-chart"></div>
|
|
161
|
+
</div>
|
|
162
|
+
<div class="mon-row2">
|
|
163
|
+
<div id="mon-msg-chart" class="mon-chart"></div>
|
|
164
|
+
<div id="mon-err-chart" class="mon-chart"></div>
|
|
165
|
+
</div>
|
|
166
|
+
<div class="mon-table-wrap" id="mon-agent-table-wrap"></div>
|
|
167
|
+
<div class="mon-err-wrap" id="mon-err-list"></div>
|
|
168
|
+
</div>
|
|
169
|
+
</section>
|
|
170
|
+
|
|
142
171
|
</main>
|
|
143
172
|
</div>
|
|
144
173
|
|
package/dist/static/style.css
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
--orange: #dd6b20;
|
|
13
13
|
--blue: #4f6ef7;
|
|
14
14
|
--magenta: #805ad5;
|
|
15
|
+
--msg-in: #1f9d55;
|
|
16
|
+
--msg-out: #2563eb;
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
/* 暗色主题 */
|
|
@@ -28,6 +30,8 @@
|
|
|
28
30
|
--orange: #db8e3c;
|
|
29
31
|
--blue: #58a6ff;
|
|
30
32
|
--magenta: #bc8cff;
|
|
33
|
+
--msg-in: #56e39f;
|
|
34
|
+
--msg-out: #79b8ff;
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
@@ -307,13 +311,6 @@ tr:hover td { background: var(--bg2); }
|
|
|
307
311
|
}
|
|
308
312
|
.theme-btn:hover { background: var(--bg3); }
|
|
309
313
|
|
|
310
|
-
/* ── Today cost in topbar ── */
|
|
311
|
-
.today-cost {
|
|
312
|
-
font-size: 12px; color: var(--green); font-weight: 600;
|
|
313
|
-
margin-left: auto; margin-right: 12px;
|
|
314
|
-
font-variant-numeric: tabular-nums;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
314
|
/* ── Usage view ── */
|
|
318
315
|
.usage-layout {
|
|
319
316
|
padding: 0; overflow: hidden; flex: 1; display: flex; flex-direction: column;
|
|
@@ -413,9 +410,119 @@ tr:hover td { background: var(--bg2); }
|
|
|
413
410
|
|
|
414
411
|
/* ── Agents 页 ── */
|
|
415
412
|
.agents-toolbar { padding: 8px 12px; border-bottom: 1px solid var(--border); }
|
|
416
|
-
.agent-ops-cell { white-space: nowrap; }
|
|
417
|
-
|
|
418
|
-
|
|
413
|
+
.agent-ops-cell { white-space: nowrap; vertical-align: middle; }
|
|
414
|
+
|
|
415
|
+
/* disabled 行淡化 */
|
|
416
|
+
tr.ag-disabled td { opacity: .5; }
|
|
417
|
+
tr.ag-disabled .ag-name { color: var(--dim); }
|
|
418
|
+
|
|
419
|
+
/* 操作区:主按钮 + ··· 下拉 */
|
|
420
|
+
.agent-ops { display: flex; align-items: center; gap: 5px; }
|
|
421
|
+
.agent-ops .ctrl-btn { padding: 2px 9px; font-size: 11px; }
|
|
422
|
+
.ops-enable { color: var(--green) !important; border-color: var(--green) !important; }
|
|
423
|
+
.ops-clear-queue { color: var(--orange) !important; border-color: var(--orange) !important; }
|
|
424
|
+
|
|
425
|
+
/* 操作进行中状态 */
|
|
426
|
+
.agent-ops-busy { display: flex; align-items: center; gap: 6px; }
|
|
427
|
+
.ops-busy-label { font-size: 11px; color: var(--dim); font-style: italic; }
|
|
428
|
+
|
|
429
|
+
/* ··· 下拉菜单 */
|
|
430
|
+
.ops-more { position: relative; }
|
|
431
|
+
.ops-more-btn { letter-spacing: 2px; padding: 2px 6px !important; }
|
|
432
|
+
.ops-dropdown {
|
|
433
|
+
display: none; position: absolute; right: 0; top: calc(100% + 4px); z-index: 100;
|
|
434
|
+
background: var(--bg2); border: 1px solid var(--border); border-radius: 6px;
|
|
435
|
+
box-shadow: 0 4px 12px rgba(0,0,0,.15); min-width: 140px; overflow: hidden;
|
|
436
|
+
}
|
|
437
|
+
.ops-more.open .ops-dropdown { display: block; }
|
|
438
|
+
.ops-dd-item {
|
|
439
|
+
display: block; width: 100%; padding: 7px 14px; text-align: left;
|
|
440
|
+
font-size: 12px; background: none; border: none; color: var(--fg);
|
|
441
|
+
cursor: pointer; text-decoration: none; white-space: nowrap;
|
|
442
|
+
}
|
|
443
|
+
.ops-dd-item:hover { background: var(--bg3); }
|
|
444
|
+
.ops-dd-item.danger { color: var(--red); }
|
|
445
|
+
.ops-dd-item.danger:hover { background: var(--bg3); }
|
|
446
|
+
|
|
447
|
+
/* 顶部统计条(对齐终端 watch aid 状态栏)*/
|
|
448
|
+
.agents-stats {
|
|
449
|
+
display: flex; flex-wrap: wrap; align-items: center; gap: 6px 18px;
|
|
450
|
+
padding: 9px 14px; border-bottom: 1px solid var(--border);
|
|
451
|
+
background: var(--bg2); font-size: 12px; font-variant-numeric: tabular-nums;
|
|
452
|
+
}
|
|
453
|
+
.agents-stats .sg { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
|
|
454
|
+
.agents-stats .sg-k { color: var(--green); font-weight: 600; }
|
|
455
|
+
.agents-stats .sg-gw { font-family: ui-monospace, Consolas, monospace; color: var(--fg); }
|
|
456
|
+
.agents-stats .num-on { color: var(--green); font-weight: 600; }
|
|
457
|
+
.agents-stats .num-off { color: var(--red); font-weight: 600; }
|
|
458
|
+
.agents-stats .in { color: var(--green); }
|
|
459
|
+
.agents-stats .out { color: var(--blue); }
|
|
460
|
+
|
|
461
|
+
/* 两行一个 agent:主行 + 信息行 */
|
|
462
|
+
#view-agents tr.ag-main > td { border-bottom: none; padding-bottom: 3px; }
|
|
463
|
+
#view-agents tr.ag-sub > td { padding-top: 0; padding-bottom: 9px; color: var(--dim); }
|
|
464
|
+
#view-agents tr.ag-main:hover td, #view-agents tr.ag-sub:hover td { background: var(--bg2); }
|
|
465
|
+
|
|
466
|
+
/* AID 单元:状态点 + 显示名(主) + aid(次,dim) */
|
|
467
|
+
.ag-id { display: flex; align-items: center; gap: 7px; }
|
|
468
|
+
.ag-id .dot { margin: 0; flex-shrink: 0; }
|
|
469
|
+
.ag-id-text { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
|
|
470
|
+
.ag-name { font-weight: 600; color: var(--fg); overflow: hidden; text-overflow: ellipsis; }
|
|
471
|
+
.ag-aid { font-size: 10.5px; color: var(--dim); font-family: ui-monospace, Consolas, monospace; overflow: hidden; text-overflow: ellipsis; }
|
|
472
|
+
|
|
473
|
+
/* 工作状态徽标(无边框,纯色文字) */
|
|
474
|
+
.state-badge { display: inline-block; padding: 1px 8px; border-radius: 10px; font-size: 11px; font-weight: 700; }
|
|
475
|
+
.state-badge.working { color: #fff; background: var(--orange); }
|
|
476
|
+
.state-badge.queued { color: #fff; background: var(--orange); }
|
|
477
|
+
.state-badge.idle { color: var(--dim); background: var(--bg3); }
|
|
478
|
+
.state-badge.connected { color: var(--green); background: var(--bg3); }
|
|
479
|
+
.state-badge.muted { color: var(--magenta); background: var(--bg3); }
|
|
480
|
+
.state-badge.stopped { color: var(--dim); background: var(--bg3); }
|
|
481
|
+
|
|
482
|
+
/* 队列数列 */
|
|
483
|
+
.ag-queue-num { color: var(--orange); font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
484
|
+
|
|
485
|
+
/* 子标签栏 */
|
|
486
|
+
.ag-subtabs { display: inline-flex; gap: 2px; }
|
|
487
|
+
.ag-subtab { background: var(--bg3); border: 1px solid var(--border); border-radius: 6px; padding: 4px 14px; font-size: 12px; color: var(--dim); cursor: pointer; font-family: inherit; }
|
|
488
|
+
.ag-subtab.active { background: var(--accent); color: #fff; border-color: var(--accent); }
|
|
489
|
+
.agents-toolbar { display: flex; align-items: center; gap: 12px; padding: 8px 12px; border-bottom: 1px solid var(--border); }
|
|
490
|
+
|
|
491
|
+
/* 操作按钮:实心立体风 */
|
|
492
|
+
.ops-stop { background: var(--red) !important; color: #fff !important; border: none !important; box-shadow: 0 2px 4px rgba(229,62,62,.3); }
|
|
493
|
+
.ops-stop:hover { opacity: 0.85; }
|
|
494
|
+
.ops-start { background: var(--green) !important; color: #fff !important; border: none !important; box-shadow: 0 2px 4px rgba(56,161,105,.3); }
|
|
495
|
+
.ops-start:hover { opacity: 0.85; }
|
|
496
|
+
.ops-clear-queue { background: var(--orange) !important; color: #fff !important; border: none !important; box-shadow: 0 2px 4px rgba(221,107,32,.3); }
|
|
497
|
+
.ops-clear-queue:hover { opacity: 0.85; }
|
|
498
|
+
.ops-enable { background: var(--green) !important; color: #fff !important; border: none !important; box-shadow: 0 2px 4px rgba(56,161,105,.3); }
|
|
499
|
+
.ops-enable:hover { opacity: 0.85; }
|
|
500
|
+
.ops-mute { background: var(--magenta) !important; color: #fff !important; border: none !important; }
|
|
501
|
+
.ops-unmute { background: var(--green) !important; color: #fff !important; border: none !important; }
|
|
502
|
+
|
|
503
|
+
/* 信息行:最近消息(进绿/出蓝,对端橙)+ 项目路径 */
|
|
504
|
+
.ag-info { display: flex; flex-direction: column; gap: 2px; }
|
|
505
|
+
.ag-msg-wrap { position: relative; }
|
|
506
|
+
.ag-msg { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 70vw; }
|
|
507
|
+
.ag-msg .arrow-in { color: var(--msg-in); font-weight: 700; }
|
|
508
|
+
.ag-msg .arrow-out { color: var(--msg-out); font-weight: 700; }
|
|
509
|
+
.ag-msg .peer { color: var(--orange); font-weight: 600; }
|
|
510
|
+
.ag-msg .text-in { color: var(--msg-in); font-weight: 500; }
|
|
511
|
+
.ag-msg .text-out { color: var(--msg-out); font-weight: 500; }
|
|
512
|
+
.ag-msg .mtag { display: inline-block; padding: 0 4px; margin: 0 2px; border-radius: 3px; font-size: 10px; background: var(--bg3); color: var(--magenta); vertical-align: middle; }
|
|
513
|
+
.ag-msg .mtags { color: var(--magenta); font-size: 10.5px; }
|
|
514
|
+
.ag-path { font-family: ui-monospace, Consolas, monospace; font-size: 10.5px; color: var(--dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 70vw; }
|
|
515
|
+
|
|
516
|
+
/* 消息 tooltip(hover 浮层)*/
|
|
517
|
+
.msg-tip { display: none; position: absolute; bottom: calc(100% + 4px); left: 0; z-index: 200; background: var(--bg2); border: 1px solid var(--border); border-radius: 8px; box-shadow: 0 4px 16px rgba(0,0,0,.2); padding: 8px 12px; min-width: 300px; max-width: 600px; white-space: normal; }
|
|
518
|
+
.ag-msg-wrap:hover .msg-tip { display: block; }
|
|
519
|
+
.tip-row { font-size: 12px; line-height: 1.8; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 500; }
|
|
520
|
+
.tip-row-in { color: var(--msg-in); }
|
|
521
|
+
.tip-row-out { color: var(--msg-out); }
|
|
522
|
+
.tip-kind { margin: 0 2px; font-weight: 600; }
|
|
523
|
+
.tip-flag { margin: 0 2px; padding: 0 4px; border-radius: 3px; background: var(--bg3); color: var(--magenta); font-size: 10.5px; }
|
|
524
|
+
.tip-row b { color: var(--orange); font-weight: 600; }
|
|
525
|
+
|
|
419
526
|
|
|
420
527
|
/* ── System 页 ── */
|
|
421
528
|
.sys-wrap { padding: 12px; overflow-y: auto; height: 100%; }
|
|
@@ -424,6 +531,28 @@ tr:hover td { background: var(--bg2); }
|
|
|
424
531
|
.card-label { font-size: 11px; color: var(--dim); text-transform: uppercase; letter-spacing: .05em; margin-bottom: 4px; }
|
|
425
532
|
.card-val { font-size: 13px; color: var(--fg); }
|
|
426
533
|
|
|
534
|
+
/* Agent 健康卡片网格 */
|
|
535
|
+
.agent-health-grid {
|
|
536
|
+
display: grid;
|
|
537
|
+
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
|
538
|
+
gap: 10px;
|
|
539
|
+
}
|
|
540
|
+
.agent-health-card {
|
|
541
|
+
background: var(--bg2);
|
|
542
|
+
border: 1px solid var(--border);
|
|
543
|
+
border-radius: 8px;
|
|
544
|
+
padding: 12px 14px;
|
|
545
|
+
}
|
|
546
|
+
.ahc-head { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; }
|
|
547
|
+
.ahc-aid { font-weight: 600; font-size: 13px; color: var(--fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
548
|
+
.ahc-status { margin-left: auto; font-size: 11px; color: var(--dim); }
|
|
549
|
+
.ahc-row { display: flex; gap: 8px; font-size: 12px; margin: 3px 0; }
|
|
550
|
+
.ahc-k { color: var(--dim); width: 32px; flex-shrink: 0; }
|
|
551
|
+
.ahc-v { color: var(--fg); flex: 1; min-width: 0; }
|
|
552
|
+
.ahc-path { font-family: var(--mono, ui-monospace, monospace); color: var(--dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
553
|
+
.ch-row { line-height: 1.6; }
|
|
554
|
+
.ahc-err { margin-top: 6px; font-size: 12px; color: var(--red); white-space: normal; word-break: break-word; }
|
|
555
|
+
|
|
427
556
|
/* ── Triggers 页 ── */
|
|
428
557
|
.trig-layout { display: flex; height: 100%; overflow: hidden; }
|
|
429
558
|
.trig-agents-col { width: 200px; border-right: 1px solid var(--border); flex-shrink: 0; overflow-y: auto; }
|
|
@@ -501,3 +630,40 @@ tr:hover td { background: var(--bg2); }
|
|
|
501
630
|
font-size: 14px; font-weight: 600; margin-bottom: 12px; color: var(--fg);
|
|
502
631
|
}
|
|
503
632
|
|
|
633
|
+
/* ── Monitor ─────────────────────────────────── */
|
|
634
|
+
.mon-layout { padding: 16px; display: flex; flex-direction: column; gap: 14px; min-height: 100%; box-sizing: border-box; }
|
|
635
|
+
.mon-toolbar { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }
|
|
636
|
+
.mon-toolbar-label { font-size: 12px; color: var(--dim); font-weight: 500; }
|
|
637
|
+
.mon-range-tabs { display: flex; gap: 2px; background: var(--bg3); border-radius: 6px; padding: 2px; }
|
|
638
|
+
.mon-range { padding: 4px 12px; border: none; background: none; border-radius: 5px; font-size: 12px; font-family: inherit; color: var(--dim); cursor: pointer; }
|
|
639
|
+
.mon-range:hover { color: var(--fg); }
|
|
640
|
+
.mon-range.active { background: var(--accent); color: #fff; }
|
|
641
|
+
.mon-legend { display: flex; gap: 14px; font-size: 11px; color: var(--dim); }
|
|
642
|
+
.mon-legend-item { display: inline-flex; align-items: center; gap: 4px; }
|
|
643
|
+
.lg-dot { display: inline-block; width: 10px; height: 3px; border-radius: 2px; }
|
|
644
|
+
.lg-proc { background: var(--accent); }
|
|
645
|
+
.lg-sys { background: var(--orange); }
|
|
646
|
+
.mon-row2 { display: flex; gap: 14px; }
|
|
647
|
+
.mon-chart { flex: 1; height: 220px; min-width: 0; background: var(--bg2); border: 1px solid var(--border); border-radius: 10px; padding: 6px; box-shadow: 0 1px 3px rgba(0,0,0,0.06); }
|
|
648
|
+
.mon-table-wrap { min-width: 0; background: var(--bg2); border: 1px solid var(--border); border-radius: 10px; padding: 14px; overflow-x: auto; box-shadow: 0 1px 3px rgba(0,0,0,0.06); }
|
|
649
|
+
.mon-section-title { font-size: 13px; font-weight: 500; color: var(--dim); margin-bottom: 10px; }
|
|
650
|
+
.mon-section-sub { font-weight: 400; color: var(--dim); font-size: 11px; }
|
|
651
|
+
.mon-err-wrap { background: var(--bg2); border: 1px solid var(--border); border-radius: 10px; padding: 14px; box-shadow: 0 1px 3px rgba(0,0,0,0.06); }
|
|
652
|
+
.mon-err-rows { max-height: 240px; overflow-y: auto; }
|
|
653
|
+
.mon-err-row { display: flex; align-items: center; gap: 8px; padding: 5px 0; border-bottom: 1px solid var(--border); font-size: 12px; }
|
|
654
|
+
.mon-err-row:last-child { border-bottom: none; }
|
|
655
|
+
.mon-err-time { flex-shrink: 0; width: 36px; color: var(--dim); font-variant-numeric: tabular-nums; }
|
|
656
|
+
.mon-err-tag { flex-shrink: 0; padding: 1px 6px; border-radius: 3px; font-size: 10px; font-weight: 500; }
|
|
657
|
+
.tag-task { background: #fef3cd; color: #856404; }
|
|
658
|
+
.tag-tool { background: #d1ecf1; color: #0c5460; }
|
|
659
|
+
[data-theme="dark"] .tag-task { background: #3d2a1a; color: #db8e3c; }
|
|
660
|
+
[data-theme="dark"] .tag-tool { background: #1a3d42; color: #76c7d4; }
|
|
661
|
+
.mon-err-aid { flex-shrink: 0; max-width: 100px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--accent); font-weight: 500; }
|
|
662
|
+
.mon-err-kind { flex-shrink: 0; max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--red); }
|
|
663
|
+
.mon-err-msg { flex: 1; color: var(--dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
664
|
+
@media (max-width: 900px) {
|
|
665
|
+
.mon-row2 { flex-direction: column; }
|
|
666
|
+
.mon-chart { height: 190px; }
|
|
667
|
+
.mon-toolbar { flex-wrap: wrap; }
|
|
668
|
+
}
|
|
669
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "evolclaw-web",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Web-based monitoring dashboard for EvolClaw",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"dist/"
|
|
11
11
|
],
|
|
12
12
|
"scripts": {
|
|
13
|
-
"build": "tsc && node -e \"try{require('child_process').execFileSync('chmod',['+x','dist/index.js'])}catch{}\" && node -e \"const fs=require('fs'),path=require('path');fs.cpSync('src/static','dist/static',{recursive:true});const f='dist/static/index.html',n=new Date(),ts=n.getFullYear()+'-'+String(n.getMonth()+1).padStart(2,'0')+'-'+String(n.getDate()).padStart(2,'0')+' '+String(n.getHours()).padStart(2,'0')+':'+String(n.getMinutes()).padStart(2,'0');fs.writeFileSync(f,fs.readFileSync(f,'utf8').replace(/(\\<span class=\\\"build-ts\\\"[^>]*\\>)[^<]+(\\<\\/span\\>)/,'$1'+ts+'$2'))\"",
|
|
13
|
+
"build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc && node -e \"try{require('child_process').execFileSync('chmod',['+x','dist/index.js'])}catch{}\" && node -e \"const fs=require('fs'),path=require('path');fs.cpSync('src/static','dist/static',{recursive:true});const f='dist/static/index.html',n=new Date(),ts=n.getFullYear()+'-'+String(n.getMonth()+1).padStart(2,'0')+'-'+String(n.getDate()).padStart(2,'0')+' '+String(n.getHours()).padStart(2,'0')+':'+String(n.getMinutes()).padStart(2,'0');fs.writeFileSync(f,fs.readFileSync(f,'utf8').replace(/(\\<span class=\\\"build-ts\\\"[^>]*\\>)[^<]+(\\<\\/span\\>)/,'$1'+ts+'$2'))\"",
|
|
14
14
|
"dev": "node dev.mjs",
|
|
15
15
|
"prepublishOnly": "npm run build"
|
|
16
16
|
},
|
package/dist/sources/control.js
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Control 数据源 — 通过 daemon IPC 的 menu.exec 代理拉取 menu.* 当前状态。
|
|
3
|
-
*
|
|
4
|
-
* snapshot: 一批 menu.list + menu.query(各 name 当前值)+ menu.options(列表类)。
|
|
5
|
-
* subscribe: 1s 轮询 + JSON diff,仅变化时 push(IPC 无推送,与 aid.ts 同款)。
|
|
6
|
-
*
|
|
7
|
-
* 写操作(update/action)不走这里——浏览器经 WS `menu` 消息直发,requestId 配对响应。
|
|
8
|
-
*/
|
|
9
|
-
import { resolvePaths } from '../paths.js';
|
|
10
|
-
import { ipcQuery } from '../ipc-client.js';
|
|
11
|
-
// 支持 query 当前值的 name
|
|
12
|
-
const QUERY_NAMES = ['system', 'pwd', 'baseagent', 'model', 'effort',
|
|
13
|
-
'chatmode', 'permission', 'activity', 'dispatch', 'session'];
|
|
14
|
-
// 列表类(options)
|
|
15
|
-
const OPTIONS_NAMES = ['session', 'agent', 'trigger'];
|
|
16
|
-
async function menuExec(payload) {
|
|
17
|
-
const p = resolvePaths();
|
|
18
|
-
const r = await ipcQuery(p.socket, { type: 'menu.exec', payload }, 5000);
|
|
19
|
-
return r?.ok ? r.response : null;
|
|
20
|
-
}
|
|
21
|
-
async function buildSnapshot() {
|
|
22
|
-
const [listResp, ...queryResps] = await Promise.all([
|
|
23
|
-
menuExec({ type: 'menu.list', id: 'ctrl-list' }),
|
|
24
|
-
...QUERY_NAMES.map((name, i) => menuExec({ type: 'menu.query', id: `ctrl-q-${i}`, name })),
|
|
25
|
-
]);
|
|
26
|
-
const optResps = await Promise.all(OPTIONS_NAMES.map((name, i) => menuExec({ type: 'menu.options', id: `ctrl-o-${i}`, name })));
|
|
27
|
-
const daemonRunning = listResp !== null;
|
|
28
|
-
const queries = {};
|
|
29
|
-
QUERY_NAMES.forEach((name, i) => { queries[name] = queryResps[i]; });
|
|
30
|
-
const options = {};
|
|
31
|
-
OPTIONS_NAMES.forEach((name, i) => { options[name] = optResps[i]; });
|
|
32
|
-
return { daemonRunning, list: listResp, queries, options };
|
|
33
|
-
}
|
|
34
|
-
export const controlSource = {
|
|
35
|
-
kind: 'control',
|
|
36
|
-
async snapshot() {
|
|
37
|
-
return buildSnapshot();
|
|
38
|
-
},
|
|
39
|
-
subscribe(_params, push) {
|
|
40
|
-
let lastJson = '';
|
|
41
|
-
let stopped = false;
|
|
42
|
-
const tick = async () => {
|
|
43
|
-
if (stopped)
|
|
44
|
-
return;
|
|
45
|
-
try {
|
|
46
|
-
const snap = await buildSnapshot();
|
|
47
|
-
const json = JSON.stringify(snap);
|
|
48
|
-
if (json !== lastJson) {
|
|
49
|
-
lastJson = json;
|
|
50
|
-
push(snap);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
catch { /* ignore transient IPC errors */ }
|
|
54
|
-
};
|
|
55
|
-
const timer = setInterval(tick, 1000);
|
|
56
|
-
return () => { stopped = true; clearInterval(timer); };
|
|
57
|
-
},
|
|
58
|
-
};
|