claude-code-kanban 2.0.0-rc.1 → 2.0.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/README.md +3 -1
- package/package.json +1 -1
- package/public/index.html +440 -186
- package/server.js +29 -12
package/README.md
CHANGED
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
[](https://www.npmjs.com/package/claude-code-kanban)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**[Live Demo & Docs](https://nikiforovall.blog/claude-code-kanban/)**
|
|
8
|
+
|
|
9
|
+
> Watch Claude Code work, in real time.
|
|
8
10
|
|
|
9
11
|

|
|
10
12
|
|
package/package.json
CHANGED
package/public/index.html
CHANGED
|
@@ -366,14 +366,49 @@
|
|
|
366
366
|
}
|
|
367
367
|
|
|
368
368
|
/* Live Updates */
|
|
369
|
+
.collapse-chevron {
|
|
370
|
+
width: 14px;
|
|
371
|
+
height: 14px;
|
|
372
|
+
stroke: var(--text-muted);
|
|
373
|
+
fill: none;
|
|
374
|
+
stroke-width: 2;
|
|
375
|
+
transition: transform 0.2s ease;
|
|
376
|
+
flex-shrink: 0;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.collapse-chevron.rotated {
|
|
380
|
+
transform: rotate(-90deg);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
.collapsible-section {
|
|
384
|
+
transition: max-height 0.2s ease, padding 0.2s ease, opacity 0.2s ease;
|
|
385
|
+
overflow: hidden;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.collapsible-section.collapsed {
|
|
389
|
+
max-height: 0 !important;
|
|
390
|
+
padding-top: 0 !important;
|
|
391
|
+
padding-bottom: 0 !important;
|
|
392
|
+
opacity: 0;
|
|
393
|
+
overflow: hidden;
|
|
394
|
+
}
|
|
395
|
+
|
|
369
396
|
.live-updates {
|
|
370
|
-
padding: 0 16px
|
|
371
|
-
max-height:
|
|
397
|
+
padding: 0 16px 8px;
|
|
398
|
+
max-height: 140px;
|
|
372
399
|
overflow-y: auto;
|
|
400
|
+
transition: max-height 0.2s ease, padding 0.2s ease, opacity 0.2s ease;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.live-updates.collapsed {
|
|
404
|
+
max-height: 0;
|
|
405
|
+
padding: 0 16px;
|
|
406
|
+
overflow: hidden;
|
|
407
|
+
opacity: 0;
|
|
373
408
|
}
|
|
374
409
|
|
|
375
410
|
.live-empty {
|
|
376
|
-
padding:
|
|
411
|
+
padding: 8px;
|
|
377
412
|
text-align: center;
|
|
378
413
|
font-size: 11px;
|
|
379
414
|
color: var(--text-muted);
|
|
@@ -382,12 +417,12 @@
|
|
|
382
417
|
.live-item {
|
|
383
418
|
display: flex;
|
|
384
419
|
align-items: flex-start;
|
|
385
|
-
gap:
|
|
386
|
-
padding: 10px
|
|
420
|
+
gap: 8px;
|
|
421
|
+
padding: 6px 10px;
|
|
387
422
|
background: var(--bg-deep);
|
|
388
423
|
border: 1px solid transparent;
|
|
389
|
-
border-radius:
|
|
390
|
-
margin-bottom:
|
|
424
|
+
border-radius: 6px;
|
|
425
|
+
margin-bottom: 3px;
|
|
391
426
|
cursor: pointer;
|
|
392
427
|
transition: all 0.15s ease;
|
|
393
428
|
}
|
|
@@ -397,14 +432,14 @@
|
|
|
397
432
|
}
|
|
398
433
|
|
|
399
434
|
.live-item .pulse {
|
|
400
|
-
width:
|
|
401
|
-
height:
|
|
435
|
+
width: 6px;
|
|
436
|
+
height: 6px;
|
|
402
437
|
margin-top: 4px;
|
|
403
438
|
background: var(--accent);
|
|
404
439
|
border-radius: 50%;
|
|
405
440
|
flex-shrink: 0;
|
|
406
441
|
animation: pulse 2s ease-in-out infinite;
|
|
407
|
-
box-shadow: 0 0
|
|
442
|
+
box-shadow: 0 0 8px var(--accent-glow);
|
|
408
443
|
}
|
|
409
444
|
|
|
410
445
|
.live-item-content {
|
|
@@ -413,7 +448,7 @@
|
|
|
413
448
|
}
|
|
414
449
|
|
|
415
450
|
.live-item-action {
|
|
416
|
-
font-size:
|
|
451
|
+
font-size: 11px;
|
|
417
452
|
color: var(--text-primary);
|
|
418
453
|
white-space: nowrap;
|
|
419
454
|
overflow: hidden;
|
|
@@ -421,9 +456,9 @@
|
|
|
421
456
|
}
|
|
422
457
|
|
|
423
458
|
.live-item-session {
|
|
424
|
-
font-size:
|
|
459
|
+
font-size: 10px;
|
|
425
460
|
color: var(--text-tertiary);
|
|
426
|
-
margin-top:
|
|
461
|
+
margin-top: 1px;
|
|
427
462
|
white-space: nowrap;
|
|
428
463
|
overflow: hidden;
|
|
429
464
|
text-overflow: ellipsis;
|
|
@@ -1173,6 +1208,7 @@
|
|
|
1173
1208
|
border-radius: 4px;
|
|
1174
1209
|
border: 1px solid transparent;
|
|
1175
1210
|
transition: border-color 0.15s ease;
|
|
1211
|
+
overflow-x: auto;
|
|
1176
1212
|
}
|
|
1177
1213
|
|
|
1178
1214
|
.detail-desc:hover {
|
|
@@ -1630,13 +1666,13 @@
|
|
|
1630
1666
|
.pinned-sessions-divider {
|
|
1631
1667
|
height: 1px; margin: 4px 8px; background: color-mix(in srgb, var(--accent) 30%, transparent);
|
|
1632
1668
|
}
|
|
1633
|
-
.agent-tabs { display: flex; gap: 0; border-bottom: 1px solid var(--border); margin-top: 16px; }
|
|
1669
|
+
.agent-tabs { display: flex; gap: 0; border-bottom: 1px solid var(--border); margin-top: 16px; align-items: center; }
|
|
1634
1670
|
.agent-tab { padding: 8px 16px; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-tertiary); cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; transition: color 0.15s, border-color 0.15s; user-select: none; }
|
|
1635
1671
|
.agent-tab:hover { color: var(--text-secondary); border-bottom-color: var(--text-muted); }
|
|
1636
1672
|
.agent-tab.active { color: var(--accent); border-bottom-color: var(--accent); }
|
|
1637
1673
|
.agent-tab-panel { display: none; padding-top: 12px; overflow: hidden; position: relative; }
|
|
1638
1674
|
.agent-tab-panel.active { display: block; }
|
|
1639
|
-
.agent-tab-copy {
|
|
1675
|
+
.agent-tab-copy { margin-left: auto; background: var(--surface-hover); border: 1px solid var(--border); border-radius: 6px; padding: 4px 6px; cursor: pointer; color: var(--text-tertiary); opacity: 0.7; transition: opacity 0.15s, color 0.15s; margin-bottom: -1px; }
|
|
1640
1676
|
.agent-tab-copy:hover { opacity: 1; color: var(--text-primary); }
|
|
1641
1677
|
.toast { position: fixed; bottom: 24px; left: 24px; transform: translateY(20px); background: var(--bg-elevated); color: var(--accent-text); border: 1px solid var(--border); border-left: 3px solid var(--accent); border-radius: 8px; padding: 10px 20px; font-size: 13px; font-weight: 600; z-index: 10000; opacity: 0; transition: opacity 0.25s, transform 0.25s; pointer-events: none; box-shadow: 0 4px 16px rgba(0,0,0,0.3); }
|
|
1642
1678
|
.toast.visible { opacity: 1; transform: translateY(0); }
|
|
@@ -1729,9 +1765,9 @@
|
|
|
1729
1765
|
.agent-footer.collapsed .agent-footer-content { display: none; }
|
|
1730
1766
|
.agent-card {
|
|
1731
1767
|
display: flex;
|
|
1732
|
-
|
|
1733
|
-
gap:
|
|
1734
|
-
padding: 8px
|
|
1768
|
+
flex-direction: column;
|
|
1769
|
+
gap: 3px;
|
|
1770
|
+
padding: 8px 12px;
|
|
1735
1771
|
background: var(--bg-elevated);
|
|
1736
1772
|
border: 1px solid var(--border);
|
|
1737
1773
|
border-radius: 8px;
|
|
@@ -1740,11 +1776,30 @@
|
|
|
1740
1776
|
overflow: hidden;
|
|
1741
1777
|
transition: opacity 0.3s;
|
|
1742
1778
|
cursor: pointer;
|
|
1779
|
+
position: relative;
|
|
1743
1780
|
}
|
|
1744
1781
|
.agent-card:hover { border-color: var(--accent); }
|
|
1745
1782
|
.agent-card.fading { opacity: 0.4; }
|
|
1783
|
+
.agent-type-row {
|
|
1784
|
+
display: flex;
|
|
1785
|
+
align-items: center;
|
|
1786
|
+
gap: 4px;
|
|
1787
|
+
min-width: 0;
|
|
1788
|
+
}
|
|
1789
|
+
.agent-type-ns {
|
|
1790
|
+
font-size: 11px; color: var(--text-muted); font-weight: 400;
|
|
1791
|
+
}
|
|
1792
|
+
.agent-type-name {
|
|
1793
|
+
font-size: 13px; font-weight: 600; color: var(--text-primary);
|
|
1794
|
+
overflow: hidden; text-overflow: ellipsis;
|
|
1795
|
+
}
|
|
1796
|
+
.agent-status-row {
|
|
1797
|
+
display: flex;
|
|
1798
|
+
align-items: center;
|
|
1799
|
+
gap: 5px;
|
|
1800
|
+
}
|
|
1746
1801
|
.agent-dot {
|
|
1747
|
-
width:
|
|
1802
|
+
width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0;
|
|
1748
1803
|
}
|
|
1749
1804
|
.agent-dot.active { background: var(--success); box-shadow: 0 0 6px var(--success); }
|
|
1750
1805
|
.agent-dot.idle { background: var(--warning); box-shadow: 0 0 6px var(--warning); }
|
|
@@ -1757,9 +1812,14 @@
|
|
|
1757
1812
|
}
|
|
1758
1813
|
.agent-message {
|
|
1759
1814
|
font-size: 11px; color: var(--text-muted);
|
|
1760
|
-
max-width:
|
|
1815
|
+
max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
1761
1816
|
}
|
|
1762
1817
|
|
|
1818
|
+
.agent-dismiss-btn {
|
|
1819
|
+
font-size: 12px; padding: 4px 10px;
|
|
1820
|
+
background: var(--bg-tertiary); color: var(--text-secondary);
|
|
1821
|
+
border: 1px solid var(--border);
|
|
1822
|
+
}
|
|
1763
1823
|
.agent-badge { font-size: 12px; cursor: default; }
|
|
1764
1824
|
|
|
1765
1825
|
/* Permission pending — indicated by ❓ badge only */
|
|
@@ -1913,10 +1973,17 @@
|
|
|
1913
1973
|
background: rgba(0, 0, 0, 0.6);
|
|
1914
1974
|
}
|
|
1915
1975
|
|
|
1976
|
+
.modal.fullscreen {
|
|
1977
|
+
width: 76vw !important;
|
|
1978
|
+
max-width: 76vw !important;
|
|
1979
|
+
height: 85vh !important;
|
|
1980
|
+
max-height: 85vh !important;
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1916
1983
|
.modal.plan-modal {
|
|
1917
1984
|
width: 60vw;
|
|
1918
1985
|
max-width: 60vw;
|
|
1919
|
-
max-height:
|
|
1986
|
+
max-height: 85vh;
|
|
1920
1987
|
display: flex;
|
|
1921
1988
|
flex-direction: column;
|
|
1922
1989
|
}
|
|
@@ -2233,6 +2300,12 @@
|
|
|
2233
2300
|
color: var(--text-primary);
|
|
2234
2301
|
}
|
|
2235
2302
|
|
|
2303
|
+
.project-group-header.kb-selected {
|
|
2304
|
+
color: var(--text-primary);
|
|
2305
|
+
background: var(--bg-hover);
|
|
2306
|
+
border-radius: 4px;
|
|
2307
|
+
}
|
|
2308
|
+
|
|
2236
2309
|
.project-group-header .group-chevron {
|
|
2237
2310
|
transition: transform 0.15s ease;
|
|
2238
2311
|
flex-shrink: 0;
|
|
@@ -2395,8 +2468,11 @@
|
|
|
2395
2468
|
|
|
2396
2469
|
<!-- Live Updates -->
|
|
2397
2470
|
<div class="sidebar-section">
|
|
2398
|
-
<div class="section-header">
|
|
2471
|
+
<div class="section-header" onclick="toggleLiveUpdates()" style="cursor: pointer;">
|
|
2399
2472
|
<span>Live Updates</span>
|
|
2473
|
+
<svg id="live-updates-chevron" class="collapse-chevron" viewBox="0 0 24 24">
|
|
2474
|
+
<path d="M6 9l6 6 6-6"/>
|
|
2475
|
+
</svg>
|
|
2400
2476
|
</div>
|
|
2401
2477
|
<div id="live-updates" class="live-updates">
|
|
2402
2478
|
<div class="live-empty">No active tasks</div>
|
|
@@ -2405,46 +2481,50 @@
|
|
|
2405
2481
|
|
|
2406
2482
|
<!-- Tasks -->
|
|
2407
2483
|
<div class="sidebar-section flex-1">
|
|
2408
|
-
<div class="section-header">
|
|
2484
|
+
<div class="section-header" onclick="toggleSection('sessions-filters', 'sessions-chevron')" style="cursor: pointer;">
|
|
2409
2485
|
<span>Sessions</span>
|
|
2410
|
-
<
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
<input
|
|
2414
|
-
id="search-input"
|
|
2415
|
-
type="text"
|
|
2416
|
-
class="search-input"
|
|
2417
|
-
placeholder="Search tasks, sessions, projects..."
|
|
2418
|
-
oninput="handleSearch(this.value)"
|
|
2419
|
-
/>
|
|
2420
|
-
<button id="search-clear-btn" class="search-clear" onclick="clearSearch()" title="Clear search" aria-label="Clear search">
|
|
2421
|
-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
2422
|
-
<path d="M18 6L6 18M6 6l12 12"/>
|
|
2423
|
-
</svg>
|
|
2424
|
-
</button>
|
|
2425
|
-
</div>
|
|
2426
|
-
<div class="filter-row">
|
|
2427
|
-
<select id="project-filter" class="filter-dropdown" onchange="filterByProject(this.value)" aria-label="Filter by project">
|
|
2428
|
-
<option value="">All Projects</option>
|
|
2429
|
-
</select>
|
|
2430
|
-
<select id="session-filter" class="filter-dropdown" onchange="filterBySessions(this.value)" aria-label="Filter by session status">
|
|
2431
|
-
<option value="all">All Sessions</option>
|
|
2432
|
-
<option value="active">Active Only</option>
|
|
2433
|
-
</select>
|
|
2486
|
+
<svg id="sessions-chevron" class="collapse-chevron" viewBox="0 0 24 24">
|
|
2487
|
+
<path d="M6 9l6 6 6-6"/>
|
|
2488
|
+
</svg>
|
|
2434
2489
|
</div>
|
|
2435
|
-
<div class="
|
|
2436
|
-
<
|
|
2437
|
-
<
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
<
|
|
2446
|
-
|
|
2447
|
-
|
|
2490
|
+
<div id="sessions-filters" class="collapsible-section">
|
|
2491
|
+
<div class="search-container">
|
|
2492
|
+
<input
|
|
2493
|
+
id="search-input"
|
|
2494
|
+
type="text"
|
|
2495
|
+
class="search-input"
|
|
2496
|
+
placeholder="Search tasks, sessions, projects..."
|
|
2497
|
+
oninput="handleSearch(this.value)"
|
|
2498
|
+
/>
|
|
2499
|
+
<button id="search-clear-btn" class="search-clear" onclick="clearSearch()" title="Clear search" aria-label="Clear search">
|
|
2500
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
2501
|
+
<path d="M18 6L6 18M6 6l12 12"/>
|
|
2502
|
+
</svg>
|
|
2503
|
+
</button>
|
|
2504
|
+
</div>
|
|
2505
|
+
<div class="filter-row">
|
|
2506
|
+
<select id="project-filter" class="filter-dropdown" onchange="filterByProject(this.value)" aria-label="Filter by project">
|
|
2507
|
+
<option value="">All Projects</option>
|
|
2508
|
+
</select>
|
|
2509
|
+
<select id="session-filter" class="filter-dropdown" onchange="filterBySessions(this.value)" aria-label="Filter by session status">
|
|
2510
|
+
<option value="all">All Sessions</option>
|
|
2511
|
+
<option value="active">Active Only</option>
|
|
2512
|
+
</select>
|
|
2513
|
+
</div>
|
|
2514
|
+
<div class="filter-row">
|
|
2515
|
+
<select id="session-limit" class="filter-dropdown" onchange="changeSessionLimit(this.value)" aria-label="Number of sessions to show">
|
|
2516
|
+
<option value="10">Show 10</option>
|
|
2517
|
+
<option value="20">Show 20</option>
|
|
2518
|
+
<option value="50">Show 50</option>
|
|
2519
|
+
<option value="all">Show All</option>
|
|
2520
|
+
</select>
|
|
2521
|
+
<button class="icon-btn reset-btn" onclick="resetState()" title="Reset all filters" aria-label="Reset all filters">
|
|
2522
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16">
|
|
2523
|
+
<path d="M3 12a9 9 0 1 1 9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"/>
|
|
2524
|
+
<path d="M3 22v-6h6"/>
|
|
2525
|
+
</svg>
|
|
2526
|
+
</button>
|
|
2527
|
+
</div>
|
|
2448
2528
|
</div>
|
|
2449
2529
|
<div id="sessions-list" class="sessions-list"></div>
|
|
2450
2530
|
</div>
|
|
@@ -2943,6 +3023,18 @@
|
|
|
2943
3023
|
renderLiveUpdates(activeTasks);
|
|
2944
3024
|
}
|
|
2945
3025
|
|
|
3026
|
+
function toggleSection(containerId, chevronId) {
|
|
3027
|
+
const container = document.getElementById(containerId);
|
|
3028
|
+
const chevron = document.getElementById(chevronId);
|
|
3029
|
+
const collapsed = container.classList.toggle('collapsed');
|
|
3030
|
+
chevron.classList.toggle('rotated', collapsed);
|
|
3031
|
+
localStorage.setItem(containerId + 'Collapsed', collapsed);
|
|
3032
|
+
}
|
|
3033
|
+
|
|
3034
|
+
function toggleLiveUpdates() {
|
|
3035
|
+
toggleSection('live-updates', 'live-updates-chevron');
|
|
3036
|
+
}
|
|
3037
|
+
|
|
2946
3038
|
function renderLiveUpdates(activeTasks) {
|
|
2947
3039
|
const container = document.getElementById('live-updates');
|
|
2948
3040
|
|
|
@@ -3410,9 +3502,18 @@
|
|
|
3410
3502
|
}
|
|
3411
3503
|
const toolParamsHtml = renderToolParamsHtml(m.params);
|
|
3412
3504
|
const toolResultHtml = renderToolResultHtml(m.toolResult, m.toolResultTruncated, m.toolResultFull);
|
|
3413
|
-
const
|
|
3414
|
-
|
|
3415
|
-
|
|
3505
|
+
const hasAgentTabs = m.tool === 'Agent' && m.agentId && (m.agentLastMessage || m.agentPrompt);
|
|
3506
|
+
let mainHtml;
|
|
3507
|
+
if (hasAgentTabs) {
|
|
3508
|
+
mainHtml = descHtml || '';
|
|
3509
|
+
} else if (fullText) {
|
|
3510
|
+
const detailEscaped = escapeHtml(fullText);
|
|
3511
|
+
const detailRendered = m.tool === 'Bash' ? highlightBash(detailEscaped) : detailEscaped;
|
|
3512
|
+
mainHtml = descHtml + `<pre class="msg-detail-pre">${detailRendered}</pre>`;
|
|
3513
|
+
} else {
|
|
3514
|
+
mainHtml = '<em>No details</em>';
|
|
3515
|
+
}
|
|
3516
|
+
body.innerHTML = mainHtml + toolParamsHtml + (hasAgentTabs ? '' : toolResultHtml) + agentExtraHtml;
|
|
3416
3517
|
} else {
|
|
3417
3518
|
const text = stripAnsi(m.fullText || m.text);
|
|
3418
3519
|
document.getElementById('msg-detail-title').textContent = m.type === 'assistant' ? 'Claude' : (m.systemLabel ? 'System' : 'User');
|
|
@@ -3431,6 +3532,7 @@
|
|
|
3431
3532
|
|
|
3432
3533
|
const meta = [formatDate(m.timestamp)];
|
|
3433
3534
|
if (m.model) meta.unshift(m.model);
|
|
3535
|
+
meta.push(`${idx + 1} of ${currentMessages.length}`);
|
|
3434
3536
|
document.getElementById('msg-detail-meta').textContent = meta.join(' · ');
|
|
3435
3537
|
currentPinDetailId = null;
|
|
3436
3538
|
updateMsgDetailPinState();
|
|
@@ -3438,10 +3540,32 @@
|
|
|
3438
3540
|
}
|
|
3439
3541
|
|
|
3440
3542
|
function closeMsgDetailModal() {
|
|
3441
|
-
|
|
3543
|
+
resetModalFullscreen('msg-detail-modal');
|
|
3442
3544
|
msgDetailFollowLatest = false;
|
|
3443
3545
|
}
|
|
3444
3546
|
|
|
3547
|
+
function toggleModalFullscreen(modalId) {
|
|
3548
|
+
const modal = document.querySelector(`#${modalId} .modal`);
|
|
3549
|
+
const isFs = modal.classList.toggle('fullscreen');
|
|
3550
|
+
updateFullscreenBtnIcon(`${modalId}-fullscreen-btn`, isFs);
|
|
3551
|
+
}
|
|
3552
|
+
|
|
3553
|
+
function resetModalFullscreen(modalId) {
|
|
3554
|
+
const modal = document.getElementById(modalId);
|
|
3555
|
+
modal.classList.remove('visible');
|
|
3556
|
+
modal.querySelector('.modal').classList.remove('fullscreen');
|
|
3557
|
+
updateFullscreenBtnIcon(`${modalId}-fullscreen-btn`, false);
|
|
3558
|
+
return modal;
|
|
3559
|
+
}
|
|
3560
|
+
|
|
3561
|
+
function updateFullscreenBtnIcon(btnId, isFullscreen) {
|
|
3562
|
+
const btn = document.getElementById(btnId);
|
|
3563
|
+
if (!btn) return;
|
|
3564
|
+
btn.innerHTML = isFullscreen
|
|
3565
|
+
? '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><polyline points="4 14 10 14 10 20"/><polyline points="20 10 14 10 14 4"/><line x1="14" y1="10" x2="21" y2="3"/><line x1="3" y1="21" x2="10" y2="14"/></svg>'
|
|
3566
|
+
: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>';
|
|
3567
|
+
}
|
|
3568
|
+
|
|
3445
3569
|
let _toastTimer = null;
|
|
3446
3570
|
function showToast(msg) {
|
|
3447
3571
|
const el = document.getElementById('toast');
|
|
@@ -3536,7 +3660,7 @@
|
|
|
3536
3660
|
const id = `expand-${++_expandIdCounter}`;
|
|
3537
3661
|
const fontSize = opts.fontSize || '0.8rem';
|
|
3538
3662
|
const maxHeight = opts.maxHeight || '';
|
|
3539
|
-
const btn = `<button onclick="var f=document.getElementById('${id}'),t=this.parentElement.nextElementSibling,expand=f.style.display==='none';f.style.display=expand?'block':'none';t.style.display=expand?'none':'block';this.textContent=expand?'Show less':'Show more'" style="background:none;border:none;color:var(--accent);cursor:pointer;font-size:${fontSize};text-decoration:underline">Show more</button>`;
|
|
3663
|
+
const btn = `<button onclick="var f=document.getElementById('${id}'),t=this.parentElement.nextElementSibling,expand=f.style.display==='none';f.style.display=expand?'block':'none';t.style.display=expand?'none':'block';this.textContent=expand?'Show less':'Show more'" style="background:none;border:none;color:var(--accent);cursor:pointer;font-size:${fontSize};text-decoration:underline;margin-left:6px">Show more</button>`;
|
|
3540
3664
|
const mhStyle = maxHeight ? `max-height:${maxHeight};` : '';
|
|
3541
3665
|
const full = `<pre id="${id}" class="msg-detail-pre" style="${mhStyle}overflow:auto;display:none">${fullHtml}</pre>`;
|
|
3542
3666
|
return { btn, full };
|
|
@@ -3545,7 +3669,9 @@
|
|
|
3545
3669
|
function autoSizeModal(modal, body) {
|
|
3546
3670
|
const hasTable = body.querySelector('table') !== null;
|
|
3547
3671
|
const hasPre = body.querySelector('pre') !== null;
|
|
3548
|
-
|
|
3672
|
+
const desired = hasTable ? 1100 : (body.textContent.length > 2000 || hasPre) ? 960 : 860;
|
|
3673
|
+
const current = parseFloat(getComputedStyle(modal).maxWidth) || 0;
|
|
3674
|
+
if (desired > current) modal.style.maxWidth = desired + 'px';
|
|
3549
3675
|
}
|
|
3550
3676
|
|
|
3551
3677
|
function renderToolResultHtml(toolResult, isTruncated, fullResult) {
|
|
@@ -3683,16 +3809,14 @@
|
|
|
3683
3809
|
const promptTrunc = promptTrimmed.length > 60 ? promptTrimmed.substring(0, 60) + '…' : promptTrimmed;
|
|
3684
3810
|
const msgHtml = promptTrunc
|
|
3685
3811
|
? `<div class="agent-message" title="${escapeHtml(promptTrimmed)}">${escapeHtml(promptTrunc)}</div>` : '';
|
|
3686
|
-
const
|
|
3687
|
-
const
|
|
3812
|
+
const rawType = a.type || 'unknown';
|
|
3813
|
+
const colonIdx = rawType.indexOf(':');
|
|
3814
|
+
const typeNs = colonIdx > 0 ? rawType.substring(0, colonIdx + 1) : '';
|
|
3815
|
+
const typeName = colonIdx > 0 ? rawType.substring(colonIdx + 1) : rawType;
|
|
3688
3816
|
return `<div class="agent-card" onclick="showAgentModal('${a.agentId}')">
|
|
3689
|
-
<span class="agent-
|
|
3690
|
-
<div
|
|
3691
|
-
|
|
3692
|
-
<div class="agent-status">${statusText}</div>
|
|
3693
|
-
${msgHtml}
|
|
3694
|
-
</div>
|
|
3695
|
-
${agentPinBtn}
|
|
3817
|
+
<div class="agent-type-row">${typeNs ? `<span class="agent-type-ns">${escapeHtml(typeNs)}</span>` : ''}<span class="agent-type-name">${escapeHtml(typeName)}</span></div>
|
|
3818
|
+
<div class="agent-status-row"><span class="agent-dot ${a.status}"></span><span class="agent-status">${statusText}</span></div>
|
|
3819
|
+
${msgHtml}
|
|
3696
3820
|
</div>`;
|
|
3697
3821
|
}).join('');
|
|
3698
3822
|
|
|
@@ -3737,6 +3861,17 @@
|
|
|
3737
3861
|
updateAgentModalPinState();
|
|
3738
3862
|
}
|
|
3739
3863
|
|
|
3864
|
+
async function dismissAgent(agentId) {
|
|
3865
|
+
if (!currentSessionId || !agentId) return;
|
|
3866
|
+
try {
|
|
3867
|
+
const res = await fetch(`/api/sessions/${currentSessionId}/agents/${agentId}/stop`, { method: 'POST' });
|
|
3868
|
+
if (res.ok) {
|
|
3869
|
+
currentWaiting = null;
|
|
3870
|
+
fetchAgents(currentSessionId);
|
|
3871
|
+
}
|
|
3872
|
+
} catch (e) { console.error('[dismissAgent]', e); }
|
|
3873
|
+
}
|
|
3874
|
+
|
|
3740
3875
|
function showAgentModal(agentId) {
|
|
3741
3876
|
const agent = currentAgents.find(a => a.agentId === agentId);
|
|
3742
3877
|
if (!agent) return;
|
|
@@ -3779,6 +3914,9 @@
|
|
|
3779
3914
|
|
|
3780
3915
|
body.innerHTML = html;
|
|
3781
3916
|
updateAgentModalPinState();
|
|
3917
|
+
autoSizeModal(modal.querySelector('.modal'), body);
|
|
3918
|
+
const dismissBtn = document.getElementById('agent-modal-dismiss-btn');
|
|
3919
|
+
dismissBtn.style.display = (agent.status === 'active' || agent.status === 'idle') ? '' : 'none';
|
|
3782
3920
|
modal.classList.add('visible');
|
|
3783
3921
|
const keyHandler = (e) => {
|
|
3784
3922
|
if (e.key === 'Escape') {
|
|
@@ -3791,7 +3929,7 @@
|
|
|
3791
3929
|
}
|
|
3792
3930
|
|
|
3793
3931
|
function closeAgentModal() {
|
|
3794
|
-
|
|
3932
|
+
resetModalFullscreen('agent-modal');
|
|
3795
3933
|
currentAgentModalId = null;
|
|
3796
3934
|
}
|
|
3797
3935
|
|
|
@@ -4047,29 +4185,34 @@
|
|
|
4047
4185
|
sessionsList.innerHTML = filteredSessions.map(renderSessionCard).join('');
|
|
4048
4186
|
}
|
|
4049
4187
|
|
|
4050
|
-
const
|
|
4051
|
-
const
|
|
4188
|
+
const navItems = getNavigableItems();
|
|
4189
|
+
const allSessions = getSessionItems();
|
|
4190
|
+
const activeIdx = allSessions.findIndex(el => el.classList.contains('active'));
|
|
4052
4191
|
if (activeIdx >= 0 && (selectedSessionIdx < 0 || sessionJustSelected)) {
|
|
4053
|
-
|
|
4054
|
-
|
|
4192
|
+
const navIdx = navItems.indexOf(allSessions[activeIdx]);
|
|
4193
|
+
selectedSessionIdx = navIdx >= 0 ? navIdx : 0;
|
|
4194
|
+
selectedSessionKbId = allSessions[activeIdx].dataset.sessionId || null;
|
|
4055
4195
|
sessionJustSelected = false;
|
|
4056
4196
|
}
|
|
4057
4197
|
|
|
4058
4198
|
if (selectedSessionKbId && focusZone === 'sidebar') {
|
|
4059
|
-
const restoredIdx =
|
|
4199
|
+
const restoredIdx = navItems.findIndex(el =>
|
|
4200
|
+
getKbId(el) === selectedSessionKbId
|
|
4201
|
+
);
|
|
4060
4202
|
if (restoredIdx >= 0) {
|
|
4061
4203
|
selectedSessionIdx = restoredIdx;
|
|
4062
|
-
|
|
4204
|
+
navItems[restoredIdx].classList.add('kb-selected');
|
|
4063
4205
|
} else {
|
|
4064
4206
|
selectedSessionIdx = -1;
|
|
4065
4207
|
selectedSessionKbId = null;
|
|
4066
4208
|
}
|
|
4067
4209
|
} else if (focusZone === 'sidebar' && selectedSessionIdx >= 0) {
|
|
4068
|
-
if (
|
|
4069
|
-
const clamped = Math.min(selectedSessionIdx,
|
|
4210
|
+
if (navItems.length > 0) {
|
|
4211
|
+
const clamped = Math.min(selectedSessionIdx, navItems.length - 1);
|
|
4070
4212
|
selectedSessionIdx = clamped;
|
|
4071
|
-
|
|
4072
|
-
|
|
4213
|
+
const el = navItems[clamped];
|
|
4214
|
+
selectedSessionKbId = getKbId(el);
|
|
4215
|
+
el.classList.add('kb-selected');
|
|
4073
4216
|
} else {
|
|
4074
4217
|
selectedSessionIdx = -1;
|
|
4075
4218
|
selectedSessionKbId = null;
|
|
@@ -4303,31 +4446,71 @@
|
|
|
4303
4446
|
}
|
|
4304
4447
|
}
|
|
4305
4448
|
|
|
4449
|
+
function getKbId(el) {
|
|
4450
|
+
return el.dataset.sessionId || el.dataset.groupPath || null;
|
|
4451
|
+
}
|
|
4452
|
+
|
|
4453
|
+
function getGroupSessionsContainer(header) {
|
|
4454
|
+
let el = header.nextElementSibling;
|
|
4455
|
+
while (el && !el.classList.contains('project-group-sessions')) el = el.nextElementSibling;
|
|
4456
|
+
return el;
|
|
4457
|
+
}
|
|
4458
|
+
|
|
4459
|
+
function getNavigableItems() {
|
|
4460
|
+
const items = [];
|
|
4461
|
+
for (const el of sessionsList.children) {
|
|
4462
|
+
if (el.classList.contains('project-group-header')) {
|
|
4463
|
+
items.push(el);
|
|
4464
|
+
if (!collapsedProjectGroups.has(el.dataset.groupPath)) {
|
|
4465
|
+
const container = getGroupSessionsContainer(el);
|
|
4466
|
+
if (container) {
|
|
4467
|
+
for (const s of container.querySelectorAll('.session-item')) items.push(s);
|
|
4468
|
+
}
|
|
4469
|
+
}
|
|
4470
|
+
} else if (el.classList.contains('session-item')) {
|
|
4471
|
+
items.push(el);
|
|
4472
|
+
}
|
|
4473
|
+
}
|
|
4474
|
+
return items;
|
|
4475
|
+
}
|
|
4476
|
+
|
|
4306
4477
|
function getSessionItems() {
|
|
4307
4478
|
return Array.from(sessionsList.querySelectorAll('.session-item'));
|
|
4308
4479
|
}
|
|
4309
4480
|
|
|
4310
|
-
function
|
|
4311
|
-
const
|
|
4312
|
-
if (items.length === 0) return;
|
|
4313
|
-
const prev = sessionsList.querySelector('.session-item.kb-selected');
|
|
4481
|
+
function clearKbSelection() {
|
|
4482
|
+
const prev = sessionsList.querySelector('.kb-selected');
|
|
4314
4483
|
if (prev) prev.classList.remove('kb-selected');
|
|
4484
|
+
}
|
|
4485
|
+
|
|
4486
|
+
function selectSessionByIndex(idx, items) {
|
|
4487
|
+
items = items || getNavigableItems();
|
|
4488
|
+
if (items.length === 0) return;
|
|
4489
|
+
clearKbSelection();
|
|
4315
4490
|
selectedSessionIdx = Math.max(0, Math.min(idx, items.length - 1));
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4491
|
+
const el = items[selectedSessionIdx];
|
|
4492
|
+
selectedSessionKbId = getKbId(el);
|
|
4493
|
+
el.classList.add('kb-selected');
|
|
4494
|
+
el.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
|
|
4319
4495
|
}
|
|
4320
4496
|
|
|
4321
|
-
function navigateSession(direction) {
|
|
4322
|
-
|
|
4497
|
+
function navigateSession(direction, items) {
|
|
4498
|
+
items = items || getNavigableItems();
|
|
4323
4499
|
if (items.length === 0) return;
|
|
4324
4500
|
if (selectedSessionIdx < 0) {
|
|
4325
|
-
selectSessionByIndex(0);
|
|
4501
|
+
selectSessionByIndex(0, items);
|
|
4326
4502
|
return;
|
|
4327
4503
|
}
|
|
4328
|
-
const
|
|
4504
|
+
const currentEl = items[selectedSessionIdx];
|
|
4505
|
+
let newIdx = selectedSessionIdx + direction;
|
|
4506
|
+
if (!currentEl || !currentEl.isConnected) {
|
|
4507
|
+
const restoredIdx = selectedSessionKbId
|
|
4508
|
+
? items.findIndex(el => getKbId(el) === selectedSessionKbId)
|
|
4509
|
+
: -1;
|
|
4510
|
+
newIdx = restoredIdx >= 0 ? restoredIdx : 0;
|
|
4511
|
+
}
|
|
4329
4512
|
if (newIdx >= 0 && newIdx < items.length) {
|
|
4330
|
-
selectSessionByIndex(newIdx);
|
|
4513
|
+
selectSessionByIndex(newIdx, items);
|
|
4331
4514
|
}
|
|
4332
4515
|
}
|
|
4333
4516
|
|
|
@@ -4338,26 +4521,56 @@
|
|
|
4338
4521
|
if (collapsed) collapsedProjectGroups.add(projectPath);
|
|
4339
4522
|
else collapsedProjectGroups.delete(projectPath);
|
|
4340
4523
|
header.classList.toggle('collapsed', collapsed);
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
if (el) el.classList.toggle('collapsed', collapsed);
|
|
4524
|
+
const container = getGroupSessionsContainer(header);
|
|
4525
|
+
if (container) container.classList.toggle('collapsed', collapsed);
|
|
4344
4526
|
try { localStorage.setItem('collapsedGroups', JSON.stringify([...collapsedProjectGroups])); } catch(_) {}
|
|
4345
4527
|
}
|
|
4346
4528
|
|
|
4347
|
-
function
|
|
4348
|
-
const items =
|
|
4529
|
+
function handleSidebarHorizontal(direction) {
|
|
4530
|
+
const items = getNavigableItems();
|
|
4349
4531
|
if (selectedSessionIdx < 0 || selectedSessionIdx >= items.length) return;
|
|
4350
|
-
const
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4532
|
+
const el = items[selectedSessionIdx];
|
|
4533
|
+
const isHeader = el.classList.contains('project-group-header');
|
|
4534
|
+
const collapse = direction < 0;
|
|
4535
|
+
|
|
4536
|
+
if (isHeader) {
|
|
4537
|
+
const groupPath = el.dataset.groupPath;
|
|
4538
|
+
const isCollapsed = collapsedProjectGroups.has(groupPath);
|
|
4539
|
+
if (collapse) {
|
|
4540
|
+
if (!isCollapsed) setGroupCollapsed(el, true);
|
|
4541
|
+
} else {
|
|
4542
|
+
if (isCollapsed) {
|
|
4543
|
+
setGroupCollapsed(el, false);
|
|
4544
|
+
} else {
|
|
4545
|
+
navigateSession(1);
|
|
4546
|
+
}
|
|
4547
|
+
}
|
|
4548
|
+
} else {
|
|
4549
|
+
if (collapse) {
|
|
4550
|
+
const container = el.closest('.project-group-sessions');
|
|
4551
|
+
if (container) {
|
|
4552
|
+
let header = container.previousElementSibling;
|
|
4553
|
+
while (header && !header.classList.contains('project-group-header')) header = header.previousElementSibling;
|
|
4554
|
+
if (header) {
|
|
4555
|
+
const headerIdx = items.indexOf(header);
|
|
4556
|
+
if (headerIdx >= 0) selectSessionByIndex(headerIdx, items);
|
|
4557
|
+
}
|
|
4558
|
+
}
|
|
4559
|
+
} else {
|
|
4560
|
+
activateSelectedSession(items);
|
|
4561
|
+
}
|
|
4562
|
+
}
|
|
4355
4563
|
}
|
|
4356
4564
|
|
|
4357
|
-
function activateSelectedSession() {
|
|
4358
|
-
|
|
4359
|
-
if (selectedSessionIdx
|
|
4360
|
-
|
|
4565
|
+
function activateSelectedSession(items) {
|
|
4566
|
+
items = items || getNavigableItems();
|
|
4567
|
+
if (selectedSessionIdx < 0 || selectedSessionIdx >= items.length) return;
|
|
4568
|
+
const el = items[selectedSessionIdx];
|
|
4569
|
+
if (el.classList.contains('project-group-header')) {
|
|
4570
|
+
const groupPath = el.dataset.groupPath;
|
|
4571
|
+
setGroupCollapsed(el, !collapsedProjectGroups.has(groupPath));
|
|
4572
|
+
} else {
|
|
4573
|
+
el.click();
|
|
4361
4574
|
}
|
|
4362
4575
|
}
|
|
4363
4576
|
|
|
@@ -4365,8 +4578,7 @@
|
|
|
4365
4578
|
const sidebar = document.querySelector('.sidebar');
|
|
4366
4579
|
// Clear all zone visuals
|
|
4367
4580
|
sidebar.classList.remove('sidebar-focused');
|
|
4368
|
-
|
|
4369
|
-
if (prevSession) prevSession.classList.remove('kb-selected');
|
|
4581
|
+
clearKbSelection();
|
|
4370
4582
|
const selCard = document.querySelector('.task-card.selected');
|
|
4371
4583
|
if (selCard) selCard.classList.remove('selected');
|
|
4372
4584
|
|
|
@@ -4377,13 +4589,13 @@
|
|
|
4377
4589
|
localStorage.setItem('sidebar-collapsed', false);
|
|
4378
4590
|
}
|
|
4379
4591
|
sidebar.classList.add('sidebar-focused');
|
|
4380
|
-
const items =
|
|
4592
|
+
const items = getNavigableItems();
|
|
4381
4593
|
if (items.length > 0) {
|
|
4382
4594
|
const activeIdx = items.findIndex(el => el.classList.contains('active'));
|
|
4383
4595
|
if (activeIdx >= 0) {
|
|
4384
4596
|
selectSessionByIndex(activeIdx);
|
|
4385
4597
|
} else if (selectedSessionKbId) {
|
|
4386
|
-
const restoredIdx = items.findIndex(el => el
|
|
4598
|
+
const restoredIdx = items.findIndex(el => getKbId(el) === selectedSessionKbId);
|
|
4387
4599
|
selectSessionByIndex(restoredIdx >= 0 ? restoredIdx : 0);
|
|
4388
4600
|
} else {
|
|
4389
4601
|
selectSessionByIndex(0);
|
|
@@ -4731,11 +4943,11 @@
|
|
|
4731
4943
|
if (e.key === 'Escape') {
|
|
4732
4944
|
e.preventDefault();
|
|
4733
4945
|
closeDeleteConfirmModal();
|
|
4734
|
-
} else if (e
|
|
4946
|
+
} else if (matchKey(e, 'ArrowLeft', 'KeyH')) {
|
|
4735
4947
|
e.preventDefault();
|
|
4736
4948
|
focusIdx = 0;
|
|
4737
4949
|
buttons[focusIdx].focus();
|
|
4738
|
-
} else if (e
|
|
4950
|
+
} else if (matchKey(e, 'ArrowRight', 'KeyL')) {
|
|
4739
4951
|
e.preventDefault();
|
|
4740
4952
|
focusIdx = 1;
|
|
4741
4953
|
buttons[focusIdx].focus();
|
|
@@ -4817,35 +5029,58 @@
|
|
|
4817
5029
|
|
|
4818
5030
|
document.getElementById('close-detail').onclick = closeDetailPanel;
|
|
4819
5031
|
|
|
5032
|
+
// Layout-independent key matching: pass Arrow* for e.key, Key* for e.code (physical position)
|
|
5033
|
+
function matchKey(e, ...keys) {
|
|
5034
|
+
if (e.ctrlKey || e.altKey || e.metaKey || e.shiftKey) return false;
|
|
5035
|
+
return keys.some(k => e.key === k || e.code === k);
|
|
5036
|
+
}
|
|
5037
|
+
|
|
4820
5038
|
document.addEventListener('keydown', (e) => {
|
|
4821
5039
|
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.tagName === 'SELECT') {
|
|
4822
5040
|
return;
|
|
4823
5041
|
}
|
|
4824
5042
|
|
|
5043
|
+
// Modal guard — only Escape, Shift+M, and msg-detail J/K navigation pass through
|
|
4825
5044
|
if (document.querySelector('.modal-overlay.visible')) {
|
|
4826
5045
|
if (e.key === 'Escape') {
|
|
4827
5046
|
document.querySelectorAll('.modal-overlay.visible').forEach(m => m.classList.remove('visible'));
|
|
4828
5047
|
msgDetailFollowLatest = false;
|
|
4829
|
-
} else if (
|
|
5048
|
+
} else if (e.code === 'KeyM' && e.shiftKey && document.getElementById('msg-detail-modal').classList.contains('visible')) {
|
|
4830
5049
|
e.preventDefault();
|
|
4831
5050
|
closeMsgDetailModal();
|
|
5051
|
+
} else if (document.getElementById('msg-detail-modal').classList.contains('visible')) {
|
|
5052
|
+
if (matchKey(e, 'ArrowDown', 'KeyJ')) {
|
|
5053
|
+
e.preventDefault();
|
|
5054
|
+
if (currentMsgDetailIdx < currentMessages.length - 1) {
|
|
5055
|
+
msgDetailFollowLatest = false;
|
|
5056
|
+
showMsgDetail(currentMsgDetailIdx + 1);
|
|
5057
|
+
} else if (currentMsgDetailIdx === currentMessages.length - 1) {
|
|
5058
|
+
msgDetailFollowLatest = true;
|
|
5059
|
+
showMsgDetail(currentMsgDetailIdx);
|
|
5060
|
+
}
|
|
5061
|
+
} else if (matchKey(e, 'ArrowUp', 'KeyK')) {
|
|
5062
|
+
e.preventDefault();
|
|
5063
|
+
if (currentMsgDetailIdx > 0) {
|
|
5064
|
+
msgDetailFollowLatest = false;
|
|
5065
|
+
showMsgDetail(currentMsgDetailIdx - 1);
|
|
5066
|
+
}
|
|
5067
|
+
}
|
|
4832
5068
|
}
|
|
4833
5069
|
return;
|
|
4834
5070
|
}
|
|
4835
5071
|
|
|
5072
|
+
// Global shortcuts
|
|
4836
5073
|
if (e.key === '[') {
|
|
4837
5074
|
e.preventDefault();
|
|
4838
5075
|
toggleSidebar();
|
|
4839
5076
|
return;
|
|
4840
5077
|
}
|
|
4841
|
-
|
|
4842
|
-
if ((e.key === 'L' || e.key === 'l') && e.shiftKey) {
|
|
5078
|
+
if (e.code === 'KeyL' && e.shiftKey) {
|
|
4843
5079
|
e.preventDefault();
|
|
4844
5080
|
toggleMessagePanel();
|
|
4845
5081
|
return;
|
|
4846
5082
|
}
|
|
4847
|
-
|
|
4848
|
-
if ((e.key === 'M' || e.key === 'm') && e.shiftKey) {
|
|
5083
|
+
if (e.code === 'KeyM' && e.shiftKey) {
|
|
4849
5084
|
e.preventDefault();
|
|
4850
5085
|
const msgDetailModal = document.getElementById('msg-detail-modal');
|
|
4851
5086
|
if (msgDetailModal.classList.contains('visible')) {
|
|
@@ -4860,30 +5095,34 @@
|
|
|
4860
5095
|
// Tab toggles focus zone
|
|
4861
5096
|
if (e.key === 'Tab') {
|
|
4862
5097
|
e.preventDefault();
|
|
5098
|
+
if (focusZone === 'sidebar') {
|
|
5099
|
+
const hasCards = document.querySelector('.task-card');
|
|
5100
|
+
if (!hasCards) return;
|
|
5101
|
+
}
|
|
4863
5102
|
setFocusZone(focusZone === 'board' ? 'sidebar' : 'board');
|
|
4864
5103
|
return;
|
|
4865
5104
|
}
|
|
4866
5105
|
|
|
4867
5106
|
// Sidebar navigation
|
|
4868
5107
|
if (focusZone === 'sidebar') {
|
|
4869
|
-
if (e
|
|
5108
|
+
if (matchKey(e, 'ArrowDown', 'KeyJ')) {
|
|
4870
5109
|
e.preventDefault();
|
|
4871
5110
|
navigateSession(1);
|
|
4872
5111
|
return;
|
|
4873
5112
|
}
|
|
4874
|
-
if (e
|
|
5113
|
+
if (matchKey(e, 'ArrowUp', 'KeyK')) {
|
|
4875
5114
|
e.preventDefault();
|
|
4876
5115
|
navigateSession(-1);
|
|
4877
5116
|
return;
|
|
4878
5117
|
}
|
|
4879
|
-
if (e
|
|
5118
|
+
if (matchKey(e, 'ArrowLeft', 'KeyH')) {
|
|
4880
5119
|
e.preventDefault();
|
|
4881
|
-
|
|
5120
|
+
handleSidebarHorizontal(-1);
|
|
4882
5121
|
return;
|
|
4883
5122
|
}
|
|
4884
|
-
if (e
|
|
5123
|
+
if (matchKey(e, 'ArrowRight', 'KeyL')) {
|
|
4885
5124
|
e.preventDefault();
|
|
4886
|
-
|
|
5125
|
+
handleSidebarHorizontal(1);
|
|
4887
5126
|
return;
|
|
4888
5127
|
}
|
|
4889
5128
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
@@ -4895,82 +5134,70 @@
|
|
|
4895
5134
|
setFocusZone('board');
|
|
4896
5135
|
return;
|
|
4897
5136
|
}
|
|
4898
|
-
if (e.key === 'p' || e.key === 'P') {
|
|
4899
|
-
e.preventDefault();
|
|
4900
|
-
const highlighted = sessionsList.querySelector('.session-item.kb-selected');
|
|
4901
|
-
const sid = highlighted?.dataset.sessionId || currentSessionId;
|
|
4902
|
-
if (sid) openPlanForSession(sid);
|
|
4903
|
-
return;
|
|
4904
|
-
}
|
|
4905
|
-
if (e.key === 'i' || e.key === 'I') {
|
|
4906
|
-
e.preventDefault();
|
|
4907
|
-
const highlighted = sessionsList.querySelector('.session-item.kb-selected');
|
|
4908
|
-
const sid = highlighted?.dataset.sessionId || currentSessionId;
|
|
4909
|
-
if (sid) showSessionInfoModal(sid);
|
|
4910
|
-
return;
|
|
4911
|
-
}
|
|
4912
|
-
if (e.key === '?' || (e.key === '/' && e.shiftKey)) {
|
|
4913
|
-
e.preventDefault();
|
|
4914
|
-
showHelpModal();
|
|
4915
|
-
}
|
|
4916
|
-
return;
|
|
4917
5137
|
}
|
|
4918
5138
|
|
|
4919
5139
|
// Board navigation
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
5140
|
+
if (focusZone === 'board') {
|
|
5141
|
+
if (matchKey(e, 'ArrowDown', 'KeyJ', 'ArrowUp', 'KeyK', 'ArrowLeft', 'KeyH', 'ArrowRight', 'KeyL')) {
|
|
5142
|
+
e.preventDefault();
|
|
5143
|
+
if (!selectedTaskId && !document.querySelector('.task-card.selected')) {
|
|
5144
|
+
setFocusZone('sidebar');
|
|
5145
|
+
return;
|
|
5146
|
+
}
|
|
5147
|
+
if (matchKey(e, 'ArrowDown', 'KeyJ')) navigateVertical(1);
|
|
5148
|
+
else if (matchKey(e, 'ArrowUp', 'KeyK')) navigateVertical(-1);
|
|
5149
|
+
else if (matchKey(e, 'ArrowLeft', 'KeyH')) navigateHorizontal(-1);
|
|
5150
|
+
else if (matchKey(e, 'ArrowRight', 'KeyL')) navigateHorizontal(1);
|
|
4927
5151
|
|
|
4928
|
-
|
|
4929
|
-
|
|
5152
|
+
if (selectedTaskId && detailPanel.classList.contains('visible')) {
|
|
5153
|
+
showTaskDetail(selectedTaskId, selectedSessionId);
|
|
5154
|
+
}
|
|
5155
|
+
return;
|
|
4930
5156
|
}
|
|
4931
|
-
return;
|
|
4932
|
-
}
|
|
4933
5157
|
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
5158
|
+
if ((e.key === 'Enter' || e.key === ' ') && selectedTaskId && e.target.tagName !== 'BUTTON') {
|
|
5159
|
+
e.preventDefault();
|
|
5160
|
+
if (detailPanel.classList.contains('visible')) {
|
|
5161
|
+
const labelEl = document.querySelector('.detail-label');
|
|
5162
|
+
const shownId = labelEl?.textContent.match(/\d+/)?.[0];
|
|
5163
|
+
if (shownId === selectedTaskId) {
|
|
5164
|
+
closeDetailPanel();
|
|
5165
|
+
} else {
|
|
5166
|
+
showTaskDetail(selectedTaskId, selectedSessionId);
|
|
5167
|
+
}
|
|
4941
5168
|
} else {
|
|
4942
5169
|
showTaskDetail(selectedTaskId, selectedSessionId);
|
|
4943
5170
|
}
|
|
4944
|
-
|
|
4945
|
-
|
|
5171
|
+
return;
|
|
5172
|
+
}
|
|
5173
|
+
|
|
5174
|
+
if (matchKey(e, 'KeyD') && selectedTaskId) {
|
|
5175
|
+
e.preventDefault();
|
|
5176
|
+
deleteTask(selectedTaskId, selectedSessionId || currentSessionId);
|
|
5177
|
+
return;
|
|
4946
5178
|
}
|
|
4947
|
-
return;
|
|
4948
5179
|
}
|
|
4949
5180
|
|
|
4950
5181
|
if (e.key === 'Escape') {
|
|
4951
5182
|
if (detailPanel.classList.contains('visible')) closeDetailPanel();
|
|
4952
5183
|
else if (messagePanelOpen) toggleMessagePanel();
|
|
4953
|
-
}
|
|
4954
|
-
|
|
4955
|
-
if (e.key === 'p' || e.key === 'P') {
|
|
4956
|
-
e.preventDefault();
|
|
4957
|
-
const sid = selectedSessionId || currentSessionId;
|
|
4958
|
-
if (sid) openPlanForSession(sid);
|
|
4959
5184
|
return;
|
|
4960
5185
|
}
|
|
4961
5186
|
|
|
4962
|
-
|
|
5187
|
+
// Shared actions — work in both sidebar and board
|
|
5188
|
+
const contextSid = focusZone === 'sidebar'
|
|
5189
|
+
? (sessionsList.querySelector('.kb-selected')?.dataset.sessionId || currentSessionId)
|
|
5190
|
+
: (selectedSessionId || currentSessionId);
|
|
5191
|
+
if (matchKey(e, 'KeyP') && !e.shiftKey) {
|
|
4963
5192
|
e.preventDefault();
|
|
4964
|
-
|
|
4965
|
-
if (sid) showSessionInfoModal(sid);
|
|
5193
|
+
if (contextSid) openPlanForSession(contextSid);
|
|
4966
5194
|
return;
|
|
4967
5195
|
}
|
|
4968
|
-
|
|
4969
|
-
if ((e.key === 'd' || e.key === 'D') && selectedTaskId) {
|
|
5196
|
+
if (matchKey(e, 'KeyI') && !e.shiftKey) {
|
|
4970
5197
|
e.preventDefault();
|
|
4971
|
-
|
|
5198
|
+
if (contextSid) showSessionInfoModal(contextSid);
|
|
5199
|
+
return;
|
|
4972
5200
|
}
|
|
4973
|
-
|
|
4974
5201
|
if (e.key === '?' || (e.key === '/' && e.shiftKey)) {
|
|
4975
5202
|
e.preventDefault();
|
|
4976
5203
|
showHelpModal();
|
|
@@ -5137,14 +5364,14 @@
|
|
|
5137
5364
|
}
|
|
5138
5365
|
if (!tabs.length) return '';
|
|
5139
5366
|
const defaultTab = responseHtml ? 'response' : tabs[0].key;
|
|
5140
|
-
const
|
|
5367
|
+
const copyBtnHtml = `<button class="agent-tab-copy" title="Copy" onclick="copyAgentTabActive('${id}',this)"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg></button>`;
|
|
5141
5368
|
const tabsHtml = tabs.map(t =>
|
|
5142
5369
|
`<div class="agent-tab${t.key === defaultTab ? ' active' : ''}" data-tab-group="${id}" data-tab-key="${t.key}" onclick="document.querySelectorAll('[data-tab-group=\\'${id}\\']').forEach(el=>{el.classList.toggle('active',el.dataset.tabKey==='${t.key}')})">${t.label}</div>`
|
|
5143
5370
|
).join('');
|
|
5144
5371
|
const panelsHtml = panels.map(p =>
|
|
5145
|
-
`<div class="agent-tab-panel${p.key === defaultTab ? ' active' : ''}" data-tab-group="${id}" data-tab-key="${p.key}"
|
|
5372
|
+
`<div class="agent-tab-panel${p.key === defaultTab ? ' active' : ''}" data-tab-group="${id}" data-tab-key="${p.key}"><div class="detail-desc rendered-md" style="font-size:13px;">${p.html}</div></div>`
|
|
5146
5373
|
).join('');
|
|
5147
|
-
return `<div class="agent-tabs">${tabsHtml}</div>${panelsHtml}`;
|
|
5374
|
+
return `<div class="agent-tabs">${tabsHtml}${copyBtnHtml}</div>${panelsHtml}`;
|
|
5148
5375
|
}
|
|
5149
5376
|
|
|
5150
5377
|
async function copyAgentTab(key, btn) {
|
|
@@ -5153,6 +5380,13 @@
|
|
|
5153
5380
|
copyWithFeedback(text, btn);
|
|
5154
5381
|
}
|
|
5155
5382
|
|
|
5383
|
+
async function copyAgentTabActive(groupId, btn) {
|
|
5384
|
+
const activePanel = document.querySelector(`.agent-tab-panel.active[data-tab-group="${groupId}"]`);
|
|
5385
|
+
if (!activePanel) return;
|
|
5386
|
+
const key = groupId + '-' + activePanel.dataset.tabKey;
|
|
5387
|
+
copyAgentTab(key, btn);
|
|
5388
|
+
}
|
|
5389
|
+
|
|
5156
5390
|
const ownerColors = [
|
|
5157
5391
|
{ bg: 'rgba(37, 99, 235, 0.14)', color: '#1d5bbf' }, // blue
|
|
5158
5392
|
{ bg: 'rgba(168, 85, 247, 0.14)', color: '#7c3aed' }, // purple
|
|
@@ -5641,7 +5875,7 @@
|
|
|
5641
5875
|
}
|
|
5642
5876
|
|
|
5643
5877
|
function closePlanModal() {
|
|
5644
|
-
|
|
5878
|
+
resetModalFullscreen('plan-modal');
|
|
5645
5879
|
}
|
|
5646
5880
|
|
|
5647
5881
|
function openPlanInEditor() {
|
|
@@ -5702,6 +5936,12 @@
|
|
|
5702
5936
|
|
|
5703
5937
|
// Init
|
|
5704
5938
|
loadTheme();
|
|
5939
|
+
['live-updates', 'sessions-filters'].forEach(id => {
|
|
5940
|
+
if (localStorage.getItem(id + 'Collapsed') === 'true') {
|
|
5941
|
+
document.getElementById(id).classList.add('collapsed');
|
|
5942
|
+
document.getElementById(id === 'live-updates' ? 'live-updates-chevron' : 'sessions-chevron').classList.add('rotated');
|
|
5943
|
+
}
|
|
5944
|
+
});
|
|
5705
5945
|
|
|
5706
5946
|
document.addEventListener('DOMContentLoaded', () => {
|
|
5707
5947
|
if (typeof marked !== 'undefined' && typeof hljs !== 'undefined') {
|
|
@@ -5788,6 +6028,9 @@
|
|
|
5788
6028
|
<button class="icon-btn" aria-label="Open in editor" title="Open in editor" onclick="openMsgInEditor()">
|
|
5789
6029
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
|
|
5790
6030
|
</button>
|
|
6031
|
+
<button id="msg-detail-fullscreen-btn" class="icon-btn" aria-label="Toggle fullscreen" title="Toggle fullscreen" onclick="toggleModalFullscreen('msg-detail-modal')">
|
|
6032
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>
|
|
6033
|
+
</button>
|
|
5791
6034
|
<button class="modal-close" aria-label="Close" onclick="closeMsgDetailModal()">
|
|
5792
6035
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6L6 18M6 6l12 12"/></svg>
|
|
5793
6036
|
</button>
|
|
@@ -5882,6 +6125,10 @@
|
|
|
5882
6125
|
<td style="padding: 4px 0; color: var(--text-secondary);"><kbd style="background: var(--bg-hover); padding: 2px 6px; border-radius: 4px; font-family: monospace;">Shift+M</kbd></td>
|
|
5883
6126
|
<td style="padding: 4px 0; color: var(--text-primary);">Open last message detail</td>
|
|
5884
6127
|
</tr>
|
|
6128
|
+
<tr>
|
|
6129
|
+
<td style="padding: 4px 0; color: var(--text-secondary);"><kbd style="background: var(--bg-hover); padding: 2px 6px; border-radius: 4px; font-family: monospace;">J/K</kbd></td>
|
|
6130
|
+
<td style="padding: 4px 0; color: var(--text-primary);">Navigate messages in detail modal</td>
|
|
6131
|
+
</tr>
|
|
5885
6132
|
</table>
|
|
5886
6133
|
</div>
|
|
5887
6134
|
</div>
|
|
@@ -5986,6 +6233,9 @@
|
|
|
5986
6233
|
<button class="icon-btn" aria-label="Copy plan" title="Copy plan" onclick="copyWithFeedback(_pendingPlanContent||'',this)">
|
|
5987
6234
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg>
|
|
5988
6235
|
</button>
|
|
6236
|
+
<button id="plan-modal-fullscreen-btn" class="icon-btn" aria-label="Toggle fullscreen" title="Toggle fullscreen" onclick="toggleModalFullscreen('plan-modal')">
|
|
6237
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>
|
|
6238
|
+
</button>
|
|
5989
6239
|
<button class="modal-close" aria-label="Close dialog" onclick="closePlanModal()">
|
|
5990
6240
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
5991
6241
|
<path d="M18 6L6 18M6 6l12 12"/>
|
|
@@ -6038,6 +6288,9 @@
|
|
|
6038
6288
|
<button class="icon-btn" id="agent-modal-copy-all" aria-label="Copy all" title="Copy prompt + response" onclick="copyAgentModalAll(this)">
|
|
6039
6289
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg>
|
|
6040
6290
|
</button>
|
|
6291
|
+
<button id="agent-modal-fullscreen-btn" class="icon-btn" aria-label="Toggle fullscreen" title="Toggle fullscreen" onclick="toggleModalFullscreen('agent-modal')">
|
|
6292
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>
|
|
6293
|
+
</button>
|
|
6041
6294
|
<button class="modal-close" aria-label="Close dialog" onclick="closeAgentModal()">
|
|
6042
6295
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
6043
6296
|
<path d="M18 6L6 18M6 6l12 12"/>
|
|
@@ -6047,6 +6300,7 @@
|
|
|
6047
6300
|
</div>
|
|
6048
6301
|
<div id="agent-modal-body" class="modal-body" style="overflow-y: auto; overflow-x: hidden; flex: 0 1 auto; min-height: 0;"></div>
|
|
6049
6302
|
<div class="modal-footer">
|
|
6303
|
+
<button id="agent-modal-dismiss-btn" class="btn agent-dismiss-btn" style="display:none" onclick="dismissAgent(currentAgentModalId);closeAgentModal()">Dismiss</button>
|
|
6050
6304
|
<button class="btn btn-primary" onclick="closeAgentModal()">Close</button>
|
|
6051
6305
|
</div>
|
|
6052
6306
|
</div>
|
package/server.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const express = require('express');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const fs = require('fs').promises;
|
|
6
|
-
const { existsSync, readdirSync, readFileSync, statSync, createReadStream } = require('fs');
|
|
6
|
+
const { existsSync, readdirSync, readFileSync, writeFileSync, statSync, createReadStream, unlinkSync } = require('fs');
|
|
7
7
|
const readline = require('readline');
|
|
8
8
|
const chokidar = require('chokidar');
|
|
9
9
|
const os = require('os');
|
|
@@ -128,6 +128,11 @@ function loadTeamConfig(teamName) {
|
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
function resolveSessionId(sessionId) {
|
|
132
|
+
const teamConfig = loadTeamConfig(sessionId);
|
|
133
|
+
return (teamConfig && teamConfig.leadSessionId) ? teamConfig.leadSessionId : sessionId;
|
|
134
|
+
}
|
|
135
|
+
|
|
131
136
|
// SSE clients for live updates
|
|
132
137
|
const clients = new Set();
|
|
133
138
|
|
|
@@ -604,7 +609,7 @@ app.get('/api/sessions', async (req, res) => {
|
|
|
604
609
|
}
|
|
605
610
|
|
|
606
611
|
// Convert map to array and sort by most recently modified
|
|
607
|
-
sessions = Array.from(sessionsMap.values());
|
|
612
|
+
let sessions = Array.from(sessionsMap.values());
|
|
608
613
|
sessions.sort((a, b) => new Date(b.modifiedAt) - new Date(a.modifiedAt));
|
|
609
614
|
|
|
610
615
|
// Apply limit if specified, but always include pinned sessions
|
|
@@ -755,12 +760,7 @@ app.get('/api/teams/:name', (req, res) => {
|
|
|
755
760
|
|
|
756
761
|
// API: Get agents for a session
|
|
757
762
|
app.get('/api/sessions/:sessionId/agents', (req, res) => {
|
|
758
|
-
|
|
759
|
-
// For team sessions, resolve to leader's session UUID
|
|
760
|
-
const teamConfig = loadTeamConfig(sessionId);
|
|
761
|
-
if (teamConfig && teamConfig.leadSessionId) {
|
|
762
|
-
sessionId = teamConfig.leadSessionId;
|
|
763
|
-
}
|
|
763
|
+
const sessionId = resolveSessionId(req.params.sessionId);
|
|
764
764
|
const agentDir = path.join(AGENT_ACTIVITY_DIR, sessionId);
|
|
765
765
|
if (!existsSync(agentDir)) return res.json({ agents: [], waitingForUser: null });
|
|
766
766
|
try {
|
|
@@ -809,6 +809,25 @@ app.get('/api/sessions/:sessionId/agents', (req, res) => {
|
|
|
809
809
|
}
|
|
810
810
|
});
|
|
811
811
|
|
|
812
|
+
app.post('/api/sessions/:sessionId/agents/:agentId/stop', (req, res) => {
|
|
813
|
+
const sessionId = resolveSessionId(req.params.sessionId);
|
|
814
|
+
const agentId = path.basename(req.params.agentId).replace(/[^a-zA-Z0-9_-]/g, '');
|
|
815
|
+
const agentFile = path.join(AGENT_ACTIVITY_DIR, sessionId, agentId + '.json');
|
|
816
|
+
if (!existsSync(agentFile)) return res.status(404).json({ error: 'Agent not found' });
|
|
817
|
+
try {
|
|
818
|
+
const agent = JSON.parse(readFileSync(agentFile, 'utf8'));
|
|
819
|
+
agent.status = 'stopped';
|
|
820
|
+
agent.stoppedAt = new Date().toISOString();
|
|
821
|
+
writeFileSync(agentFile, JSON.stringify(agent), 'utf8');
|
|
822
|
+
// Also remove waiting state if present
|
|
823
|
+
const waitingFile = path.join(AGENT_ACTIVITY_DIR, sessionId, '_waiting.json');
|
|
824
|
+
if (existsSync(waitingFile)) unlinkSync(waitingFile);
|
|
825
|
+
res.json({ ok: true });
|
|
826
|
+
} catch (e) {
|
|
827
|
+
res.status(500).json({ error: 'Failed to stop agent' });
|
|
828
|
+
}
|
|
829
|
+
});
|
|
830
|
+
|
|
812
831
|
app.get('/api/sessions/:sessionId/messages', (req, res) => {
|
|
813
832
|
const limit = Math.min(parseInt(req.query.limit, 10) || 10, 50);
|
|
814
833
|
const metadata = loadSessionMetadata();
|
|
@@ -819,10 +838,8 @@ app.get('/api/sessions/:sessionId/messages', (req, res) => {
|
|
|
819
838
|
const agentMessages = messages.filter(m => m.tool === 'Agent' && m.toolUseId);
|
|
820
839
|
if (agentMessages.length) {
|
|
821
840
|
const progressMap = getProgressMap(jsonlPath);
|
|
822
|
-
|
|
823
|
-
const
|
|
824
|
-
if (teamConfig && teamConfig.leadSessionId) sessionId = teamConfig.leadSessionId;
|
|
825
|
-
const agentDir = path.join(AGENT_ACTIVITY_DIR, sessionId);
|
|
841
|
+
const resolvedSid = resolveSessionId(req.params.sessionId);
|
|
842
|
+
const agentDir = path.join(AGENT_ACTIVITY_DIR, resolvedSid);
|
|
826
843
|
for (const msg of agentMessages) {
|
|
827
844
|
const entry = progressMap[msg.toolUseId];
|
|
828
845
|
if (entry) {
|