clay-server 4.1.0-beta.9 → 4.1.0

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 (111) hide show
  1. package/lib/context-usage.js +47 -0
  2. package/lib/issues-mcp-server.js +1 -1
  3. package/lib/issues-service.js +3 -1
  4. package/lib/loop-registry-occurrence.js +1 -0
  5. package/lib/notes.js +20 -3
  6. package/lib/os-users.js +6 -0
  7. package/lib/project-connection.js +14 -3
  8. package/lib/project-file-path.js +13 -0
  9. package/lib/project-file-watch.js +19 -8
  10. package/lib/project-filesystem.js +10 -16
  11. package/lib/project-http.js +53 -48
  12. package/lib/project-logs-mcp-server.js +8 -8
  13. package/lib/project-logs-schema.js +1 -1
  14. package/lib/project-logs-service.js +46 -13
  15. package/lib/project-logs-store.js +17 -15
  16. package/lib/project-logs.js +70 -0
  17. package/lib/project-loop.js +1 -0
  18. package/lib/project-notifications.js +1 -1
  19. package/lib/project-scheduled-result-store.js +131 -0
  20. package/lib/project-scheduled-task-execution.js +35 -2
  21. package/lib/project-session-notes.js +11 -4
  22. package/lib/project-sessions.js +7 -0
  23. package/lib/project-user-message.js +47 -0
  24. package/lib/project.js +53 -3
  25. package/lib/public/app.js +26 -9
  26. package/lib/public/css/avatar-imprints.css +1 -1
  27. package/lib/public/css/command-palette.css +20 -0
  28. package/lib/public/css/git-panel.css +13 -12
  29. package/lib/public/css/git-placard.css +4 -4
  30. package/lib/public/css/issues.css +78 -31
  31. package/lib/public/css/mobile-nav.css +7 -0
  32. package/lib/public/css/notifications-center.css +3 -3
  33. package/lib/public/css/project-logs.css +15 -0
  34. package/lib/public/css/sidebar.css +7 -0
  35. package/lib/public/css/sticky-notes.css +29 -0
  36. package/lib/public/modules/app-connection.js +9 -1
  37. package/lib/public/modules/app-favicon.js +10 -0
  38. package/lib/public/modules/app-messages.js +43 -12
  39. package/lib/public/modules/app-notifications.js +2 -0
  40. package/lib/public/modules/app-panels.js +77 -23
  41. package/lib/public/modules/app-projects.js +2 -0
  42. package/lib/public/modules/app-rate-limit.js +148 -61
  43. package/lib/public/modules/avatar-imprint.js +25 -70
  44. package/lib/public/modules/avatar.js +12 -4
  45. package/lib/public/modules/chat-render-runtime.js +20 -0
  46. package/lib/public/modules/clay-issue-links.js +23 -2
  47. package/lib/public/modules/clay-log-links.js +11 -1
  48. package/lib/public/modules/context-view-preference.js +143 -0
  49. package/lib/public/modules/default-vendor.js +116 -0
  50. package/lib/public/modules/filebrowser-tabs.js +1 -0
  51. package/lib/public/modules/filebrowser.js +45 -18
  52. package/lib/public/modules/issues-render.js +36 -10
  53. package/lib/public/modules/issues.js +95 -13
  54. package/lib/public/modules/markdown.js +3 -1
  55. package/lib/public/modules/pane-bridge.js +14 -8
  56. package/lib/public/modules/pane-issue-bridge.js +27 -0
  57. package/lib/public/modules/permission-hints.js +13 -0
  58. package/lib/public/modules/profile.js +9 -9
  59. package/lib/public/modules/project-activation.js +49 -0
  60. package/lib/public/modules/project-logs-render.js +13 -3
  61. package/lib/public/modules/project-logs.js +45 -15
  62. package/lib/public/modules/right-workbench.js +44 -0
  63. package/lib/public/modules/scheduled-result-client.js +33 -0
  64. package/lib/public/modules/scheduled-result-display.js +50 -0
  65. package/lib/public/modules/scheduled-result-notification.js +31 -0
  66. package/lib/public/modules/scheduled-task-presentation.js +15 -0
  67. package/lib/public/modules/scheduled-tasks.js +9 -21
  68. package/lib/public/modules/sidebar-mobile.js +51 -3
  69. package/lib/public/modules/sidebar-sessions.js +65 -5
  70. package/lib/public/modules/split-session-boundary.js +28 -0
  71. package/lib/public/modules/split-view.js +42 -7
  72. package/lib/public/modules/sticky-notes-browser.js +130 -18
  73. package/lib/public/modules/sticky-notes.js +2 -3
  74. package/lib/public/modules/terminal.js +4 -4
  75. package/lib/public/modules/thinking-lifecycle.js +4 -1
  76. package/lib/public/modules/tools.js +5 -1
  77. package/lib/scheduled-run-state.js +10 -2
  78. package/lib/scheduler.js +1 -0
  79. package/lib/sdk-bridge.js +97 -61
  80. package/lib/sdk-message-processor.js +44 -13
  81. package/lib/sdk-skill-discovery.js +6 -28
  82. package/lib/sdk-turn-queue.js +14 -0
  83. package/lib/server-context-view.js +53 -0
  84. package/lib/server-default-vendor.js +60 -0
  85. package/lib/server.js +23 -6
  86. package/lib/session-notes-mcp-server.js +3 -5
  87. package/lib/session-pair-factory.js +2 -2
  88. package/lib/session-title-generator.js +89 -0
  89. package/lib/session-title-policy.js +8 -2
  90. package/lib/sessions.js +26 -1
  91. package/lib/user-presence.js +6 -0
  92. package/lib/users-context-view-preferences.js +65 -0
  93. package/lib/users-default-vendor-preferences.js +80 -0
  94. package/lib/users.js +12 -0
  95. package/lib/ws-schema.js +11 -0
  96. package/lib/yoke/acp-agent-profiles.js +15 -2
  97. package/lib/yoke/adapters/acp.js +3 -2
  98. package/lib/yoke/adapters/antigravity.js +2 -2
  99. package/lib/yoke/adapters/claude-worker.js +11 -12
  100. package/lib/yoke/adapters/claude.js +75 -22
  101. package/lib/yoke/adapters/codex.js +216 -29
  102. package/lib/yoke/adapters/kiro.js +6 -5
  103. package/lib/yoke/claude-context-usage.js +57 -0
  104. package/lib/yoke/claude-message-correlation.js +31 -0
  105. package/lib/yoke/claude-model-switch.js +15 -0
  106. package/lib/yoke/index.js +5 -1
  107. package/lib/yoke/mcp-bridge-server.js +18 -5
  108. package/lib/yoke/session-skill-catalog.js +45 -0
  109. package/lib/yoke/skill-discovery.js +60 -20
  110. package/lib/yoke/vendor-registry.js +1 -1
  111. package/package.json +5 -7
@@ -1,7 +1,20 @@
1
- #issues-panel { position: relative; width: 48%; max-width: 760px; min-width: 360px; height: calc(100% - 16px); margin: 8px; align-self: center; display: flex; flex-direction: column; background: var(--bg); color: var(--text); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; flex-shrink: 0; }
1
+ #issues-panel { position: relative; width: 50%; max-width: 720px; min-width: 360px; height: calc(100% - 16px); margin: 8px 8px 8px 10px; min-height: 0; align-self: center; display: flex; flex-direction: column; background: var(--bg); color: var(--text); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; flex-shrink: 0; }
2
+ @media (min-width: 1024px) {
3
+ #issues-panel {
4
+ box-shadow:
5
+ 4px 8px 18px rgba(var(--shadow-rgb), 0.14),
6
+ 2px 2px 4px rgba(var(--shadow-rgb), 0.08),
7
+ inset 0 1px 0 rgba(255, 255, 255, 0.04);
8
+ animation: workbench-panel-in 0.18s cubic-bezier(0.2, 0.8, 0.2, 1);
9
+ transition: max-width 0.2s ease, width 0.2s ease, box-shadow 0.2s ease;
10
+ }
11
+ }
12
+ @media (prefers-reduced-motion: reduce) {
13
+ #issues-panel { animation: none; }
14
+ }
2
15
  #issues-panel.hidden { display: none; }
3
16
  #issues-panel.issues-wide { width: 70%; max-width: 1200px; }
4
- #issues-panel.panel-fullscreen { width: 100%; max-width: none; height: 100%; margin: 0; }
17
+ #issues-panel.panel-fullscreen { width: 100%; max-width: none; min-width: 0; height: 100%; margin: 0; border: 0; border-radius: 0; box-shadow: none; animation: none; }
5
18
  #issues-panel header { height: 48px; box-sizing: border-box; display: flex; align-items: center; gap: 12px; padding: 0 16px; border-bottom: 1px solid var(--border-subtle); flex: 0 0 auto; }
6
19
  #issues-panel .issues-title { display: inline-flex; align-items: center; gap: 7px; font-weight: 700; }
7
20
  #issues-panel .issues-title .lucide { width: 15px; color: var(--accent); }
@@ -11,10 +24,10 @@
11
24
  #issues-panel .issues-icon-btn .lucide { width: 15px; }
12
25
  #issues-panel .issues-icon-btn.hidden { display: none; }
13
26
  #issues-panel .issues-icon-btn[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); }
14
- #issues-panel button, #issues-panel input, #issues-panel textarea, #issues-panel select { font: inherit; color: inherit; background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 8px 10px; }
27
+ #issues-panel :where(button:not(.clayos-issue-link):not(.clayos-log-link), input, textarea, select) { font: inherit; color: inherit; background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 8px 10px; }
15
28
  #issues-panel button { cursor: pointer; }
16
- #issues-panel button:hover { background: var(--bg-hover, rgba(128,128,128,.12)); }
17
- #issues-panel button:disabled { opacity: .5; cursor: wait; }
29
+ #issues-panel button:not(.clayos-issue-link):not(.clayos-log-link):hover { background: var(--bg-hover, rgba(128,128,128,.12)); }
30
+ #issues-panel button:disabled { opacity: .5; cursor: default; }
18
31
  #issues-panel :focus-visible { outline: 2px solid var(--accent, #b98655); outline-offset: 2px; }
19
32
  .issues-filters { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding: 12px 14px; border-bottom: 1px solid var(--border-subtle); background: color-mix(in srgb, var(--bg-alt) 72%, transparent); }
20
33
  .issues-search { flex: 1; min-width: 120px; height: 36px; display: flex; align-items: center; gap: 8px; padding: 0 10px; border: 1px solid var(--border); border-radius: 6px; background: var(--bg); color: var(--text-dimmer); }
@@ -25,35 +38,44 @@
25
38
  .issues-notice { margin: 0; padding: 0 16px; font-size: 12px; color: var(--text-muted); }
26
39
  .issue-row { display: block; width: 100%; text-align: left; margin: 0; padding: 15px 18px 14px !important; border: 0 !important; border-bottom: 1px solid var(--border-subtle) !important; border-left: 2px solid transparent !important; border-radius: 0 !important; background: transparent !important; }
27
40
  .issue-row:hover { background: color-mix(in srgb, var(--accent) 5%, transparent) !important; border-left-color: var(--accent) !important; }
28
- .issue-row-head { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; }
41
+ .issue-row-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 7px; }
29
42
  .issue-type { padding: 2px 7px; border-radius: 999px; background: rgba(var(--overlay-rgb), .08); color: var(--text-secondary); font-size: 10px; font-weight: 700; text-transform: uppercase; }
30
- .issue-row strong { display: block; font-size: 14px; }
43
+ .issue-row strong { flex: 1; min-width: 0; font-size: 14px; font-weight: 700; letter-spacing: -.01em; overflow-wrap: anywhere; }
31
44
  .issue-row p { margin: 7px 0 0; color: var(--text-secondary); font-size: 12.5px; line-height: 1.55; }
32
- .issue-row small, .issue-detail small { color: var(--text-muted); }
45
+
33
46
  .issue-row small { font-size: 10.5px; font-family: var(--font-mono); }
47
+ .issue-row-meta { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; margin-top: 8px; color: var(--text-dimmer); font: 10.5px/1.5 var(--font-mono); }
48
+ .issue-row-meta .issue-status { font-family: var(--font-sans); }
34
49
  .issue-status { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; letter-spacing: .03em; }
35
50
  .issue-status::before { content: ''; width: 7px; height: 7px; border: 1px solid currentColor; border-radius: 50%; }
36
- [data-status="in_progress"] { color: #bd923f; }
37
- [data-status="resolved"] { color: #479b77; }
38
- [data-status="closed"] { color: var(--text-muted); }
51
+ .issue-status[data-status="in_progress"] { color: #bd923f; }
52
+ .issue-status[data-status="resolved"] { color: #479b77; }
53
+ .issue-status[data-status="closed"] { color: var(--text-muted); }
39
54
  .issue-detail { max-width: 760px; margin: 0 auto; padding: 32px 28px 52px; }
40
- .issue-detail h2 { margin: 10px 0; font-family: var(--font-display); font-size: clamp(24px, 2.8vw, 34px); line-height: 1.12; }
41
- .issue-detail > p { font-size: 14px; line-height: 1.6; }
42
- .issue-detail > small { font-size: 11px; font-family: var(--font-mono); }
43
- .issue-detail .markdown-body { margin: 24px 0; }
44
- .issue-detail .markdown-body { font-size: 14px; line-height: 1.75; }
45
- .issue-detail section { margin-top: 24px; overflow-wrap: anywhere; }
46
- .issue-detail h3 { font-size: 12px; color: var(--text-muted); }
47
- #issues-panel .issue-discussion { border-top: 1px solid var(--border-subtle); }
48
- #issues-panel .issue-comment { padding: 12px 0; border-bottom: 1px solid var(--border-subtle); }
49
- #issues-panel .issue-comment-meta { color: var(--text-muted); font: 10.5px/1.4 var(--font-mono); }
50
- #issues-panel .issue-comment p { margin: 6px 0 0; font-size: 13px; line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere; }
51
- #issues-panel .issue-comment small { display: block; margin-top: 7px; color: var(--text-dimmer); font-size: 11px; }
52
- #issues-panel .issue-discussion-empty { color: var(--text-muted); font-size: 13px; }
53
- #issues-panel #issue-comment-form { margin-top: 16px; }
54
- #issues-panel #issue-comment-form label { display: block; margin-bottom: 6px; color: var(--text-muted); font-size: 11px; }
55
- #issues-panel #issue-comment-input { width: 100%; box-sizing: border-box; min-height: 76px; resize: vertical; font-size: 13px; line-height: 1.55; }
56
- #issues-panel .issue-comment-status { min-height: 1.4em; margin: 6px 0; color: var(--text-muted); font-size: 11px; }
55
+ .issue-doc-chips { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; margin-bottom: 10px; }
56
+ .issue-detail .issue-doc-title { margin: 0 0 10px; font-family: var(--font-display); font-size: clamp(24px, 2.8vw, 34px); letter-spacing: -.025em; line-height: 1.12; overflow-wrap: anywhere; }
57
+ .issue-doc-summary { color: var(--text-secondary); font-size: 14px; line-height: 1.6; }
58
+ .issue-detail .issue-doc-summary > p { margin: 0 0 13px; }
59
+ .issue-byline { margin: 0 0 18px; padding-bottom: 18px; border-bottom: 2px solid var(--border-subtle); color: var(--text-dimmer); font: 11px/1.6 var(--font-mono); overflow-wrap: anywhere; }
60
+ .issue-doc-body { margin: 24px 0 0; font-size: 14px; line-height: 1.75; overflow-wrap: anywhere; }
61
+ .issue-detail section { margin-top: 26px; overflow-wrap: anywhere; }
62
+ .issue-detail section h3 { margin: 0 0 12px; font-family: var(--font-display); font-size: 15px; color: var(--text); }
63
+ .issue-evidence { padding-top: 18px; border-top: 1px solid var(--border-subtle); font-size: 13px; line-height: 1.65; }
64
+ #issues-panel .issue-discussion { margin-top: 30px; padding-top: 18px; border-top: 1px solid var(--border-subtle); }
65
+ .issue-discussion h3 > span { margin-left: 4px; font: 11px var(--font-mono); color: var(--text-dimmer); }
66
+ #issues-panel .issue-comment { padding: 10px 12px; margin-bottom: 8px; border: 1px solid var(--border-subtle); border-radius: 9px; background: var(--bg-alt); }
67
+ .issue-comment-meta { margin-bottom: 5px; color: var(--text-dimmer); font: 10.5px/1.4 var(--font-mono); }
68
+ .issue-comment .markdown-body { font-size: 13px; line-height: 1.55; overflow-wrap: anywhere; }
69
+ .issue-comment .markdown-body > :first-child { margin-top: 0; }
70
+ .issue-comment .markdown-body > :last-child { margin-bottom: 0; }
71
+ .issue-comment-review { margin-top: 9px; padding: 8px 10px; border-left: 2px solid var(--accent); background: rgba(var(--overlay-rgb), .04); border-radius: 0 7px 7px 0; }
72
+ .issue-comment-review > span { display: block; margin-bottom: 5px; color: var(--text-dimmer); font: 10.5px var(--font-mono); }
73
+ .issue-discussion-empty { margin: 0; color: var(--text-dimmer); font-size: 12px; }
74
+ #issue-comment-form { display: grid; gap: 8px; margin-top: 18px; }
75
+ #issue-comment-form label { color: var(--text-secondary); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; }
76
+ #issues-panel #issue-comment-input { width: 100%; box-sizing: border-box; min-height: 80px; resize: vertical; font-size: 13px; line-height: 1.55; border-radius: 8px; padding: 10px; background: var(--bg-alt); }
77
+ #issue-comment-form .issue-comment-status { min-height: 16px; margin: 0; color: var(--text-dimmer); font-size: 11px; }
78
+ .issue-comment-actions { display: flex; justify-content: flex-end; }
57
79
  #issues-panel .issues-delete-dialog { position: absolute; inset: 0; z-index: 2; display: grid; place-items: center; padding: 24px; background: rgba(0, 0, 0, .38); }
58
80
  #issues-panel .issues-delete-dialog.hidden { display: none; }
59
81
  #issues-panel .issues-delete-card { width: min(360px, 100%); box-sizing: border-box; padding: 22px; border: 1px solid var(--border); border-radius: 10px; background: var(--bg); box-shadow: 0 14px 40px rgba(0, 0, 0, .24); }
@@ -78,15 +100,16 @@
78
100
  .issues-content > h2 { padding: 0 28px; }
79
101
  .issues-content > h2 { margin: 0 0 10px; font-family: var(--font-display); font-size: 14px; line-height: 1.2; }
80
102
  .issues-history-note { margin: 0; padding: 14px 18px; border-bottom: 1px solid var(--border-subtle); color: var(--text-dimmer); font-size: 11px; font-family: var(--font-mono); }
81
- .clayos-issue-link { display: inline-flex; max-width: 100%; border: 1px solid var(--border); border-radius: 5px; background: var(--bg); color: inherit; font: inherit; font-size: .85em; padding: 2px 7px; cursor: pointer; vertical-align: baseline; overflow-wrap: anywhere; }
82
- @media (max-width: 1023px) { #issues-panel, #issues-panel.issues-wide { position: fixed; inset: 0; z-index: 150; width: 100%; max-width: none; min-width: 0; height: 100%; margin: 0; border-radius: 0; padding-top: var(--safe-top, 0px); padding-bottom: var(--safe-bottom, 0px); box-sizing: border-box; } #issues-panel button { min-height: 36px; } }
103
+
104
+ @media (max-width: 1023px) { #issues-panel, #issues-panel.issues-wide { position: fixed; inset: 0; z-index: 300; width: 100%; max-width: none; min-width: 0; height: 100%; margin: 0; border: 0; border-radius: 0; padding-top: var(--safe-top, 0px); padding-bottom: var(--safe-bottom, 0px); box-sizing: border-box; } #issues-panel button:not(.clayos-issue-link):not(.clayos-log-link) { min-height: 36px; } }
105
+ @media (max-width: 1023px) { #issues-panel [data-issues-wide], #issues-panel [data-issues-full] { display: none; } }
83
106
  @media (max-width: 390px) {
84
107
  #issues-panel header { gap: 4px; padding: 8px; }
85
108
  #issues-panel header button { padding: 7px; }
86
109
  #issues-panel [data-issues-wide], #issues-panel [data-issues-full] { display: none; }
87
110
  .issues-filters { display: grid; grid-template-columns: 1fr 1fr; padding: 8px; }
88
111
  .issues-filters .issues-search { grid-column: 1 / -1; width: 100%; box-sizing: border-box; }
89
- .issues-content { padding: 10px; }
112
+ .issues-content { padding: 0; }
90
113
  .issue-row { padding: 12px !important; }
91
114
  .issue-detail h2 { font-size: 20px; }
92
115
  }
@@ -99,3 +122,27 @@
99
122
  .issues-content > h2 { padding-right: 18px; padding-left: 18px; }
100
123
  .issue-detail { padding: 24px 18px 38px; }
101
124
  }
125
+
126
+ #issues-panel { font-family: var(--font-sans); font-size: 13px; }
127
+ #issues-panel .issues-title { font-size: 13px; }
128
+ .issues-notice:empty { display: none; }
129
+ .issues-notice:not(:empty) { padding: 10px 16px; border-bottom: 1px solid var(--border-subtle); line-height: 1.5; }
130
+ .issues-inline-update { display: inline-flex; align-items: center; gap: 7px; width: 100%; box-sizing: border-box; margin: 0 0 8px; padding: 7px 9px; border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--border)); border-radius: 7px; background: color-mix(in srgb, var(--accent) 7%, transparent); color: var(--text-secondary); font-size: 11px; }
131
+ .issues-inline-update button { margin-left: auto; padding: 3px 8px !important; border-color: var(--accent) !important; color: var(--accent) !important; font-size: 11px !important; font-weight: 700; }
132
+ .issue-type { letter-spacing: .03em; flex-shrink: 0; }
133
+ #issues-panel .issue-actions { margin: 0 0 24px; gap: 6px; }
134
+ #issues-panel .issue-actions button, #issues-panel .issue-comment-actions button { display: inline-flex; align-items: center; justify-content: center; gap: 6px; padding: 7px 10px; border-radius: 7px; font-size: 11px; font-weight: 600; background: var(--bg-alt); color: var(--text-secondary); }
135
+ #issues-panel .issue-actions .lucide { width: 13px; height: 13px; }
136
+ #issues-panel button.issue-primary { border-color: var(--accent); background: var(--accent); color: #fff; }
137
+ #issues-panel button.issue-primary:hover { background: var(--accent-hover, var(--accent)); }
138
+ #issues-panel .issue-actions button.issue-danger { margin-left: auto; color: var(--danger); background: transparent; }
139
+ #issues-panel #issue-form .issue-actions { margin-top: 18px; }
140
+ #issues-panel.panel-fullscreen .issue-detail { padding: clamp(28px, 5vw, 64px); }
141
+ .issues-load-more { padding: 16px; text-align: center; }
142
+ #issues-panel .issues-filters select { height: 36px; max-width: 42%; }
143
+ @media (max-width: 480px) {
144
+ .issues-filters .issues-search { flex-basis: 100%; }
145
+ #issues-panel .issues-filters select { flex: 1; max-width: none; }
146
+ .issue-row-head strong { flex-basis: 100%; }
147
+ #issues-panel .issue-actions button.issue-danger { margin-left: 0; }
148
+ }
@@ -423,6 +423,13 @@
423
423
  .mobile-vendor-list .mobile-session-new-vendor:active {
424
424
  background: rgba(var(--overlay-rgb), 0.1);
425
425
  }
426
+ .mobile-vendor-row { display: flex; align-items: stretch; gap: 4px; }
427
+ .mobile-vendor-row .mobile-session-new-vendor { flex: 1 1 auto; min-width: 0; }
428
+ .mobile-vendor-set-default { border: 1px solid var(--border-subtle); border-radius: 8px; background: transparent; color: var(--text-dimmer); padding: 0 8px; font-size: 11px; white-space: nowrap; }
429
+ .mobile-vendor-set-default:active { background: rgba(var(--overlay-rgb), 0.1); }
430
+ .mobile-vendor-set-default:disabled { opacity: 0.55; }
431
+ .mobile-session-new-preference-status { padding: 4px 8px 8px; color: var(--error); font-size: 11px; }
432
+ .mobile-session-new-fallback-note { color: var(--text-muted); }
426
433
  .mobile-vendor-note {
427
434
  margin-left: auto;
428
435
  font-size: 12px;
@@ -181,7 +181,7 @@
181
181
  margin-top: 8px;
182
182
  }
183
183
  .notif-banner-allow, .notif-banner-always, .notif-banner-deny, .notif-banner-goto,
184
- .notif-banner-tui-open, .notif-banner-tui-goto {
184
+ .notif-banner-tui-open, .notif-banner-tui-goto, .notif-banner-result-open {
185
185
  padding: 4px 10px;
186
186
  border-radius: 6px;
187
187
  font-size: 11px;
@@ -191,11 +191,11 @@
191
191
  border: none;
192
192
  transition: opacity 0.15s, background 0.15s;
193
193
  }
194
- .notif-banner-tui-open {
194
+ .notif-banner-tui-open, .notif-banner-result-open {
195
195
  background: var(--accent, #6c5ce7);
196
196
  color: #fff;
197
197
  }
198
- .notif-banner-tui-open:hover { opacity: 0.85; }
198
+ .notif-banner-tui-open:hover, .notif-banner-result-open:hover { opacity: 0.85; }
199
199
  .notif-banner-tui-goto {
200
200
  background: var(--accent2);
201
201
  border: none;
@@ -196,3 +196,18 @@
196
196
  .project-log-row { padding: 14px 14px 13px; }
197
197
  .project-log-document { padding: 24px 18px 38px; }
198
198
  }
199
+ .project-log-session-button {
200
+ align-self: flex-start;
201
+ display: inline-flex;
202
+ align-items: center;
203
+ gap: 6px;
204
+ margin: 0 0 16px;
205
+ border: 1px solid var(--border);
206
+ border-radius: 8px;
207
+ padding: 7px 10px;
208
+ background: var(--bg-alt);
209
+ color: var(--text);
210
+ cursor: pointer;
211
+ }
212
+
213
+ .project-log-session-button:hover { border-color: var(--accent); }
@@ -1464,6 +1464,13 @@
1464
1464
 
1465
1465
  /* --- New-session vendor picker --- */
1466
1466
  .session-new-menu { min-width: 200px; }
1467
+ .session-new-vendor-row { display: flex; align-items: stretch; }
1468
+ .session-new-vendor-row .session-new-vendor { flex: 1 1 auto; min-width: 0; }
1469
+ .session-new-set-default { border: 0; background: transparent; color: var(--text-dimmer); padding: 0 8px; font-size: 10px; cursor: pointer; }
1470
+ .session-new-set-default:hover { color: var(--text); background: rgba(var(--overlay-rgb), 0.05); }
1471
+ .session-new-set-default:disabled { opacity: 0.55; cursor: wait; }
1472
+ .session-new-preference-status { padding: 6px 10px; color: var(--error); font-size: 11px; }
1473
+ .session-new-fallback-note { color: var(--text-muted); border-bottom: 1px solid var(--border); }
1467
1474
 
1468
1475
  .session-ctx-sep {
1469
1476
  height: 1px;
@@ -764,6 +764,35 @@
764
764
  .notes-browser-card-action:hover { background: var(--bg-alt); color: var(--text); }
765
765
  .notes-browser-card-action:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
766
766
 
767
+ .notes-delete-dialog {
768
+ position: absolute;
769
+ inset: 0;
770
+ z-index: 2;
771
+ display: flex;
772
+ align-items: center;
773
+ justify-content: center;
774
+ padding: 24px;
775
+ background: rgba(var(--shadow-rgb), 0.28);
776
+ }
777
+ .notes-delete-dialog.hidden { display: none; }
778
+ .notes-delete-dialog-card {
779
+ width: min(420px, 100%);
780
+ padding: 20px;
781
+ border: 1px solid var(--border);
782
+ border-radius: 10px;
783
+ background: var(--bg);
784
+ box-shadow: 0 12px 36px rgba(var(--shadow-rgb), 0.24);
785
+ }
786
+ .notes-delete-dialog-card h2 { margin: 0 0 10px; font-size: 16px; }
787
+ .notes-delete-dialog-card p { margin: 8px 0; color: var(--text-secondary); font-size: 12px; }
788
+ .notes-delete-dialog-title { font-weight: 700; color: var(--text) !important; overflow-wrap: anywhere; }
789
+ .notes-delete-dialog-status { min-height: 18px; }
790
+ .notes-delete-dialog-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }
791
+ .notes-delete-dialog-actions button { padding: 7px 12px; border: 1px solid var(--border); border-radius: 6px; background: var(--bg); color: var(--text); font: inherit; cursor: pointer; }
792
+ .notes-delete-dialog-actions button.danger { background: var(--danger, #b42318); border-color: var(--danger, #b42318); color: #fff; }
793
+ .notes-delete-dialog-actions button:disabled { opacity: 0.55; cursor: default; }
794
+ .notes-delete-dialog-actions button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
795
+
767
796
  .notes-browser-card-body {
768
797
  flex: 1;
769
798
  font-size: 11.5px;
@@ -17,6 +17,9 @@ import { resumeHomeChat } from './home-mate-chat.js';
17
17
  import { requestHomeSurfacePreference } from './home-surface.js';
18
18
  import { isHomeDebatesSurface } from './home-sub-surface.js';
19
19
  import { beginDefaultAiConnection, requestDefaultAi } from './default-ai.js';
20
+ import { beginContextViewConnection, requestContextView } from './context-view-preference.js';
21
+ import { beginDefaultVendorConnection, requestDefaultVendor } from './default-vendor.js';
22
+ import { clearProjectSplitState } from './split-session-boundary.js';
20
23
 
21
24
  var reconnectTimer = null;
22
25
  var reconnectDelay = 1000;
@@ -233,7 +236,8 @@ export function connect() {
233
236
 
234
237
  var protocol = location.protocol === "https:" ? "wss:" : "ws:";
235
238
  var socketPath = store.get('wsPath');
236
- store.set({ socketPath: socketPath, activeProjectSlug: null, sessionActivatedProjectSlug: null });
239
+ if (store.get('socketPath') && store.get('socketPath') !== socketPath) clearProjectSplitState();
240
+ store.set({ socketPath: socketPath, activeProjectSlug: null, sessionActivatedProjectSlug: null, sessionListProjectSlug: null, splitGroupsProjectSlug: null });
237
241
  var newWs = new WebSocket(protocol + "//" + location.host + socketPath);
238
242
  setWs(newWs);
239
243
 
@@ -277,6 +281,10 @@ export function connect() {
277
281
  onConnected();
278
282
  beginDefaultAiConnection();
279
283
  requestDefaultAi();
284
+ beginDefaultVendorConnection();
285
+ requestDefaultVendor();
286
+ beginContextViewConnection();
287
+ requestContextView();
280
288
  };
281
289
 
282
290
  newWs.onclose = function (e) {
@@ -194,6 +194,16 @@ export function stopUrgentBlink() {
194
194
  }
195
195
 
196
196
  export function setActivity(text) {
197
+ var thinkingState = store.get('thinkingState');
198
+ if (text === "thinking" && thinkingState && thinkingState.active) {
199
+ // Live Thinking already owns the tail progress UI. Compaction and tool
200
+ // activity intentionally continue through so their distinct states show.
201
+ if (getActivityEl()) {
202
+ getActivityEl().remove();
203
+ setActivityEl(null);
204
+ }
205
+ return;
206
+ }
197
207
  if (text) {
198
208
  if (!getActivityEl()) {
199
209
  var _actEl = document.createElement("div");
@@ -19,6 +19,8 @@ import { refreshMobileChatSheet } from './sidebar-mobile.js';
19
19
  import { renderMateSessionList, handleMateSearchResults, updateMateSidebarProfile } from './mate-sidebar.js';
20
20
  import { openHomeChat, handleHomeMateHistory, handleHomeMateDelta, handleHomeMateSegment, handleHomeMateDone, handleHomeMateError, handleHomeMateSessionsState } from './home-mate-chat.js';
21
21
  import { handleHomeSurfaceState } from './home-surface.js';
22
+ import { handleDefaultVendorMessage } from './default-vendor.js';
23
+ import { handleContextViewMessage } from './context-view-preference.js';
22
24
  import { handleHomeMateMemoryState, handleHomeMateKnowledgeState } from './home-mate-settings.js';
23
25
  import { renderKnowledgeList, handleKnowledgeContent } from './mate-knowledge.js';
24
26
  import { renderMemoryList } from './mate-memory.js';
@@ -44,7 +46,8 @@ import { tuiModalHandleTermOutput, tuiModalHandleTermResized, tuiModalHandleTerm
44
46
  import { updateTerminalList, handleContextSourcesState, updateEmailAccountList, updateEmailUnreadCounts, handleEmailTestResult, handleEmailAddResult, handleEmailRemoveResult } from './context-sources.js';
45
47
  import { refreshEmailSettings } from './user-settings.js';
46
48
  import { handleNotesList, handleNoteCreated, handleNoteUpdated, handleNoteDeleted, handleNoteWritten } from './sticky-notes.js';
47
- import { handleProjectLogsState, handleProjectLogEntry, handleProjectLogCommented, handleProjectLogCommentReviewed, handleProjectLogDeleted, handleProjectLogUpdated, handleProjectLogsError } from './project-logs.js';
49
+ import { handleNoteDeleteResult } from './sticky-notes-browser.js';
50
+ import { handleProjectLogsState, handleProjectLogEntry, handleProjectLogCommented, handleProjectLogCommentReviewed, handleProjectLogDeleted, handleProjectLogUpdated, handleProjectLogsError, handleScheduledTaskResultsState, handleScheduledTaskResultCreated, handleScheduledTaskResultSession } from './project-logs.js';
48
51
  import { handleSkillInstalled, handleSkillUninstalled } from './skills.js';
49
52
  import { showRewindModal, onRewindComplete, setRewindMode, onRewindError, clearPendingRewindUuid, addRewindButton } from './rewind.js';
50
53
  import { checkAdminAccess } from './admin.js';
@@ -63,9 +66,10 @@ import { setStatus } from './app-connection.js';
63
66
  import { handleWhatsNewState, handleWhatsNewSeenResult, setKnownEntries as setWhatsNewKnownEntries } from './whats-new.js';
64
67
  import { closeArticle as closeWhatsNewArticle } from './whats-new-article.js';
65
68
  import { resolvePaneSession, resolveSwitchedVendor } from './pane-session.js';
69
+ import { markProjectSessionListHydrated, applyProjectSplitGroups, clearProjectSplitState } from './split-session-boundary.js';
66
70
  import { selectDefaultVendorForBlankSession } from './vendor-selection.js';
67
71
  import { getModelInfoUpdate, modelEntryValue, modelEntryMatches, handleModelSelectionResult, requestVendorModels } from './model-picker.js';
68
- import { getModelEffortLevels, accumulateUsage, updateUsagePanel, accumulateContext, updateContextPanel, renderCtxPopover, updateStatusPanel } from './app-panels.js';
72
+ import { getModelEffortLevels, accumulateUsage, updateUsagePanel, accumulateContext, updateContextPanel, renderCtxPopover, updateStatusPanel, markContextUnavailable } from './app-panels.js';
69
73
  import { updateProjectList, resetClientState, showUpdateAvailable, handleRemoveProjectCheckResult, handleRemoveProjectResult, handleBrowseDirResult, handleAddProjectResult, handleCloneProgress, finishProjectSessionActivation } from './app-projects.js';
70
74
  import { updateHistorySentinel, prependOlderHistory } from './app-header.js';
71
75
  import { hideHomeHub, showHomeHub } from './app-home-hub.js';
@@ -97,6 +101,8 @@ export function processMessage(msg) {
97
101
  if (handleAutonomousRunMessage(msg)) return;
98
102
  if (handleLoopInterviewMessage(msg)) return;
99
103
  if (handleScheduledTaskMessage(msg)) return;
104
+ if (handleDefaultVendorMessage(msg)) return;
105
+ if (handleContextViewMessage(msg)) return;
100
106
  if (msg && msg.type === "schedule_message_result") {
101
107
  handleScheduleMessageResult(msg);
102
108
  return;
@@ -226,9 +232,8 @@ export function processMessage(msg) {
226
232
  applyDeadSessionTodoCompaction();
227
233
  }
228
234
  // Restore cached rich context usage BEFORE updateContextPanel runs
229
- if (msg.contextUsage) {
230
- store.set({ richContextUsage: msg.contextUsage });
231
- }
235
+ if (msg.contextUsage && !msg.contextUsage.unavailable) store.set({ richContextUsage: msg.contextUsage });
236
+ else markContextUnavailable();
232
237
  // Restore accurate context data from the last result in full history
233
238
  if (msg.lastUsage || msg.lastModelUsage) {
234
239
  accumulateContext(msg.lastCost, msg.lastUsage, msg.lastModelUsage, msg.lastStreamInputTokens);
@@ -330,10 +335,13 @@ export function processMessage(msg) {
330
335
  // start receiving the new project's session_switched. The TUI
331
336
  // host lives on document.body (it's position: fixed), so it
332
337
  // survives project navigation unless we detach explicitly here.
338
+ if (msg.slug && store.get('activeProjectSlug') && store.get('activeProjectSlug') !== msg.slug) {
339
+ clearProjectSplitState();
340
+ }
333
341
  detachTuiView();
334
342
  store.set({ projectName: msg.project || msg.cwd, vendorInfo: msg.vendors || {} });
335
343
  if (msg.cwd) store.set({ cwd: msg.cwd });
336
- if (msg.slug) store.set({ currentSlug: msg.slug, activeProjectSlug: msg.slug });
344
+ if (msg.slug) store.set({ currentSlug: msg.slug, activeProjectSlug: msg.slug, sessionListProjectSlug: null, splitGroupsProjectSlug: null });
337
345
  try { var _is = store.snap(); localStorage.setItem("clay-project-name-" + (_is.currentSlug || "default"), _is.projectName); } catch (e) {}
338
346
  // In mate DM, keep title as mate name and re-apply mate color
339
347
  if (store.get('dmMode') && store.get('dmTargetUser') && store.get('dmTargetUser').isMate) {
@@ -690,6 +698,7 @@ export function processMessage(msg) {
690
698
  break;
691
699
 
692
700
  case "session_list":
701
+ markProjectSessionListHydrated();
693
702
  renderMateSessionList(msg.sessions || []);
694
703
  renderSessionList(msg.sessions || []);
695
704
  syncPaneTitles();
@@ -701,13 +710,14 @@ export function processMessage(msg) {
701
710
  }
702
711
  }
703
712
  handlePaletteSessionSwitch();
713
+ maybeRestoreSplitGroup();
704
714
  break;
705
715
 
706
716
  case "split_groups":
707
- store.set({ splitGroups: msg.groups || [] });
717
+ applyProjectSplitGroups(msg.groups || []);
708
718
  renderSessionList(null);
709
- maybeRestoreSplitGroup();
710
719
  syncPaneTitles();
720
+ maybeRestoreSplitGroup();
711
721
  break;
712
722
 
713
723
  case "split_group_result":
@@ -888,8 +898,8 @@ export function processMessage(msg) {
888
898
  }
889
899
  // Reload survival: a restored active session that is a split-group
890
900
  // member reopens its group (no-op when a split is already open).
891
- maybeRestoreSplitGroup();
892
901
  if (finishProjectSessionActivation()) hideHomeHub();
902
+ maybeRestoreSplitGroup();
893
903
  break;
894
904
 
895
905
  case "session_full_access_changed":
@@ -1044,6 +1054,9 @@ export function processMessage(msg) {
1044
1054
  case "thinking_start":
1045
1055
  removeMatePreThinking();
1046
1056
  startThinking();
1057
+ // The live Thinking entry is the progress affordance while reasoning
1058
+ // is streaming; avoid a second bouncing indicator at the same tail.
1059
+ setActivity(null);
1047
1060
  break;
1048
1061
 
1049
1062
  case "thinking_delta":
@@ -1171,7 +1184,7 @@ export function processMessage(msg) {
1171
1184
 
1172
1185
  case "permission_request":
1173
1186
  setActivity(null);
1174
- renderPermissionRequest(msg.requestId, msg.toolName, msg.toolInput, msg.decisionReason, msg.mateId, msg.vendor);
1187
+ renderPermissionRequest(msg.requestId, msg.toolName, msg.toolInput, msg.decisionReason, msg.mateId, msg.vendor, msg);
1175
1188
  startUrgentBlink();
1176
1189
  break;
1177
1190
 
@@ -1187,7 +1200,7 @@ export function processMessage(msg) {
1187
1200
 
1188
1201
  case "permission_request_pending":
1189
1202
  setActivity(null);
1190
- renderPermissionRequest(msg.requestId, msg.toolName, msg.toolInput, msg.decisionReason, msg.mateId, msg.vendor);
1203
+ renderPermissionRequest(msg.requestId, msg.toolName, msg.toolInput, msg.decisionReason, msg.mateId, msg.vendor, msg);
1191
1204
  startUrgentBlink();
1192
1205
  break;
1193
1206
 
@@ -1271,8 +1284,10 @@ export function processMessage(msg) {
1271
1284
  break;
1272
1285
 
1273
1286
  case "context_usage":
1287
+ if (msg.sessionId != null && msg.sessionId !== store.get("activeSessionId")) break;
1274
1288
  if (msg.data && !store.get('replayingHistory')) {
1275
- store.set({ richContextUsage: msg.data });
1289
+ if (msg.data.unavailable) markContextUnavailable();
1290
+ else store.set({ richContextUsage: msg.data });
1276
1291
  // UI sync handled by store subscriber in app-panels.js
1277
1292
  }
1278
1293
  break;
@@ -1635,6 +1650,10 @@ export function processMessage(msg) {
1635
1650
  handleNoteDeleted(msg);
1636
1651
  break;
1637
1652
 
1653
+ case "note_delete_result":
1654
+ handleNoteDeleteResult(msg);
1655
+ break;
1656
+
1638
1657
  case "project_logs_state":
1639
1658
  handleProjectLogsState(msg);
1640
1659
  break;
@@ -1663,6 +1682,18 @@ export function processMessage(msg) {
1663
1682
  handleProjectLogsError(msg);
1664
1683
  break;
1665
1684
 
1685
+ case "scheduled_task_results_state":
1686
+ handleScheduledTaskResultsState(msg);
1687
+ break;
1688
+
1689
+ case "scheduled_task_result_created":
1690
+ handleScheduledTaskResultCreated(msg);
1691
+ break;
1692
+
1693
+ case "scheduled_task_result_session":
1694
+ handleScheduledTaskResultSession(msg);
1695
+ break;
1696
+
1666
1697
  case "process_stats":
1667
1698
  updateStatusPanel(msg);
1668
1699
  updateSettingsStats(msg);
@@ -1,3 +1,4 @@
1
+ import { applyPermissionHints } from './permission-hints.js';
1
2
  // app-notifications.js - Notification banners (Apple banner style)
2
3
  // New notifications appear as individual banners top-right, auto-dismiss after 3s.
3
4
  // Bell button click shows all stored notifications as banners.
@@ -190,6 +191,7 @@ function showBanner(notif, autoDismissMs) {
190
191
  (!isEmpty ? '<button class="notif-banner-close">' + iconHtml("x") + '</button>' : '');
191
192
 
192
193
  bannerContainer.appendChild(banner);
194
+ if (isPermission) applyPermissionHints(banner, notif.meta);
193
195
  refreshIcons();
194
196
  ensureClearAllButton();
195
197