clay-server 2.14.0-beta.8 → 2.14.0-beta.9

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.
@@ -1431,32 +1431,89 @@ body.mate-dm-active .mate-tool-group .tool-name {
1431
1431
  color: var(--text-muted);
1432
1432
  }
1433
1433
 
1434
- /* --- Mate Permission: conversational style --- */
1434
+ /* --- Mate Permission: conversational chat bubble --- */
1435
1435
  body.mate-dm-active .mate-permission {
1436
- border-radius: 12px;
1437
- border: 1px solid var(--border);
1436
+ border: none;
1437
+ border-radius: 0;
1438
+ background: none;
1439
+ box-shadow: none;
1440
+ padding: 4px 16px;
1441
+ }
1442
+ body.mate-dm-active .mate-permission:hover {
1438
1443
  background: var(--bg-alt);
1439
- overflow: hidden;
1440
1444
  }
1441
- body.mate-dm-active .mate-permission .permission-header {
1442
- display: flex;
1443
- align-items: center;
1444
- gap: 10px;
1445
- padding: 12px 16px 8px;
1445
+ .mate-permission-ask {
1446
+ font-size: 15px;
1447
+ line-height: 1.46;
1448
+ color: var(--text);
1449
+ padding-left: 36px; /* align with name (avatar 28px + gap 8px) */
1450
+ margin-bottom: 8px;
1446
1451
  }
1447
- .mate-permission-avatar {
1448
- width: 24px;
1449
- height: 24px;
1450
- border-radius: 6px;
1451
- flex-shrink: 0;
1452
+ .mate-permission-details {
1453
+ padding-left: 36px;
1454
+ margin-bottom: 8px;
1455
+ font-size: 12px;
1456
+ color: var(--text-muted);
1452
1457
  }
1453
- body.mate-dm-active .mate-permission .permission-title {
1454
- font-size: 14px;
1455
- font-weight: 600;
1458
+ .mate-permission-details summary {
1459
+ cursor: pointer;
1460
+ user-select: none;
1456
1461
  }
1457
- body.mate-dm-active .mate-permission .permission-actions {
1458
- padding: 8px 16px 12px;
1462
+ .mate-permission-details pre {
1463
+ font-size: 11px;
1464
+ margin: 4px 0 0;
1465
+ padding: 8px;
1466
+ background: rgba(var(--overlay-rgb), 0.04);
1467
+ border-radius: 6px;
1468
+ overflow-x: auto;
1469
+ max-height: 200px;
1470
+ }
1471
+ .mate-permission-actions {
1472
+ display: flex;
1459
1473
  gap: 6px;
1474
+ padding-left: 36px;
1475
+ padding-bottom: 4px;
1476
+ }
1477
+ .mate-permission-reply {
1478
+ padding: 5px 14px;
1479
+ border-radius: 16px;
1480
+ font-size: 13px;
1481
+ font-weight: 500;
1482
+ font-family: inherit;
1483
+ cursor: pointer;
1484
+ border: 1px solid var(--border);
1485
+ background: var(--bg-alt);
1486
+ color: var(--text);
1487
+ transition: background 0.15s, border-color 0.15s;
1488
+ }
1489
+ .mate-permission-reply:hover {
1490
+ border-color: var(--text-dimmer);
1491
+ background: rgba(var(--overlay-rgb), 0.06);
1492
+ }
1493
+ .mate-permission-allow {
1494
+ background: var(--accent, #6c5ce7);
1495
+ color: #fff;
1496
+ border-color: var(--accent, #6c5ce7);
1497
+ }
1498
+ .mate-permission-allow:hover {
1499
+ opacity: 0.9;
1500
+ background: var(--accent, #6c5ce7);
1501
+ border-color: var(--accent, #6c5ce7);
1502
+ }
1503
+ .mate-permission-deny {
1504
+ color: var(--text-muted);
1505
+ }
1506
+ /* Resolved state */
1507
+ body.mate-dm-active .mate-permission.resolved .mate-permission-actions {
1508
+ pointer-events: none;
1509
+ }
1510
+ body.mate-dm-active .mate-permission.resolved .mate-permission-reply {
1511
+ display: none;
1512
+ }
1513
+ body.mate-dm-active .mate-permission.resolved .permission-decision-label {
1514
+ font-size: 12px;
1515
+ color: var(--text-dimmer);
1516
+ padding-left: 36px;
1460
1517
  }
1461
1518
 
1462
1519
  /* --- Mate Activity: avatar + text (hidden, dots row is enough) --- */
@@ -1475,20 +1532,6 @@ body.mate-dm-active .ask-user-mate-header {
1475
1532
  margin-bottom: 8px;
1476
1533
  }
1477
1534
 
1478
- /* --- Mate Permission: avatar + name header --- */
1479
- body.mate-dm-active .mate-permission .permission-header {
1480
- display: flex;
1481
- align-items: center;
1482
- gap: 10px;
1483
- padding: 12px 16px 8px;
1484
- }
1485
- .mate-permission-avatar {
1486
- width: 24px;
1487
- height: 24px;
1488
- border-radius: 6px;
1489
- flex-shrink: 0;
1490
- }
1491
-
1492
1535
  /* --- Interstitial elements: indent to align with message content (16px pad + 36px avatar + 8px gap = 60px) --- */
1493
1536
  body.mate-dm-active .thinking-item,
1494
1537
  body.mate-dm-active .tool-item,
@@ -398,25 +398,22 @@ export function renderPermissionRequest(requestId, toolName, toolInput, decision
398
398
  return;
399
399
  }
400
400
 
401
+ // Mate DM: render as conversational chat bubble instead of formal dialog
402
+ if (ctx.isMateDm && ctx.isMateDm()) {
403
+ renderMatePermission(requestId, toolName, toolInput);
404
+ return;
405
+ }
406
+
401
407
  var container = document.createElement("div");
402
408
  container.className = "permission-container";
403
- if (ctx.isMateDm()) container.classList.add("mate-permission");
404
409
  container.dataset.requestId = requestId;
405
410
 
406
411
  // Header
407
412
  var header = document.createElement("div");
408
413
  header.className = "permission-header";
409
- if (ctx.isMateDm()) {
410
- var mateName = ctx.getMateName();
411
- var mateAvatar = ctx.getMateAvatarUrl();
412
- header.innerHTML =
413
- '<img class="mate-permission-avatar" src="' + escapeHtml(mateAvatar) + '" alt="">' +
414
- '<span class="permission-title">' + escapeHtml(mateName) + ' wants to do something</span>';
415
- } else {
416
- header.innerHTML =
417
- '<span class="permission-icon">' + iconHtml("shield") + '</span>' +
418
- '<span class="permission-title">Permission Required</span>';
419
- }
414
+ header.innerHTML =
415
+ '<span class="permission-icon">' + iconHtml("shield") + '</span>' +
416
+ '<span class="permission-title">Permission Required</span>';
420
417
 
421
418
  // Body
422
419
  var body = document.createElement("div");
@@ -642,6 +639,108 @@ function sendPlanResponse(container, requestId, decision, feedback) {
642
639
  delete pendingPermissions[requestId];
643
640
  }
644
641
 
642
+ function matePermissionVerb(toolName) {
643
+ switch (toolName) {
644
+ case "Write": return "write to";
645
+ case "Edit": return "edit";
646
+ case "Read": return "read";
647
+ case "Bash": return "run a command on";
648
+ case "Grep": return "search";
649
+ case "Glob": return "search for files in";
650
+ case "WebFetch": return "fetch";
651
+ case "WebSearch": return "search the web for";
652
+ default: return "use " + toolName + " on";
653
+ }
654
+ }
655
+
656
+ function matePermissionTarget(toolName, toolInput) {
657
+ if (!toolInput || typeof toolInput !== "object") return "";
658
+ switch (toolName) {
659
+ case "Write": case "Edit": case "Read": return shortPath(toolInput.file_path);
660
+ case "Bash": return toolInput.description || (toolInput.command || "").substring(0, 60);
661
+ case "Grep": return toolInput.pattern || "";
662
+ case "Glob": return toolInput.pattern || "";
663
+ case "WebFetch": return toolInput.url || "";
664
+ case "WebSearch": return toolInput.query || "";
665
+ default: return "";
666
+ }
667
+ }
668
+
669
+ function renderMatePermission(requestId, toolName, toolInput) {
670
+ var mateName = ctx.getMateName();
671
+ var mateAvatar = ctx.getMateAvatarUrl();
672
+ var verb = matePermissionVerb(toolName);
673
+ var target = matePermissionTarget(toolName, toolInput);
674
+
675
+ var container = document.createElement("div");
676
+ container.className = "permission-container mate-permission";
677
+ container.dataset.requestId = requestId;
678
+
679
+ // Chat bubble: avatar + name + time
680
+ var headerRow = document.createElement("div");
681
+ headerRow.className = "dm-bubble-header";
682
+ headerRow.style.cssText = "display:flex;align-items:center;gap:8px;margin-bottom:6px";
683
+ headerRow.innerHTML =
684
+ '<img class="dm-bubble-avatar" src="' + escapeHtml(mateAvatar) + '" alt="" style="display:block;width:28px;height:28px;border-radius:6px">' +
685
+ '<span class="dm-bubble-name">' + escapeHtml(mateName) + '</span>' +
686
+ '<span class="dm-bubble-time">' + String(new Date().getHours()).padStart(2, "0") + ":" + String(new Date().getMinutes()).padStart(2, "0") + '</span>';
687
+ container.appendChild(headerRow);
688
+
689
+ // Conversational ask text
690
+ var askText = document.createElement("div");
691
+ askText.className = "mate-permission-ask";
692
+ var askMsg = "Can I " + verb + (target ? " " : "") + (target ? target : "") + "?";
693
+ askText.textContent = askMsg;
694
+ container.appendChild(askText);
695
+
696
+ // Collapsible details (subtle)
697
+ var details = document.createElement("details");
698
+ details.className = "mate-permission-details";
699
+ var detailsSummary = document.createElement("summary");
700
+ detailsSummary.textContent = "Details";
701
+ var detailsPre = document.createElement("pre");
702
+ detailsPre.textContent = JSON.stringify(toolInput, null, 2);
703
+ details.appendChild(detailsSummary);
704
+ details.appendChild(detailsPre);
705
+ container.appendChild(details);
706
+
707
+ // Quick reply buttons (chat-style)
708
+ var actions = document.createElement("div");
709
+ actions.className = "permission-actions mate-permission-actions";
710
+
711
+ var allowBtn = document.createElement("button");
712
+ allowBtn.className = "mate-permission-reply mate-permission-allow";
713
+ allowBtn.textContent = "Sure";
714
+ allowBtn.addEventListener("click", function () {
715
+ sendPermissionResponse(container, requestId, "allow");
716
+ });
717
+
718
+ var alwaysBtn = document.createElement("button");
719
+ alwaysBtn.className = "mate-permission-reply mate-permission-always";
720
+ alwaysBtn.textContent = "Always allow this";
721
+ alwaysBtn.addEventListener("click", function () {
722
+ sendPermissionResponse(container, requestId, "allow_always");
723
+ });
724
+
725
+ var denyBtn = document.createElement("button");
726
+ denyBtn.className = "mate-permission-reply mate-permission-deny";
727
+ denyBtn.textContent = "No";
728
+ denyBtn.addEventListener("click", function () {
729
+ sendPermissionResponse(container, requestId, "deny");
730
+ });
731
+
732
+ actions.appendChild(allowBtn);
733
+ actions.appendChild(alwaysBtn);
734
+ actions.appendChild(denyBtn);
735
+ container.appendChild(actions);
736
+
737
+ ctx.addToMessages(container);
738
+ pendingPermissions[requestId] = container;
739
+ refreshIcons();
740
+ ctx.setActivity(null);
741
+ ctx.scrollToBottom();
742
+ }
743
+
645
744
  function sendPermissionResponse(container, requestId, decision) {
646
745
  if (container.classList.contains("resolved")) return;
647
746
  container.classList.add("resolved");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clay-server",
3
- "version": "2.14.0-beta.8",
3
+ "version": "2.14.0-beta.9",
4
4
  "description": "Web UI for Claude Code. Any device. Push notifications.",
5
5
  "bin": {
6
6
  "clay-server": "./bin/cli.js",