clay-server 5.3.0-beta.6 → 5.3.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/project-admin-overview.js +22 -11
  2. package/lib/project-background-tasks.js +76 -0
  3. package/lib/project-connection.js +1 -1
  4. package/lib/project-sessions.js +12 -5
  5. package/lib/project-split-views.js +12 -3
  6. package/lib/project-view-store.js +7 -5
  7. package/lib/project-worker-conversation.js +5 -0
  8. package/lib/public/app.js +7 -0
  9. package/lib/public/css/contextual-clay.css +2 -1
  10. package/lib/public/css/mate-conversation.css +1 -1
  11. package/lib/public/css/pending-message-queue.css +24 -19
  12. package/lib/public/css/project-admin-overview.css +42 -13
  13. package/lib/public/css/shared-browser.css +31 -8
  14. package/lib/public/css/split-view-layout.css +92 -7
  15. package/lib/public/css/tool-pane.css +4 -7
  16. package/lib/public/index.html +5 -5
  17. package/lib/public/modules/agent-message-bubbles.js +96 -0
  18. package/lib/public/modules/app-header.js +6 -0
  19. package/lib/public/modules/app-messages.js +26 -9
  20. package/lib/public/modules/background-task-previews.js +8 -0
  21. package/lib/public/modules/background-task-viewer.js +97 -0
  22. package/lib/public/modules/background-tasks-ui.js +34 -125
  23. package/lib/public/modules/chat-bubble-renderer.js +11 -5
  24. package/lib/public/modules/contextual-clay-geometry.js +7 -3
  25. package/lib/public/modules/pane-activation.js +5 -3
  26. package/lib/public/modules/pane-header-tooltips.js +32 -0
  27. package/lib/public/modules/pending-message-queue-drag.js +69 -0
  28. package/lib/public/modules/pending-message-queue.js +3 -33
  29. package/lib/public/modules/permission-control.js +6 -5
  30. package/lib/public/modules/project-admin-overview.js +125 -10
  31. package/lib/public/modules/project-grouping.js +9 -0
  32. package/lib/public/modules/server-settings-controls.js +33 -4
  33. package/lib/public/modules/session-folder-toolbar.js +1 -1
  34. package/lib/public/modules/session-tool-item.js +86 -0
  35. package/lib/public/modules/settings-select.js +2 -1
  36. package/lib/public/modules/shared-browser-tabs.js +37 -21
  37. package/lib/public/modules/sidebar-projects.js +1 -10
  38. package/lib/public/modules/split-session-empty-pane.js +47 -0
  39. package/lib/public/modules/split-view-create-menu.js +74 -65
  40. package/lib/public/modules/split-view-layout-scope.js +4 -0
  41. package/lib/public/modules/split-view-picker-actions.js +71 -0
  42. package/lib/public/modules/split-view-picker-render.js +81 -0
  43. package/lib/public/modules/split-view-presentation-renderer.js +8 -8
  44. package/lib/public/modules/split-view-worker-activity.js +2 -2
  45. package/lib/public/modules/split-view-worker-transcript.js +70 -33
  46. package/lib/public/modules/split-view-workers.js +6 -4
  47. package/lib/public/modules/terminal-viewport.js +14 -0
  48. package/lib/public/modules/terminal.js +3 -4
  49. package/lib/public/modules/theme-palette.js +177 -0
  50. package/lib/public/modules/theme.js +1 -174
  51. package/lib/public/modules/tool-pane-chrome.js +7 -1
  52. package/lib/public/modules/tools.js +5 -89
  53. package/lib/public/modules/tooltip.js +32 -6
  54. package/lib/public/modules/wireframe-workbench.js +2 -2
  55. package/lib/public/modules/worker-message-previews.js +39 -0
  56. package/lib/public/pane-assets/app-5W6KJXK5.js +1 -0
  57. package/lib/public/pane-assets/chunk-2IJUTAB6.js +2 -0
  58. package/lib/public/pane-assets/{chunk-BMHTBRMO.js → chunk-7OVNC5HT.js} +1 -1
  59. package/lib/public/pane-assets/chunk-BQN7B62H.js +3 -0
  60. package/lib/public/pane-assets/{chunk-2AIWCI6Y.js → chunk-EMLN2Y7L.js} +1 -1
  61. package/lib/public/pane-assets/{chunk-VKYBAVWT.js → chunk-ENPAHXLB.js} +1 -1
  62. package/lib/public/pane-assets/chunk-EPBGGZRT.js +1 -0
  63. package/lib/public/pane-assets/chunk-EYTE56IA.js +1 -0
  64. package/lib/public/pane-assets/{chunk-6NYCNWVF.js → chunk-FQTNR4ZS.js} +1 -1
  65. package/lib/public/pane-assets/chunk-L6LSA5WI.js +1 -0
  66. package/lib/public/pane-assets/chunk-M57UIGZV.js +1 -0
  67. package/lib/public/pane-assets/chunk-MGTFTEJP.js +1 -0
  68. package/lib/public/pane-assets/chunk-MMG6MYCN.js +1 -0
  69. package/lib/public/pane-assets/chunk-MZLMEXMW.js +1 -0
  70. package/lib/public/pane-assets/chunk-OG3E5SVA.js +166 -0
  71. package/lib/public/pane-assets/chunk-RGAFZ3T2.js +1 -0
  72. package/lib/public/pane-assets/chunk-RNDRURMF.js +1 -0
  73. package/lib/public/pane-assets/{chunk-PV4PCH2V.js → chunk-SJOT74VW.js} +1 -1
  74. package/lib/public/pane-assets/{chunk-LDIZLKB2.js → chunk-SJTGHIN5.js} +1 -1
  75. package/lib/public/pane-assets/chunk-SLMAFKI2.js +1 -0
  76. package/lib/public/pane-assets/chunk-U3I5KY3B.js +1 -0
  77. package/lib/public/pane-assets/{chunk-VNAV23CM.js → chunk-UPXU2IPC.js} +1 -1
  78. package/lib/public/pane-assets/{chunk-TMGSDFJI.js → chunk-VEBYD7TL.js} +1 -1
  79. package/lib/public/pane-assets/chunk-XBHYNXXT.js +1 -0
  80. package/lib/public/pane-assets/manifest.json +411 -399
  81. package/lib/public/pane-assets/style-BSKKK54Q.css +1 -0
  82. package/lib/sdk-message-processor.js +5 -2
  83. package/lib/server-storage.js +27 -3
  84. package/lib/server.js +4 -2
  85. package/lib/sessions.js +1 -1
  86. package/lib/storage-usage.js +29 -7
  87. package/lib/terminal-manager.js +2 -2
  88. package/lib/worker-message-previews.js +50 -0
  89. package/lib/ws-schema.js +1 -1
  90. package/lib/yoke/adapters/claude-worker.js +8 -0
  91. package/lib/yoke/adapters/claude.js +17 -2
  92. package/lib/yoke/claude-task-reader.js +94 -0
  93. package/lib/yoke/interface.js +1 -0
  94. package/package.json +1 -1
  95. package/lib/public/pane-assets/app-7UZ727NA.js +0 -1
  96. package/lib/public/pane-assets/chunk-6MIHIQ2W.js +0 -1
  97. package/lib/public/pane-assets/chunk-6UJ2ALOB.js +0 -1
  98. package/lib/public/pane-assets/chunk-6XK2OATZ.js +0 -1
  99. package/lib/public/pane-assets/chunk-BKIDR2ME.js +0 -1
  100. package/lib/public/pane-assets/chunk-GEFCFZEN.js +0 -1
  101. package/lib/public/pane-assets/chunk-GN2NQEVC.js +0 -2
  102. package/lib/public/pane-assets/chunk-IMLMBPT4.js +0 -166
  103. package/lib/public/pane-assets/chunk-K5S6AILM.js +0 -1
  104. package/lib/public/pane-assets/chunk-OWNNLZ36.js +0 -1
  105. package/lib/public/pane-assets/chunk-P2C3LOWL.js +0 -3
  106. package/lib/public/pane-assets/chunk-R4LMPTKU.js +0 -1
  107. package/lib/public/pane-assets/chunk-VWTHIQCE.js +0 -1
  108. package/lib/public/pane-assets/chunk-WM3K5AFH.js +0 -1
  109. package/lib/public/pane-assets/chunk-XOB3O327.js +0 -1
  110. package/lib/public/pane-assets/chunk-XOOUCFYT.js +0 -1
  111. package/lib/public/pane-assets/style-ZM7OOU3M.css +0 -1
@@ -0,0 +1,14 @@
1
+ // Attachment snapshots describe the previous PTY size, not the current pane.
2
+ export function hasTerminalViewport(tab) {
3
+ var rect = tab && tab.bodyEl && tab.bodyEl.getBoundingClientRect();
4
+ return !!(rect && rect.width > 0 && rect.height > 0);
5
+ }
6
+
7
+ export function applyTerminalSize(tab, message, active, refit) {
8
+ if (!tab || !tab.xterm || !(message.cols > 0 && message.rows > 0)) return;
9
+ if (message.initial === true && active) {
10
+ if (hasTerminalViewport(tab)) refit();
11
+ return;
12
+ }
13
+ tab.xterm.resize(message.cols, message.rows);
14
+ }
@@ -8,6 +8,7 @@ import { copyToClipboard } from './utils.js';
8
8
  import { getTerminalTheme } from './theme.js';
9
9
  import { getTerminalFontFamily, getTerminalFontSize, onTerminalFontChange } from './terminal-prefs.js';
10
10
  import { createKeyToolbar } from './terminal-toolbar.js';
11
+ import { applyTerminalSize, hasTerminalViewport } from './terminal-viewport.js';
11
12
 
12
13
  var ctx;
13
14
  var tabs = new Map(); // termId -> { id, title, exited, xterm, fitAddon, bodyEl }
@@ -482,7 +483,7 @@ function fitTerminal() {
482
483
  fitRafId = null;
483
484
  if (!activeTabId) return;
484
485
  var tab = tabs.get(activeTabId);
485
- if (!tab || !tab.fitAddon || !tab.xterm) return;
486
+ if (!isOpen || !tab || !tab.fitAddon || !tab.xterm || !hasTerminalViewport(tab)) return;
486
487
 
487
488
  try {
488
489
  tab.fitAddon.fit();
@@ -787,9 +788,7 @@ export function handleTermResized(msg) {
787
788
  handleTerminalProjection(msg);
788
789
  if (!msg.id) return;
789
790
  var tab = tabs.get(msg.id);
790
- if (tab && tab.xterm && msg.cols > 0 && msg.rows > 0) {
791
- tab.xterm.resize(msg.cols, msg.rows);
792
- }
791
+ applyTerminalSize(tab, msg, isOpen && msg.id === activeTabId, fitTerminal);
793
792
  }
794
793
 
795
794
  export function handleTermExited(msg) {
@@ -0,0 +1,177 @@
1
+ // --- Color utilities ---
2
+
3
+ function hexToRgb(hex) {
4
+ var h = hex.replace("#", "");
5
+ return {
6
+ r: parseInt(h.substring(0, 2), 16),
7
+ g: parseInt(h.substring(2, 4), 16),
8
+ b: parseInt(h.substring(4, 6), 16)
9
+ };
10
+ }
11
+
12
+ function rgbToHex(r, g, b) {
13
+ return "#" + [r, g, b].map(function (v) {
14
+ var c = Math.max(0, Math.min(255, Math.round(v)));
15
+ return c.toString(16).padStart(2, "0");
16
+ }).join("");
17
+ }
18
+
19
+ function darken(hex, amount) {
20
+ var c = hexToRgb(hex);
21
+ var f = 1 - amount;
22
+ return rgbToHex(c.r * f, c.g * f, c.b * f);
23
+ }
24
+
25
+ function lighten(hex, amount) {
26
+ var c = hexToRgb(hex);
27
+ return rgbToHex(
28
+ c.r + (255 - c.r) * amount,
29
+ c.g + (255 - c.g) * amount,
30
+ c.b + (255 - c.b) * amount
31
+ );
32
+ }
33
+
34
+ function mixColors(hex1, hex2, weight) {
35
+ var c1 = hexToRgb(hex1);
36
+ var c2 = hexToRgb(hex2);
37
+ var w = weight;
38
+ return rgbToHex(
39
+ c1.r * w + c2.r * (1 - w),
40
+ c1.g * w + c2.g * (1 - w),
41
+ c1.b * w + c2.b * (1 - w)
42
+ );
43
+ }
44
+
45
+ function hexToRgba(hex, alpha) {
46
+ var c = hexToRgb(hex);
47
+ return "rgba(" + c.r + ", " + c.g + ", " + c.b + ", " + alpha + ")";
48
+ }
49
+
50
+ function luminance(hex) {
51
+ var c = hexToRgb(hex);
52
+ return (0.299 * c.r + 0.587 * c.g + 0.114 * c.b) / 255;
53
+ }
54
+
55
+ var DEFAULT_DARK_THEME_ID = "clay-dark";
56
+ var DEFAULT_LIGHT_THEME_ID = "clay-light";
57
+
58
+ // Embedded defaults keep the first render branded before /api/themes loads.
59
+ var defaultDarkFallback = {
60
+ name: "Clay Studio Dark", variant: "dark",
61
+ base00: "171715", base01: "20201D", base02: "393934", base03: "686861",
62
+ base04: "A0A098", base05: "D1D1CA", base06: "E8E8E2", base07: "FAFAF5",
63
+ base08: "FF7479", base09: "7776FF", base0A: "E0B45B", base0B: "07E5A3",
64
+ base0C: "5FD2C0", base0D: "8AA7FF", base0E: "C39AF3", base0F: "D69A7D",
65
+ accent2: "07E5A3", link: "7F7EC8"
66
+ };
67
+
68
+ var defaultLightFallback = {
69
+ name: "Clay Studio Light", variant: "light",
70
+ base00: "F7F7F3", base01: "EEEEEA", base02: "D7D7D0", base03: "A2A29B",
71
+ base04: "73736C", base05: "44443F", base06: "252522", base07: "151513",
72
+ base08: "C84B50", base09: "5857FC", base0A: "956A19", base0B: "087B59",
73
+ base0C: "187A7C", base0D: "3F62B4", base0E: "7A52A8", base0F: "9A5A46",
74
+ accent2: "07E5A3", link: "4948B8"
75
+ };
76
+
77
+ // --- Compute CSS variables from a base16 palette ---
78
+ function computeVars(theme) {
79
+ var b = {};
80
+ var keys = ["base00","base01","base02","base03","base04","base05","base06","base07",
81
+ "base08","base09","base0A","base0B","base0C","base0D","base0E","base0F"];
82
+ for (var i = 0; i < keys.length; i++) {
83
+ b[keys[i]] = "#" + theme[keys[i]];
84
+ }
85
+
86
+ var isLight = theme.variant === "light";
87
+ var accent2 = theme.accent2 ? "#" + theme.accent2 : b.base0D;
88
+ var link = theme.link ? "#" + theme.link : b.base0D;
89
+
90
+ return {
91
+ "--bg": b.base00,
92
+ "--bg-alt": b.base01,
93
+ "--text": b.base06,
94
+ "--text-secondary": b.base05,
95
+ "--text-muted": b.base04,
96
+ "--text-dimmer": b.base03,
97
+ "--accent": b.base09,
98
+ "--accent-hover": isLight ? darken(b.base09, 0.12) : lighten(b.base09, 0.12),
99
+ "--accent-bg": hexToRgba(b.base09, 0.12),
100
+ "--link": link,
101
+ "--link-hover": isLight ? darken(link, 0.10) : lighten(link, 0.10),
102
+ "--code-bg": isLight ? darken(b.base00, 0.03) : darken(b.base00, 0.15),
103
+ "--border": b.base02,
104
+ "--border-subtle": mixColors(b.base00, b.base02, 0.6),
105
+ "--input-bg": isLight ? darken(b.base00, 0.04) : mixColors(b.base01, b.base02, 0.5),
106
+ "--ask-mate-bg": isLight ? mixColors("#ffffff", darken(b.base00, 0.04), 0.6) : mixColors(b.base00, mixColors(b.base01, b.base02, 0.5), 0.6),
107
+ "--user-bubble": isLight ? darken(b.base01, 0.03) : mixColors(b.base01, b.base02, 0.3),
108
+ "--error": b.base08,
109
+ "--success": b.base0B,
110
+ "--warning": b.base0A,
111
+ "--sidebar-bg": isLight ? darken(b.base00, 0.02) : darken(b.base00, 0.10),
112
+ "--sidebar-hover": isLight ? darken(b.base00, 0.06) : mixColors(b.base00, b.base01, 0.5),
113
+ "--sidebar-active": isLight ? darken(b.base01, 0.05) : mixColors(b.base01, b.base02, 0.5),
114
+ "--filebrowser-bg": isLight ? lighten(b.base00, 0.03) : lighten(b.base00, 0.04),
115
+ "--filebrowser-border": isLight ? darken(b.base00, 0.08) : mixColors(b.base02, b.base00, 0.5),
116
+ "--accent-8": hexToRgba(b.base09, 0.08),
117
+ "--accent-12": hexToRgba(b.base09, 0.12),
118
+ "--accent-15": hexToRgba(b.base09, 0.15),
119
+ "--accent-20": hexToRgba(b.base09, 0.20),
120
+ "--accent-25": hexToRgba(b.base09, 0.25),
121
+ "--accent-30": hexToRgba(b.base09, 0.30),
122
+ "--accent2": accent2,
123
+ "--accent2-hover": isLight ? darken(accent2, 0.12) : lighten(accent2, 0.12),
124
+ "--accent2-bg": hexToRgba(accent2, 0.12),
125
+ "--accent2-8": hexToRgba(accent2, 0.08),
126
+ "--accent2-12": hexToRgba(accent2, 0.12),
127
+ "--accent2-15": hexToRgba(accent2, 0.15),
128
+ "--accent2-20": hexToRgba(accent2, 0.20),
129
+ "--accent2-25": hexToRgba(accent2, 0.25),
130
+ "--accent2-30": hexToRgba(accent2, 0.30),
131
+ "--error-8": hexToRgba(b.base08, 0.08),
132
+ "--error-12": hexToRgba(b.base08, 0.12),
133
+ "--error-15": hexToRgba(b.base08, 0.15),
134
+ "--error-25": hexToRgba(b.base08, 0.25),
135
+ "--success-8": hexToRgba(b.base0B, 0.08),
136
+ "--success-12": hexToRgba(b.base0B, 0.12),
137
+ "--success-15": hexToRgba(b.base0B, 0.15),
138
+ "--success-25": hexToRgba(b.base0B, 0.25),
139
+ "--warning-bg": hexToRgba(b.base0A, 0.12),
140
+ "--overlay-rgb": isLight ? "0,0,0" : "255,255,255",
141
+ "--shadow-rgb": "0,0,0",
142
+ "--hl-comment": b.base03,
143
+ "--hl-keyword": b.base0E,
144
+ "--hl-string": b.base0B,
145
+ "--hl-number": b.base09,
146
+ "--hl-function": b.base0D,
147
+ "--hl-variable": b.base08,
148
+ "--hl-type": b.base0A,
149
+ "--hl-constant": b.base09,
150
+ "--hl-tag": b.base08,
151
+ "--hl-attr": b.base0D,
152
+ "--hl-regexp": b.base0C,
153
+ "--hl-meta": b.base0F,
154
+ "--hl-builtin": b.base09,
155
+ "--hl-symbol": b.base0F,
156
+ "--hl-addition": b.base0B,
157
+ "--hl-deletion": b.base08
158
+ };
159
+ }
160
+
161
+ function validateTheme(t) {
162
+ if (!t || typeof t !== "object") return false;
163
+ if (!t.name || typeof t.name !== "string") return false;
164
+ var keys = ["base00","base01","base02","base03","base04","base05","base06","base07",
165
+ "base08","base09","base0A","base0B","base0C","base0D","base0E","base0F"];
166
+ for (var i = 0; i < keys.length; i++) {
167
+ if (!t[keys[i]] || !/^[0-9a-fA-F]{6}$/.test(t[keys[i]])) return false;
168
+ }
169
+ if (t.variant && t.variant !== "dark" && t.variant !== "light") return false;
170
+ if (!t.variant) {
171
+ t.variant = luminance("#" + t.base00) > 0.5 ? "light" : "dark";
172
+ }
173
+ return true;
174
+ }
175
+
176
+
177
+ export { hexToRgb, rgbToHex, darken, lighten, mixColors, hexToRgba, luminance, computeVars, validateTheme, defaultDarkFallback, defaultLightFallback, DEFAULT_DARK_THEME_ID, DEFAULT_LIGHT_THEME_ID };
@@ -5,165 +5,7 @@ import { setTuiSessionTheme } from './session-tui-view.js';
5
5
  import { setTuiAttentionTheme } from './tui-attention.js';
6
6
  import { updateMermaidTheme } from './markdown.js';
7
7
 
8
- // --- Color utilities ---
9
-
10
- function hexToRgb(hex) {
11
- var h = hex.replace("#", "");
12
- return {
13
- r: parseInt(h.substring(0, 2), 16),
14
- g: parseInt(h.substring(2, 4), 16),
15
- b: parseInt(h.substring(4, 6), 16)
16
- };
17
- }
18
-
19
- function rgbToHex(r, g, b) {
20
- return "#" + [r, g, b].map(function (v) {
21
- var c = Math.max(0, Math.min(255, Math.round(v)));
22
- return c.toString(16).padStart(2, "0");
23
- }).join("");
24
- }
25
-
26
- function darken(hex, amount) {
27
- var c = hexToRgb(hex);
28
- var f = 1 - amount;
29
- return rgbToHex(c.r * f, c.g * f, c.b * f);
30
- }
31
-
32
- function lighten(hex, amount) {
33
- var c = hexToRgb(hex);
34
- return rgbToHex(
35
- c.r + (255 - c.r) * amount,
36
- c.g + (255 - c.g) * amount,
37
- c.b + (255 - c.b) * amount
38
- );
39
- }
40
-
41
- function mixColors(hex1, hex2, weight) {
42
- var c1 = hexToRgb(hex1);
43
- var c2 = hexToRgb(hex2);
44
- var w = weight;
45
- return rgbToHex(
46
- c1.r * w + c2.r * (1 - w),
47
- c1.g * w + c2.g * (1 - w),
48
- c1.b * w + c2.b * (1 - w)
49
- );
50
- }
51
-
52
- function hexToRgba(hex, alpha) {
53
- var c = hexToRgb(hex);
54
- return "rgba(" + c.r + ", " + c.g + ", " + c.b + ", " + alpha + ")";
55
- }
56
-
57
- function luminance(hex) {
58
- var c = hexToRgb(hex);
59
- return (0.299 * c.r + 0.587 * c.g + 0.114 * c.b) / 255;
60
- }
61
-
62
- var DEFAULT_DARK_THEME_ID = "clay-dark";
63
- var DEFAULT_LIGHT_THEME_ID = "clay-light";
64
-
65
- // Embedded defaults keep the first render branded before /api/themes loads.
66
- var defaultDarkFallback = {
67
- name: "Clay Studio Dark", variant: "dark",
68
- base00: "171715", base01: "20201D", base02: "393934", base03: "686861",
69
- base04: "A0A098", base05: "D1D1CA", base06: "E8E8E2", base07: "FAFAF5",
70
- base08: "FF7479", base09: "7776FF", base0A: "E0B45B", base0B: "07E5A3",
71
- base0C: "5FD2C0", base0D: "8AA7FF", base0E: "C39AF3", base0F: "D69A7D",
72
- accent2: "07E5A3", link: "7F7EC8"
73
- };
74
-
75
- var defaultLightFallback = {
76
- name: "Clay Studio Light", variant: "light",
77
- base00: "F7F7F3", base01: "EEEEEA", base02: "D7D7D0", base03: "A2A29B",
78
- base04: "73736C", base05: "44443F", base06: "252522", base07: "151513",
79
- base08: "C84B50", base09: "5857FC", base0A: "956A19", base0B: "087B59",
80
- base0C: "187A7C", base0D: "3F62B4", base0E: "7A52A8", base0F: "9A5A46",
81
- accent2: "07E5A3", link: "4948B8"
82
- };
83
-
84
- // --- Compute CSS variables from a base16 palette ---
85
- function computeVars(theme) {
86
- var b = {};
87
- var keys = ["base00","base01","base02","base03","base04","base05","base06","base07",
88
- "base08","base09","base0A","base0B","base0C","base0D","base0E","base0F"];
89
- for (var i = 0; i < keys.length; i++) {
90
- b[keys[i]] = "#" + theme[keys[i]];
91
- }
92
-
93
- var isLight = theme.variant === "light";
94
- var accent2 = theme.accent2 ? "#" + theme.accent2 : b.base0D;
95
- var link = theme.link ? "#" + theme.link : b.base0D;
96
-
97
- return {
98
- "--bg": b.base00,
99
- "--bg-alt": b.base01,
100
- "--text": b.base06,
101
- "--text-secondary": b.base05,
102
- "--text-muted": b.base04,
103
- "--text-dimmer": b.base03,
104
- "--accent": b.base09,
105
- "--accent-hover": isLight ? darken(b.base09, 0.12) : lighten(b.base09, 0.12),
106
- "--accent-bg": hexToRgba(b.base09, 0.12),
107
- "--link": link,
108
- "--link-hover": isLight ? darken(link, 0.10) : lighten(link, 0.10),
109
- "--code-bg": isLight ? darken(b.base00, 0.03) : darken(b.base00, 0.15),
110
- "--border": b.base02,
111
- "--border-subtle": mixColors(b.base00, b.base02, 0.6),
112
- "--input-bg": isLight ? darken(b.base00, 0.04) : mixColors(b.base01, b.base02, 0.5),
113
- "--ask-mate-bg": isLight ? mixColors("#ffffff", darken(b.base00, 0.04), 0.6) : mixColors(b.base00, mixColors(b.base01, b.base02, 0.5), 0.6),
114
- "--user-bubble": isLight ? darken(b.base01, 0.03) : mixColors(b.base01, b.base02, 0.3),
115
- "--error": b.base08,
116
- "--success": b.base0B,
117
- "--warning": b.base0A,
118
- "--sidebar-bg": isLight ? darken(b.base00, 0.02) : darken(b.base00, 0.10),
119
- "--sidebar-hover": isLight ? darken(b.base00, 0.06) : mixColors(b.base00, b.base01, 0.5),
120
- "--sidebar-active": isLight ? darken(b.base01, 0.05) : mixColors(b.base01, b.base02, 0.5),
121
- "--filebrowser-bg": isLight ? lighten(b.base00, 0.03) : lighten(b.base00, 0.04),
122
- "--filebrowser-border": isLight ? darken(b.base00, 0.08) : mixColors(b.base02, b.base00, 0.5),
123
- "--accent-8": hexToRgba(b.base09, 0.08),
124
- "--accent-12": hexToRgba(b.base09, 0.12),
125
- "--accent-15": hexToRgba(b.base09, 0.15),
126
- "--accent-20": hexToRgba(b.base09, 0.20),
127
- "--accent-25": hexToRgba(b.base09, 0.25),
128
- "--accent-30": hexToRgba(b.base09, 0.30),
129
- "--accent2": accent2,
130
- "--accent2-hover": isLight ? darken(accent2, 0.12) : lighten(accent2, 0.12),
131
- "--accent2-bg": hexToRgba(accent2, 0.12),
132
- "--accent2-8": hexToRgba(accent2, 0.08),
133
- "--accent2-12": hexToRgba(accent2, 0.12),
134
- "--accent2-15": hexToRgba(accent2, 0.15),
135
- "--accent2-20": hexToRgba(accent2, 0.20),
136
- "--accent2-25": hexToRgba(accent2, 0.25),
137
- "--accent2-30": hexToRgba(accent2, 0.30),
138
- "--error-8": hexToRgba(b.base08, 0.08),
139
- "--error-12": hexToRgba(b.base08, 0.12),
140
- "--error-15": hexToRgba(b.base08, 0.15),
141
- "--error-25": hexToRgba(b.base08, 0.25),
142
- "--success-8": hexToRgba(b.base0B, 0.08),
143
- "--success-12": hexToRgba(b.base0B, 0.12),
144
- "--success-15": hexToRgba(b.base0B, 0.15),
145
- "--success-25": hexToRgba(b.base0B, 0.25),
146
- "--warning-bg": hexToRgba(b.base0A, 0.12),
147
- "--overlay-rgb": isLight ? "0,0,0" : "255,255,255",
148
- "--shadow-rgb": "0,0,0",
149
- "--hl-comment": b.base03,
150
- "--hl-keyword": b.base0E,
151
- "--hl-string": b.base0B,
152
- "--hl-number": b.base09,
153
- "--hl-function": b.base0D,
154
- "--hl-variable": b.base08,
155
- "--hl-type": b.base0A,
156
- "--hl-constant": b.base09,
157
- "--hl-tag": b.base08,
158
- "--hl-attr": b.base0D,
159
- "--hl-regexp": b.base0C,
160
- "--hl-meta": b.base0F,
161
- "--hl-builtin": b.base09,
162
- "--hl-symbol": b.base0F,
163
- "--hl-addition": b.base0B,
164
- "--hl-deletion": b.base08
165
- };
166
- }
8
+ import { hexToRgb, rgbToHex, darken, lighten, mixColors, hexToRgba, luminance, computeVars, validateTheme, defaultDarkFallback, defaultLightFallback, DEFAULT_DARK_THEME_ID, DEFAULT_LIGHT_THEME_ID } from './theme-palette.js';
167
9
 
168
10
  var defaultExactVars = computeVars(defaultDarkFallback);
169
11
 
@@ -396,21 +238,6 @@ function loadThemes() {
396
238
  });
397
239
  }
398
240
 
399
- function validateTheme(t) {
400
- if (!t || typeof t !== "object") return false;
401
- if (!t.name || typeof t.name !== "string") return false;
402
- var keys = ["base00","base01","base02","base03","base04","base05","base06","base07",
403
- "base08","base09","base0A","base0B","base0C","base0D","base0E","base0F"];
404
- for (var i = 0; i < keys.length; i++) {
405
- if (!t[keys[i]] || !/^[0-9a-fA-F]{6}$/.test(t[keys[i]])) return false;
406
- }
407
- if (t.variant && t.variant !== "dark" && t.variant !== "light") return false;
408
- if (!t.variant) {
409
- t.variant = luminance("#" + t.base00) > 0.5 ? "light" : "dark";
410
- }
411
- return true;
412
- }
413
-
414
241
  // --- Light / Dark mode toggle ---
415
242
 
416
243
  // Returns the system preferred mode
@@ -31,7 +31,13 @@ export function renderToolPaneChrome(panel, name) {
31
31
  var actions = original.querySelector('.terminal-header-actions, .shared-browser-window, .file-viewer-window-actions');
32
32
  header.append(kind, title, space); if (actions) header.appendChild(actions);
33
33
  panel.insertBefore(header, panel.firstChild);
34
- if (name === 'browser') { original.hidden = true; var close = header.querySelector('[data-action="hide"]'); if (close) { close.title = 'Close browser pane'; close.setAttribute('aria-label', 'Close browser pane'); } }
34
+ if (name === 'browser') {
35
+ header.classList.add('browser-pane-header');
36
+ var tabs = panel.querySelector('.shared-browser-tabs');
37
+ if (tabs) header.insertBefore(tabs, space);
38
+ kind.setAttribute('aria-label', 'Browser'); kind.setAttribute('data-tip', 'Browser');
39
+ original.hidden = true; var close = header.querySelector('[data-action="hide"]'); if (close) { close.title = 'Close browser pane'; close.setAttribute('aria-label', 'Close browser pane'); }
40
+ }
35
41
  else original.classList.add('tool-pane-tab-row');
36
42
  var observer = new MutationObserver(function () { update(); });
37
43
  observer.observe(panel, { childList: true, characterData: true, subtree: true, attributes: true, attributeFilter: ['aria-selected'] });
@@ -1,5 +1,5 @@
1
+ import { createSessionToolItem, createSessionToolGroup, sessionToolGroupSummary } from './session-tool-item.js';
1
2
  import { renderProductReview } from './product-review.js';
2
- import { clayToolGroupSummary } from './clay-tool-presentation.js';
3
3
  import { applyClayToolItem, applyClayToolResult, finishClayToolItem, findEndedClayTool, clayToolResultGroup, bindToolGroupDisclosure, syncToolGroupDisclosure, syncClayToolGroup } from './clay-tool-activity.js';
4
4
  import { rememberMountedToolGroup, mountedToolGroup, transcriptToolGroups, popupChatRenderingEnabled, popupChatRenderingActive, syncPopupActivityGroup, syncPopupChatToolGroups as syncPopupGroups } from './popup-chat-rendering.js';
5
5
  import { escapeHtml, copyToClipboard } from './utils.js';
@@ -80,61 +80,12 @@ function findToolGroup(groupId) {
80
80
  return toolGroups[groupId] || null;
81
81
  }
82
82
 
83
- function toolGroupSummary(group) {
84
- var claySummary = clayToolGroupSummary(group, tools);
85
- if (claySummary) return claySummary;
86
- var names = group.toolNames;
87
- var count = names.length;
88
- var allDone = group.doneCount >= count;
89
-
90
- // Count by tool name
91
- var counts = {};
92
- for (var i = 0; i < names.length; i++) {
93
- counts[names[i]] = (counts[names[i]] || 0) + 1;
94
- }
95
- var uniqueNames = Object.keys(counts);
96
-
97
- if (uniqueNames.length === 1) {
98
- var name = uniqueNames[0];
99
- var n = counts[name];
100
- if (allDone) {
101
- switch (name) {
102
- case "Read": return "Read " + n + " file" + (n > 1 ? "s" : "");
103
- case "Edit": return "Edited " + n + " file" + (n > 1 ? "s" : "");
104
- case "Write": return "Wrote " + n + " file" + (n > 1 ? "s" : "");
105
- case "Bash": return "Ran " + n + " command" + (n > 1 ? "s" : "");
106
- case "Grep": return "Searched " + n + " pattern" + (n > 1 ? "s" : "");
107
- case "Glob": return "Found " + n + " pattern" + (n > 1 ? "s" : "");
108
- case "Task": return "Ran " + n + " task" + (n > 1 ? "s" : "");
109
- case "WebSearch": return "Searched " + n + " quer" + (n > 1 ? "ies" : "y");
110
- case "WebFetch": return "Fetched " + n + " URL" + (n > 1 ? "s" : "");
111
- default: return "Ran " + n + " tool" + (n > 1 ? "s" : "");
112
- }
113
- }
114
- switch (name) {
115
- case "Read": return "Reading " + n + " file" + (n > 1 ? "s" : "") + "...";
116
- case "Edit": return "Editing " + n + " file" + (n > 1 ? "s" : "") + "...";
117
- case "Write": return "Writing " + n + " file" + (n > 1 ? "s" : "") + "...";
118
- case "Bash": return "Running " + n + " command" + (n > 1 ? "s" : "") + "...";
119
- case "Grep": return "Searching " + n + " pattern" + (n > 1 ? "s" : "") + "...";
120
- case "Glob": return "Finding " + n + " pattern" + (n > 1 ? "s" : "") + "...";
121
- case "Task": return "Running " + n + " task" + (n > 1 ? "s" : "") + "...";
122
- case "WebSearch": return "Searching " + n + " quer" + (n > 1 ? "ies" : "y") + "...";
123
- case "WebFetch": return "Fetching " + n + " URL" + (n > 1 ? "s" : "") + "...";
124
- default: return "Running " + n + " tool" + (n > 1 ? "s" : "") + "...";
125
- }
126
- }
127
-
128
- // Mixed tools
129
- if (allDone) return "Ran " + count + " tools";
130
- return "Running " + count + " tools...";
131
- }
132
83
 
133
84
  function updateToolGroupHeader(group) {
134
85
  if (!group || !group.el) return;
135
86
  var popupChat = group.popupChat && popupChatRenderingActive();
136
87
  var label = group.el.querySelector(".tool-group-label");
137
- var summary = toolGroupSummary(group);
88
+ var summary = sessionToolGroupSummary(group, tools);
138
89
  if (label && !popupChat) label.textContent = summary;
139
90
 
140
91
  var allDone = group.doneCount >= group.toolCount;
@@ -1644,31 +1595,12 @@ export function createToolItem(id, name) {
1644
1595
  // Group management: create new group or reuse existing open group
1645
1596
  if (!currentToolGroup || currentToolGroup.closed) {
1646
1597
  toolGroupCounter++;
1647
- var groupEl = document.createElement("div");
1648
- groupEl.className = "tool-group";
1649
1598
  var identity = resolveProjectAssistantIdentity();
1650
1599
  var isMateToolGroup = identity.kind === 'mate';
1651
- if (isMateToolGroup) groupEl.classList.add("mate-tool-group");
1600
+ var groupEl = createSessionToolGroup(isMateToolGroup ? identity.avatarUrl : null);
1601
+ if (isMateToolGroup) groupEl.classList.add('mate-tool-group');
1652
1602
  groupEl.dataset.groupId = "g" + toolGroupCounter;
1653
1603
 
1654
- var toolGroupInner =
1655
- '<div class="tool-group-header" style="display:none">' +
1656
- '<span class="tool-group-chevron">' + iconHtml("chevron-right") + '</span>' +
1657
- '<span class="tool-group-bullet"></span>' +
1658
- '<span class="tool-group-label">Running...</span>' +
1659
- '<span class="tool-group-status-icon">' + iconHtml("loader", "icon-spin") + '</span>' +
1660
- '</div>' +
1661
- '<div class="tool-group-items"></div>';
1662
-
1663
- if (isMateToolGroup) {
1664
- var mateAvatar = identity.avatarUrl;
1665
- groupEl.innerHTML =
1666
- '<img class="dm-bubble-avatar dm-bubble-avatar-mate" src="' + escapeHtml(mateAvatar) + '" alt="">' +
1667
- '<div class="dm-bubble-content">' + toolGroupInner + '</div>';
1668
- } else {
1669
- groupEl.innerHTML = toolGroupInner;
1670
- }
1671
-
1672
1604
  applyProjectAssistantIdentity(groupEl, identity);
1673
1605
  bindToolGroupDisclosure(groupEl, function () {
1674
1606
  var group = mountedToolGroup(groupEl);
@@ -1694,23 +1626,7 @@ export function createToolItem(id, name) {
1694
1626
  rememberMountedToolGroup(currentToolGroup);
1695
1627
  }
1696
1628
 
1697
- var el = document.createElement("div");
1698
- el.className = "tool-item";
1699
- el.dataset.toolId = id;
1700
- el.innerHTML =
1701
- '<div class="tool-header">' +
1702
- '<span class="tool-chevron">' + iconHtml("chevron-right") + '</span>' +
1703
- '<span class="tool-bullet"></span>' +
1704
- '<span class="tool-name"></span>' +
1705
- '<span class="tool-desc"></span>' +
1706
- '<span class="tool-status-icon">' + iconHtml("loader", "icon-spin") + '</span>' +
1707
- '</div>' +
1708
- '<div class="tool-subtitle">' +
1709
- '<span class="tool-connector">&#9492;</span>' +
1710
- '<span class="tool-subtitle-text">Running...</span>' +
1711
- '</div>';
1712
-
1713
- el.querySelector(".tool-name").textContent = name;
1629
+ var el = createSessionToolItem(id, name);
1714
1630
 
1715
1631
  tools[id] = { el: el, name: name, input: null, done: false, groupId: currentToolGroup.id };
1716
1632
  applyClayToolItem(tools[id]);
@@ -1,3 +1,5 @@
1
+ import { initPaneHeaderTooltips } from './pane-header-tooltips.js';
2
+
1
3
  // --- Global JS tooltip system ---
2
4
  // Unified tooltip using [data-tip] attribute.
3
5
  // Usage: initTooltips() auto-binds, converts [title] to [data-tip].
@@ -9,13 +11,15 @@ var SHOW_DELAY = 120;
9
11
  var currentTarget = null;
10
12
 
11
13
  function initTooltips() {
14
+ if (tooltipEl) return;
12
15
  // Create singleton tooltip element
13
16
  tooltipEl = document.createElement("div");
14
- tooltipEl.className = "tooltip";
17
+ tooltipEl.className = "tooltip"; tooltipEl.id = "clay-tooltip"; tooltipEl.setAttribute("role", "tooltip"); tooltipEl.setAttribute("aria-hidden", "true");
15
18
  document.body.appendChild(tooltipEl);
16
19
 
17
20
  // Convert existing title attributes to data-tip in target areas
18
21
  convertTitles();
22
+ initPaneHeaderTooltips();
19
23
 
20
24
  // Delegate hover events on document for [data-tip]
21
25
  document.addEventListener("mouseover", function (e) {
@@ -34,6 +38,13 @@ function initTooltips() {
34
38
  hideTooltip();
35
39
  });
36
40
 
41
+ document.addEventListener("focusin", function (event) {
42
+ var target = event.target.closest("[data-tip], [data-tip-html]");
43
+ if (target) scheduleShow(target);
44
+ });
45
+ document.addEventListener("focusout", function () { cancelShow(); hideTooltip(); });
46
+ document.addEventListener("keydown", function (event) { if (event.key === "Escape") { cancelShow(); hideTooltip(); } });
47
+ window.addEventListener("blur", function () { cancelShow(); hideTooltip(); });
37
48
  document.addEventListener("pointerdown", function () {
38
49
  cancelShow();
39
50
  hideTooltip();
@@ -58,8 +69,8 @@ function convertTitles() {
58
69
  var el = els[i];
59
70
  if (!el.getAttribute("data-tip")) {
60
71
  el.setAttribute("data-tip", el.getAttribute("title"));
61
- el.removeAttribute("title");
62
72
  }
73
+ el.removeAttribute("title");
63
74
  }
64
75
  }
65
76
 
@@ -83,17 +94,23 @@ function cancelShow() {
83
94
  }
84
95
 
85
96
  function showTooltipAt(target) {
86
- if (!tooltipEl) return;
97
+ if (!tooltipEl || !target.isConnected || !target.getClientRects().length) return;
98
+ // A message preview already describes this Worker/task tab.
99
+ if (target.getAttribute('aria-describedby') === 'agent-message-bubble' && document.getElementById('agent-message-bubble')) return;
87
100
  // Suppress tooltip when an associated popover/picker is open
88
101
  var suppressSel = target.getAttribute("data-tip-suppress-when-open");
89
102
  if (suppressSel) {
90
103
  var openEl = document.querySelector(suppressSel);
91
- if (openEl && !openEl.classList.contains("hidden")) return;
104
+ if (openEl && !openEl.hidden && !openEl.classList.contains("hidden")) return;
92
105
  }
93
106
  var html = target.getAttribute("data-tip-html");
94
107
  var text = target.getAttribute("data-tip");
95
108
  if (!html && !text) return;
109
+ if (currentTarget && currentTarget !== target) hideTooltip();
96
110
  currentTarget = target;
111
+ var described = (target.getAttribute('aria-describedby') || '').split(/\s+/).filter(Boolean);
112
+ if (described.indexOf('clay-tooltip') < 0) described.push('clay-tooltip');
113
+ target.setAttribute('aria-describedby', described.join(' '));
97
114
 
98
115
  if (html) {
99
116
  tooltipEl.innerHTML = html;
@@ -113,6 +130,7 @@ function showTooltipAt(target) {
113
130
  tooltipEl.style.top = "-9999px";
114
131
  tooltipEl.style.left = "0";
115
132
  tooltipEl.style.right = "";
133
+ tooltipEl.setAttribute("aria-hidden", "false");
116
134
  tooltipEl.classList.add("visible");
117
135
 
118
136
  // Position after layout
@@ -144,9 +162,17 @@ function showTooltipAt(target) {
144
162
 
145
163
  function hideTooltip() {
146
164
  if (tooltipEl) {
147
- tooltipEl.classList.remove("visible");
165
+ tooltipEl.classList.remove("visible"); tooltipEl.setAttribute("aria-hidden", "true");
166
+ }
167
+ if (currentTarget) {
168
+ var described = (currentTarget.getAttribute('aria-describedby') || '').split(/\s+/).filter(function (id) { return id && id !== 'clay-tooltip'; });
169
+ if (described.length) currentTarget.setAttribute('aria-describedby', described.join(' ')); else currentTarget.removeAttribute('aria-describedby');
148
170
  }
149
171
  currentTarget = null;
150
172
  }
151
173
 
152
- export { initTooltips, registerTooltip };
174
+ function pruneTooltip() { if (currentTarget && (!currentTarget.isConnected || !currentTarget.getClientRects().length)) { cancelShow(); hideTooltip(); } }
175
+
176
+ function dismissTooltip() { cancelShow(); hideTooltip(); }
177
+
178
+ export { initTooltips, registerTooltip, pruneTooltip, dismissTooltip };