claude-code-kanban 2.2.0 → 2.3.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/lib/parsers.js +20 -2
- package/package.json +1 -1
- package/public/app.js +101 -12
- package/public/index.html +1 -0
- package/public/style.css +16 -0
- package/server.js +37 -4
package/lib/parsers.js
CHANGED
|
@@ -541,6 +541,7 @@ function buildAgentProgressMap(jsonlPath) {
|
|
|
541
541
|
const tmToolIdRe = /"tool_use_id":"([^"]+)"/;
|
|
542
542
|
const tmAgentIdRe = /agent_id: ([a-zA-Z0-9_@-]+)/;
|
|
543
543
|
const nameByToolUseId = {};
|
|
544
|
+
const descByToolUseId = {};
|
|
544
545
|
for (const line of content.split('\n')) {
|
|
545
546
|
if (line.includes('"agent_progress"')) {
|
|
546
547
|
const agentMatch = re.exec(line);
|
|
@@ -574,8 +575,24 @@ function buildAgentProgressMap(jsonlPath) {
|
|
|
574
575
|
const blocks = obj.message?.content;
|
|
575
576
|
if (Array.isArray(blocks)) {
|
|
576
577
|
for (const b of blocks) {
|
|
577
|
-
if (b.type === 'tool_use' && b.name === 'Agent' && b.id
|
|
578
|
-
nameByToolUseId[b.id] = b.input.name;
|
|
578
|
+
if (b.type === 'tool_use' && b.name === 'Agent' && b.id) {
|
|
579
|
+
if (b.input?.name) nameByToolUseId[b.id] = b.input.name;
|
|
580
|
+
if (b.input?.description) descByToolUseId[b.id] = b.input.description;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
} catch (_) {}
|
|
585
|
+
} else if (line.includes('"toolUseResult"') && line.includes('"agentId"') && line.includes('"tool_result"')) {
|
|
586
|
+
try {
|
|
587
|
+
const obj = JSON.parse(line);
|
|
588
|
+
const tur = obj.toolUseResult;
|
|
589
|
+
if (tur?.agentId) {
|
|
590
|
+
const blocks = obj.message?.content;
|
|
591
|
+
if (Array.isArray(blocks)) {
|
|
592
|
+
for (const b of blocks) {
|
|
593
|
+
if (b.type === 'tool_result' && b.tool_use_id && !map[b.tool_use_id]) {
|
|
594
|
+
map[b.tool_use_id] = { agentId: tur.agentId, prompt: tur.prompt || null };
|
|
595
|
+
}
|
|
579
596
|
}
|
|
580
597
|
}
|
|
581
598
|
}
|
|
@@ -584,6 +601,7 @@ function buildAgentProgressMap(jsonlPath) {
|
|
|
584
601
|
}
|
|
585
602
|
for (const [key, entry] of Object.entries(map)) {
|
|
586
603
|
if (nameByToolUseId[key]) entry.name = nameByToolUseId[key];
|
|
604
|
+
if (descByToolUseId[key]) entry.description = descByToolUseId[key];
|
|
587
605
|
}
|
|
588
606
|
} catch (_) {}
|
|
589
607
|
return map;
|
package/package.json
CHANGED
package/public/app.js
CHANGED
|
@@ -25,6 +25,7 @@ let agentPollInterval = null;
|
|
|
25
25
|
let selectedTaskId = null;
|
|
26
26
|
let selectedSessionId = null;
|
|
27
27
|
let focusZone = 'board'; // 'board' | 'sidebar'
|
|
28
|
+
let appConfig = { marketplaceUrl: null };
|
|
28
29
|
let selectedSessionIdx = -1;
|
|
29
30
|
let selectedSessionKbId = null;
|
|
30
31
|
let sessionJustSelected = false;
|
|
@@ -36,6 +37,7 @@ let msgUserScrolledUp = false;
|
|
|
36
37
|
const MSG_MAX_LOADED = 200;
|
|
37
38
|
let currentProjectPath = null;
|
|
38
39
|
let currentProjectSessionIds = [];
|
|
40
|
+
const dismissedSessionIds = new Set();
|
|
39
41
|
|
|
40
42
|
function resetMessageScrollState() {
|
|
41
43
|
msgUserScrolledUp = false;
|
|
@@ -627,7 +629,10 @@ async function viewAgentLog(agentId) {
|
|
|
627
629
|
await fetchAgents(currentSessionId);
|
|
628
630
|
agent = findAgentById(agentId);
|
|
629
631
|
}
|
|
630
|
-
if (!agent)
|
|
632
|
+
if (!agent) {
|
|
633
|
+
if (!currentSessionId) return;
|
|
634
|
+
agent = { agentId: agentId, type: 'Agent', _sourceSessionId: currentSessionId };
|
|
635
|
+
}
|
|
631
636
|
const resolvedId = agent.agentId;
|
|
632
637
|
const shortId = resolvedId.length > 8 ? resolvedId.slice(0, 8) : resolvedId;
|
|
633
638
|
const agentSessionId = agent._sourceSessionId || currentSessionId;
|
|
@@ -652,6 +657,7 @@ async function viewAgentLog(agentId) {
|
|
|
652
657
|
const data = JSON.parse(e.data);
|
|
653
658
|
currentMessages = data.messages;
|
|
654
659
|
if (messagePanelOpen) renderMessages(data.messages);
|
|
660
|
+
maybeFollowLatest();
|
|
655
661
|
} catch (_) {}
|
|
656
662
|
});
|
|
657
663
|
agentLogSSE.onerror = () => {};
|
|
@@ -684,6 +690,7 @@ async function fetchAgentMessages() {
|
|
|
684
690
|
if (!agentLogMode || agentLogMode.agentId !== agentId) return;
|
|
685
691
|
currentMessages = data.messages;
|
|
686
692
|
if (messagePanelOpen) renderMessages(data.messages);
|
|
693
|
+
maybeFollowLatest();
|
|
687
694
|
} catch (e) {
|
|
688
695
|
console.error('[fetchAgentMessages]', e);
|
|
689
696
|
}
|
|
@@ -737,9 +744,7 @@ async function fetchMessages(sessionId) {
|
|
|
737
744
|
}
|
|
738
745
|
}
|
|
739
746
|
|
|
740
|
-
|
|
741
|
-
showMsgDetail(currentMessages.length - 1);
|
|
742
|
-
}
|
|
747
|
+
maybeFollowLatest();
|
|
743
748
|
} catch (e) {
|
|
744
749
|
console.error('[fetchMessages]', e);
|
|
745
750
|
}
|
|
@@ -1317,6 +1322,8 @@ function _renderPinToDetail(pin) {
|
|
|
1317
1322
|
}
|
|
1318
1323
|
|
|
1319
1324
|
const SESSION_PIN_SVG = PIN_SVG.replace('width="14" height="14"', 'width="12" height="12"');
|
|
1325
|
+
const MARKETPLACE_SVG =
|
|
1326
|
+
'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 2L3 6v14a2 2 0 002 2h14a2 2 0 002-2V6l-3-4z"/><line x1="3" y1="6" x2="21" y2="6"/><path d="M16 10a4 4 0 01-8 0"/></svg>';
|
|
1320
1327
|
|
|
1321
1328
|
//#endregion
|
|
1322
1329
|
|
|
@@ -1538,8 +1545,15 @@ function formatTaskToolDetail(params) {
|
|
|
1538
1545
|
}
|
|
1539
1546
|
function getToolDetail(tool, params, detail) {
|
|
1540
1547
|
if (TASK_TOOLS.has(tool)) return formatTaskToolDetail(params);
|
|
1541
|
-
if (detail) return
|
|
1542
|
-
|
|
1548
|
+
if (!detail) return '';
|
|
1549
|
+
let extra = '';
|
|
1550
|
+
if (tool === 'Read' && params) {
|
|
1551
|
+
const parts = [];
|
|
1552
|
+
if (params.offset) parts.push(`L${params.offset}`);
|
|
1553
|
+
if (params.limit) parts.push(`+${params.limit}`);
|
|
1554
|
+
if (parts.length) extra = ` <span style="color:var(--text-muted);opacity:.7">${parts.join(' ')}</span>`;
|
|
1555
|
+
}
|
|
1556
|
+
return ` <span style="color:var(--text-muted)">${escapeHtml(detail)}</span>${extra}`;
|
|
1543
1557
|
}
|
|
1544
1558
|
function renderTaskResult(toolResult) {
|
|
1545
1559
|
if (!toolResult) return '';
|
|
@@ -1828,10 +1842,12 @@ function renderAgentFooter() {
|
|
|
1828
1842
|
: a.status === 'idle'
|
|
1829
1843
|
? `idle · ${formatDuration(elapsed)}`
|
|
1830
1844
|
: `active · ${formatDuration(elapsed)}`;
|
|
1845
|
+
const descText = a.description || '';
|
|
1831
1846
|
const promptTrimmed = stripAnsi(stripTeammateWrapper((a.prompt || '').trim())).replace(/[\r\n]+/g, ' ');
|
|
1832
|
-
const
|
|
1833
|
-
const
|
|
1834
|
-
|
|
1847
|
+
const displayText = descText || promptTrimmed;
|
|
1848
|
+
const displayTrunc = displayText.length > 60 ? `${displayText.substring(0, 60)}…` : displayText;
|
|
1849
|
+
const msgHtml = displayTrunc
|
|
1850
|
+
? `<div class="agent-message" title="${escapeHtml(displayText)}">${escapeHtml(displayTrunc)}</div>`
|
|
1835
1851
|
: '';
|
|
1836
1852
|
const rawType = a.type || 'unknown';
|
|
1837
1853
|
const colonIdx = rawType.indexOf(':');
|
|
@@ -2091,6 +2107,7 @@ function renderSessions() {
|
|
|
2091
2107
|
const now = Date.now();
|
|
2092
2108
|
const activeSessionIds = new Set();
|
|
2093
2109
|
filteredSessions = filteredSessions.filter((s) => {
|
|
2110
|
+
if (dismissedSessionIds.has(s.id)) return false;
|
|
2094
2111
|
const isActive =
|
|
2095
2112
|
s.hasMessages &&
|
|
2096
2113
|
((!s.sharedTaskList && (s.pending > 0 || s.inProgress > 0)) ||
|
|
@@ -2219,6 +2236,7 @@ function renderSessions() {
|
|
|
2219
2236
|
${session.hasRunningAgents ? '<span class="agent-badge" title="Active agents">🤖</span>' : ''}
|
|
2220
2237
|
${session.planSourceSessionId ? `<span class="plan-indicator" title="Implements plan — click to reveal plan session" onclick="event.stopPropagation(); revealPlanSession('${escapeHtml(session.planSourceSessionId)}')">📋</span>` : ''}
|
|
2221
2238
|
${session.hasWaitingForUser ? '<span class="agent-badge" title="Waiting for user">❓</span>' : ''}
|
|
2239
|
+
${(window.__HUB__?.enabled || appConfig.marketplaceUrl) && session.project ? `<span class="marketplace-btn" data-project-path="${escapeHtml(session.project)}" onclick="event.stopPropagation(); openMarketplace(this.dataset.projectPath)" title="Open in Marketplace">${MARKETPLACE_SVG}</span>` : ''}
|
|
2222
2240
|
${isLive ? '<span class="pulse"></span>' : ''}
|
|
2223
2241
|
</span>
|
|
2224
2242
|
<div class="progress-bar"><div class="progress-fill" style="width: ${percent}%"></div></div>
|
|
@@ -2770,7 +2788,7 @@ function navigateSession(direction, items) {
|
|
|
2770
2788
|
}
|
|
2771
2789
|
const currentEl = items[selectedSessionIdx];
|
|
2772
2790
|
let newIdx = selectedSessionIdx + direction;
|
|
2773
|
-
if (!currentEl
|
|
2791
|
+
if (!currentEl?.isConnected) {
|
|
2774
2792
|
const restoredIdx = selectedSessionKbId ? items.findIndex((el) => getKbId(el) === selectedSessionKbId) : -1;
|
|
2775
2793
|
newIdx = restoredIdx >= 0 ? restoredIdx : 0;
|
|
2776
2794
|
}
|
|
@@ -4081,7 +4099,12 @@ function setupEventSource() {
|
|
|
4081
4099
|
}
|
|
4082
4100
|
|
|
4083
4101
|
if (data.type === 'team-update') {
|
|
4084
|
-
|
|
4102
|
+
const teamSession = sessions.find((s) => s.isTeam && s.teamName === data.teamName);
|
|
4103
|
+
if (teamSession) {
|
|
4104
|
+
debouncedRefresh(teamSession.id, false);
|
|
4105
|
+
} else if (currentSessionId) {
|
|
4106
|
+
debouncedRefresh(currentSessionId, false);
|
|
4107
|
+
}
|
|
4085
4108
|
}
|
|
4086
4109
|
};
|
|
4087
4110
|
}
|
|
@@ -4238,6 +4261,12 @@ function renderContextDetail(raw) {
|
|
|
4238
4261
|
//#endregion
|
|
4239
4262
|
|
|
4240
4263
|
//#region UTILS
|
|
4264
|
+
function maybeFollowLatest() {
|
|
4265
|
+
if (msgDetailFollowLatest && currentMessages.length) {
|
|
4266
|
+
showMsgDetail(currentMessages.length - 1);
|
|
4267
|
+
}
|
|
4268
|
+
}
|
|
4269
|
+
|
|
4241
4270
|
function isSessionActive(s) {
|
|
4242
4271
|
return s.hasRecentLog || s.inProgress > 0 || s.hasActiveAgents || s.hasWaitingForUser;
|
|
4243
4272
|
}
|
|
@@ -4908,6 +4937,7 @@ function showInfoModal(session, teamConfig, tasks, planContent) {
|
|
|
4908
4937
|
bodyEl.innerHTML = html;
|
|
4909
4938
|
_infoModalSessionId = session.id;
|
|
4910
4939
|
updateStickyBtnState();
|
|
4940
|
+
updateDismissBtnState();
|
|
4911
4941
|
modal.classList.add('visible');
|
|
4912
4942
|
|
|
4913
4943
|
const keyHandler = (e) => {
|
|
@@ -4925,6 +4955,25 @@ function closeTeamModal() {
|
|
|
4925
4955
|
document.getElementById('team-modal').classList.remove('visible');
|
|
4926
4956
|
}
|
|
4927
4957
|
|
|
4958
|
+
// biome-ignore lint/correctness/noUnusedVariables: used in HTML
|
|
4959
|
+
function toggleDismissSession(sessionId) {
|
|
4960
|
+
if (dismissedSessionIds.has(sessionId)) {
|
|
4961
|
+
dismissedSessionIds.delete(sessionId);
|
|
4962
|
+
} else {
|
|
4963
|
+
dismissedSessionIds.add(sessionId);
|
|
4964
|
+
}
|
|
4965
|
+
updateDismissBtnState();
|
|
4966
|
+
renderSessions();
|
|
4967
|
+
}
|
|
4968
|
+
|
|
4969
|
+
function updateDismissBtnState() {
|
|
4970
|
+
const btn = document.getElementById('session-info-dismiss-btn');
|
|
4971
|
+
if (!btn || !_infoModalSessionId) return;
|
|
4972
|
+
const isDismissed = dismissedSessionIds.has(_infoModalSessionId);
|
|
4973
|
+
btn.textContent = isDismissed ? 'Restore' : 'Dismiss';
|
|
4974
|
+
btn.title = isDismissed ? 'Restore — show in active list again' : 'Dismiss — hide from active list';
|
|
4975
|
+
}
|
|
4976
|
+
|
|
4928
4977
|
let _planSessionId = null;
|
|
4929
4978
|
|
|
4930
4979
|
//#endregion
|
|
@@ -4991,6 +5040,18 @@ function openFolderInEditor(folder, file) {
|
|
|
4991
5040
|
postAndToast('/api/open-folder', body, 'folder');
|
|
4992
5041
|
}
|
|
4993
5042
|
|
|
5043
|
+
// biome-ignore lint/correctness/noUnusedVariables: used in HTML
|
|
5044
|
+
function openMarketplace(projectPath) {
|
|
5045
|
+
const params = new URLSearchParams({ project: projectPath });
|
|
5046
|
+
if (window.__HUB__?.enabled) {
|
|
5047
|
+
hubNavigate('marketplace', `?${params}`);
|
|
5048
|
+
} else if (appConfig.marketplaceUrl) {
|
|
5049
|
+
const url = new URL(appConfig.marketplaceUrl);
|
|
5050
|
+
url.search = params.toString();
|
|
5051
|
+
window.open(url.toString(), '_blank');
|
|
5052
|
+
}
|
|
5053
|
+
}
|
|
5054
|
+
|
|
4994
5055
|
//#endregion
|
|
4995
5056
|
|
|
4996
5057
|
//#region OWNER_FILTER
|
|
@@ -4999,7 +5060,7 @@ function updateOwnerFilter() {
|
|
|
4999
5060
|
const select = document.getElementById('owner-filter');
|
|
5000
5061
|
|
|
5001
5062
|
const session = sessions.find((s) => s.id === currentSessionId);
|
|
5002
|
-
if (!session
|
|
5063
|
+
if (!session?.isTeam) {
|
|
5003
5064
|
bar.classList.remove('visible');
|
|
5004
5065
|
return;
|
|
5005
5066
|
}
|
|
@@ -5169,6 +5230,13 @@ if (urlState.search) {
|
|
|
5169
5230
|
document.getElementById('search-clear-btn').classList.add('visible');
|
|
5170
5231
|
}
|
|
5171
5232
|
|
|
5233
|
+
fetch('/api/config')
|
|
5234
|
+
.then((r) => r.json())
|
|
5235
|
+
.then((c) => {
|
|
5236
|
+
appConfig = c;
|
|
5237
|
+
})
|
|
5238
|
+
.catch(() => {});
|
|
5239
|
+
|
|
5172
5240
|
fetchSessions().then(async () => {
|
|
5173
5241
|
if (urlState.projectView) {
|
|
5174
5242
|
try {
|
|
@@ -5209,3 +5277,24 @@ window.addEventListener('popstate', () => {
|
|
|
5209
5277
|
if (s.messages !== messagePanelOpen) toggleMessagePanel();
|
|
5210
5278
|
});
|
|
5211
5279
|
//#endregion
|
|
5280
|
+
|
|
5281
|
+
// #region HUB_INTEGRATION
|
|
5282
|
+
(async function initHub() {
|
|
5283
|
+
const cfg = await fetch('/hub-config')
|
|
5284
|
+
.then((r) => r.json())
|
|
5285
|
+
.catch(() => ({}));
|
|
5286
|
+
if (!cfg.enabled) return;
|
|
5287
|
+
window.__HUB__ = cfg;
|
|
5288
|
+
document.addEventListener('keydown', (e) => {
|
|
5289
|
+
if (e.ctrlKey && e.altKey && (e.key === 'ArrowLeft' || e.key === 'ArrowRight')) {
|
|
5290
|
+
e.preventDefault();
|
|
5291
|
+
window.parent?.postMessage({ type: 'hub:keydown', key: e.key }, '*');
|
|
5292
|
+
}
|
|
5293
|
+
});
|
|
5294
|
+
})();
|
|
5295
|
+
|
|
5296
|
+
window.hubNavigate = function hubNavigate(app, url) {
|
|
5297
|
+
if (!window.__HUB__?.enabled) return;
|
|
5298
|
+
window.parent?.postMessage({ type: 'hub:navigate', app, url }, '*');
|
|
5299
|
+
};
|
|
5300
|
+
// #endregion HUB_INTEGRATION
|
package/public/index.html
CHANGED
|
@@ -496,6 +496,7 @@
|
|
|
496
496
|
</div>
|
|
497
497
|
<div id="team-modal-body" class="modal-body"></div>
|
|
498
498
|
<div class="modal-footer">
|
|
499
|
+
<button id="session-info-dismiss-btn" class="btn btn-secondary" onclick="toggleDismissSession(_infoModalSessionId)">Dismiss</button>
|
|
499
500
|
<button class="btn btn-primary" onclick="closeTeamModal()">Close</button>
|
|
500
501
|
</div>
|
|
501
502
|
</div>
|
package/public/style.css
CHANGED
|
@@ -3330,6 +3330,22 @@ pre.mermaid svg {
|
|
|
3330
3330
|
color: var(--accent);
|
|
3331
3331
|
}
|
|
3332
3332
|
|
|
3333
|
+
.marketplace-btn {
|
|
3334
|
+
color: #888;
|
|
3335
|
+
cursor: pointer;
|
|
3336
|
+
display: inline-flex;
|
|
3337
|
+
align-items: center;
|
|
3338
|
+
transition:
|
|
3339
|
+
color 0.15s,
|
|
3340
|
+
filter 0.15s;
|
|
3341
|
+
border-radius: 3px;
|
|
3342
|
+
}
|
|
3343
|
+
|
|
3344
|
+
.marketplace-btn:hover {
|
|
3345
|
+
color: var(--accent);
|
|
3346
|
+
filter: drop-shadow(0 0 3px var(--accent));
|
|
3347
|
+
}
|
|
3348
|
+
|
|
3333
3349
|
.project-group-header .group-count {
|
|
3334
3350
|
font-weight: 400;
|
|
3335
3351
|
color: var(--text-muted);
|
package/server.js
CHANGED
|
@@ -48,6 +48,17 @@ function getClaudeDir() {
|
|
|
48
48
|
return process.env.CLAUDE_DIR || path.join(os.homedir(), '.claude');
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
function getMarketplaceUrl() {
|
|
52
|
+
const idx = process.argv.findIndex(arg => arg.startsWith('--marketplace-url'));
|
|
53
|
+
if (idx !== -1) {
|
|
54
|
+
const arg = process.argv[idx];
|
|
55
|
+
if (arg.includes('=')) return arg.split('=').slice(1).join('=');
|
|
56
|
+
if (process.argv[idx + 1]) return process.argv[idx + 1];
|
|
57
|
+
}
|
|
58
|
+
return process.env.MARKETPLACE_URL || null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const MARKETPLACE_URL = getMarketplaceUrl();
|
|
51
62
|
const CLAUDE_DIR = getClaudeDir();
|
|
52
63
|
const TASKS_DIR = path.join(CLAUDE_DIR, 'tasks');
|
|
53
64
|
const PROJECTS_DIR = path.join(CLAUDE_DIR, 'projects');
|
|
@@ -181,6 +192,10 @@ app.param('taskId', (req, res, next, val) => {
|
|
|
181
192
|
// Parse JSON bodies
|
|
182
193
|
app.use(express.json());
|
|
183
194
|
|
|
195
|
+
app.get('/hub-config', (_req, res) => {
|
|
196
|
+
res.json({ enabled: !!process.env.CLAUDE_HUB, url: process.env.HUB_URL || null });
|
|
197
|
+
});
|
|
198
|
+
|
|
184
199
|
// Serve static files
|
|
185
200
|
app.get('/sw.js', (req, res) => {
|
|
186
201
|
res.setHeader('Cache-Control', 'no-cache');
|
|
@@ -1016,14 +1031,17 @@ app.get('/api/sessions/:sessionId/agents', (req, res) => {
|
|
|
1016
1031
|
|
|
1017
1032
|
const agentsNeedingPrompt = agents.filter(a => !a.prompt);
|
|
1018
1033
|
const agentsNeedingName = agents.filter(a => !a.agentName);
|
|
1019
|
-
|
|
1034
|
+
const agentsNeedingDesc = agents.filter(a => !a.description);
|
|
1035
|
+
if ((agentsNeedingPrompt.length || agentsNeedingName.length || agentsNeedingDesc.length) && meta.jsonlPath) {
|
|
1020
1036
|
let byAgentId = {};
|
|
1021
1037
|
let nameByAgentId = {};
|
|
1038
|
+
let descByAgentId = {};
|
|
1022
1039
|
try {
|
|
1023
1040
|
const progressMap = getProgressMap(meta.jsonlPath);
|
|
1024
1041
|
for (const entry of Object.values(progressMap)) {
|
|
1025
1042
|
if (entry.prompt && !byAgentId[entry.agentId]) byAgentId[entry.agentId] = entry.prompt;
|
|
1026
1043
|
if (entry.name && !nameByAgentId[entry.agentId]) nameByAgentId[entry.agentId] = entry.name;
|
|
1044
|
+
if (entry.description && !descByAgentId[entry.agentId]) descByAgentId[entry.agentId] = entry.description;
|
|
1027
1045
|
}
|
|
1028
1046
|
} catch (_) {}
|
|
1029
1047
|
for (const agent of agentsNeedingPrompt) {
|
|
@@ -1034,6 +1052,9 @@ app.get('/api/sessions/:sessionId/agents', (req, res) => {
|
|
|
1034
1052
|
for (const agent of agentsNeedingName) {
|
|
1035
1053
|
if (nameByAgentId[agent.agentId]) agent.agentName = nameByAgentId[agent.agentId];
|
|
1036
1054
|
}
|
|
1055
|
+
for (const agent of agentsNeedingDesc) {
|
|
1056
|
+
if (descByAgentId[agent.agentId]) agent.description = descByAgentId[agent.agentId];
|
|
1057
|
+
}
|
|
1037
1058
|
}
|
|
1038
1059
|
|
|
1039
1060
|
const agentsNeedingModel = agents.filter(a => !a.model);
|
|
@@ -1199,6 +1220,7 @@ app.get('/api/sessions/:sessionId/messages', (req, res) => {
|
|
|
1199
1220
|
const entry = progressMap[msg.toolUseId];
|
|
1200
1221
|
if (entry) {
|
|
1201
1222
|
msg.agentId = entry.agentId;
|
|
1223
|
+
if (entry.description) msg.agentDescription = entry.description;
|
|
1202
1224
|
if (entry.prompt && !msg.agentPrompt) msg.agentPrompt = entry.prompt;
|
|
1203
1225
|
try {
|
|
1204
1226
|
const agentFile = path.join(agentDir, entry.agentId + '.json');
|
|
@@ -1244,6 +1266,10 @@ app.get('/api/version', (req, res) => {
|
|
|
1244
1266
|
res.json({ version: pkg.version });
|
|
1245
1267
|
});
|
|
1246
1268
|
|
|
1269
|
+
app.get('/api/config', (req, res) => {
|
|
1270
|
+
res.json({ marketplaceUrl: MARKETPLACE_URL });
|
|
1271
|
+
});
|
|
1272
|
+
|
|
1247
1273
|
// API: Get all tasks across all sessions
|
|
1248
1274
|
app.get('/api/tasks/all', async (req, res) => {
|
|
1249
1275
|
try {
|
|
@@ -1445,9 +1471,16 @@ watcher.on('all', (event, filePath) => {
|
|
|
1445
1471
|
function broadcastToMappedSessions(taskListName, event, filePath) {
|
|
1446
1472
|
const { listToSessions } = loadAllTaskMaps();
|
|
1447
1473
|
const map = listToSessions[taskListName];
|
|
1448
|
-
if (
|
|
1449
|
-
|
|
1450
|
-
|
|
1474
|
+
if (map) {
|
|
1475
|
+
for (const sid of Object.keys(map)) {
|
|
1476
|
+
broadcast({ type: 'update', event, sessionId: sid, file: path.basename(filePath) });
|
|
1477
|
+
}
|
|
1478
|
+
return;
|
|
1479
|
+
}
|
|
1480
|
+
// Fallback: check if taskListName is a team name
|
|
1481
|
+
const cfg = loadTeamConfig(taskListName);
|
|
1482
|
+
if (cfg?.leadSessionId) {
|
|
1483
|
+
broadcast({ type: 'update', event, sessionId: cfg.leadSessionId, file: path.basename(filePath) });
|
|
1451
1484
|
}
|
|
1452
1485
|
}
|
|
1453
1486
|
|