@cluesmith/codev 1.3.0 → 1.4.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/bin/af.js +0 -0
- package/bin/codev.js +0 -0
- package/bin/consult.js +0 -0
- package/bin/generate-image.js +0 -0
- package/dist/agent-farm/cli.d.ts.map +1 -1
- package/dist/agent-farm/cli.js +2 -1
- package/dist/agent-farm/cli.js.map +1 -1
- package/dist/agent-farm/commands/cleanup.js +12 -51
- package/dist/agent-farm/commands/cleanup.js.map +1 -1
- package/dist/agent-farm/commands/spawn.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn.js +13 -1
- package/dist/agent-farm/commands/spawn.js.map +1 -1
- package/dist/agent-farm/servers/dashboard-server.js +107 -5
- package/dist/agent-farm/servers/dashboard-server.js.map +1 -1
- package/dist/agent-farm/types.d.ts +1 -0
- package/dist/agent-farm/types.d.ts.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +2 -17
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt.d.ts.map +1 -1
- package/dist/commands/adopt.js +27 -2
- package/dist/commands/adopt.js.map +1 -1
- package/dist/commands/consult/index.d.ts.map +1 -1
- package/dist/commands/consult/index.js +23 -7
- package/dist/commands/consult/index.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +51 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +23 -2
- package/dist/commands/init.js.map +1 -1
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +23 -0
- package/dist/version.js.map +1 -0
- package/package.json +1 -1
- package/skeleton/DEPENDENCIES.md +3 -3
- package/skeleton/protocols/maintain/protocol.md +2 -2
- package/skeleton/{docs → resources}/commands/codev.md +0 -39
- package/skeleton/{docs → resources}/commands/consult.md +12 -2
- package/skeleton/{docs → resources}/commands/overview.md +0 -1
- package/skeleton/roles/architect.md +22 -0
- package/skeleton/roles/builder.md +22 -0
- package/skeleton/templates/arch.md +56 -0
- package/skeleton/templates/pr-overview.md +73 -0
- package/templates/dashboard-split.html +526 -164
- package/templates/open.html +285 -2
- package/templates/tower.html +71 -12
- package/dist/agent-farm/index.d.ts +0 -7
- package/dist/agent-farm/index.d.ts.map +0 -1
- package/dist/agent-farm/index.js +0 -373
- package/dist/agent-farm/index.js.map +0 -1
- package/skeleton/bin/agent-farm +0 -7
- package/skeleton/bin/codev-doctor +0 -335
- package/skeleton/resources/lessons-learned.md +0 -30
- /package/skeleton/{roles/review-types → consult-types}/impl-review.md +0 -0
- /package/skeleton/{roles/review-types → consult-types}/integration-review.md +0 -0
- /package/skeleton/{roles/review-types → consult-types}/plan-review.md +0 -0
- /package/skeleton/{roles/review-types → consult-types}/pr-ready.md +0 -0
- /package/skeleton/{roles/review-types → consult-types}/spec-review.md +0 -0
- /package/skeleton/{docs → resources}/commands/agent-farm.md +0 -0
- /package/skeleton/{AGENTS.md.template → templates/AGENTS.md} +0 -0
- /package/skeleton/{CLAUDE.md.template → templates/CLAUDE.md} +0 -0
package/templates/open.html
CHANGED
|
@@ -13,11 +13,14 @@
|
|
|
13
13
|
</script>
|
|
14
14
|
<style>
|
|
15
15
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
16
|
-
body {
|
|
16
|
+
html, body {
|
|
17
17
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
18
18
|
background: #1a1a1a;
|
|
19
19
|
color: #fff;
|
|
20
|
-
|
|
20
|
+
height: 100%;
|
|
21
|
+
}
|
|
22
|
+
body.preview-active {
|
|
23
|
+
overflow: hidden;
|
|
21
24
|
}
|
|
22
25
|
.header {
|
|
23
26
|
padding: 15px 20px;
|
|
@@ -199,6 +202,78 @@
|
|
|
199
202
|
outline: none;
|
|
200
203
|
}
|
|
201
204
|
|
|
205
|
+
/* Search bar */
|
|
206
|
+
.search-bar {
|
|
207
|
+
display: none;
|
|
208
|
+
position: fixed;
|
|
209
|
+
top: 10px;
|
|
210
|
+
right: 20px;
|
|
211
|
+
background: #2a2a2a;
|
|
212
|
+
border: 1px solid #444;
|
|
213
|
+
border-radius: 6px;
|
|
214
|
+
padding: 8px 12px;
|
|
215
|
+
z-index: 250;
|
|
216
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
|
|
217
|
+
}
|
|
218
|
+
.search-bar.active {
|
|
219
|
+
display: flex;
|
|
220
|
+
align-items: center;
|
|
221
|
+
gap: 8px;
|
|
222
|
+
}
|
|
223
|
+
.search-bar input {
|
|
224
|
+
background: #1a1a1a;
|
|
225
|
+
border: 1px solid #444;
|
|
226
|
+
border-radius: 4px;
|
|
227
|
+
color: #fff;
|
|
228
|
+
padding: 6px 10px;
|
|
229
|
+
font-size: 14px;
|
|
230
|
+
width: 250px;
|
|
231
|
+
outline: none;
|
|
232
|
+
}
|
|
233
|
+
.search-bar input:focus {
|
|
234
|
+
border-color: #3b82f6;
|
|
235
|
+
}
|
|
236
|
+
.search-bar .search-nav {
|
|
237
|
+
display: flex;
|
|
238
|
+
align-items: center;
|
|
239
|
+
gap: 4px;
|
|
240
|
+
}
|
|
241
|
+
.search-bar .search-nav button {
|
|
242
|
+
background: #444;
|
|
243
|
+
border: none;
|
|
244
|
+
color: #fff;
|
|
245
|
+
padding: 4px 8px;
|
|
246
|
+
border-radius: 4px;
|
|
247
|
+
cursor: pointer;
|
|
248
|
+
font-size: 14px;
|
|
249
|
+
}
|
|
250
|
+
.search-bar .search-nav button:hover {
|
|
251
|
+
background: #555;
|
|
252
|
+
}
|
|
253
|
+
.search-bar .search-count {
|
|
254
|
+
color: #888;
|
|
255
|
+
font-size: 12px;
|
|
256
|
+
min-width: 60px;
|
|
257
|
+
}
|
|
258
|
+
.search-bar .search-close {
|
|
259
|
+
background: none;
|
|
260
|
+
border: none;
|
|
261
|
+
color: #888;
|
|
262
|
+
cursor: pointer;
|
|
263
|
+
font-size: 18px;
|
|
264
|
+
padding: 0 4px;
|
|
265
|
+
}
|
|
266
|
+
.search-bar .search-close:hover {
|
|
267
|
+
color: #fff;
|
|
268
|
+
}
|
|
269
|
+
.search-highlight {
|
|
270
|
+
background: rgba(250, 204, 21, 0.4);
|
|
271
|
+
border-radius: 2px;
|
|
272
|
+
}
|
|
273
|
+
.search-highlight.current {
|
|
274
|
+
background: rgba(59, 130, 246, 0.6);
|
|
275
|
+
}
|
|
276
|
+
|
|
202
277
|
/* Notification toast */
|
|
203
278
|
.notification {
|
|
204
279
|
position: fixed;
|
|
@@ -401,6 +476,17 @@
|
|
|
401
476
|
<!-- Editor mode -->
|
|
402
477
|
<textarea id="editor" spellcheck="false"></textarea>
|
|
403
478
|
|
|
479
|
+
<!-- Search Bar -->
|
|
480
|
+
<div class="search-bar" id="searchBar">
|
|
481
|
+
<input type="text" id="searchInput" placeholder="Search..." autocomplete="off" />
|
|
482
|
+
<div class="search-nav">
|
|
483
|
+
<span class="search-count" id="searchCount"></span>
|
|
484
|
+
<button onclick="searchPrev()" title="Previous (Shift+Enter)">↑</button>
|
|
485
|
+
<button onclick="searchNext()" title="Next (Enter)">↓</button>
|
|
486
|
+
</div>
|
|
487
|
+
<button class="search-close" onclick="closeSearch()" title="Close (Esc)">×</button>
|
|
488
|
+
</div>
|
|
489
|
+
|
|
404
490
|
<!-- Comment Dialog -->
|
|
405
491
|
<div class="overlay" id="overlay">
|
|
406
492
|
<div class="dialog">
|
|
@@ -702,12 +788,14 @@
|
|
|
702
788
|
renderPreview();
|
|
703
789
|
viewMode.style.display = 'none';
|
|
704
790
|
previewContainer.style.display = 'block';
|
|
791
|
+
document.body.classList.add('preview-active');
|
|
705
792
|
toggleIcon.textContent = '📝';
|
|
706
793
|
toggleText.textContent = 'Annotate';
|
|
707
794
|
} else {
|
|
708
795
|
// Switch back to annotated view
|
|
709
796
|
viewMode.style.display = 'grid';
|
|
710
797
|
previewContainer.style.display = 'none';
|
|
798
|
+
document.body.classList.remove('preview-active');
|
|
711
799
|
toggleIcon.textContent = '👁';
|
|
712
800
|
toggleText.textContent = 'Preview';
|
|
713
801
|
}
|
|
@@ -1377,6 +1465,201 @@
|
|
|
1377
1465
|
}
|
|
1378
1466
|
});
|
|
1379
1467
|
|
|
1468
|
+
// ==================== Search Functions ====================
|
|
1469
|
+
|
|
1470
|
+
let searchMatches = [];
|
|
1471
|
+
let currentMatchIndex = -1;
|
|
1472
|
+
let searchActive = false;
|
|
1473
|
+
|
|
1474
|
+
function openSearch() {
|
|
1475
|
+
const searchBar = document.getElementById('searchBar');
|
|
1476
|
+
const searchInput = document.getElementById('searchInput');
|
|
1477
|
+
searchBar.classList.add('active');
|
|
1478
|
+
searchInput.focus();
|
|
1479
|
+
searchInput.select();
|
|
1480
|
+
searchActive = true;
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
function closeSearch() {
|
|
1484
|
+
const searchBar = document.getElementById('searchBar');
|
|
1485
|
+
searchBar.classList.remove('active');
|
|
1486
|
+
clearSearchHighlights();
|
|
1487
|
+
searchMatches = [];
|
|
1488
|
+
currentMatchIndex = -1;
|
|
1489
|
+
searchActive = false;
|
|
1490
|
+
document.getElementById('searchCount').textContent = '';
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
function clearSearchHighlights() {
|
|
1494
|
+
document.querySelectorAll('.search-highlight').forEach(el => {
|
|
1495
|
+
const parent = el.parentNode;
|
|
1496
|
+
parent.replaceChild(document.createTextNode(el.textContent), el);
|
|
1497
|
+
parent.normalize();
|
|
1498
|
+
});
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
function performSearch(query) {
|
|
1502
|
+
clearSearchHighlights();
|
|
1503
|
+
searchMatches = [];
|
|
1504
|
+
currentMatchIndex = -1;
|
|
1505
|
+
|
|
1506
|
+
if (!query) {
|
|
1507
|
+
document.getElementById('searchCount').textContent = '';
|
|
1508
|
+
return;
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
const viewMode = document.getElementById('viewMode');
|
|
1512
|
+
const codeLines = viewMode.querySelectorAll('.code-line');
|
|
1513
|
+
const queryLower = query.toLowerCase();
|
|
1514
|
+
|
|
1515
|
+
codeLines.forEach((codeLine, lineIndex) => {
|
|
1516
|
+
const walker = document.createTreeWalker(codeLine, NodeFilter.SHOW_TEXT, null, false);
|
|
1517
|
+
const textNodes = [];
|
|
1518
|
+
while (walker.nextNode()) {
|
|
1519
|
+
textNodes.push(walker.currentNode);
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
textNodes.forEach(textNode => {
|
|
1523
|
+
const text = textNode.textContent;
|
|
1524
|
+
const textLower = text.toLowerCase();
|
|
1525
|
+
let startIndex = 0;
|
|
1526
|
+
let index;
|
|
1527
|
+
|
|
1528
|
+
while ((index = textLower.indexOf(queryLower, startIndex)) !== -1) {
|
|
1529
|
+
searchMatches.push({
|
|
1530
|
+
node: textNode,
|
|
1531
|
+
index: index,
|
|
1532
|
+
length: query.length,
|
|
1533
|
+
lineIndex: lineIndex
|
|
1534
|
+
});
|
|
1535
|
+
startIndex = index + 1;
|
|
1536
|
+
}
|
|
1537
|
+
});
|
|
1538
|
+
});
|
|
1539
|
+
|
|
1540
|
+
// Highlight matches (in reverse to preserve indices)
|
|
1541
|
+
const processedNodes = new Set();
|
|
1542
|
+
searchMatches.slice().reverse().forEach((match, reverseIdx) => {
|
|
1543
|
+
const idx = searchMatches.length - 1 - reverseIdx;
|
|
1544
|
+
if (processedNodes.has(match.node)) return;
|
|
1545
|
+
|
|
1546
|
+
const text = match.node.textContent;
|
|
1547
|
+
const parent = match.node.parentNode;
|
|
1548
|
+
|
|
1549
|
+
// Find all matches in this node
|
|
1550
|
+
const nodeMatches = searchMatches.filter(m => m.node === match.node);
|
|
1551
|
+
processedNodes.add(match.node);
|
|
1552
|
+
|
|
1553
|
+
// Build new content with highlights
|
|
1554
|
+
let lastEnd = 0;
|
|
1555
|
+
const fragment = document.createDocumentFragment();
|
|
1556
|
+
|
|
1557
|
+
nodeMatches.forEach((m, i) => {
|
|
1558
|
+
// Text before match
|
|
1559
|
+
if (m.index > lastEnd) {
|
|
1560
|
+
fragment.appendChild(document.createTextNode(text.substring(lastEnd, m.index)));
|
|
1561
|
+
}
|
|
1562
|
+
// Highlighted match
|
|
1563
|
+
const span = document.createElement('span');
|
|
1564
|
+
span.className = 'search-highlight';
|
|
1565
|
+
span.textContent = text.substring(m.index, m.index + m.length);
|
|
1566
|
+
span.dataset.matchIndex = searchMatches.indexOf(m);
|
|
1567
|
+
fragment.appendChild(span);
|
|
1568
|
+
lastEnd = m.index + m.length;
|
|
1569
|
+
});
|
|
1570
|
+
|
|
1571
|
+
// Text after last match
|
|
1572
|
+
if (lastEnd < text.length) {
|
|
1573
|
+
fragment.appendChild(document.createTextNode(text.substring(lastEnd)));
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
parent.replaceChild(fragment, match.node);
|
|
1577
|
+
});
|
|
1578
|
+
|
|
1579
|
+
updateSearchCount();
|
|
1580
|
+
|
|
1581
|
+
// Jump to first match
|
|
1582
|
+
if (searchMatches.length > 0) {
|
|
1583
|
+
currentMatchIndex = 0;
|
|
1584
|
+
highlightCurrentMatch();
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
function updateSearchCount() {
|
|
1589
|
+
const countEl = document.getElementById('searchCount');
|
|
1590
|
+
if (searchMatches.length === 0) {
|
|
1591
|
+
countEl.textContent = 'No results';
|
|
1592
|
+
} else {
|
|
1593
|
+
countEl.textContent = `${currentMatchIndex + 1} of ${searchMatches.length}`;
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
function highlightCurrentMatch() {
|
|
1598
|
+
// Remove current class from all
|
|
1599
|
+
document.querySelectorAll('.search-highlight.current').forEach(el => {
|
|
1600
|
+
el.classList.remove('current');
|
|
1601
|
+
});
|
|
1602
|
+
|
|
1603
|
+
// Add current class to current match
|
|
1604
|
+
const currentHighlight = document.querySelector(`.search-highlight[data-match-index="${currentMatchIndex}"]`);
|
|
1605
|
+
if (currentHighlight) {
|
|
1606
|
+
currentHighlight.classList.add('current');
|
|
1607
|
+
currentHighlight.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
updateSearchCount();
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
function searchNext() {
|
|
1614
|
+
if (searchMatches.length === 0) return;
|
|
1615
|
+
currentMatchIndex = (currentMatchIndex + 1) % searchMatches.length;
|
|
1616
|
+
highlightCurrentMatch();
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
function searchPrev() {
|
|
1620
|
+
if (searchMatches.length === 0) return;
|
|
1621
|
+
currentMatchIndex = (currentMatchIndex - 1 + searchMatches.length) % searchMatches.length;
|
|
1622
|
+
highlightCurrentMatch();
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
// Search input handlers
|
|
1626
|
+
document.getElementById('searchInput').addEventListener('input', (e) => {
|
|
1627
|
+
performSearch(e.target.value);
|
|
1628
|
+
});
|
|
1629
|
+
|
|
1630
|
+
document.getElementById('searchInput').addEventListener('keydown', (e) => {
|
|
1631
|
+
if (e.key === 'Enter') {
|
|
1632
|
+
e.preventDefault();
|
|
1633
|
+
if (e.shiftKey) {
|
|
1634
|
+
searchPrev();
|
|
1635
|
+
} else {
|
|
1636
|
+
searchNext();
|
|
1637
|
+
}
|
|
1638
|
+
} else if (e.key === 'Escape') {
|
|
1639
|
+
closeSearch();
|
|
1640
|
+
}
|
|
1641
|
+
});
|
|
1642
|
+
|
|
1643
|
+
// Cmd/Ctrl+F to open search, Cmd/Ctrl+G for next match
|
|
1644
|
+
document.addEventListener('keydown', (e) => {
|
|
1645
|
+
if ((e.ctrlKey || e.metaKey) && e.key === 'f') {
|
|
1646
|
+
e.preventDefault();
|
|
1647
|
+
openSearch();
|
|
1648
|
+
}
|
|
1649
|
+
if ((e.ctrlKey || e.metaKey) && e.key === 'g') {
|
|
1650
|
+
e.preventDefault();
|
|
1651
|
+
if (searchActive) {
|
|
1652
|
+
if (e.shiftKey) {
|
|
1653
|
+
searchPrev();
|
|
1654
|
+
} else {
|
|
1655
|
+
searchNext();
|
|
1656
|
+
}
|
|
1657
|
+
} else {
|
|
1658
|
+
openSearch();
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
});
|
|
1662
|
+
|
|
1380
1663
|
// FILE_CONTENT will be injected by the server
|
|
1381
1664
|
</script>
|
|
1382
1665
|
</body>
|
package/templates/tower.html
CHANGED
|
@@ -152,28 +152,42 @@
|
|
|
152
152
|
font-size: 15px;
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
/* Instance cards -
|
|
155
|
+
/* Instance cards - dynamic grid based on count */
|
|
156
156
|
.instances {
|
|
157
157
|
display: grid;
|
|
158
|
-
grid-template-columns: repeat(4, 1fr);
|
|
159
158
|
gap: 16px;
|
|
160
159
|
margin-bottom: 32px;
|
|
161
160
|
}
|
|
162
161
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
162
|
+
.instances-1 {
|
|
163
|
+
grid-template-columns: 1fr;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.instances-2 {
|
|
167
|
+
grid-template-columns: repeat(2, 1fr);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.instances-3 {
|
|
171
|
+
grid-template-columns: repeat(3, 1fr);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.instances-many {
|
|
175
|
+
grid-template-columns: repeat(3, 1fr);
|
|
167
176
|
}
|
|
168
177
|
|
|
169
178
|
@media (max-width: 1200px) {
|
|
170
|
-
.instances
|
|
179
|
+
.instances-2,
|
|
180
|
+
.instances-3,
|
|
181
|
+
.instances-many {
|
|
171
182
|
grid-template-columns: repeat(2, 1fr);
|
|
172
183
|
}
|
|
173
184
|
}
|
|
174
185
|
|
|
175
186
|
@media (max-width: 800px) {
|
|
176
|
-
.instances
|
|
187
|
+
.instances-1,
|
|
188
|
+
.instances-2,
|
|
189
|
+
.instances-3,
|
|
190
|
+
.instances-many {
|
|
177
191
|
grid-template-columns: 1fr;
|
|
178
192
|
}
|
|
179
193
|
}
|
|
@@ -204,10 +218,28 @@
|
|
|
204
218
|
}
|
|
205
219
|
|
|
206
220
|
.instance-path-row {
|
|
207
|
-
|
|
221
|
+
display: flex;
|
|
222
|
+
align-items: center;
|
|
223
|
+
gap: 8px;
|
|
224
|
+
padding: 8px 20px;
|
|
208
225
|
border-bottom: 1px solid var(--border);
|
|
209
226
|
}
|
|
210
227
|
|
|
228
|
+
.copy-btn {
|
|
229
|
+
background: none;
|
|
230
|
+
border: none;
|
|
231
|
+
color: var(--text-muted);
|
|
232
|
+
cursor: pointer;
|
|
233
|
+
padding: 4px;
|
|
234
|
+
font-size: 12px;
|
|
235
|
+
opacity: 0.6;
|
|
236
|
+
transition: opacity 0.15s;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.copy-btn:hover {
|
|
240
|
+
opacity: 1;
|
|
241
|
+
}
|
|
242
|
+
|
|
211
243
|
.instance-name {
|
|
212
244
|
font-size: 20px;
|
|
213
245
|
font-weight: 600;
|
|
@@ -254,9 +286,14 @@
|
|
|
254
286
|
}
|
|
255
287
|
|
|
256
288
|
.instance-path {
|
|
257
|
-
font-size:
|
|
289
|
+
font-size: 12px;
|
|
258
290
|
color: var(--text-muted);
|
|
259
291
|
font-family: monospace;
|
|
292
|
+
overflow: hidden;
|
|
293
|
+
text-overflow: ellipsis;
|
|
294
|
+
white-space: nowrap;
|
|
295
|
+
flex: 1;
|
|
296
|
+
min-width: 0;
|
|
260
297
|
}
|
|
261
298
|
|
|
262
299
|
.instance-body {
|
|
@@ -282,11 +319,14 @@
|
|
|
282
319
|
display: flex;
|
|
283
320
|
align-items: center;
|
|
284
321
|
gap: 12px;
|
|
322
|
+
min-width: 0;
|
|
323
|
+
flex: 1;
|
|
285
324
|
}
|
|
286
325
|
|
|
287
326
|
.port-type {
|
|
288
327
|
font-size: 15px;
|
|
289
328
|
color: var(--text-secondary);
|
|
329
|
+
flex-shrink: 0;
|
|
290
330
|
min-width: 100px;
|
|
291
331
|
}
|
|
292
332
|
|
|
@@ -294,6 +334,9 @@
|
|
|
294
334
|
font-size: 15px;
|
|
295
335
|
font-family: monospace;
|
|
296
336
|
color: var(--text-muted);
|
|
337
|
+
overflow: hidden;
|
|
338
|
+
text-overflow: ellipsis;
|
|
339
|
+
white-space: nowrap;
|
|
297
340
|
}
|
|
298
341
|
|
|
299
342
|
.port-status {
|
|
@@ -313,6 +356,7 @@
|
|
|
313
356
|
.port-actions {
|
|
314
357
|
display: flex;
|
|
315
358
|
gap: 8px;
|
|
359
|
+
flex-shrink: 0;
|
|
316
360
|
}
|
|
317
361
|
|
|
318
362
|
.port-actions a {
|
|
@@ -643,9 +687,13 @@
|
|
|
643
687
|
</div>
|
|
644
688
|
`;
|
|
645
689
|
} else {
|
|
690
|
+
const countClass = runningInstances.length === 1 ? 'instances-1'
|
|
691
|
+
: runningInstances.length === 2 ? 'instances-2'
|
|
692
|
+
: runningInstances.length === 3 ? 'instances-3'
|
|
693
|
+
: 'instances-many';
|
|
646
694
|
content.innerHTML = `
|
|
647
695
|
<h2 class="section-header">Running Instances</h2>
|
|
648
|
-
<div class="instances">
|
|
696
|
+
<div class="instances ${countClass}">
|
|
649
697
|
${runningInstances.map(renderInstance).join('')}
|
|
650
698
|
</div>
|
|
651
699
|
`;
|
|
@@ -677,7 +725,7 @@
|
|
|
677
725
|
<div class="port-info">
|
|
678
726
|
<span class="port-status ${port.active ? 'active' : 'inactive'}"></span>
|
|
679
727
|
<span class="port-type">${escapeHtml(port.type)}</span>
|
|
680
|
-
<span class="port-url"
|
|
728
|
+
<span class="port-url">Port ${port.port}</span>
|
|
681
729
|
</div>
|
|
682
730
|
<div class="port-actions">
|
|
683
731
|
<a href="${escapeHtml(port.url)}" target="_blank" class="${port.active ? '' : 'disabled'}">
|
|
@@ -714,6 +762,7 @@
|
|
|
714
762
|
<span class="instance-path" title="${escapeHtml(instance.projectPath)}">
|
|
715
763
|
${escapeHtml(instance.projectPath)}
|
|
716
764
|
</span>
|
|
765
|
+
<button class="copy-btn" onclick="copyPath('${escapeHtml(instance.projectPath)}')" title="Copy path">📋</button>
|
|
717
766
|
</div>
|
|
718
767
|
<div class="instance-body">
|
|
719
768
|
<div class="ports-list">
|
|
@@ -1001,6 +1050,16 @@
|
|
|
1001
1050
|
return date.toLocaleDateString() + ' ' + date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
|
1002
1051
|
}
|
|
1003
1052
|
|
|
1053
|
+
// Copy path to clipboard
|
|
1054
|
+
async function copyPath(path) {
|
|
1055
|
+
try {
|
|
1056
|
+
await navigator.clipboard.writeText(path);
|
|
1057
|
+
showToast('Path copied', 'success');
|
|
1058
|
+
} catch (err) {
|
|
1059
|
+
showToast('Failed to copy', 'error');
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1004
1063
|
// HTML escape
|
|
1005
1064
|
function escapeHtml(str) {
|
|
1006
1065
|
if (!str) return '';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent-farm/index.ts"],"names":[],"mappings":";AAEA;;;GAGG"}
|