clay-server 3.4.0-beta.2 → 3.4.0-beta.20

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 (80) hide show
  1. package/lib/daemon-projects.js +3 -3
  2. package/lib/daemon.js +59 -59
  3. package/lib/project-connection.js +35 -7
  4. package/lib/project-debate.js +4 -0
  5. package/lib/project-mate-interaction.js +21 -1
  6. package/lib/project-memory.js +3 -0
  7. package/lib/project-models.js +220 -0
  8. package/lib/project-session-handoff.js +162 -0
  9. package/lib/project-sessions.js +13 -45
  10. package/lib/project-worker-proposal.js +49 -14
  11. package/lib/project.js +38 -80
  12. package/lib/public/antigravity-avatar.png +0 -0
  13. package/lib/public/app.js +29 -0
  14. package/lib/public/copilot-avatar.svg +5 -0
  15. package/lib/public/css/command-palette.css +22 -2
  16. package/lib/public/css/icon-strip.css +29 -13
  17. package/lib/public/css/input.css +56 -0
  18. package/lib/public/css/mates.css +6 -0
  19. package/lib/public/css/menus.css +38 -25
  20. package/lib/public/css/messages.css +9 -0
  21. package/lib/public/css/pane.css +16 -3
  22. package/lib/public/css/pwa-mobile.css +17 -0
  23. package/lib/public/css/session-actions.css +98 -0
  24. package/lib/public/css/title-bar.css +19 -0
  25. package/lib/public/grok-avatar.svg +4 -0
  26. package/lib/public/index.html +29 -7
  27. package/lib/public/junie-avatar.svg +11 -0
  28. package/lib/public/kimi-avatar.svg +4 -0
  29. package/lib/public/modules/agent-config-selects.js +69 -0
  30. package/lib/public/modules/app-header.js +4 -22
  31. package/lib/public/modules/app-messages.js +54 -11
  32. package/lib/public/modules/app-panels.js +36 -83
  33. package/lib/public/modules/app-projects.js +3 -1
  34. package/lib/public/modules/app-rendering.js +19 -4
  35. package/lib/public/modules/background-tasks-ui.js +55 -0
  36. package/lib/public/modules/mate-sidebar.js +11 -3
  37. package/lib/public/modules/model-picker.js +263 -0
  38. package/lib/public/modules/notifications.js +7 -1
  39. package/lib/public/modules/pane-bridge.js +11 -0
  40. package/lib/public/modules/pane-links.js +23 -0
  41. package/lib/public/modules/project-switcher.js +7 -6
  42. package/lib/public/modules/session-actions.js +294 -0
  43. package/lib/public/modules/sidebar-mates.js +1 -1
  44. package/lib/public/modules/sidebar-mobile.js +2 -1
  45. package/lib/public/modules/sidebar-projects.js +34 -43
  46. package/lib/public/modules/sidebar-sessions.js +20 -6
  47. package/lib/public/modules/split-pair-ui.js +16 -77
  48. package/lib/public/modules/split-view.js +3 -0
  49. package/lib/public/modules/tools.js +6 -1
  50. package/lib/public/modules/vendor-priority.js +14 -0
  51. package/lib/public/modules/vendor-selection.js +20 -0
  52. package/lib/public/modules/worker-proposal.js +5 -1
  53. package/lib/public/modules/worktree-location.js +17 -0
  54. package/lib/public/qwen-avatar.svg +4 -0
  55. package/lib/public/style.css +4 -2
  56. package/lib/sdk-bridge.js +99 -56
  57. package/lib/sdk-message-processor.js +26 -4
  58. package/lib/session-handoff-context.js +110 -0
  59. package/lib/session-notes-mcp-server.js +8 -1
  60. package/lib/sessions.js +4 -0
  61. package/lib/worktree.js +9 -4
  62. package/lib/ws-schema.js +9 -1
  63. package/lib/yoke/acp-agent-profiles.js +64 -14
  64. package/lib/yoke/adapters/antigravity.js +417 -0
  65. package/lib/yoke/adapters/claude.js +34 -0
  66. package/lib/yoke/adapters/codex.js +101 -5
  67. package/lib/yoke/adapters/copilot.js +7 -0
  68. package/lib/yoke/adapters/grok.js +7 -0
  69. package/lib/yoke/adapters/junie.js +7 -0
  70. package/lib/yoke/adapters/kimi.js +7 -0
  71. package/lib/yoke/adapters/kiro.js +2 -2
  72. package/lib/yoke/adapters/qwen.js +7 -0
  73. package/lib/yoke/codex-app-server.js +25 -8
  74. package/lib/yoke/index.js +67 -28
  75. package/lib/yoke/instructions.js +3 -0
  76. package/lib/yoke/interface.js +12 -0
  77. package/lib/yoke/vendor-registry.js +61 -6
  78. package/package.json +1 -1
  79. package/lib/public/gemini-avatar.svg +0 -11
  80. package/lib/yoke/adapters/gemini.js +0 -7
package/lib/public/app.js CHANGED
@@ -60,10 +60,12 @@ import { initRateLimit, handleRateLimitEvent as _rlHandleRateLimitEvent, updateR
60
60
  import { initCursors, handleRemoteCursorMove as _curHandleRemoteCursorMove, handleRemoteCursorLeave as _curHandleRemoteCursorLeave, handleRemoteSelection as _curHandleRemoteSelection, clearRemoteCursors as _curClearRemoteCursors, initCursorToggle } from './modules/app-cursors.js';
61
61
  import { initFavicon, updateFavicon as _favUpdateFavicon, setSendBtnMode as _favSetSendBtnMode, blinkIO as _favBlinkIO, blinkSessionDot as _favBlinkSessionDot, updateCrossProjectBlink as _favUpdateCrossProjectBlink, startUrgentBlink as _favStartUrgentBlink, stopUrgentBlink as _favStopUrgentBlink, setActivity as _favSetActivity, drawFaviconAnimFrame as _favDrawFaviconAnimFrame } from './modules/app-favicon.js';
62
62
  import { initHeader, closeSessionInfoPopover as _hdrCloseSessionInfoPopover, updateHistorySentinel as _hdrUpdateHistorySentinel, requestMoreHistory as _hdrRequestMoreHistory, prependOlderHistory as _hdrPrependOlderHistory } from './modules/app-header.js';
63
+ import { initSessionActions } from './modules/session-actions.js';
63
64
  import { initMisc, flushPendingExtMessages, showImageModal as _miscShowImageModal, closeImageModal as _miscCloseImageModal, showPasteModal as _miscShowPasteModal, closePasteModal as _miscClosePasteModal, showConfirm as _miscShowConfirm, hideConfirm as _miscHideConfirm, showForceChangePinOverlay as _miscShowForceChangePinOverlay, sendExtensionCommand as _miscSendExtensionCommand, handleExtensionResult as _miscHandleExtensionResult } from './modules/app-misc.js';
64
65
  import { initSkillInstall, requireSkills as _siRequireSkills, requireClayMateInterview as _siRequireClayMateInterview, handleSkillInstallWs as _siHandleSkillInstallWs } from './modules/app-skills-install.js';
65
66
  import { initDebateUi, showDebateConcludeConfirm as _debShowDebateConcludeConfirm, exitDebateConcludeMode as _debExitDebateConcludeMode, handleDebateConcludeSend as _debHandleDebateConcludeSend, showDebateEndedMode as _debShowDebateEndedMode, exitDebateEndedMode as _debExitDebateEndedMode, showDebateUserFloor as _debShowDebateUserFloor, exitDebateFloorMode as _debExitDebateFloorMode, handleDebateFloorSend as _debHandleDebateFloorSend, renderDebateUserFloorDone as _debRenderDebateUserFloorDone, showDebateSticky as _debShowDebateSticky, showDebateBottomBar as _debShowDebateBottomBar, removeDebateBottomBar as _debRemoveDebateBottomBar, sendDebateStickyComment as _debSendDebateStickyComment, updateDebateRound as _debUpdateDebateRound } from './modules/app-debate-ui.js';
66
67
  import { initLoopUi, updateLoopInputVisibility as _loopUpdateLoopInputVisibility, updateLoopButton as _loopUpdateLoopButton, showLoopBanner as _loopShowLoopBanner, updateLoopBanner as _loopUpdateLoopBanner, updateRalphBars as _loopUpdateRalphBars, showRalphCraftingBar as _loopShowRalphCraftingBar, showRalphApprovalBar as _loopShowRalphApprovalBar, updateRalphApprovalStatus as _loopUpdateRalphApprovalStatus, openRalphPreviewModal as _loopOpenRalphPreviewModal, showExecModal as _loopShowExecModal, closeExecModal as _loopCloseExecModal, updateExecModalStatus as _loopUpdateExecModalStatus } from './modules/app-loop-ui.js';
68
+ import { initBackgroundTasksUi } from './modules/background-tasks-ui.js';
67
69
  import { initLoopWizard, openRalphWizard as _loopOpenRalphWizard, closeRalphWizard as _loopCloseRalphWizard, getWizardSource as _loopGetWizardSource } from './modules/app-loop-wizard.js';
68
70
  import { initAppNotifications, handleNotificationsState as _notifHandleState, handleNotificationCreated as _notifHandleCreated, handleNotificationDismissed as _notifHandleDismissed, handleNotificationDismissedAll as _notifHandleDismissedAll } from './modules/app-notifications.js';
69
71
  import { initWhatsNew, handleWhatsNewState as _wnHandleState, handleWhatsNewSeenResult as _wnHandleSeenResult } from './modules/whats-new.js';
@@ -295,6 +297,8 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
295
297
  slashCommands: [],
296
298
  processing: false,
297
299
  activeSessionId: null,
300
+ activeBackgroundTasks: [],
301
+ sessionVendorBound: false,
298
302
  cliSessionId: null,
299
303
  isHeadlessMode: false,
300
304
  savedMainSlug: null,
@@ -338,6 +342,12 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
338
342
  markdownSlideLevelExplicit: false,
339
343
  currentModel: "",
340
344
  currentModels: [],
345
+ modelListVendor: "",
346
+ modelListStatus: "idle",
347
+ modelListError: "",
348
+ modelRequestId: "",
349
+ modelSelectionPending: null,
350
+ modelSelectionError: "",
341
351
  // Project's last-used vendor; seeds the sidebar's "New session" button.
342
352
  lastVendor: "",
343
353
  // Static adapter metadata sent before any vendor is initialized.
@@ -556,6 +566,22 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
556
566
  var newMsgBtnDefault = "\u2193 Latest";
557
567
  var newMsgBtnActivity = "\u2193 New activity";
558
568
 
569
+ // The composer grows for mobile tabs, safe areas, multiline input, and the
570
+ // keyboard. Keep the jump button immediately above its real height instead
571
+ // of relying on one fixed bottom offset.
572
+ function positionNewMsgButton() {
573
+ var inputArea = $("input-area");
574
+ if (!inputArea) return;
575
+ newMsgBtn.style.bottom = (inputArea.offsetHeight + 12) + "px";
576
+ }
577
+ var inputAreaForNewMsgBtn = $("input-area");
578
+ if (inputAreaForNewMsgBtn && window.ResizeObserver) {
579
+ new ResizeObserver(positionNewMsgButton).observe(inputAreaForNewMsgBtn);
580
+ } else {
581
+ window.addEventListener("resize", positionNewMsgButton);
582
+ }
583
+ positionNewMsgButton();
584
+
559
585
  messagesEl.addEventListener("scroll", function () {
560
586
  // While sticky-bottom is armed (e.g. just after history_done or a "New
561
587
  // activity" click), suppress "user scrolled up" detection. Growth-induced
@@ -616,6 +642,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
616
642
 
617
643
  // --- Header module (rename, info popover, history) ---
618
644
  initHeader();
645
+ initSessionActions();
619
646
 
620
647
  // --- Skill Install module ---
621
648
  initSkillInstall();
@@ -624,6 +651,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
624
651
  initDebateUi();
625
652
 
626
653
  initLoopUi();
654
+ initBackgroundTasksUi();
627
655
  initLoopWizard();
628
656
 
629
657
  // --- Notifications module ---
@@ -932,6 +960,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
932
960
  messagesEl: messagesEl,
933
961
  sessionListEl: sessionListEl,
934
962
  scrollToBottom: scrollToBottom,
963
+ forceScrollToBottom: forceScrollToBottom,
935
964
  basePath: basePath,
936
965
  toggleUsagePanel: toggleUsagePanel,
937
966
  toggleStatusPanel: toggleStatusPanel,
@@ -0,0 +1,5 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="GitHub Copilot CLI">
2
+ <rect width="64" height="64" rx="14" fill="#24292f"/>
3
+ <path d="M15 25c0-8 7-14 17-14s17 6 17 14v15c0 8-7 13-17 13s-17-5-17-13zm8 1v13c0 4 4 7 9 7s9-3 9-7V26c0-4-4-7-9-7s-9 3-9 7z" fill="#fff"/>
4
+ <circle cx="27" cy="30" r="3" fill="#24292f"/><circle cx="37" cy="30" r="3" fill="#24292f"/>
5
+ </svg>
@@ -434,6 +434,7 @@
434
434
  on hover/active, and a 4-direction drop-shadow + white glow on the
435
435
  emoji img for readability on either background. */
436
436
  .project-switcher-item .cmd-palette-item-icon {
437
+ position: relative;
437
438
  width: 44px;
438
439
  height: 44px;
439
440
  font-size: 28px;
@@ -447,6 +448,26 @@
447
448
  flex-shrink: 0;
448
449
  transition: background 0.15s, color 0.15s;
449
450
  }
451
+ .project-switcher-external-badge {
452
+ position: absolute;
453
+ right: -5px;
454
+ bottom: -5px;
455
+ width: 17px;
456
+ height: 17px;
457
+ display: flex;
458
+ align-items: center;
459
+ justify-content: center;
460
+ border: 2px solid var(--bg);
461
+ border-radius: 50%;
462
+ background: var(--warning);
463
+ color: var(--bg);
464
+ pointer-events: none;
465
+ }
466
+ .project-switcher-item .cmd-palette-item-icon .project-switcher-external-badge .lucide {
467
+ width: 9px;
468
+ height: 9px;
469
+ stroke-width: 2.8;
470
+ }
450
471
  .project-switcher-item .cmd-palette-item-icon .lucide {
451
472
  width: 22px;
452
473
  height: 22px;
@@ -515,8 +536,7 @@
515
536
  letter-spacing: 0.5px;
516
537
  }
517
538
 
518
- /* Disabled tile (e.g. worktree with worktreeAccessible: false). Not a
519
- valid switch target, so skip highlight, skip click, visually dim. */
539
+ /* Disabled tiles are skipped by keyboard and pointer selection. */
520
540
  .project-switcher-item.disabled {
521
541
  opacity: 0.35;
522
542
  cursor: not-allowed;
@@ -1257,20 +1257,27 @@
1257
1257
  z-index: 1;
1258
1258
  }
1259
1259
 
1260
- /* Disabled/inaccessible worktree */
1261
- .icon-strip-wt-item.wt-disabled {
1262
- opacity: 0.35;
1263
- cursor: not-allowed;
1264
- }
1265
-
1266
- .icon-strip-wt-item.wt-disabled::after {
1267
- content: "\1F6AB";
1260
+ /* Worktree registered outside the main project folder. It remains usable;
1261
+ the badge communicates location without treating it as an error. */
1262
+ .worktree-external-badge {
1268
1263
  position: absolute;
1269
- font-size: 14px;
1264
+ right: 5px;
1265
+ bottom: 1px;
1266
+ width: 14px;
1267
+ height: 14px;
1268
+ display: flex;
1269
+ align-items: center;
1270
+ justify-content: center;
1271
+ border-radius: 50%;
1272
+ border: 2px solid var(--sidebar-bg);
1273
+ background: var(--warning);
1274
+ color: var(--bg);
1270
1275
  z-index: 3;
1271
- filter: grayscale(0.3);
1276
+ pointer-events: none;
1272
1277
  }
1273
1278
 
1279
+ .worktree-external-badge .lucide { width: 8px; height: 8px; stroke-width: 2.8; }
1280
+
1274
1281
  /* Group add button */
1275
1282
  .icon-strip-group-add {
1276
1283
  width: 30px;
@@ -1420,11 +1427,20 @@ select.wt-modal-input {
1420
1427
  opacity: 0.85;
1421
1428
  }
1422
1429
 
1423
- .mobile-project-item.wt-disabled {
1424
- opacity: 0.35;
1425
- cursor: not-allowed;
1430
+ .mobile-worktree-external-badge {
1431
+ width: 20px;
1432
+ height: 20px;
1433
+ display: inline-flex;
1434
+ align-items: center;
1435
+ justify-content: center;
1436
+ border-radius: 7px;
1437
+ background: color-mix(in srgb, var(--warning) 14%, transparent);
1438
+ color: var(--warning);
1439
+ flex-shrink: 0;
1426
1440
  }
1427
1441
 
1442
+ .mobile-worktree-external-badge .lucide { width: 12px; height: 12px; stroke-width: 2.4; }
1443
+
1428
1444
  .mobile-folder-chevron {
1429
1445
  font-size: 8px;
1430
1446
  color: var(--text-dimmer);
@@ -667,6 +667,50 @@
667
667
  position: relative;
668
668
  }
669
669
 
670
+ .background-tasks-bar {
671
+ max-width: var(--content-width);
672
+ margin: 0 auto 8px;
673
+ border: 1px solid var(--border);
674
+ border-radius: 8px;
675
+ background: var(--input-bg);
676
+ overflow: hidden;
677
+ }
678
+
679
+ .background-tasks-toggle {
680
+ width: 100%;
681
+ display: flex;
682
+ align-items: center;
683
+ gap: 7px;
684
+ padding: 8px 10px;
685
+ border: 0;
686
+ background: transparent;
687
+ color: var(--text-secondary);
688
+ cursor: pointer;
689
+ font: inherit;
690
+ text-align: left;
691
+ }
692
+
693
+ .background-tasks-chip, .session-background-task-count {
694
+ display: inline-flex;
695
+ align-items: center;
696
+ justify-content: center;
697
+ min-width: 16px;
698
+ height: 16px;
699
+ padding: 0 4px;
700
+ border-radius: 8px;
701
+ background: var(--accent);
702
+ color: var(--bg);
703
+ font-size: 10px;
704
+ font-weight: 700;
705
+ }
706
+
707
+ .background-tasks-list { padding: 0 10px 8px; }
708
+ .background-task-row { display: flex; align-items: center; gap: 8px; padding: 6px 0; border-top: 1px solid var(--border-subtle); }
709
+ .background-task-description { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
710
+ .background-task-type { padding: 2px 6px; border-radius: 5px; background: var(--code-bg); color: var(--text-muted); font-size: 11px; }
711
+ .background-task-stop { border: 1px solid var(--border); border-radius: 5px; padding: 3px 7px; background: transparent; color: var(--text-secondary); cursor: pointer; font: inherit; font-size: 12px; }
712
+ .background-task-stop:hover { color: var(--text); border-color: var(--text-muted); }
713
+
670
714
  #input-row {
671
715
  display: flex;
672
716
  flex-direction: column;
@@ -790,6 +834,7 @@
790
834
  opacity: 0.35;
791
835
  cursor: default;
792
836
  }
837
+ .vendor-toggle-btn.disabled:not(.active) { display: none; }
793
838
  .vendor-toggle-icon {
794
839
  width: 16px;
795
840
  height: 16px;
@@ -799,6 +844,17 @@
799
844
  .vendor-toggle-label {
800
845
  pointer-events: none;
801
846
  }
847
+ .vendor-toggle-btn.experimental::after,
848
+ .vendor-experimental-badge {
849
+ content: "🧪";
850
+ font-size: 10px;
851
+ line-height: 1;
852
+ font-weight: 400;
853
+ filter: saturate(0.85);
854
+ }
855
+ .vendor-experimental-badge {
856
+ margin-left: auto;
857
+ }
802
858
  @media (min-width: 901px) {
803
859
  .vendor-toggle-btn:not(.active) .vendor-toggle-label { display: none; }
804
860
  .vendor-toggle-btn:not(.active) { padding: 0 8px; }
@@ -682,6 +682,12 @@
682
682
  .mate-vendor-label {
683
683
  pointer-events: none;
684
684
  }
685
+ .mate-vendor-btn.experimental::after {
686
+ content: "🧪";
687
+ font-size: 9px;
688
+ line-height: 1;
689
+ font-weight: 400;
690
+ }
685
691
  .mate-vendor-btn:not(.active) .mate-vendor-label { display: none; }
686
692
 
687
693
  /* Collapse button inside mate header: white to match header style */
@@ -43,30 +43,9 @@
43
43
  #header-rename-btn:hover { color: var(--text-secondary); background: rgba(var(--overlay-rgb),0.04); border-color: var(--border); }
44
44
  #header-rename-btn .lucide { width: 13px; height: 13px; }
45
45
 
46
- #header-add-worker-btn {
47
- display: flex;
48
- align-items: center;
49
- justify-content: center;
50
- width: 24px;
51
- height: 24px;
52
- border: 1px solid transparent;
53
- background: none;
54
- color: var(--text-dimmer);
55
- cursor: pointer;
56
- border-radius: 8px;
57
- flex-shrink: 0;
58
- padding: 0;
59
- margin-left: 4px;
60
- transition: color 0.15s, background 0.15s, border-color 0.15s;
61
- }
62
- #header-add-worker-btn:hover { color: var(--text-secondary); background: rgba(var(--overlay-rgb),0.04); border-color: var(--border); }
63
- #header-add-worker-btn .lucide { width: 13px; height: 13px; }
64
- #header-add-worker-btn.hidden { display: none; }
65
- body.dm-mode #header-add-worker-btn { display: none; }
66
-
67
- /* "Close terminal" button: sits just left of the rename pencil during a live
68
- TUI session. Matches the rename button's chrome; reds out on hover since it
69
- stops the running claude (the session stays resumable). */
46
+ /* "Close terminal" button for a live TUI session. Matches the session-control
47
+ chrome; reds out on hover since it stops the running agent while preserving
48
+ the resumable session. */
70
49
  #header-tui-close-btn {
71
50
  display: flex;
72
51
  align-items: center;
@@ -667,6 +646,41 @@ body.dm-mode #header-add-worker-btn { display: none; }
667
646
  color: var(--text-dimmer);
668
647
  font-style: italic;
669
648
  }
649
+ .config-model-state {
650
+ display: flex;
651
+ align-items: center;
652
+ gap: 10px;
653
+ min-width: 280px;
654
+ padding: 10px 14px;
655
+ color: var(--text-secondary);
656
+ font-size: 12px;
657
+ white-space: normal;
658
+ }
659
+ .config-model-state > div { flex: 1; min-width: 0; }
660
+ .config-model-state-title { color: var(--text); font-weight: 600; }
661
+ .config-model-state-detail { margin-top: 2px; color: var(--text-muted); line-height: 1.35; }
662
+ .config-model-spinner {
663
+ width: 14px;
664
+ height: 14px;
665
+ flex: 0 0 auto;
666
+ border: 2px solid var(--border);
667
+ border-top-color: var(--accent);
668
+ border-radius: 50%;
669
+ animation: config-model-spin 0.8s linear infinite;
670
+ }
671
+ @keyframes config-model-spin { to { transform: rotate(360deg); } }
672
+ .config-model-retry {
673
+ flex: 0 0 auto;
674
+ border: 1px solid var(--border);
675
+ border-radius: 5px;
676
+ padding: 4px 8px;
677
+ background: var(--surface-raised);
678
+ color: var(--text-secondary);
679
+ font: inherit;
680
+ cursor: pointer;
681
+ }
682
+ .config-model-retry:hover { color: var(--text); border-color: var(--text-muted); }
683
+ .config-radio-item.pending { color: var(--accent); opacity: 0.75; }
670
684
 
671
685
  /* Segmented control for effort */
672
686
  .config-segmented {
@@ -980,4 +994,3 @@ body.dm-mode #header-add-worker-btn { display: none; }
980
994
  #config-chip .config-chip-icon { display: inline; width: 14px; height: 14px; }
981
995
  #config-chip-label { display: none; }
982
996
  }
983
-
@@ -5,12 +5,21 @@
5
5
  #messages {
6
6
  flex: 1;
7
7
  overflow-y: auto;
8
+ overflow-x: hidden;
8
9
  -webkit-overflow-scrolling: touch;
9
10
  overscroll-behavior-y: contain;
10
11
  padding: 20px 0 12px;
11
12
  position: relative;
12
13
  }
13
14
 
15
+ /* Rich message content can contain wide tables, diagrams, or generated HTML.
16
+ Keep that content inside the chat scroller; nested code blocks still own
17
+ their intentional horizontal scrolling. */
18
+ #messages > * {
19
+ min-width: 0;
20
+ max-width: 100%;
21
+ }
22
+
14
23
  /* --- Remote cursors (Figma-style) --- */
15
24
  .remote-cursor {
16
25
  pointer-events: none;
@@ -23,6 +23,10 @@ body.pane-mode #sticky-notes-container {
23
23
  display: none !important;
24
24
  }
25
25
 
26
+ body.pane-mode .notif-banner-container {
27
+ display: none !important;
28
+ }
29
+
26
30
  body.pane-mode #main-area {
27
31
  border: 0;
28
32
  border-radius: 0;
@@ -96,7 +100,8 @@ body.pane-mode #input-area {
96
100
  }
97
101
 
98
102
  .split-pane-title {
99
- flex: 1;
103
+ flex: 0 1 auto;
104
+ max-width: 46%;
100
105
  min-width: 0;
101
106
  overflow: hidden;
102
107
  text-overflow: ellipsis;
@@ -198,15 +203,18 @@ button.split-pair-role:hover { filter: brightness(1.25); }
198
203
  max-width: var(--content-width);
199
204
  margin: 0 auto;
200
205
  padding: 4px 10px;
201
- border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
202
- border-bottom: 0;
203
206
  border-radius: 8px 8px 0 0;
204
207
  background: color-mix(in srgb, var(--accent) 8%, var(--bg));
205
208
  color: var(--text-secondary);
206
209
  font-size: 11px;
207
210
  line-height: 1.4;
211
+ transition: box-shadow 0.2s;
208
212
  }
209
213
  .pane-delegation-notice.visible { display: flex; }
214
+ .pane-delegation-notice.visible:has(+ #input-wrapper #input-row:focus-within) {
215
+ box-shadow: 0 0 0 1px var(--border);
216
+ clip-path: inset(-1px -1px 0 -1px);
217
+ }
210
218
  .pane-delegation-notice.visible + #input-wrapper #input-row {
211
219
  border-radius: 0 0 8px 8px;
212
220
  }
@@ -279,12 +287,17 @@ button.split-pair-role:hover { filter: brightness(1.25); }
279
287
  color: var(--text-dimmer);
280
288
  cursor: pointer;
281
289
  flex-shrink: 0;
290
+ margin-left: auto;
282
291
  }
283
292
 
284
293
  .split-pane-context.has-data {
285
294
  display: inline-flex;
286
295
  }
287
296
 
297
+ .split-pane-context:not(.has-data) + .split-pane-close {
298
+ margin-left: auto;
299
+ }
300
+
288
301
  .split-pane-context:hover {
289
302
  background: var(--bg-alt);
290
303
  color: var(--text);
@@ -0,0 +1,17 @@
1
+ /* In an iOS Home Screen app, a 100%-tall root can be measured against the
2
+ shortened safe-area viewport. Use the physical viewport for the root while
3
+ retaining safe-area padding on controls inside the app. */
4
+ @media (max-width: 768px) {
5
+ html.pwa-standalone,
6
+ html.pwa-standalone body {
7
+ height: 100vh;
8
+ }
9
+ }
10
+
11
+ @media (max-width: 768px) and (display-mode: standalone),
12
+ (max-width: 768px) and (display-mode: fullscreen) {
13
+ html,
14
+ body {
15
+ height: 100vh;
16
+ }
17
+ }
@@ -0,0 +1,98 @@
1
+ #header-session-actions-btn {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ justify-content: center;
5
+ width: 28px;
6
+ height: 28px;
7
+ padding: 0;
8
+ border: 1px solid transparent;
9
+ border-radius: 8px;
10
+ background: transparent;
11
+ color: var(--text-dimmer);
12
+ cursor: pointer;
13
+ flex-shrink: 0;
14
+ transition: color 0.15s, background 0.15s, border-color 0.15s;
15
+ }
16
+
17
+ #header-session-actions-btn:hover,
18
+ #header-session-actions-btn[aria-expanded="true"] {
19
+ color: var(--text);
20
+ background: rgba(var(--overlay-rgb), 0.05);
21
+ border-color: var(--border);
22
+ }
23
+
24
+ #header-session-actions-btn.hidden { display: none; }
25
+ #header-session-actions-btn .lucide { width: 16px; height: 16px; }
26
+
27
+ .session-actions-menu {
28
+ position: fixed;
29
+ z-index: 10020;
30
+ width: 286px;
31
+ padding: 6px;
32
+ border: 1px solid var(--border);
33
+ border-radius: 12px;
34
+ background: color-mix(in srgb, var(--bg) 96%, transparent);
35
+ box-shadow: 0 14px 38px rgba(var(--shadow-rgb), 0.32), 0 2px 8px rgba(var(--shadow-rgb), 0.2);
36
+ backdrop-filter: blur(18px);
37
+ }
38
+
39
+ .session-actions-row {
40
+ width: 100%;
41
+ border: 0;
42
+ background: transparent;
43
+ color: var(--text);
44
+ font: inherit;
45
+ text-align: left;
46
+ cursor: pointer;
47
+ }
48
+
49
+ .session-actions-row {
50
+ display: grid;
51
+ grid-template-columns: 30px minmax(0, 1fr) 16px;
52
+ align-items: center;
53
+ gap: 8px;
54
+ min-height: 54px;
55
+ padding: 7px 8px;
56
+ border-radius: 8px;
57
+ }
58
+
59
+ .session-actions-row:hover { background: var(--bg-alt); }
60
+ .session-actions-row:disabled { cursor: default; opacity: 0.42; }
61
+ .session-actions-row:disabled:hover { background: transparent; }
62
+
63
+ .session-actions-row-icon {
64
+ display: grid;
65
+ place-items: center;
66
+ width: 28px;
67
+ height: 28px;
68
+ border: 1px solid var(--border-subtle);
69
+ border-radius: 8px;
70
+ background: rgba(var(--overlay-rgb), 0.035);
71
+ color: var(--accent2);
72
+ }
73
+
74
+ .session-actions-row-icon .lucide { width: 15px; height: 15px; }
75
+ .session-actions-row-copy { display: flex; min-width: 0; flex-direction: column; gap: 2px; }
76
+ .session-actions-row-copy strong { font-size: 12px; font-weight: 750; }
77
+ .session-actions-row-copy > span { color: var(--text-dimmer); font-size: 10px; line-height: 1.25; }
78
+ .session-actions-row-chevron { color: var(--text-dimmer); }
79
+ .session-actions-row-chevron .lucide { width: 13px; height: 13px; }
80
+
81
+ .handoff-modal { width: min(420px, calc(100vw - 32px)); }
82
+ .handoff-modal-desc { margin: -10px 0 14px; color: var(--text-dimmer); font-size: 12px; line-height: 1.45; }
83
+ .handoff-modal-source {
84
+ display: flex;
85
+ align-items: center;
86
+ gap: 10px;
87
+ margin-bottom: 14px;
88
+ padding: 10px;
89
+ border: 1px solid var(--border-subtle);
90
+ border-radius: 9px;
91
+ background: var(--bg-alt);
92
+ }
93
+ .handoff-modal-source > img { width: 26px; height: 26px; object-fit: contain; border-radius: 6px; }
94
+ .handoff-modal-source > span { display: grid; min-width: 0; gap: 1px; }
95
+ .handoff-modal-source strong { overflow: hidden; color: var(--text); font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
96
+ .handoff-modal-source span span { color: var(--text-dimmer); font-size: 10px; }
97
+ .handoff-modal-field + .handoff-modal-field { margin-top: 10px; }
98
+ .handoff-modal-field .wt-modal-label { margin-top: 0; }
@@ -324,6 +324,25 @@
324
324
  display: none !important;
325
325
  }
326
326
 
327
+ .title-bar-content {
328
+ height: calc(48px + var(--safe-top));
329
+ padding: var(--safe-top) 16px 0;
330
+ }
331
+
332
+ /* The inline title editor must own the header while the keyboard is open.
333
+ Leaving the other controls visible made its usable width nearly zero. */
334
+ .title-bar-content.session-renaming .status,
335
+ .title-bar-content.session-renaming #header-left > :not(.header-rename-input) {
336
+ display: none !important;
337
+ }
338
+
339
+ .title-bar-content.session-renaming .header-rename-input {
340
+ flex: 1 1 100%;
341
+ width: 100%;
342
+ min-height: 36px;
343
+ font-size: 16px;
344
+ }
345
+
327
346
  #sidebar-column {
328
347
  width: 0 !important;
329
348
  min-width: 0 !important;
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="Grok Build">
2
+ <rect width="64" height="64" rx="14" fill="#111"/>
3
+ <path d="M45 17A21 21 0 1 0 49 42H35v-9h22v4A25 25 0 1 1 51 13z" fill="#fff"/>
4
+ </svg>