clay-server 2.14.0-beta.7 → 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) --- */
@@ -1464,6 +1521,17 @@ body.mate-dm-active .activity-inline {
1464
1521
  display: none;
1465
1522
  }
1466
1523
 
1524
+ /* --- Mate AskUserQuestion: avatar + name header --- */
1525
+ .ask-user-mate-header {
1526
+ display: none;
1527
+ }
1528
+ body.mate-dm-active .ask-user-mate-header {
1529
+ display: flex;
1530
+ align-items: center;
1531
+ gap: 8px;
1532
+ margin-bottom: 8px;
1533
+ }
1534
+
1467
1535
  /* --- Interstitial elements: indent to align with message content (16px pad + 36px avatar + 8px gap = 60px) --- */
1468
1536
  body.mate-dm-active .thinking-item,
1469
1537
  body.mate-dm-active .tool-item,
@@ -189,6 +189,19 @@ export function renderAskUserQuestion(toolId, input) {
189
189
  container.className = "ask-user-container";
190
190
  container.dataset.toolId = toolId;
191
191
 
192
+ // Mate DM: inject avatar + name header into ask-user container
193
+ if (ctx.isMateDm && ctx.isMateDm()) {
194
+ var mateName = ctx.getMateName();
195
+ var mateAvatar = ctx.getMateAvatarUrl();
196
+ var mateHeader = document.createElement("div");
197
+ mateHeader.className = "dm-bubble-header ask-user-mate-header";
198
+ mateHeader.innerHTML =
199
+ '<img class="dm-bubble-avatar" src="' + escapeHtml(mateAvatar) + '" alt="" style="display:block;width:28px;height:28px;border-radius:6px">' +
200
+ '<span class="dm-bubble-name">' + escapeHtml(mateName) + '</span>' +
201
+ '<span class="dm-bubble-time">' + String(new Date().getHours()).padStart(2, "0") + ":" + String(new Date().getMinutes()).padStart(2, "0") + '</span>';
202
+ container.appendChild(mateHeader);
203
+ }
204
+
192
205
  var answers = {};
193
206
  var multiSelections = {};
194
207
 
@@ -385,25 +398,22 @@ export function renderPermissionRequest(requestId, toolName, toolInput, decision
385
398
  return;
386
399
  }
387
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
+
388
407
  var container = document.createElement("div");
389
408
  container.className = "permission-container";
390
- if (ctx.isMateDm()) container.classList.add("mate-permission");
391
409
  container.dataset.requestId = requestId;
392
410
 
393
411
  // Header
394
412
  var header = document.createElement("div");
395
413
  header.className = "permission-header";
396
- if (ctx.isMateDm()) {
397
- var mateName = ctx.getMateName();
398
- var mateAvatar = ctx.getMateAvatarUrl();
399
- header.innerHTML =
400
- '<img class="mate-permission-avatar" src="' + escapeHtml(mateAvatar) + '" alt="">' +
401
- '<span class="permission-title">' + escapeHtml(mateName) + ' wants to do something</span>';
402
- } else {
403
- header.innerHTML =
404
- '<span class="permission-icon">' + iconHtml("shield") + '</span>' +
405
- '<span class="permission-title">Permission Required</span>';
406
- }
414
+ header.innerHTML =
415
+ '<span class="permission-icon">' + iconHtml("shield") + '</span>' +
416
+ '<span class="permission-title">Permission Required</span>';
407
417
 
408
418
  // Body
409
419
  var body = document.createElement("div");
@@ -629,6 +639,108 @@ function sendPlanResponse(container, requestId, decision, feedback) {
629
639
  delete pendingPermissions[requestId];
630
640
  }
631
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
+
632
744
  function sendPermissionResponse(container, requestId, decision) {
633
745
  if (container.classList.contains("resolved")) return;
634
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.7",
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",