@ai-setting/roy-plugin-task-show 0.6.12 → 0.8.5
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/cli-tasks-tree-adapter.d.ts +143 -0
- package/dist/cli-tasks-tree-adapter.d.ts.map +1 -0
- package/dist/cli-tasks-tree-adapter.js +400 -0
- package/dist/cli-tasks-tree-adapter.js.map +1 -0
- package/dist/plugin.d.ts +62 -6
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +147 -29
- package/dist/plugin.js.map +1 -1
- package/dist/server.d.ts +19 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +211 -89
- package/dist/server.js.map +1 -1
- package/dist/task-detail-mermaid.d.ts +171 -0
- package/dist/task-detail-mermaid.d.ts.map +1 -0
- package/dist/task-detail-mermaid.js +697 -0
- package/dist/task-detail-mermaid.js.map +1 -0
- package/dist/task-operations-html.d.ts.map +1 -1
- package/dist/task-operations-html.js +31 -8
- package/dist/task-operations-html.js.map +1 -1
- package/dist/tasks-tree-cache.d.ts +44 -0
- package/dist/tasks-tree-cache.d.ts.map +1 -0
- package/dist/tasks-tree-cache.js +111 -0
- package/dist/tasks-tree-cache.js.map +1 -0
- package/package.json +6 -2
- package/plugin.json +2 -2
- package/public/app.js +534 -34
- package/public/index.html +54 -21
- package/public/style.css +502 -0
- package/public/task-operations.js +27 -0
- package/public/tasks-tree.js +449 -0
package/public/index.html
CHANGED
|
@@ -5,20 +5,66 @@
|
|
|
5
5
|
<title>roy-plugin-task-show</title>
|
|
6
6
|
<link rel="stylesheet" href="/static/style.css" />
|
|
7
7
|
</head>
|
|
8
|
-
<body data-live-refresh>
|
|
8
|
+
<body data-live-refresh data-view="tasks-tree">
|
|
9
9
|
<header class="topbar">
|
|
10
|
-
<h1
|
|
10
|
+
<h1>🌳 roy-plugin-task-show · Tasks Tree</h1>
|
|
11
11
|
<p class="meta">
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
Hierarchical view of <code>roy-agent</code> tasks (driven by
|
|
13
|
+
<code>roy-agent tasks tree --json</code>).
|
|
14
14
|
</p>
|
|
15
15
|
<p class="meta connection-status" data-connection>
|
|
16
16
|
<span class="conn-dot conn-disconnected"></span>
|
|
17
17
|
<span class="conn-label">Connecting…</span>
|
|
18
18
|
</p>
|
|
19
19
|
</header>
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
|
|
21
|
+
<section class="panel tree-controls">
|
|
22
|
+
<div class="tree-controls-row">
|
|
23
|
+
<label class="tree-search">
|
|
24
|
+
<span>🔎</span>
|
|
25
|
+
<input type="search" data-tree-search placeholder="Filter by id or title (case-insensitive)" />
|
|
26
|
+
</label>
|
|
27
|
+
<div class="tree-filter-group" role="group" aria-label="Status filter">
|
|
28
|
+
<button type="button" class="tree-filter-btn is-active" data-tree-status="">all</button>
|
|
29
|
+
<button type="button" class="tree-filter-btn" data-tree-status="active">active</button>
|
|
30
|
+
<button type="button" class="tree-filter-btn" data-tree-status="todo">todo</button>
|
|
31
|
+
<button type="button" class="tree-filter-btn" data-tree-status="completed">completed</button>
|
|
32
|
+
<button type="button" class="tree-filter-btn" data-tree-status="paused">paused</button>
|
|
33
|
+
<button type="button" class="tree-filter-btn" data-tree-status="cancelled">cancelled</button>
|
|
34
|
+
</div>
|
|
35
|
+
<div class="tree-filter-group" role="group" aria-label="Priority filter">
|
|
36
|
+
<button type="button" class="tree-filter-btn is-active" data-tree-priority="">all priority</button>
|
|
37
|
+
<button type="button" class="tree-filter-btn" data-tree-priority="high">high</button>
|
|
38
|
+
<button type="button" class="tree-filter-btn" data-tree-priority="medium">medium</button>
|
|
39
|
+
<button type="button" class="tree-filter-btn" data-tree-priority="low">low</button>
|
|
40
|
+
</div>
|
|
41
|
+
<div class="tree-filter-group" role="group" aria-label="Tree actions">
|
|
42
|
+
<button type="button" class="tree-filter-btn" data-tree-action="expand">expand all</button>
|
|
43
|
+
<button type="button" class="tree-filter-btn" data-tree-action="collapse">collapse all</button>
|
|
44
|
+
<button type="button" class="tree-filter-btn" data-tree-action="refresh">↻ refresh</button>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
<p class="meta tree-summary" data-tree-summary>Loading…</p>
|
|
48
|
+
</section>
|
|
49
|
+
|
|
50
|
+
<section class="panel tree-panel" aria-label="Task hierarchy">
|
|
51
|
+
<div class="tasks-tree" data-tasks-tree role="tree" aria-busy="true">
|
|
52
|
+
<p class="empty">Loading task tree…</p>
|
|
53
|
+
</div>
|
|
54
|
+
</section>
|
|
55
|
+
|
|
56
|
+
<section class="panel tree-legend">
|
|
57
|
+
<h2>How to read this tree</h2>
|
|
58
|
+
<ul>
|
|
59
|
+
<li>Each <strong>chevron (▶ / ▼)</strong> expands or collapses a node's children. By default the first <strong>three levels</strong> are open so the hierarchy is obvious at a glance.</li>
|
|
60
|
+
<li>Use <strong>expand all</strong> / <strong>collapse all</strong> at the top to control the whole tree, or click a single chevron to drill into one branch.</li>
|
|
61
|
+
<li>Filter chips restrict by <strong>status</strong> or <strong>priority</strong>; the search box matches against id or title.</li>
|
|
62
|
+
<li>Click any task title or id (<code>#1234</code>) to open its per-task detail page (tool-call flow + operations timeline).</li>
|
|
63
|
+
</ul>
|
|
64
|
+
</section>
|
|
65
|
+
|
|
66
|
+
<section class="panel tree-legacy-hidden" id="legacy-sessions" hidden>
|
|
67
|
+
<h2>Live tool-call sessions (legacy view)</h2>
|
|
22
68
|
<p class="empty">
|
|
23
69
|
The <code>roy-agent</code> host process has not recorded any tool
|
|
24
70
|
calls yet. Trigger a session — for example by sending a message in
|
|
@@ -32,21 +78,8 @@
|
|
|
32
78
|
<tbody></tbody>
|
|
33
79
|
</table>
|
|
34
80
|
</section>
|
|
35
|
-
|
|
36
|
-
<h2>How to read this page</h2>
|
|
37
|
-
<ul>
|
|
38
|
-
<li>The page subscribes to <code>/api/events</code> (SSE) for real-time updates.</li>
|
|
39
|
-
<li>If the SSE connection fails, a 3-second polling fallback keeps the page fresh.</li>
|
|
40
|
-
<li>Useful endpoints:
|
|
41
|
-
<ul>
|
|
42
|
-
<li><a href="/api/sessions">/api/sessions</a> — JSON list of recorded sessions.</li>
|
|
43
|
-
<li><a href="/api/events">/api/events</a> — SSE event stream.</li>
|
|
44
|
-
<li><a href="/static/style.css">/static/style.css</a> — bundled CSS.</li>
|
|
45
|
-
<li><a href="/static/app.js">/static/app.js</a> — bundled JS.</li>
|
|
46
|
-
</ul>
|
|
47
|
-
</li>
|
|
48
|
-
</ul>
|
|
49
|
-
</section>
|
|
81
|
+
|
|
50
82
|
<script src="/static/app.js"></script>
|
|
83
|
+
<script src="/static/tasks-tree.js"></script>
|
|
51
84
|
</body>
|
|
52
85
|
</html>
|
package/public/style.css
CHANGED
|
@@ -221,6 +221,28 @@ table.toolcalls .result {
|
|
|
221
221
|
word-break: break-all;
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
+
/* v0.8.0+ tool-row collapsed / expanded / highlight states. The row
|
|
225
|
+
starts in `.collapsed` (input/output <details> closed) and gets
|
|
226
|
+
toggled to `.expanded` on click. The `.highlight` class is added
|
|
227
|
+
for 2s by the Mermaid `__toolClick` callback so the user sees a
|
|
228
|
+
yellow flash pointing at the target row. */
|
|
229
|
+
table.toolcalls tr.tool-row {
|
|
230
|
+
transition: background 0.3s ease-out;
|
|
231
|
+
}
|
|
232
|
+
table.toolcalls tr.tool-row.collapsed .tool-detail summary {
|
|
233
|
+
color: var(--muted);
|
|
234
|
+
}
|
|
235
|
+
table.toolcalls tr.tool-row.expanded .tool-detail summary {
|
|
236
|
+
color: var(--link);
|
|
237
|
+
}
|
|
238
|
+
table.toolcalls tr.tool-row.highlight {
|
|
239
|
+
background: rgba(255, 200, 0, 0.30) !important;
|
|
240
|
+
transition: background 0.3s ease-out;
|
|
241
|
+
}
|
|
242
|
+
table.toolcalls tr.tool-row.highlight:hover {
|
|
243
|
+
background: rgba(255, 200, 0, 0.36) !important;
|
|
244
|
+
}
|
|
245
|
+
|
|
224
246
|
.status {
|
|
225
247
|
font-size: 11px;
|
|
226
248
|
font-weight: 600;
|
|
@@ -339,6 +361,17 @@ details summary {
|
|
|
339
361
|
/* keeps the existing panel rhythm */
|
|
340
362
|
}
|
|
341
363
|
|
|
364
|
+
.panel-lifecycle {
|
|
365
|
+
/* The "Task lifecycle + tools" Mermaid section in the detail page. */
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
.lifecycle-hint {
|
|
369
|
+
margin-left: 8px;
|
|
370
|
+
font-size: 11.5px;
|
|
371
|
+
color: var(--muted);
|
|
372
|
+
font-weight: normal;
|
|
373
|
+
}
|
|
374
|
+
|
|
342
375
|
.op-timeline {
|
|
343
376
|
list-style: none;
|
|
344
377
|
margin: 0;
|
|
@@ -452,6 +485,59 @@ details summary {
|
|
|
452
485
|
margin-right: 4px;
|
|
453
486
|
}
|
|
454
487
|
|
|
488
|
+
/* v0.8.0+ always-visible description / process blocks (no <details>
|
|
489
|
+
collapse unless the description is > 600 chars, in which case the
|
|
490
|
+
legacy details fallback kicks in). The two blocks share a panel
|
|
491
|
+
rhythm and use a left-border accent so the eye can separate them
|
|
492
|
+
at a glance. */
|
|
493
|
+
.op-desc-block,
|
|
494
|
+
.op-proc-block {
|
|
495
|
+
background: var(--panel-2);
|
|
496
|
+
border: 1px solid var(--border);
|
|
497
|
+
border-left: 3px solid var(--border);
|
|
498
|
+
border-radius: 6px;
|
|
499
|
+
padding: 6px 10px 8px;
|
|
500
|
+
margin-top: 6px;
|
|
501
|
+
font-size: 13px;
|
|
502
|
+
line-height: 1.5;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
.op-desc-block {
|
|
506
|
+
border-left-color: var(--accent);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
.op-proc-block {
|
|
510
|
+
border-left-color: var(--muted);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
.op-block-label {
|
|
514
|
+
display: inline-block;
|
|
515
|
+
font-size: 11px;
|
|
516
|
+
font-weight: 600;
|
|
517
|
+
letter-spacing: 0.04em;
|
|
518
|
+
color: var(--muted);
|
|
519
|
+
text-transform: uppercase;
|
|
520
|
+
margin-bottom: 4px;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.op-desc-block .op-desc {
|
|
524
|
+
margin: 0;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
.op-proc-block .op-proc-body {
|
|
528
|
+
font-size: 12.5px;
|
|
529
|
+
color: var(--text);
|
|
530
|
+
white-space: pre-wrap;
|
|
531
|
+
word-break: break-word;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
.op-desc-empty,
|
|
535
|
+
.op-proc-empty {
|
|
536
|
+
color: var(--muted);
|
|
537
|
+
font-style: italic;
|
|
538
|
+
font-size: 12px;
|
|
539
|
+
}
|
|
540
|
+
|
|
455
541
|
/* Status colors per canonical milestone type */
|
|
456
542
|
.op-status-create .op-bullet { background: #1e40af; border-color: #3b82f6; }
|
|
457
543
|
.op-status-create .op-badge { background: #1e3a8a; color: #dbeafe; border-color: #3b82f6; }
|
|
@@ -525,3 +611,419 @@ details summary {
|
|
|
525
611
|
margin-left: 0;
|
|
526
612
|
}
|
|
527
613
|
}
|
|
614
|
+
|
|
615
|
+
/* ------------------------------------------------------------------------- */
|
|
616
|
+
/* Tasks tree (v0.8.0+) */
|
|
617
|
+
/* ------------------------------------------------------------------------- */
|
|
618
|
+
|
|
619
|
+
.tree-controls {
|
|
620
|
+
border-left: 3px solid var(--accent);
|
|
621
|
+
}
|
|
622
|
+
.tree-controls-row {
|
|
623
|
+
display: flex;
|
|
624
|
+
flex-wrap: wrap;
|
|
625
|
+
align-items: center;
|
|
626
|
+
gap: 12px;
|
|
627
|
+
margin-bottom: 8px;
|
|
628
|
+
}
|
|
629
|
+
.tree-search {
|
|
630
|
+
display: inline-flex;
|
|
631
|
+
align-items: center;
|
|
632
|
+
gap: 6px;
|
|
633
|
+
background: var(--code-bg);
|
|
634
|
+
border: 1px solid var(--border);
|
|
635
|
+
border-radius: 6px;
|
|
636
|
+
padding: 4px 10px;
|
|
637
|
+
flex: 1 1 240px;
|
|
638
|
+
min-width: 220px;
|
|
639
|
+
max-width: 380px;
|
|
640
|
+
}
|
|
641
|
+
.tree-search input {
|
|
642
|
+
background: transparent;
|
|
643
|
+
border: none;
|
|
644
|
+
color: var(--text);
|
|
645
|
+
font-size: 13px;
|
|
646
|
+
outline: none;
|
|
647
|
+
flex: 1;
|
|
648
|
+
min-width: 0;
|
|
649
|
+
}
|
|
650
|
+
.tree-search input::placeholder {
|
|
651
|
+
color: var(--muted);
|
|
652
|
+
opacity: 0.7;
|
|
653
|
+
}
|
|
654
|
+
.tree-filter-group {
|
|
655
|
+
display: inline-flex;
|
|
656
|
+
flex-wrap: wrap;
|
|
657
|
+
gap: 4px;
|
|
658
|
+
background: var(--code-bg);
|
|
659
|
+
border: 1px solid var(--border);
|
|
660
|
+
border-radius: 6px;
|
|
661
|
+
padding: 3px;
|
|
662
|
+
}
|
|
663
|
+
.tree-filter-btn {
|
|
664
|
+
background: transparent;
|
|
665
|
+
color: var(--muted);
|
|
666
|
+
border: 1px solid transparent;
|
|
667
|
+
border-radius: 4px;
|
|
668
|
+
padding: 4px 10px;
|
|
669
|
+
cursor: pointer;
|
|
670
|
+
font-size: 12px;
|
|
671
|
+
line-height: 1.4;
|
|
672
|
+
transition: all 120ms ease;
|
|
673
|
+
}
|
|
674
|
+
.tree-filter-btn:hover {
|
|
675
|
+
color: var(--text);
|
|
676
|
+
border-color: var(--border);
|
|
677
|
+
}
|
|
678
|
+
.tree-filter-btn.is-active {
|
|
679
|
+
background: var(--accent);
|
|
680
|
+
color: #0b1220;
|
|
681
|
+
font-weight: 600;
|
|
682
|
+
border-color: var(--accent);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
.tree-summary {
|
|
686
|
+
margin-top: 8px;
|
|
687
|
+
font-size: 12.5px;
|
|
688
|
+
}
|
|
689
|
+
.tree-summary .stale-pill {
|
|
690
|
+
display: inline-block;
|
|
691
|
+
background: var(--warn);
|
|
692
|
+
color: #1a1300;
|
|
693
|
+
font-weight: 700;
|
|
694
|
+
padding: 1px 7px;
|
|
695
|
+
border-radius: 999px;
|
|
696
|
+
font-size: 10.5px;
|
|
697
|
+
margin-left: 4px;
|
|
698
|
+
letter-spacing: 0.02em;
|
|
699
|
+
text-transform: uppercase;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
.tree-panel {
|
|
703
|
+
border-left: 3px solid var(--good);
|
|
704
|
+
}
|
|
705
|
+
.tasks-tree {
|
|
706
|
+
min-height: 80px;
|
|
707
|
+
font-size: 13px;
|
|
708
|
+
}
|
|
709
|
+
.tree-list,
|
|
710
|
+
.tree-children {
|
|
711
|
+
list-style: none;
|
|
712
|
+
margin: 0;
|
|
713
|
+
padding: 0;
|
|
714
|
+
}
|
|
715
|
+
.tree-children {
|
|
716
|
+
margin-left: 0;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
.tree-item {
|
|
720
|
+
position: relative;
|
|
721
|
+
margin: 2px 0;
|
|
722
|
+
}
|
|
723
|
+
.tree-item.tree-item-hidden {
|
|
724
|
+
display: none;
|
|
725
|
+
}
|
|
726
|
+
.tree-row {
|
|
727
|
+
display: flex;
|
|
728
|
+
align-items: center;
|
|
729
|
+
gap: 8px;
|
|
730
|
+
padding: 6px 8px 6px 8px;
|
|
731
|
+
border-radius: 6px;
|
|
732
|
+
background: rgba(255, 255, 255, 0.015);
|
|
733
|
+
border: 1px solid transparent;
|
|
734
|
+
transition: background 120ms ease, border-color 120ms ease;
|
|
735
|
+
}
|
|
736
|
+
.tree-row:hover {
|
|
737
|
+
background: rgba(96, 165, 250, 0.06);
|
|
738
|
+
border-color: rgba(96, 165, 250, 0.25);
|
|
739
|
+
}
|
|
740
|
+
.tree-row-meta {
|
|
741
|
+
margin-top: 4px;
|
|
742
|
+
font-size: 11.5px;
|
|
743
|
+
color: var(--muted);
|
|
744
|
+
font-style: italic;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
.tree-toggler {
|
|
748
|
+
display: inline-flex;
|
|
749
|
+
align-items: center;
|
|
750
|
+
justify-content: center;
|
|
751
|
+
width: 22px;
|
|
752
|
+
height: 22px;
|
|
753
|
+
background: transparent;
|
|
754
|
+
color: var(--accent);
|
|
755
|
+
border: 1px solid var(--border);
|
|
756
|
+
border-radius: 4px;
|
|
757
|
+
cursor: pointer;
|
|
758
|
+
font-size: 11px;
|
|
759
|
+
padding: 0;
|
|
760
|
+
flex-shrink: 0;
|
|
761
|
+
transition: background 120ms ease;
|
|
762
|
+
}
|
|
763
|
+
.tree-toggler:hover {
|
|
764
|
+
background: rgba(96, 165, 250, 0.12);
|
|
765
|
+
}
|
|
766
|
+
.tree-toggler-leaf {
|
|
767
|
+
border-color: transparent;
|
|
768
|
+
color: var(--muted);
|
|
769
|
+
cursor: default;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
.tree-id {
|
|
773
|
+
font-family: "JetBrains Mono", Menlo, Monaco, monospace;
|
|
774
|
+
font-size: 12.5px;
|
|
775
|
+
font-weight: 600;
|
|
776
|
+
color: var(--accent);
|
|
777
|
+
flex-shrink: 0;
|
|
778
|
+
min-width: 52px;
|
|
779
|
+
}
|
|
780
|
+
.tree-id:hover {
|
|
781
|
+
text-decoration: underline;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
.tree-type-badge {
|
|
785
|
+
display: inline-block;
|
|
786
|
+
font-size: 10.5px;
|
|
787
|
+
font-family: "JetBrains Mono", Menlo, Monaco, monospace;
|
|
788
|
+
text-transform: uppercase;
|
|
789
|
+
color: var(--muted);
|
|
790
|
+
border: 1px solid var(--border);
|
|
791
|
+
border-radius: 4px;
|
|
792
|
+
padding: 1px 5px;
|
|
793
|
+
flex-shrink: 0;
|
|
794
|
+
letter-spacing: 0.04em;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
.tree-title {
|
|
798
|
+
color: var(--text);
|
|
799
|
+
flex: 1 1 auto;
|
|
800
|
+
min-width: 0;
|
|
801
|
+
overflow: hidden;
|
|
802
|
+
text-overflow: ellipsis;
|
|
803
|
+
white-space: nowrap;
|
|
804
|
+
}
|
|
805
|
+
.tree-title:hover {
|
|
806
|
+
text-decoration: underline;
|
|
807
|
+
color: var(--accent);
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
.tree-tags {
|
|
811
|
+
display: inline-flex;
|
|
812
|
+
flex-wrap: wrap;
|
|
813
|
+
gap: 3px;
|
|
814
|
+
flex-shrink: 0;
|
|
815
|
+
}
|
|
816
|
+
.tree-tag {
|
|
817
|
+
display: inline-block;
|
|
818
|
+
font-size: 10.5px;
|
|
819
|
+
background: rgba(96, 165, 250, 0.12);
|
|
820
|
+
color: #bfdbfe;
|
|
821
|
+
border: 1px solid rgba(96, 165, 250, 0.3);
|
|
822
|
+
border-radius: 999px;
|
|
823
|
+
padding: 1px 7px;
|
|
824
|
+
white-space: nowrap;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
.tree-progress {
|
|
828
|
+
display: inline-flex;
|
|
829
|
+
align-items: center;
|
|
830
|
+
gap: 6px;
|
|
831
|
+
flex-shrink: 0;
|
|
832
|
+
background: var(--code-bg);
|
|
833
|
+
border: 1px solid var(--border);
|
|
834
|
+
border-radius: 999px;
|
|
835
|
+
padding: 2px 8px;
|
|
836
|
+
font-size: 10.5px;
|
|
837
|
+
color: var(--muted);
|
|
838
|
+
min-width: 80px;
|
|
839
|
+
position: relative;
|
|
840
|
+
overflow: hidden;
|
|
841
|
+
}
|
|
842
|
+
.tree-progress-bar {
|
|
843
|
+
position: absolute;
|
|
844
|
+
left: 0;
|
|
845
|
+
top: 0;
|
|
846
|
+
bottom: 0;
|
|
847
|
+
background: rgba(34, 197, 94, 0.22);
|
|
848
|
+
border-right: 1px solid rgba(34, 197, 94, 0.45);
|
|
849
|
+
}
|
|
850
|
+
.tree-progress-label {
|
|
851
|
+
position: relative;
|
|
852
|
+
z-index: 1;
|
|
853
|
+
font-family: "JetBrains Mono", Menlo, Monaco, monospace;
|
|
854
|
+
font-weight: 600;
|
|
855
|
+
color: var(--text);
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
.tree-updated {
|
|
859
|
+
font-size: 10.5px;
|
|
860
|
+
color: var(--muted);
|
|
861
|
+
font-family: "JetBrains Mono", Menlo, Monaco, monospace;
|
|
862
|
+
flex-shrink: 0;
|
|
863
|
+
white-space: nowrap;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
/* Branch lines — drawn as left borders on each child item so the tree
|
|
867
|
+
stays legible even with deep nesting. Each level offsets the lines by
|
|
868
|
+
the same 22px we use for indentation. v0.8.3: bumped the line weight
|
|
869
|
+
and contrast so the hierarchy is visible without squinting. */
|
|
870
|
+
.tree-children .tree-item {
|
|
871
|
+
border-left: 2px solid rgba(148, 163, 184, 0.45);
|
|
872
|
+
margin-left: 11px;
|
|
873
|
+
padding-left: 0;
|
|
874
|
+
}
|
|
875
|
+
.tree-children .tree-item .tree-row {
|
|
876
|
+
border-left: 2px solid transparent;
|
|
877
|
+
margin-left: -2px;
|
|
878
|
+
padding-left: 2px;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
/* v0.8.3: render-time indent is computed as `depth * 22` in JS, but we
|
|
882
|
+
also bump the depth-0 row padding so it lines up with the toggler
|
|
883
|
+
size — without this the leaf dots look detached from their row. */
|
|
884
|
+
.tree-row {
|
|
885
|
+
display: flex;
|
|
886
|
+
align-items: center;
|
|
887
|
+
gap: 8px;
|
|
888
|
+
padding: 6px 8px 6px 8px;
|
|
889
|
+
border-radius: 6px;
|
|
890
|
+
background: rgba(255, 255, 255, 0.015);
|
|
891
|
+
border: 1px solid transparent;
|
|
892
|
+
transition: background 120ms ease, border-color 120ms ease;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
/* v0.8.3: parent rows get a subtle accent so the user can immediately
|
|
896
|
+
tell which rows have children — even before they click the chevron. */
|
|
897
|
+
.tree-item-branch > .tree-row {
|
|
898
|
+
background: rgba(96, 165, 250, 0.04);
|
|
899
|
+
border-color: rgba(96, 165, 250, 0.18);
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
/* v0.8.3: depth-based indentation for visual scanning. We tag each
|
|
903
|
+
tree-row with its depth so the CSS can add a coloured left rail —
|
|
904
|
+
darker for roots, fading toward the leaves. */
|
|
905
|
+
.tree-row[data-depth="0"] {
|
|
906
|
+
box-shadow: inset 3px 0 0 rgba(96, 165, 250, 0.55);
|
|
907
|
+
}
|
|
908
|
+
.tree-row[data-depth="1"] {
|
|
909
|
+
box-shadow: inset 3px 0 0 rgba(96, 165, 250, 0.30);
|
|
910
|
+
}
|
|
911
|
+
.tree-row[data-depth="2"] {
|
|
912
|
+
box-shadow: inset 3px 0 0 rgba(96, 165, 250, 0.18);
|
|
913
|
+
}
|
|
914
|
+
.tree-row[data-depth="3"] {
|
|
915
|
+
box-shadow: inset 3px 0 0 rgba(148, 163, 184, 0.30);
|
|
916
|
+
}
|
|
917
|
+
.tree-row[data-depth="4"],
|
|
918
|
+
.tree-row[data-depth="5"],
|
|
919
|
+
.tree-row[data-depth="6"] {
|
|
920
|
+
box-shadow: inset 3px 0 0 rgba(148, 163, 184, 0.20);
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
/* v0.8.3: per-depth depth pill in the summary line. */
|
|
924
|
+
.tree-depth-breakdown {
|
|
925
|
+
display: inline-flex;
|
|
926
|
+
flex-wrap: wrap;
|
|
927
|
+
gap: 4px;
|
|
928
|
+
margin-left: 4px;
|
|
929
|
+
}
|
|
930
|
+
.tree-depth-pill {
|
|
931
|
+
display: inline-block;
|
|
932
|
+
padding: 1px 7px;
|
|
933
|
+
border-radius: 999px;
|
|
934
|
+
font-size: 11px;
|
|
935
|
+
border: 1px solid rgba(148, 163, 184, 0.35);
|
|
936
|
+
background: rgba(96, 165, 250, 0.08);
|
|
937
|
+
color: #cbd5e1;
|
|
938
|
+
}
|
|
939
|
+
.tree-depth-pill[data-depth="0"] {
|
|
940
|
+
background: rgba(96, 165, 250, 0.18);
|
|
941
|
+
color: #bfdbfe;
|
|
942
|
+
border-color: rgba(96, 165, 250, 0.55);
|
|
943
|
+
}
|
|
944
|
+
.tree-depth-pill[data-depth="1"] {
|
|
945
|
+
background: rgba(96, 165, 250, 0.10);
|
|
946
|
+
color: #cbd5e1;
|
|
947
|
+
border-color: rgba(96, 165, 250, 0.30);
|
|
948
|
+
}
|
|
949
|
+
.tree-depth-pill[data-depth="2"] {
|
|
950
|
+
background: rgba(96, 165, 250, 0.06);
|
|
951
|
+
color: #cbd5e1;
|
|
952
|
+
border-color: rgba(96, 165, 250, 0.22);
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
/* v0.8.3: legacy sections stay hidden. The id="legacy-sessions" hook
|
|
956
|
+
lets a future debug toggle restore them without code changes. */
|
|
957
|
+
.tree-legacy-hidden,
|
|
958
|
+
.tree-legacy-hidden[hidden] {
|
|
959
|
+
display: none !important;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
/* v0.8.3: condensed legend so it doesn't dominate the page above the
|
|
963
|
+
fold. Keeps the same content, tighter padding. */
|
|
964
|
+
.tree-legend {
|
|
965
|
+
padding-top: 8px;
|
|
966
|
+
padding-bottom: 8px;
|
|
967
|
+
font-size: 12.5px;
|
|
968
|
+
}
|
|
969
|
+
.tree-legend h2 {
|
|
970
|
+
font-size: 13px;
|
|
971
|
+
margin-bottom: 4px;
|
|
972
|
+
color: var(--muted);
|
|
973
|
+
text-transform: uppercase;
|
|
974
|
+
letter-spacing: 0.04em;
|
|
975
|
+
}
|
|
976
|
+
.tree-legend ul {
|
|
977
|
+
margin: 0;
|
|
978
|
+
padding-left: 18px;
|
|
979
|
+
display: grid;
|
|
980
|
+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
981
|
+
gap: 2px 16px;
|
|
982
|
+
}
|
|
983
|
+
.tree-legend li {
|
|
984
|
+
margin: 0;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
/* Status badge color tweaks — keep the existing palette, just make the
|
|
988
|
+
ones we use most in the tree (active / completed / todo) more vivid. */
|
|
989
|
+
.badge.badge-active {
|
|
990
|
+
background: rgba(59, 130, 246, 0.18);
|
|
991
|
+
color: #93c5fd;
|
|
992
|
+
border: 1px solid rgba(59, 130, 246, 0.5);
|
|
993
|
+
}
|
|
994
|
+
.badge.badge-completed {
|
|
995
|
+
background: rgba(34, 197, 94, 0.18);
|
|
996
|
+
color: #86efac;
|
|
997
|
+
border: 1px solid rgba(34, 197, 94, 0.5);
|
|
998
|
+
}
|
|
999
|
+
.badge.badge-todo {
|
|
1000
|
+
background: rgba(148, 163, 184, 0.18);
|
|
1001
|
+
color: #cbd5e1;
|
|
1002
|
+
border: 1px solid rgba(148, 163, 184, 0.4);
|
|
1003
|
+
}
|
|
1004
|
+
.badge.badge-paused {
|
|
1005
|
+
background: rgba(245, 158, 11, 0.18);
|
|
1006
|
+
color: #fcd34d;
|
|
1007
|
+
border: 1px solid rgba(245, 158, 11, 0.45);
|
|
1008
|
+
}
|
|
1009
|
+
.badge.badge-cancelled {
|
|
1010
|
+
background: rgba(239, 68, 68, 0.18);
|
|
1011
|
+
color: #fca5a5;
|
|
1012
|
+
border: 1px solid rgba(239, 68, 68, 0.45);
|
|
1013
|
+
}
|
|
1014
|
+
.badge.badge-priority-high {
|
|
1015
|
+
background: rgba(239, 68, 68, 0.18);
|
|
1016
|
+
color: #fca5a5;
|
|
1017
|
+
border: 1px solid rgba(239, 68, 68, 0.45);
|
|
1018
|
+
}
|
|
1019
|
+
.badge.badge-priority-medium {
|
|
1020
|
+
background: rgba(245, 158, 11, 0.18);
|
|
1021
|
+
color: #fcd34d;
|
|
1022
|
+
border: 1px solid rgba(245, 158, 11, 0.45);
|
|
1023
|
+
}
|
|
1024
|
+
.badge.badge-priority-low {
|
|
1025
|
+
background: rgba(148, 163, 184, 0.18);
|
|
1026
|
+
color: #cbd5e1;
|
|
1027
|
+
border: 1px solid rgba(148, 163, 184, 0.4);
|
|
1028
|
+
}
|
|
1029
|
+
|
|
@@ -205,6 +205,16 @@
|
|
|
205
205
|
var merged = mergeNodes(self.lastOps, r.ops);
|
|
206
206
|
self.lastOps = merged;
|
|
207
207
|
swapIn(renderPipelineHtml(merged, r.stale, self.taskId));
|
|
208
|
+
// v0.8.0+: cache the latest operations for the Mermaid
|
|
209
|
+
// re-renderer. Once operations are loaded, `app.js` will pick
|
|
210
|
+
// them up via `window.__lifecycleOps` and rebuild the Mermaid
|
|
211
|
+
// source with the per-operation subgraphs + click callbacks.
|
|
212
|
+
window.__lifecycleOps = {
|
|
213
|
+
taskId: self.taskId,
|
|
214
|
+
operations: merged,
|
|
215
|
+
fetchedAt: Date.now(),
|
|
216
|
+
};
|
|
217
|
+
notifyMermaidRebuild();
|
|
208
218
|
if (r.terminal) {
|
|
209
219
|
self.stopped = true;
|
|
210
220
|
return;
|
|
@@ -225,6 +235,23 @@
|
|
|
225
235
|
});
|
|
226
236
|
};
|
|
227
237
|
|
|
238
|
+
/**
|
|
239
|
+
* Fire a CustomEvent the app.js Mermaid re-renderer listens to.
|
|
240
|
+
* We don't import a global helper to keep this file standalone.
|
|
241
|
+
*/
|
|
242
|
+
function notifyMermaidRebuild() {
|
|
243
|
+
try {
|
|
244
|
+
var ev = new CustomEvent("task-show:lifecycle-ops-loaded", {
|
|
245
|
+
detail: { taskId: window.__lifecycleOps && window.__lifecycleOps.taskId },
|
|
246
|
+
});
|
|
247
|
+
window.dispatchEvent(ev);
|
|
248
|
+
} catch (_) {
|
|
249
|
+
// CustomEvent may not exist on ancient browsers — that's fine,
|
|
250
|
+
// app.js simply won't get the hint and the next SSE update will
|
|
251
|
+
// pick the ops up via window.__lifecycleOps instead.
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
228
255
|
PipelineController.prototype.scheduleNext = function (failed) {
|
|
229
256
|
var self = this;
|
|
230
257
|
if (this.timer) clearTimeout(this.timer);
|