claude-code-kanban 2.2.0-rc.13 → 2.2.0-rc.15
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/lib/parsers.js +21 -0
- package/package.json +1 -1
- package/public/app.js +106 -19
- package/public/index.html +11 -5
- package/public/style.css +26 -0
- package/server.js +7 -1
package/lib/parsers.js
CHANGED
|
@@ -494,6 +494,11 @@ function readRecentMessages(jsonlPath, limit = 10) {
|
|
|
494
494
|
require('fs').closeSync(fd);
|
|
495
495
|
fd = null;
|
|
496
496
|
messages.sort((a, b) => (a.timestamp || '').localeCompare(b.timestamp || ''));
|
|
497
|
+
for (let i = messages.length - 1; i > 0; i--) {
|
|
498
|
+
if (messages[i].systemLabel === 'Compacted' && messages[i - 1].systemLabel === 'Compacted') {
|
|
499
|
+
messages.splice(i, 1);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
497
502
|
return messages.slice(-limit);
|
|
498
503
|
} catch (e) {
|
|
499
504
|
if (fd) try { require('fs').closeSync(fd); } catch (_) {}
|
|
@@ -535,6 +540,7 @@ function buildAgentProgressMap(jsonlPath) {
|
|
|
535
540
|
const bgAgentIdRe = /agentId: ([a-zA-Z0-9_@-]+)/;
|
|
536
541
|
const tmToolIdRe = /"tool_use_id":"([^"]+)"/;
|
|
537
542
|
const tmAgentIdRe = /agent_id: ([a-zA-Z0-9_@-]+)/;
|
|
543
|
+
const nameByToolUseId = {};
|
|
538
544
|
for (const line of content.split('\n')) {
|
|
539
545
|
if (line.includes('"agent_progress"')) {
|
|
540
546
|
const agentMatch = re.exec(line);
|
|
@@ -562,8 +568,23 @@ function buildAgentProgressMap(jsonlPath) {
|
|
|
562
568
|
if (toolIdMatch && agentMatch && !map[toolIdMatch[1]]) {
|
|
563
569
|
map[toolIdMatch[1]] = { agentId: agentMatch[1], prompt: null };
|
|
564
570
|
}
|
|
571
|
+
} else if (line.includes('"assistant"') && line.includes('"tool_use"') && line.includes('"Agent"')) {
|
|
572
|
+
try {
|
|
573
|
+
const obj = JSON.parse(line);
|
|
574
|
+
const blocks = obj.message?.content;
|
|
575
|
+
if (Array.isArray(blocks)) {
|
|
576
|
+
for (const b of blocks) {
|
|
577
|
+
if (b.type === 'tool_use' && b.name === 'Agent' && b.id && b.input?.name) {
|
|
578
|
+
nameByToolUseId[b.id] = b.input.name;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
} catch (_) {}
|
|
565
583
|
}
|
|
566
584
|
}
|
|
585
|
+
for (const [key, entry] of Object.entries(map)) {
|
|
586
|
+
if (nameByToolUseId[key]) entry.name = nameByToolUseId[key];
|
|
587
|
+
}
|
|
567
588
|
} catch (_) {}
|
|
568
589
|
return map;
|
|
569
590
|
}
|
package/package.json
CHANGED
package/public/app.js
CHANGED
|
@@ -1254,17 +1254,26 @@ function savePinnedSessions() {
|
|
|
1254
1254
|
localStorage.setItem('sticky-sessions', JSON.stringify([...stickySessionIds]));
|
|
1255
1255
|
}
|
|
1256
1256
|
|
|
1257
|
-
// unpinned → pinned → sticky → unpinned
|
|
1258
1257
|
// biome-ignore lint/correctness/noUnusedVariables: used in HTML
|
|
1259
1258
|
function toggleSessionPin(sessionId) {
|
|
1259
|
+
if (pinnedSessionIds.has(sessionId)) {
|
|
1260
|
+
pinnedSessionIds.delete(sessionId);
|
|
1261
|
+
stickySessionIds.delete(sessionId);
|
|
1262
|
+
} else {
|
|
1263
|
+
pinnedSessionIds.add(sessionId);
|
|
1264
|
+
}
|
|
1265
|
+
savePinnedSessions();
|
|
1266
|
+
renderSessions();
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
// biome-ignore lint/correctness/noUnusedVariables: used in HTML
|
|
1270
|
+
function toggleSessionSticky(sessionId) {
|
|
1260
1271
|
if (stickySessionIds.has(sessionId)) {
|
|
1261
1272
|
stickySessionIds.delete(sessionId);
|
|
1262
1273
|
pinnedSessionIds.delete(sessionId);
|
|
1263
|
-
} else if (pinnedSessionIds.has(sessionId)) {
|
|
1264
|
-
pinnedSessionIds.delete(sessionId);
|
|
1265
|
-
stickySessionIds.add(sessionId);
|
|
1266
1274
|
} else {
|
|
1267
1275
|
pinnedSessionIds.add(sessionId);
|
|
1276
|
+
stickySessionIds.add(sessionId);
|
|
1268
1277
|
}
|
|
1269
1278
|
savePinnedSessions();
|
|
1270
1279
|
renderSessions();
|
|
@@ -1653,6 +1662,13 @@ function makeExpandToggle(_truncatedHtml, fullHtml, opts = {}) {
|
|
|
1653
1662
|
}
|
|
1654
1663
|
|
|
1655
1664
|
function autoSizeModal(modal, body) {
|
|
1665
|
+
modal.style.maxWidth = '';
|
|
1666
|
+
modal.classList.remove('has-mermaid');
|
|
1667
|
+
const hasMermaid = body.querySelector('pre.mermaid') !== null;
|
|
1668
|
+
if (hasMermaid) {
|
|
1669
|
+
modal.classList.add('has-mermaid');
|
|
1670
|
+
return;
|
|
1671
|
+
}
|
|
1656
1672
|
const hasTable = body.querySelector('table') !== null;
|
|
1657
1673
|
const hasPre = body.querySelector('pre') !== null;
|
|
1658
1674
|
const desired = hasTable ? 1100 : body.textContent.length > 2000 || hasPre ? 960 : 860;
|
|
@@ -1745,8 +1761,9 @@ function renderAgentFooter() {
|
|
|
1745
1761
|
// or started >30s after previous stopped (legitimate re-spawn). Filter the rest.
|
|
1746
1762
|
const byType = {};
|
|
1747
1763
|
for (const a of agents) {
|
|
1748
|
-
|
|
1749
|
-
byType[
|
|
1764
|
+
const groupKey = a.agentName || a.type;
|
|
1765
|
+
if (!byType[groupKey]) byType[groupKey] = [];
|
|
1766
|
+
byType[groupKey].push(a);
|
|
1750
1767
|
}
|
|
1751
1768
|
const filtered = [];
|
|
1752
1769
|
for (const group of Object.values(byType)) {
|
|
@@ -1820,10 +1837,15 @@ function renderAgentFooter() {
|
|
|
1820
1837
|
const colonIdx = rawType.indexOf(':');
|
|
1821
1838
|
const typeNs = colonIdx > 0 ? rawType.substring(0, colonIdx + 1) : '';
|
|
1822
1839
|
const typeName = colonIdx > 0 ? rawType.substring(colonIdx + 1) : rawType;
|
|
1840
|
+
const agentNameVal = a.agentName || null;
|
|
1841
|
+
const nameColor = agentNameVal ? getOwnerColor(agentNameVal) : null;
|
|
1842
|
+
const nameBadgeHtml = nameColor
|
|
1843
|
+
? `<span class="task-owner-badge task-owner-badge--compact" style="background:${nameColor.bg};color:${nameColor.color}">${escapeHtml(agentNameVal)}</span>`
|
|
1844
|
+
: '';
|
|
1823
1845
|
const agentColor = resolveNamedColor(a.color);
|
|
1824
1846
|
const colorStyle = agentColor ? ` style="border-left:3px solid ${agentColor.color}"` : '';
|
|
1825
1847
|
return `<div class="agent-card"${colorStyle} onclick="showAgentModal('${a.agentId}')">
|
|
1826
|
-
<div class="agent-type-row">${typeNs ? `<span class="agent-type-ns">${escapeHtml(typeNs)}</span>` : ''}<span class="agent-type-name">${escapeHtml(typeName)}</span
|
|
1848
|
+
<div class="agent-type-row">${typeNs ? `<span class="agent-type-ns">${escapeHtml(typeNs)}</span>` : ''}<span class="agent-type-name">${escapeHtml(typeName)}</span>${nameBadgeHtml}</div>
|
|
1827
1849
|
<div class="agent-status-row"><span class="agent-dot ${a.status}"></span><span class="agent-status">${statusText}</span></div>
|
|
1828
1850
|
${msgHtml}
|
|
1829
1851
|
</div>`;
|
|
@@ -1923,13 +1945,21 @@ function showAgentModal(agentId) {
|
|
|
1923
1945
|
const elapsed = stopped && started ? stopped.getTime() - started.getTime() : started ? now - started.getTime() : 0;
|
|
1924
1946
|
|
|
1925
1947
|
const statusDot = `<span class="agent-dot ${agent.status}" style="display:inline-block;vertical-align:middle;margin-right:6px;"></span>`;
|
|
1926
|
-
|
|
1948
|
+
const modalNameLabel = agent.agentName ? ` · ${escapeHtml(agent.agentName)}` : '';
|
|
1949
|
+
title.innerHTML = `${statusDot} ${escapeHtml(agent.type || 'unknown')}${modalNameLabel}`;
|
|
1927
1950
|
|
|
1928
1951
|
const rows = [
|
|
1929
1952
|
['Status', agent.status],
|
|
1930
1953
|
['Agent ID', `<code style="font-size:12px;color:var(--text-tertiary)">${escapeHtml(agent.agentId)}</code>`],
|
|
1931
1954
|
['Duration', formatDuration(elapsed)],
|
|
1932
1955
|
];
|
|
1956
|
+
if (agent.agentName) {
|
|
1957
|
+
const ownerColor = getOwnerColor(agent.agentName);
|
|
1958
|
+
rows.push([
|
|
1959
|
+
'Owner',
|
|
1960
|
+
`<span class="task-owner-badge" style="background:${ownerColor.bg};color:${ownerColor.color}">${escapeHtml(agent.agentName)}</span>`,
|
|
1961
|
+
]);
|
|
1962
|
+
}
|
|
1933
1963
|
if (agent.model)
|
|
1934
1964
|
rows.push(['Model', `<code style="font-size:12px;color:var(--text-tertiary)">${escapeHtml(agent.model)}</code>`]);
|
|
1935
1965
|
if (started) rows.push(['Started', started.toLocaleTimeString()]);
|
|
@@ -2167,7 +2197,7 @@ function renderSessions() {
|
|
|
2167
2197
|
|
|
2168
2198
|
const pinState = getSessionPinState(session.id);
|
|
2169
2199
|
const pinClass = pinState === 'sticky' ? ' sticky' : pinState === 'pinned' ? ' pinned' : '';
|
|
2170
|
-
const pinTitle = pinState === '
|
|
2200
|
+
const pinTitle = pinState === 'pinned' || pinState === 'sticky' ? 'Unpin' : 'Pin';
|
|
2171
2201
|
const showCtx = !!session.contextStatus;
|
|
2172
2202
|
return `
|
|
2173
2203
|
<button onclick="fetchTasks('${session.id}')" data-session-id="${session.id}" class="session-item ${isActive ? 'active' : ''} ${session.hasWaitingForUser ? 'permission-pending' : ''} ${!session.hasRecentLog && !session.inProgress && !session.hasWaitingForUser ? 'stale' : ''} ${showCtx ? 'has-context' : ''}" title="${tooltip}">
|
|
@@ -4243,6 +4273,33 @@ function renderMarkdown(text) {
|
|
|
4243
4273
|
return `<pre style="white-space:pre-wrap;margin:0;">${escapeHtml(text)}</pre>`;
|
|
4244
4274
|
}
|
|
4245
4275
|
|
|
4276
|
+
function isLightTheme() {
|
|
4277
|
+
const saved = localStorage.getItem('theme');
|
|
4278
|
+
return (
|
|
4279
|
+
document.body.classList.contains('light') || (!saved && window.matchMedia('(prefers-color-scheme: light)').matches)
|
|
4280
|
+
);
|
|
4281
|
+
}
|
|
4282
|
+
|
|
4283
|
+
function getMermaidTheme() {
|
|
4284
|
+
return isLightTheme() ? 'default' : 'dark';
|
|
4285
|
+
}
|
|
4286
|
+
|
|
4287
|
+
function initMermaidBlocks(container) {
|
|
4288
|
+
if (typeof mermaid === 'undefined') return;
|
|
4289
|
+
const blocks = (container || document).querySelectorAll('pre.mermaid:not([data-processed])');
|
|
4290
|
+
if (blocks.length) mermaid.run({ nodes: [...blocks] });
|
|
4291
|
+
}
|
|
4292
|
+
|
|
4293
|
+
function reinitMermaidTheme() {
|
|
4294
|
+
if (typeof mermaid === 'undefined') return;
|
|
4295
|
+
mermaid.initialize({ startOnLoad: false, theme: getMermaidTheme() });
|
|
4296
|
+
document.querySelectorAll('pre.mermaid[data-processed]').forEach((el) => {
|
|
4297
|
+
el.removeAttribute('data-processed');
|
|
4298
|
+
el.innerHTML = escapeHtml(el.getAttribute('data-original') || '');
|
|
4299
|
+
});
|
|
4300
|
+
initMermaidBlocks();
|
|
4301
|
+
}
|
|
4302
|
+
|
|
4246
4303
|
const _agentTabTexts = {};
|
|
4247
4304
|
|
|
4248
4305
|
function renderAgentTabs(promptHtml, responseHtml, promptText, responseText) {
|
|
@@ -4506,22 +4563,21 @@ function toggleTheme() {
|
|
|
4506
4563
|
updateThemeIcon();
|
|
4507
4564
|
updateThemeColor(!isCurrentlyLight);
|
|
4508
4565
|
syncHljsTheme();
|
|
4566
|
+
reinitMermaidTheme();
|
|
4509
4567
|
}
|
|
4510
4568
|
|
|
4511
4569
|
function syncHljsTheme() {
|
|
4512
|
-
const
|
|
4513
|
-
const dark = document.getElementById('hljs-theme-dark');
|
|
4514
|
-
const light = document.getElementById('hljs-theme-light');
|
|
4515
|
-
if (dark) dark
|
|
4516
|
-
if (light) light
|
|
4570
|
+
const light = isLightTheme();
|
|
4571
|
+
const dark$ = document.getElementById('hljs-theme-dark');
|
|
4572
|
+
const light$ = document.getElementById('hljs-theme-light');
|
|
4573
|
+
if (dark$) dark$.disabled = light;
|
|
4574
|
+
if (light$) light$.disabled = !light;
|
|
4517
4575
|
}
|
|
4518
4576
|
|
|
4519
4577
|
function updateThemeIcon() {
|
|
4520
|
-
const
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
document.getElementById('theme-icon-dark').style.display = isLight ? 'none' : 'block';
|
|
4524
|
-
document.getElementById('theme-icon-light').style.display = isLight ? 'block' : 'none';
|
|
4578
|
+
const light = isLightTheme();
|
|
4579
|
+
document.getElementById('theme-icon-dark').style.display = light ? 'none' : 'block';
|
|
4580
|
+
document.getElementById('theme-icon-light').style.display = light ? 'block' : 'none';
|
|
4525
4581
|
}
|
|
4526
4582
|
|
|
4527
4583
|
function loadTheme() {
|
|
@@ -4695,8 +4751,20 @@ async function showSessionInfoModal(sessionId) {
|
|
|
4695
4751
|
showInfoModal(session, teamConfig, tasks, planContent);
|
|
4696
4752
|
}
|
|
4697
4753
|
|
|
4754
|
+
let _infoModalSessionId = null;
|
|
4698
4755
|
let _pendingPlanContent = null;
|
|
4699
4756
|
|
|
4757
|
+
function updateStickyBtnState() {
|
|
4758
|
+
const stickyBtn = document.getElementById('session-info-sticky-btn');
|
|
4759
|
+
if (!stickyBtn || !_infoModalSessionId) return;
|
|
4760
|
+
const isSticky = stickySessionIds.has(_infoModalSessionId);
|
|
4761
|
+
stickyBtn.style.display = '';
|
|
4762
|
+
stickyBtn.classList.toggle('active', isSticky);
|
|
4763
|
+
stickyBtn.title = isSticky ? 'Remove sticky pin' : 'Sticky pin — always show at top';
|
|
4764
|
+
const svg = stickyBtn.querySelector('svg');
|
|
4765
|
+
if (svg) svg.setAttribute('fill', isSticky ? 'currentColor' : 'none');
|
|
4766
|
+
}
|
|
4767
|
+
|
|
4700
4768
|
function showInfoModal(session, teamConfig, tasks, planContent) {
|
|
4701
4769
|
const modal = document.getElementById('team-modal');
|
|
4702
4770
|
const titleEl = document.getElementById('team-modal-title');
|
|
@@ -4834,6 +4902,8 @@ function showInfoModal(session, teamConfig, tasks, planContent) {
|
|
|
4834
4902
|
}
|
|
4835
4903
|
|
|
4836
4904
|
bodyEl.innerHTML = html;
|
|
4905
|
+
_infoModalSessionId = session.id;
|
|
4906
|
+
updateStickyBtnState();
|
|
4837
4907
|
modal.classList.add('visible');
|
|
4838
4908
|
|
|
4839
4909
|
const keyHandler = (e) => {
|
|
@@ -4996,6 +5066,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
4996
5066
|
if (typeof marked !== 'undefined' && typeof hljs !== 'undefined') {
|
|
4997
5067
|
const renderer = new marked.Renderer();
|
|
4998
5068
|
renderer.code = ({ text, lang }) => {
|
|
5069
|
+
if (lang === 'mermaid') {
|
|
5070
|
+
return `<pre class="mermaid" data-original="${escapeHtml(text)}">${escapeHtml(text)}</pre>`;
|
|
5071
|
+
}
|
|
4999
5072
|
let highlighted;
|
|
5000
5073
|
if (lang && hljs.getLanguage(lang)) {
|
|
5001
5074
|
highlighted = hljs.highlight(text, { language: lang }).value;
|
|
@@ -5006,6 +5079,20 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
5006
5079
|
};
|
|
5007
5080
|
marked.use({ renderer });
|
|
5008
5081
|
}
|
|
5082
|
+
|
|
5083
|
+
if (typeof mermaid !== 'undefined') {
|
|
5084
|
+
mermaid.initialize({ startOnLoad: false, theme: getMermaidTheme() });
|
|
5085
|
+
let mermaidPending = false;
|
|
5086
|
+
const mo = new MutationObserver(() => {
|
|
5087
|
+
if (mermaidPending) return;
|
|
5088
|
+
mermaidPending = true;
|
|
5089
|
+
queueMicrotask(() => {
|
|
5090
|
+
mermaidPending = false;
|
|
5091
|
+
initMermaidBlocks();
|
|
5092
|
+
});
|
|
5093
|
+
});
|
|
5094
|
+
mo.observe(document.body, { childList: true, subtree: true });
|
|
5095
|
+
}
|
|
5009
5096
|
});
|
|
5010
5097
|
|
|
5011
5098
|
loadSidebarState();
|
package/public/index.html
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/styles/github-dark.min.css" id="hljs-theme-dark">
|
|
21
21
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/styles/github.min.css" id="hljs-theme-light" disabled>
|
|
22
22
|
<script defer src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/highlight.min.js"></script>
|
|
23
|
+
<script defer src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
|
|
23
24
|
<script defer src="/app.js"></script>
|
|
24
25
|
</head>
|
|
25
26
|
<body>
|
|
@@ -482,11 +483,16 @@
|
|
|
482
483
|
<div class="modal" onclick="event.stopPropagation()">
|
|
483
484
|
<div class="modal-header">
|
|
484
485
|
<h3 id="team-modal-title" class="modal-title">Team</h3>
|
|
485
|
-
<
|
|
486
|
-
<
|
|
487
|
-
<path d="
|
|
488
|
-
</
|
|
489
|
-
|
|
486
|
+
<div style="display:flex;align-items:center;gap:4px;">
|
|
487
|
+
<button id="session-info-sticky-btn" class="icon-btn" style="display:none" title="Sticky pin — always show at top" onclick="toggleSessionSticky(_infoModalSessionId); updateStickyBtnState()">
|
|
488
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2 L15 9 L22 9 L17 14 L19 22 L12 18 L5 22 L7 14 L2 9 L9 9 Z"/></svg>
|
|
489
|
+
</button>
|
|
490
|
+
<button class="modal-close" aria-label="Close dialog" onclick="closeTeamModal()">
|
|
491
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
492
|
+
<path d="M18 6L6 18M6 6l12 12"/>
|
|
493
|
+
</svg>
|
|
494
|
+
</button>
|
|
495
|
+
</div>
|
|
490
496
|
</div>
|
|
491
497
|
<div id="team-modal-body" class="modal-body"></div>
|
|
492
498
|
<div class="modal-footer">
|
package/public/style.css
CHANGED
|
@@ -2009,6 +2009,9 @@ body::before {
|
|
|
2009
2009
|
fill: var(--warning);
|
|
2010
2010
|
stroke: var(--warning);
|
|
2011
2011
|
}
|
|
2012
|
+
#session-info-sticky-btn.active {
|
|
2013
|
+
color: var(--warning);
|
|
2014
|
+
}
|
|
2012
2015
|
.pinned-sessions-divider {
|
|
2013
2016
|
height: 1px;
|
|
2014
2017
|
margin: 4px 8px;
|
|
@@ -2418,6 +2421,13 @@ body::before {
|
|
|
2418
2421
|
overflow: hidden;
|
|
2419
2422
|
text-overflow: ellipsis;
|
|
2420
2423
|
}
|
|
2424
|
+
.task-owner-badge--compact {
|
|
2425
|
+
font-size: 9px;
|
|
2426
|
+
padding: 2px 6px;
|
|
2427
|
+
border-radius: 3px;
|
|
2428
|
+
margin-left: 6px;
|
|
2429
|
+
vertical-align: middle;
|
|
2430
|
+
}
|
|
2421
2431
|
.agent-status-row {
|
|
2422
2432
|
display: flex;
|
|
2423
2433
|
align-items: center;
|
|
@@ -3165,6 +3175,22 @@ select.form-input option:checked {
|
|
|
3165
3175
|
|
|
3166
3176
|
/* #endregion */
|
|
3167
3177
|
|
|
3178
|
+
/* #region MERMAID */
|
|
3179
|
+
pre.mermaid {
|
|
3180
|
+
text-align: center;
|
|
3181
|
+
background: transparent;
|
|
3182
|
+
overflow-x: auto;
|
|
3183
|
+
}
|
|
3184
|
+
pre.mermaid svg {
|
|
3185
|
+
max-width: 100%;
|
|
3186
|
+
}
|
|
3187
|
+
.modal.has-mermaid {
|
|
3188
|
+
width: 80vw;
|
|
3189
|
+
max-width: 80vw;
|
|
3190
|
+
max-height: 90vh;
|
|
3191
|
+
}
|
|
3192
|
+
/* #endregion */
|
|
3193
|
+
|
|
3168
3194
|
/* #region ANIMATIONS */
|
|
3169
3195
|
@keyframes fadeSlideIn {
|
|
3170
3196
|
from {
|
package/server.js
CHANGED
|
@@ -1015,12 +1015,15 @@ app.get('/api/sessions/:sessionId/agents', (req, res) => {
|
|
|
1015
1015
|
}
|
|
1016
1016
|
|
|
1017
1017
|
const agentsNeedingPrompt = agents.filter(a => !a.prompt);
|
|
1018
|
-
|
|
1018
|
+
const agentsNeedingName = agents.filter(a => !a.agentName);
|
|
1019
|
+
if ((agentsNeedingPrompt.length || agentsNeedingName.length) && meta.jsonlPath) {
|
|
1019
1020
|
let byAgentId = {};
|
|
1021
|
+
let nameByAgentId = {};
|
|
1020
1022
|
try {
|
|
1021
1023
|
const progressMap = getProgressMap(meta.jsonlPath);
|
|
1022
1024
|
for (const entry of Object.values(progressMap)) {
|
|
1023
1025
|
if (entry.prompt && !byAgentId[entry.agentId]) byAgentId[entry.agentId] = entry.prompt;
|
|
1026
|
+
if (entry.name && !nameByAgentId[entry.agentId]) nameByAgentId[entry.agentId] = entry.name;
|
|
1024
1027
|
}
|
|
1025
1028
|
} catch (_) {}
|
|
1026
1029
|
for (const agent of agentsNeedingPrompt) {
|
|
@@ -1028,6 +1031,9 @@ app.get('/api/sessions/:sessionId/agents', (req, res) => {
|
|
|
1028
1031
|
|| (() => { try { return extractPromptFromTranscript(subagentJsonlPath(meta, agent.agentId)); } catch (_) { return null; } })();
|
|
1029
1032
|
if (prompt) persistPrompt(agent, prompt);
|
|
1030
1033
|
}
|
|
1034
|
+
for (const agent of agentsNeedingName) {
|
|
1035
|
+
if (nameByAgentId[agent.agentId]) agent.agentName = nameByAgentId[agent.agentId];
|
|
1036
|
+
}
|
|
1031
1037
|
}
|
|
1032
1038
|
|
|
1033
1039
|
const agentsNeedingModel = agents.filter(a => !a.model);
|