harness-bujang 0.5.4 → 0.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +34 -6
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1344,7 +1344,7 @@ function render() {
1344
1344
  html += '</div>';
1345
1345
  html += '</div>';
1346
1346
 
1347
- html += '<div class="flex-1 overflow-y-auto">';
1347
+ html += '<div id="room-list" class="flex-1 overflow-y-auto">';
1348
1348
  // When 'unread' filter is active, only show rooms with unread > 0.
1349
1349
  const visibleRooms = state.filter === 'unread'
1350
1350
  ? ROOMS.filter((r) => unreadByRoom[r.id] > 0)
@@ -1431,8 +1431,27 @@ function render() {
1431
1431
  }
1432
1432
  html += '</div>';
1433
1433
 
1434
+ // Save scroll positions BEFORE replacing innerHTML \u2014 otherwise every 2s poll
1435
+ // resets the sidebar room-list scroll to top, and the conversation re-snaps
1436
+ // to the bottom even if the user was reading older messages.
1437
+ const oldRoomList = document.getElementById('room-list');
1438
+ const oldConv = document.getElementById('conversation');
1439
+ const savedRoomScroll = oldRoomList ? oldRoomList.scrollTop : 0;
1440
+ let savedConvScroll = null;
1441
+ let convWasAtBottom = true;
1442
+ if (oldConv) {
1443
+ savedConvScroll = oldConv.scrollTop;
1444
+ // "At bottom" within ~80px \u2014 if user was at bottom we keep them at bottom
1445
+ // (so new messages stay visible). If they scrolled up, preserve position.
1446
+ convWasAtBottom = (oldConv.scrollHeight - oldConv.scrollTop - oldConv.clientHeight) < 80;
1447
+ }
1448
+
1434
1449
  root.innerHTML = html;
1435
1450
 
1451
+ // Restore scroll positions.
1452
+ const newRoomList = document.getElementById('room-list');
1453
+ if (newRoomList) newRoomList.scrollTop = savedRoomScroll;
1454
+
1436
1455
  // Re-bind filter buttons (\uC804\uCCB4 / \uC548\uC77D\uC74C).
1437
1456
  document.querySelectorAll('[data-filter]').forEach((el) => {
1438
1457
  el.addEventListener('click', () => {
@@ -1455,11 +1474,20 @@ function render() {
1455
1474
  });
1456
1475
  });
1457
1476
 
1458
- // Auto-scroll the selected room to the bottom on first render of that room.
1477
+ // Conversation scroll handling:
1478
+ // - First render of a room \u2192 scroll to bottom (latest msg visible)
1479
+ // - User was at bottom \u2192 keep at new bottom (so new msgs auto-show)
1480
+ // - User scrolled up to read history \u2192 preserve their position
1459
1481
  const conv = document.getElementById('conversation');
1460
- if (conv && conv.dataset.scrolled !== state.selectedRoom) {
1461
- conv.scrollTop = conv.scrollHeight;
1462
- conv.dataset.scrolled = state.selectedRoom;
1482
+ if (conv) {
1483
+ if (conv.dataset.scrolled !== state.selectedRoom) {
1484
+ conv.scrollTop = conv.scrollHeight;
1485
+ conv.dataset.scrolled = state.selectedRoom;
1486
+ } else if (convWasAtBottom) {
1487
+ conv.scrollTop = conv.scrollHeight;
1488
+ } else if (savedConvScroll !== null) {
1489
+ conv.scrollTop = savedConvScroll;
1490
+ }
1463
1491
  }
1464
1492
  }
1465
1493
 
@@ -2171,7 +2199,7 @@ async function main() {
2171
2199
  break;
2172
2200
  case "--version":
2173
2201
  case "-v":
2174
- console.log("0.5.4");
2202
+ console.log("0.5.5");
2175
2203
  break;
2176
2204
  case "--help":
2177
2205
  case "-h":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "harness-bujang",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
4
4
  "description": "Install the Harness-Bujang multi-agent harness into any project — Director, 7 specialist teams, real-time chat-room UI. Korean and English personas. Works with Claude Code, Cursor, Cline, Aider, or any tool that reads .claude/agents/.",
5
5
  "keywords": [
6
6
  "claude-code",