clay-server 5.1.0-beta.1 → 6.0.0-beta.1

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 (222) hide show
  1. package/LICENSES/README.md +4 -0
  2. package/LICENSES/dicebear-avatars.md +16 -0
  3. package/bin/cli.js +9 -91
  4. package/lib/daemon-project-access.js +7 -1
  5. package/lib/daemon-settings.js +11 -0
  6. package/lib/daemon.js +10 -37
  7. package/lib/dicebear-avatar.js +62 -0
  8. package/lib/knowledge-db-service.js +175 -0
  9. package/lib/knowledge-db-validation.js +0 -0
  10. package/lib/knowledge-document-index.js +49 -0
  11. package/lib/knowledge-draft-store.js +56 -0
  12. package/lib/knowledge-file-store.js +199 -0
  13. package/lib/knowledge-markdown.js +128 -0
  14. package/lib/linear-store.js +35 -8
  15. package/lib/mate-knowledge-mcp-server.js +29 -6
  16. package/lib/mate-knowledge-service.js +23 -2
  17. package/lib/mate-knowledge-sync.js +36 -21
  18. package/lib/mate-workspace-color.js +4 -0
  19. package/lib/mates.js +18 -0
  20. package/lib/os-users.js +5 -16
  21. package/lib/project-connection.js +36 -9
  22. package/lib/project-debate-proposal.js +6 -0
  23. package/lib/project-debate-workspace.js +43 -0
  24. package/lib/project-debate.js +1 -0
  25. package/lib/project-filesystem.js +21 -39
  26. package/lib/project-knowledge.js +315 -136
  27. package/lib/project-mate-creation-proposal.js +1 -0
  28. package/lib/project-mate-interaction.js +2 -2
  29. package/lib/project-server-settings.js +31 -0
  30. package/lib/project-sessions.js +92 -182
  31. package/lib/project-user-knowledge.js +60 -0
  32. package/lib/project.js +59 -18
  33. package/lib/public/app.js +79 -71
  34. package/lib/public/clay-studio-wordmark-bold.svg +20 -0
  35. package/lib/public/css/clay-workspace.css +105 -0
  36. package/lib/public/css/debates-workbench.css +47 -0
  37. package/lib/public/css/home-debate-live.css +26 -0
  38. package/lib/public/css/home-hub.css +3 -1
  39. package/lib/public/css/home-mate-model-picker.css +15 -131
  40. package/lib/public/css/home-mate-settings.css +168 -16
  41. package/lib/public/css/icon-strip.css +249 -32
  42. package/lib/public/css/input.css +3 -1
  43. package/lib/public/css/mate-conversation.css +176 -0
  44. package/lib/public/css/mate-knowledge-workbench.css +118 -0
  45. package/lib/public/css/mate-workspace-color.css +16 -0
  46. package/lib/public/css/mates.css +28 -28
  47. package/lib/public/css/messages.css +1 -114
  48. package/lib/public/css/mobile-nav.css +16 -16
  49. package/lib/public/css/overlays.css +8 -0
  50. package/lib/public/css/project-logs.css +7 -0
  51. package/lib/public/css/project-mate-creation.css +105 -0
  52. package/lib/public/css/project-settings-modal.css +56 -0
  53. package/lib/public/css/right-workbench.css +3 -3
  54. package/lib/public/css/server-settings-system.css +125 -0
  55. package/lib/public/css/session-folders.css +80 -21
  56. package/lib/public/css/session-github.css +25 -16
  57. package/lib/public/css/settings-ui.css +247 -22
  58. package/lib/public/css/shared-browser.css +2 -0
  59. package/lib/public/css/sidebar.css +183 -107
  60. package/lib/public/css/title-bar.css +156 -1
  61. package/lib/public/css/worker-delegation.css +47 -0
  62. package/lib/public/css/worker-proposal.css +72 -150
  63. package/lib/public/css/you.css +74 -0
  64. package/lib/public/index.html +203 -547
  65. package/lib/public/modules/account-island.js +232 -0
  66. package/lib/public/modules/admin-settings-email.js +197 -0
  67. package/lib/public/modules/admin-settings-invitations.js +183 -0
  68. package/lib/public/modules/admin-settings-projects.js +198 -0
  69. package/lib/public/modules/admin-settings-ui.js +100 -0
  70. package/lib/public/modules/admin-settings-users.js +331 -0
  71. package/lib/public/modules/admin.js +19 -949
  72. package/lib/public/modules/app-cursors.js +19 -43
  73. package/lib/public/modules/app-debate-ui.js +4 -3
  74. package/lib/public/modules/app-dm.js +0 -2
  75. package/lib/public/modules/app-header.js +106 -0
  76. package/lib/public/modules/app-message-router.js +12 -3
  77. package/lib/public/modules/app-messages.js +47 -61
  78. package/lib/public/modules/app-notifications.js +4 -7
  79. package/lib/public/modules/app-projects.js +5 -38
  80. package/lib/public/modules/app-rate-limit.js +70 -12
  81. package/lib/public/modules/app-rendering.js +12 -13
  82. package/lib/public/modules/avatar.js +25 -9
  83. package/lib/public/modules/chat-render-runtime.js +16 -4
  84. package/lib/public/modules/command-palette.js +2 -15
  85. package/lib/public/modules/context-sources.js +27 -18
  86. package/lib/public/modules/cursor-sharing-preference.js +3 -3
  87. package/lib/public/modules/debate-controls.js +299 -0
  88. package/lib/public/modules/debate.js +2 -0
  89. package/lib/public/modules/debates-workbench.js +339 -0
  90. package/lib/public/modules/default-ai.js +88 -65
  91. package/lib/public/modules/header-tui-font.js +10 -20
  92. package/lib/public/modules/home-debate-controls.js +18 -289
  93. package/lib/public/modules/home-mate-avatar-editor.js +228 -0
  94. package/lib/public/modules/home-mate-color-picker.js +66 -0
  95. package/lib/public/modules/home-mate-creation.js +1 -1
  96. package/lib/public/modules/home-mate-instructions.js +90 -0
  97. package/lib/public/modules/home-mate-model-picker.js +80 -271
  98. package/lib/public/modules/home-mate-profile-editor.js +72 -0
  99. package/lib/public/modules/home-mate-settings.js +118 -125
  100. package/lib/public/modules/home-shell.js +3 -0
  101. package/lib/public/modules/home-surface-boot.js +1 -9
  102. package/lib/public/modules/icon-strip-tooltip.js +95 -0
  103. package/lib/public/modules/knowledge-db-edit-state.js +35 -0
  104. package/lib/public/modules/knowledge-db-workbench.js +234 -0
  105. package/lib/public/modules/knowledge-history-state.js +55 -0
  106. package/lib/public/modules/knowledge-markdown-editor.js +57 -0
  107. package/lib/public/modules/knowledge-preview-links.js +70 -0
  108. package/lib/public/modules/knowledge-workbench-shell.js +21 -0
  109. package/lib/public/modules/linear-settings.js +3 -2
  110. package/lib/public/modules/markdown.js +5 -6
  111. package/lib/public/modules/mate-knowledge-workbench-state.js +174 -0
  112. package/lib/public/modules/mate-knowledge-workbench.js +500 -0
  113. package/lib/public/modules/mate-knowledge.js +11 -3
  114. package/lib/public/modules/mate-management.js +54 -10
  115. package/lib/public/modules/mate-sidebar.js +11 -1
  116. package/lib/public/modules/mate-workspace-color.js +33 -0
  117. package/lib/public/modules/mention.js +5 -13
  118. package/lib/public/modules/notification-settings.js +81 -0
  119. package/lib/public/modules/notifications.js +44 -28
  120. package/lib/public/modules/personal-settings-dialog.js +51 -0
  121. package/lib/public/modules/profile.js +66 -24
  122. package/lib/public/modules/project-chat-identity.js +79 -0
  123. package/lib/public/modules/project-debate-planning-workspace.js +250 -0
  124. package/lib/public/modules/project-debate-workspace.js +185 -0
  125. package/lib/public/modules/project-header-identity.js +127 -0
  126. package/lib/public/modules/project-logs-render.js +9 -4
  127. package/lib/public/modules/project-mate-creation-workspace.js +414 -0
  128. package/lib/public/modules/project-mate-navigation.js +238 -0
  129. package/lib/public/modules/project-session-navigation.js +29 -0
  130. package/lib/public/modules/project-settings-environment.js +106 -0
  131. package/lib/public/modules/project-settings.js +72 -628
  132. package/lib/public/modules/project-switcher.js +6 -8
  133. package/lib/public/modules/projects-hub-view.js +5 -6
  134. package/lib/public/modules/projects-hub.js +2 -6
  135. package/lib/public/modules/qrcode.js +27 -8
  136. package/lib/public/modules/search-clay-chat.js +8 -11
  137. package/lib/public/modules/server-settings-controls.js +316 -0
  138. package/lib/public/modules/server-settings-environment.js +194 -0
  139. package/lib/public/modules/server-settings-navigation.js +39 -0
  140. package/lib/public/modules/server-settings-state.js +54 -0
  141. package/lib/public/modules/server-settings.js +116 -788
  142. package/lib/public/modules/server-storage-settings.js +84 -0
  143. package/lib/public/modules/session-activity-tooltip.js +12 -0
  144. package/lib/public/modules/session-create-form.js +86 -14
  145. package/lib/public/modules/session-create.js +50 -7
  146. package/lib/public/modules/session-github.js +2 -1
  147. package/lib/public/modules/session-list-visibility.js +41 -0
  148. package/lib/public/modules/session-presence-ui.js +3 -0
  149. package/lib/public/modules/session-title-marquee.js +51 -0
  150. package/lib/public/modules/settings-env-values.js +34 -0
  151. package/lib/public/modules/settings-select.js +121 -0
  152. package/lib/public/modules/shared-browser.js +10 -7
  153. package/lib/public/modules/sidebar-mates.js +3 -50
  154. package/lib/public/modules/sidebar-mobile.js +63 -60
  155. package/lib/public/modules/sidebar-projects.js +84 -97
  156. package/lib/public/modules/sidebar-session-folders-ui.js +2 -2
  157. package/lib/public/modules/sidebar-session-hierarchy.js +149 -70
  158. package/lib/public/modules/sidebar-sessions.js +49 -50
  159. package/lib/public/modules/sidebar.js +11 -13
  160. package/lib/public/modules/stt-picker.js +14 -5
  161. package/lib/public/modules/terminal-prefs.js +22 -0
  162. package/lib/public/modules/theme.js +88 -52
  163. package/lib/public/modules/thinking-lifecycle.js +7 -6
  164. package/lib/public/modules/tool-palette-order.js +4 -3
  165. package/lib/public/modules/tool-palette.js +13 -3
  166. package/lib/public/modules/tools.js +22 -22
  167. package/lib/public/modules/user-settings-account.js +318 -0
  168. package/lib/public/modules/user-settings-appearance.js +55 -0
  169. package/lib/public/modules/user-settings-editors.js +24 -0
  170. package/lib/public/modules/user-settings-integrations.js +104 -0
  171. package/lib/public/modules/user-settings-layout.js +80 -0
  172. package/lib/public/modules/user-settings-preferences.js +48 -0
  173. package/lib/public/modules/user-settings-profile.js +53 -0
  174. package/lib/public/modules/user-settings-themes.js +38 -0
  175. package/lib/public/modules/user-settings-voice.js +75 -0
  176. package/lib/public/modules/user-settings.js +53 -480
  177. package/lib/public/modules/worker-proposal.js +42 -8
  178. package/lib/public/modules/worker-runtime-picker.js +115 -0
  179. package/lib/public/modules/you-activity.js +121 -0
  180. package/lib/public/modules/you.js +251 -0
  181. package/lib/public/style.css +20 -8
  182. package/lib/public/vendor/codemirror/LICENSE +21 -0
  183. package/lib/public/vendor/codemirror/codemirror.css +344 -0
  184. package/lib/public/vendor/codemirror/codemirror.js +9884 -0
  185. package/lib/public/vendor/codemirror/continuelist.js +101 -0
  186. package/lib/public/vendor/codemirror/markdown.js +886 -0
  187. package/lib/public/vendor/codemirror/show-hint.css +37 -0
  188. package/lib/public/vendor/codemirror/show-hint.js +523 -0
  189. package/lib/sdk-bridge.js +15 -3
  190. package/lib/sdk-message-processor.js +16 -4
  191. package/lib/sdk-quota-snapshot.js +37 -0
  192. package/lib/server-admin.js +11 -0
  193. package/lib/server-appearance-settings.js +71 -0
  194. package/lib/server-home-chat-events.js +1 -1
  195. package/lib/server-home-chat.js +25 -3
  196. package/lib/server-home-debate-planning.js +4 -1
  197. package/lib/server-home-debates.js +2 -0
  198. package/lib/server-home-mate-creation.js +4 -1
  199. package/lib/server-linear.js +14 -8
  200. package/lib/server-mate-instructions.js +44 -0
  201. package/lib/server-mates.js +12 -3
  202. package/lib/server-notification-settings.js +67 -0
  203. package/lib/server-palette.js +1 -1
  204. package/lib/server-settings.js +69 -1
  205. package/lib/server-storage.js +56 -0
  206. package/lib/server-user-knowledge.js +119 -0
  207. package/lib/server.js +31 -3
  208. package/lib/session-visibility.js +7 -2
  209. package/lib/sessions.js +34 -9
  210. package/lib/startup-projects.js +40 -0
  211. package/lib/storage-usage.js +127 -0
  212. package/lib/user-knowledge-service.js +167 -0
  213. package/lib/users-permissions.js +7 -0
  214. package/lib/users-preferences.js +0 -74
  215. package/lib/users-project-mate-filter-preferences.js +39 -0
  216. package/lib/users.js +6 -4
  217. package/lib/workspace-query-access.js +4 -1
  218. package/lib/ws-schema.js +52 -4
  219. package/lib/yoke/adapters/codex.js +8 -45
  220. package/lib/yoke/codex-model-catalog.js +40 -0
  221. package/lib/yoke/codex-rate-limits.js +26 -0
  222. package/package.json +12 -3
@@ -0,0 +1,37 @@
1
+ .CodeMirror-hints {
2
+ position: absolute;
3
+ z-index: 10;
4
+ overflow: hidden;
5
+ list-style: none;
6
+
7
+ margin: 0;
8
+ padding: 2px;
9
+
10
+ -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
11
+ -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
12
+ box-shadow: 2px 3px 5px rgba(0,0,0,.2);
13
+ border-radius: 3px;
14
+ border: 1px solid silver;
15
+
16
+ background: white;
17
+ font-size: 90%;
18
+ font-family: monospace;
19
+
20
+ max-height: 20em;
21
+ overflow-y: auto;
22
+ box-sizing: border-box;
23
+ }
24
+
25
+ .CodeMirror-hint {
26
+ margin: 0;
27
+ padding: 0 4px;
28
+ border-radius: 2px;
29
+ white-space: pre;
30
+ color: black;
31
+ cursor: pointer;
32
+ }
33
+
34
+ li.CodeMirror-hint-active {
35
+ background: #08f;
36
+ color: white;
37
+ }
@@ -0,0 +1,523 @@
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: https://codemirror.net/5/LICENSE
3
+
4
+ // declare global: DOMRect
5
+
6
+ (function(mod) {
7
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
8
+ mod(require("../../lib/codemirror"));
9
+ else if (typeof define == "function" && define.amd) // AMD
10
+ define(["../../lib/codemirror"], mod);
11
+ else // Plain browser env
12
+ mod(CodeMirror);
13
+ })(function(CodeMirror) {
14
+ "use strict";
15
+
16
+ var HINT_ELEMENT_CLASS = "CodeMirror-hint";
17
+ var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";
18
+
19
+ // This is the old interface, kept around for now to stay
20
+ // backwards-compatible.
21
+ CodeMirror.showHint = function(cm, getHints, options) {
22
+ if (!getHints) return cm.showHint(options);
23
+ if (options && options.async) getHints.async = true;
24
+ var newOpts = {hint: getHints};
25
+ if (options) for (var prop in options) newOpts[prop] = options[prop];
26
+ return cm.showHint(newOpts);
27
+ };
28
+
29
+ CodeMirror.defineExtension("showHint", function(options) {
30
+ options = parseOptions(this, this.getCursor("start"), options);
31
+ var selections = this.listSelections()
32
+ if (selections.length > 1) return;
33
+ // By default, don't allow completion when something is selected.
34
+ // A hint function can have a `supportsSelection` property to
35
+ // indicate that it can handle selections.
36
+ if (this.somethingSelected()) {
37
+ if (!options.hint.supportsSelection) return;
38
+ // Don't try with cross-line selections
39
+ for (var i = 0; i < selections.length; i++)
40
+ if (selections[i].head.line != selections[i].anchor.line) return;
41
+ }
42
+
43
+ if (this.state.completionActive) this.state.completionActive.close();
44
+ var completion = this.state.completionActive = new Completion(this, options);
45
+ if (!completion.options.hint) return;
46
+
47
+ CodeMirror.signal(this, "startCompletion", this);
48
+ completion.update(true);
49
+ });
50
+
51
+ CodeMirror.defineExtension("closeHint", function() {
52
+ if (this.state.completionActive) this.state.completionActive.close()
53
+ })
54
+
55
+ function Completion(cm, options) {
56
+ this.cm = cm;
57
+ this.options = options;
58
+ this.widget = null;
59
+ this.debounce = 0;
60
+ this.tick = 0;
61
+ this.startPos = this.cm.getCursor("start");
62
+ this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length;
63
+
64
+ if (this.options.updateOnCursorActivity) {
65
+ var self = this;
66
+ cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
67
+ }
68
+ }
69
+
70
+ var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
71
+ return setTimeout(fn, 1000/60);
72
+ };
73
+ var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
74
+
75
+ Completion.prototype = {
76
+ close: function() {
77
+ if (!this.active()) return;
78
+ this.cm.state.completionActive = null;
79
+ this.tick = null;
80
+ if (this.options.updateOnCursorActivity) {
81
+ this.cm.off("cursorActivity", this.activityFunc);
82
+ }
83
+
84
+ if (this.widget && this.data) CodeMirror.signal(this.data, "close");
85
+ if (this.widget) this.widget.close();
86
+ CodeMirror.signal(this.cm, "endCompletion", this.cm);
87
+ },
88
+
89
+ active: function() {
90
+ return this.cm.state.completionActive == this;
91
+ },
92
+
93
+ pick: function(data, i) {
94
+ var completion = data.list[i], self = this;
95
+ this.cm.operation(function() {
96
+ if (completion.hint)
97
+ completion.hint(self.cm, data, completion);
98
+ else
99
+ self.cm.replaceRange(getText(completion), completion.from || data.from,
100
+ completion.to || data.to, "complete");
101
+ CodeMirror.signal(data, "pick", completion);
102
+ self.cm.scrollIntoView();
103
+ });
104
+ if (this.options.closeOnPick) {
105
+ this.close();
106
+ }
107
+ },
108
+
109
+ cursorActivity: function() {
110
+ if (this.debounce) {
111
+ cancelAnimationFrame(this.debounce);
112
+ this.debounce = 0;
113
+ }
114
+
115
+ var identStart = this.startPos;
116
+ if(this.data) {
117
+ identStart = this.data.from;
118
+ }
119
+
120
+ var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
121
+ if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
122
+ pos.ch < identStart.ch || this.cm.somethingSelected() ||
123
+ (!pos.ch || this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
124
+ this.close();
125
+ } else {
126
+ var self = this;
127
+ this.debounce = requestAnimationFrame(function() {self.update();});
128
+ if (this.widget) this.widget.disable();
129
+ }
130
+ },
131
+
132
+ update: function(first) {
133
+ if (this.tick == null) return
134
+ var self = this, myTick = ++this.tick
135
+ fetchHints(this.options.hint, this.cm, this.options, function(data) {
136
+ if (self.tick == myTick) self.finishUpdate(data, first)
137
+ })
138
+ },
139
+
140
+ finishUpdate: function(data, first) {
141
+ if (this.data) CodeMirror.signal(this.data, "update");
142
+
143
+ var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
144
+ if (this.widget) this.widget.close();
145
+
146
+ this.data = data;
147
+
148
+ if (data && data.list.length) {
149
+ if (picked && data.list.length == 1) {
150
+ this.pick(data, 0);
151
+ } else {
152
+ this.widget = new Widget(this, data);
153
+ CodeMirror.signal(data, "shown");
154
+ }
155
+ }
156
+ }
157
+ };
158
+
159
+ function parseOptions(cm, pos, options) {
160
+ var editor = cm.options.hintOptions;
161
+ var out = {};
162
+ for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
163
+ if (editor) for (var prop in editor)
164
+ if (editor[prop] !== undefined) out[prop] = editor[prop];
165
+ if (options) for (var prop in options)
166
+ if (options[prop] !== undefined) out[prop] = options[prop];
167
+ if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos)
168
+ return out;
169
+ }
170
+
171
+ function getText(completion) {
172
+ if (typeof completion == "string") return completion;
173
+ else return completion.text;
174
+ }
175
+
176
+ function buildKeyMap(completion, handle) {
177
+ var baseMap = {
178
+ Up: function() {handle.moveFocus(-1);},
179
+ Down: function() {handle.moveFocus(1);},
180
+ PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);},
181
+ PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);},
182
+ Home: function() {handle.setFocus(0);},
183
+ End: function() {handle.setFocus(handle.length - 1);},
184
+ Enter: handle.pick,
185
+ Tab: handle.pick,
186
+ Esc: handle.close
187
+ };
188
+
189
+ var mac = /Mac/.test(navigator.platform);
190
+
191
+ if (mac) {
192
+ baseMap["Ctrl-P"] = function() {handle.moveFocus(-1);};
193
+ baseMap["Ctrl-N"] = function() {handle.moveFocus(1);};
194
+ }
195
+
196
+ var custom = completion.options.customKeys;
197
+ var ourMap = custom ? {} : baseMap;
198
+ function addBinding(key, val) {
199
+ var bound;
200
+ if (typeof val != "string")
201
+ bound = function(cm) { return val(cm, handle); };
202
+ // This mechanism is deprecated
203
+ else if (baseMap.hasOwnProperty(val))
204
+ bound = baseMap[val];
205
+ else
206
+ bound = val;
207
+ ourMap[key] = bound;
208
+ }
209
+ if (custom)
210
+ for (var key in custom) if (custom.hasOwnProperty(key))
211
+ addBinding(key, custom[key]);
212
+ var extra = completion.options.extraKeys;
213
+ if (extra)
214
+ for (var key in extra) if (extra.hasOwnProperty(key))
215
+ addBinding(key, extra[key]);
216
+ return ourMap;
217
+ }
218
+
219
+ function getHintElement(hintsElement, el) {
220
+ while (el && el != hintsElement) {
221
+ if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el;
222
+ el = el.parentNode;
223
+ }
224
+ }
225
+
226
+ function Widget(completion, data) {
227
+ this.id = "cm-complete-" + Math.floor(Math.random(1e6))
228
+ this.completion = completion;
229
+ this.data = data;
230
+ this.picked = false;
231
+ var widget = this, cm = completion.cm;
232
+ var ownerDocument = cm.getInputField().ownerDocument;
233
+ var parentWindow = ownerDocument.defaultView || ownerDocument.parentWindow;
234
+
235
+ var hints = this.hints = ownerDocument.createElement("ul");
236
+ hints.setAttribute("role", "listbox")
237
+ hints.setAttribute("aria-expanded", "true")
238
+ hints.id = this.id
239
+ var theme = completion.cm.options.theme;
240
+ hints.className = "CodeMirror-hints " + theme;
241
+ this.selectedHint = data.selectedHint || 0;
242
+
243
+ var completions = data.list;
244
+ for (var i = 0; i < completions.length; ++i) {
245
+ var elt = hints.appendChild(ownerDocument.createElement("li")), cur = completions[i];
246
+ var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS);
247
+ if (cur.className != null) className = cur.className + " " + className;
248
+ elt.className = className;
249
+ if (i == this.selectedHint) elt.setAttribute("aria-selected", "true")
250
+ elt.id = this.id + "-" + i
251
+ elt.setAttribute("role", "option")
252
+ if (cur.render) cur.render(elt, data, cur);
253
+ else elt.appendChild(ownerDocument.createTextNode(cur.displayText || getText(cur)));
254
+ elt.hintId = i;
255
+ }
256
+
257
+ var container = completion.options.container || ownerDocument.body;
258
+ var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);
259
+ var left = pos.left, top = pos.bottom, below = true;
260
+ var offsetLeft = 0, offsetTop = 0;
261
+ if (container !== ownerDocument.body) {
262
+ // We offset the cursor position because left and top are relative to the offsetParent's top left corner.
263
+ var isContainerPositioned = ['absolute', 'relative', 'fixed'].indexOf(parentWindow.getComputedStyle(container).position) !== -1;
264
+ var offsetParent = isContainerPositioned ? container : container.offsetParent;
265
+ var offsetParentPosition = offsetParent.getBoundingClientRect();
266
+ var bodyPosition = ownerDocument.body.getBoundingClientRect();
267
+ offsetLeft = (offsetParentPosition.left - bodyPosition.left - offsetParent.scrollLeft);
268
+ offsetTop = (offsetParentPosition.top - bodyPosition.top - offsetParent.scrollTop);
269
+ }
270
+ hints.style.left = (left - offsetLeft) + "px";
271
+ hints.style.top = (top - offsetTop) + "px";
272
+
273
+ // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
274
+ var winW = parentWindow.innerWidth || Math.max(ownerDocument.body.offsetWidth, ownerDocument.documentElement.offsetWidth);
275
+ var winH = parentWindow.innerHeight || Math.max(ownerDocument.body.offsetHeight, ownerDocument.documentElement.offsetHeight);
276
+ container.appendChild(hints);
277
+ cm.getInputField().setAttribute("aria-autocomplete", "list")
278
+ cm.getInputField().setAttribute("aria-owns", this.id)
279
+ cm.getInputField().setAttribute("aria-activedescendant", this.id + "-" + this.selectedHint)
280
+
281
+ var box = completion.options.moveOnOverlap ? hints.getBoundingClientRect() : new DOMRect();
282
+ var scrolls = completion.options.paddingForScrollbar ? hints.scrollHeight > hints.clientHeight + 1 : false;
283
+
284
+ // Compute in the timeout to avoid reflow on init
285
+ var startScroll;
286
+ setTimeout(function() { startScroll = cm.getScrollInfo(); });
287
+
288
+ var overlapY = box.bottom - winH;
289
+ if (overlapY > 0) { // Does not fit below
290
+ var height = box.bottom - box.top, spaceAbove = box.top - (pos.bottom - pos.top) - 2
291
+ if (winH - box.top < spaceAbove) { // More room at the top
292
+ if (height > spaceAbove) hints.style.height = (height = spaceAbove) + "px";
293
+ hints.style.top = ((top = pos.top - height) - offsetTop) + "px";
294
+ below = false;
295
+ } else {
296
+ hints.style.height = (winH - box.top - 2) + "px";
297
+ }
298
+ }
299
+ var overlapX = box.right - winW;
300
+ if (scrolls) overlapX += cm.display.nativeBarWidth;
301
+ if (overlapX > 0) {
302
+ if (box.right - box.left > winW) {
303
+ hints.style.width = (winW - 5) + "px";
304
+ overlapX -= (box.right - box.left) - winW;
305
+ }
306
+ hints.style.left = (left = Math.max(pos.left - overlapX - offsetLeft, 0)) + "px";
307
+ }
308
+ if (scrolls) for (var node = hints.firstChild; node; node = node.nextSibling)
309
+ node.style.paddingRight = cm.display.nativeBarWidth + "px"
310
+
311
+ cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
312
+ moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
313
+ setFocus: function(n) { widget.changeActive(n); },
314
+ menuSize: function() { return widget.screenAmount(); },
315
+ length: completions.length,
316
+ close: function() { completion.close(); },
317
+ pick: function() { widget.pick(); },
318
+ data: data
319
+ }));
320
+
321
+ if (completion.options.closeOnUnfocus) {
322
+ var closingOnBlur;
323
+ cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });
324
+ cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
325
+ }
326
+
327
+ cm.on("scroll", this.onScroll = function() {
328
+ var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
329
+ if (!startScroll) startScroll = cm.getScrollInfo();
330
+ var newTop = top + startScroll.top - curScroll.top;
331
+ var point = newTop - (parentWindow.pageYOffset || (ownerDocument.documentElement || ownerDocument.body).scrollTop);
332
+ if (!below) point += hints.offsetHeight;
333
+ if (point <= editor.top || point >= editor.bottom) return completion.close();
334
+ hints.style.top = newTop + "px";
335
+ hints.style.left = (left + startScroll.left - curScroll.left) + "px";
336
+ });
337
+
338
+ CodeMirror.on(hints, "dblclick", function(e) {
339
+ var t = getHintElement(hints, e.target || e.srcElement);
340
+ if (t && t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}
341
+ });
342
+
343
+ CodeMirror.on(hints, "click", function(e) {
344
+ var t = getHintElement(hints, e.target || e.srcElement);
345
+ if (t && t.hintId != null) {
346
+ widget.changeActive(t.hintId);
347
+ if (completion.options.completeOnSingleClick) widget.pick();
348
+ }
349
+ });
350
+
351
+ CodeMirror.on(hints, "mousedown", function() {
352
+ setTimeout(function(){cm.focus();}, 20);
353
+ });
354
+
355
+ // The first hint doesn't need to be scrolled to on init
356
+ var selectedHintRange = this.getSelectedHintRange();
357
+ if (selectedHintRange.from !== 0 || selectedHintRange.to !== 0) {
358
+ this.scrollToActive();
359
+ }
360
+
361
+ CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]);
362
+ return true;
363
+ }
364
+
365
+ Widget.prototype = {
366
+ close: function() {
367
+ if (this.completion.widget != this) return;
368
+ this.completion.widget = null;
369
+ if (this.hints.parentNode) this.hints.parentNode.removeChild(this.hints);
370
+ this.completion.cm.removeKeyMap(this.keyMap);
371
+ var input = this.completion.cm.getInputField()
372
+ input.removeAttribute("aria-activedescendant")
373
+ input.removeAttribute("aria-owns")
374
+
375
+ var cm = this.completion.cm;
376
+ if (this.completion.options.closeOnUnfocus) {
377
+ cm.off("blur", this.onBlur);
378
+ cm.off("focus", this.onFocus);
379
+ }
380
+ cm.off("scroll", this.onScroll);
381
+ },
382
+
383
+ disable: function() {
384
+ this.completion.cm.removeKeyMap(this.keyMap);
385
+ var widget = this;
386
+ this.keyMap = {Enter: function() { widget.picked = true; }};
387
+ this.completion.cm.addKeyMap(this.keyMap);
388
+ },
389
+
390
+ pick: function() {
391
+ this.completion.pick(this.data, this.selectedHint);
392
+ },
393
+
394
+ changeActive: function(i, avoidWrap) {
395
+ if (i >= this.data.list.length)
396
+ i = avoidWrap ? this.data.list.length - 1 : 0;
397
+ else if (i < 0)
398
+ i = avoidWrap ? 0 : this.data.list.length - 1;
399
+ if (this.selectedHint == i) return;
400
+ var node = this.hints.childNodes[this.selectedHint];
401
+ if (node) {
402
+ node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
403
+ node.removeAttribute("aria-selected")
404
+ }
405
+ node = this.hints.childNodes[this.selectedHint = i];
406
+ node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
407
+ node.setAttribute("aria-selected", "true")
408
+ this.completion.cm.getInputField().setAttribute("aria-activedescendant", node.id)
409
+ this.scrollToActive()
410
+ CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
411
+ },
412
+
413
+ scrollToActive: function() {
414
+ var selectedHintRange = this.getSelectedHintRange();
415
+ var node1 = this.hints.childNodes[selectedHintRange.from];
416
+ var node2 = this.hints.childNodes[selectedHintRange.to];
417
+ var firstNode = this.hints.firstChild;
418
+ if (node1.offsetTop < this.hints.scrollTop)
419
+ this.hints.scrollTop = node1.offsetTop - firstNode.offsetTop;
420
+ else if (node2.offsetTop + node2.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
421
+ this.hints.scrollTop = node2.offsetTop + node2.offsetHeight - this.hints.clientHeight + firstNode.offsetTop;
422
+ },
423
+
424
+ screenAmount: function() {
425
+ return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
426
+ },
427
+
428
+ getSelectedHintRange: function() {
429
+ var margin = this.completion.options.scrollMargin || 0;
430
+ return {
431
+ from: Math.max(0, this.selectedHint - margin),
432
+ to: Math.min(this.data.list.length - 1, this.selectedHint + margin),
433
+ };
434
+ }
435
+ };
436
+
437
+ function applicableHelpers(cm, helpers) {
438
+ if (!cm.somethingSelected()) return helpers
439
+ var result = []
440
+ for (var i = 0; i < helpers.length; i++)
441
+ if (helpers[i].supportsSelection) result.push(helpers[i])
442
+ return result
443
+ }
444
+
445
+ function fetchHints(hint, cm, options, callback) {
446
+ if (hint.async) {
447
+ hint(cm, callback, options)
448
+ } else {
449
+ var result = hint(cm, options)
450
+ if (result && result.then) result.then(callback)
451
+ else callback(result)
452
+ }
453
+ }
454
+
455
+ function resolveAutoHints(cm, pos) {
456
+ var helpers = cm.getHelpers(pos, "hint"), words
457
+ if (helpers.length) {
458
+ var resolved = function(cm, callback, options) {
459
+ var app = applicableHelpers(cm, helpers);
460
+ function run(i) {
461
+ if (i == app.length) return callback(null)
462
+ fetchHints(app[i], cm, options, function(result) {
463
+ if (result && result.list.length > 0) callback(result)
464
+ else run(i + 1)
465
+ })
466
+ }
467
+ run(0)
468
+ }
469
+ resolved.async = true
470
+ resolved.supportsSelection = true
471
+ return resolved
472
+ } else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
473
+ return function(cm) { return CodeMirror.hint.fromList(cm, {words: words}) }
474
+ } else if (CodeMirror.hint.anyword) {
475
+ return function(cm, options) { return CodeMirror.hint.anyword(cm, options) }
476
+ } else {
477
+ return function() {}
478
+ }
479
+ }
480
+
481
+ CodeMirror.registerHelper("hint", "auto", {
482
+ resolve: resolveAutoHints
483
+ });
484
+
485
+ CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
486
+ var cur = cm.getCursor(), token = cm.getTokenAt(cur)
487
+ var term, from = CodeMirror.Pos(cur.line, token.start), to = cur
488
+ if (token.start < cur.ch && /\w/.test(token.string.charAt(cur.ch - token.start - 1))) {
489
+ term = token.string.substr(0, cur.ch - token.start)
490
+ } else {
491
+ term = ""
492
+ from = cur
493
+ }
494
+ var found = [];
495
+ for (var i = 0; i < options.words.length; i++) {
496
+ var word = options.words[i];
497
+ if (word.slice(0, term.length) == term)
498
+ found.push(word);
499
+ }
500
+
501
+ if (found.length) return {list: found, from: from, to: to};
502
+ });
503
+
504
+ CodeMirror.commands.autocomplete = CodeMirror.showHint;
505
+
506
+ var defaultOptions = {
507
+ hint: CodeMirror.hint.auto,
508
+ completeSingle: true,
509
+ alignWithWord: true,
510
+ closeCharacters: /[\s()\[\]{};:>,]/,
511
+ closeOnPick: true,
512
+ closeOnUnfocus: true,
513
+ updateOnCursorActivity: true,
514
+ completeOnSingleClick: true,
515
+ container: null,
516
+ customKeys: null,
517
+ extraKeys: null,
518
+ paddingForScrollbar: true,
519
+ moveOnOverlap: true,
520
+ };
521
+
522
+ CodeMirror.defineOption("hintOptions", null);
523
+ });
package/lib/sdk-bridge.js CHANGED
@@ -795,6 +795,9 @@ function createSDKBridge(opts) {
795
795
  }
796
796
 
797
797
  function handlePreToolUsePolicy(session, toolName, input) {
798
+ var youTool = /^(?:mcp__clay-you__)?(?:search_user_knowledge|read_user_knowledge|report_user_observation|list_user_observations|curate_user_knowledge)$/.test(toolName);
799
+ if (session.youCurator && !youTool) return { behavior: "deny", message: "User Knowledge review may only use Clay's owner-bound knowledge tools." };
800
+ if (youTool) return { behavior: "allow", updatedInput: input };
798
801
  var debateDecision = homeDebateToolPolicy.initialToolDecision(session, toolName, input);
799
802
  if (debateDecision) return debateDecision;
800
803
  // The dynamic proposal tool is bound to this exact query session. It only
@@ -1107,6 +1110,7 @@ function createSDKBridge(opts) {
1107
1110
  if (codexCatalogCandidate.userInputVersion) session.codexUserInputToolCatalogVersion = codexCatalogCandidate.userInputVersion;
1108
1111
  if (codexCatalogCandidate.sharedBrowserVersion) session.codexSharedBrowserToolCatalogVersion = codexCatalogCandidate.sharedBrowserVersion;
1109
1112
  if (codexCatalogCandidate.issuesVersion) session.codexIssuesToolCatalogVersion = codexCatalogCandidate.issuesVersion;
1113
+ if (codexCatalogCandidate.youVersion) session.codexYouToolCatalogVersion = codexCatalogCandidate.youVersion;
1110
1114
  if (codexCatalogCandidate.linearVersion) session.codexLinearToolCatalogVersion = codexCatalogCandidate.linearVersion;
1111
1115
  sm.saveSessionFile(session);
1112
1116
  codexCatalogCandidate = null;
@@ -1730,6 +1734,10 @@ function createSDKBridge(opts) {
1730
1734
  // still reaches Clay's canUseTool callback, as before.
1731
1735
  claudeOpts.permissionMode = modeToApply || "default";
1732
1736
  }
1737
+ if (session.youCurator) {
1738
+ claudeOpts.permissionMode = "default";
1739
+ claudeOpts.allowDangerouslySkipPermissions = false;
1740
+ }
1733
1741
  // Clear one-shot acceptEditsAfterStart regardless of which branch ran above,
1734
1742
  // so the flag does not linger into subsequent turns.
1735
1743
  if (session.acceptEditsAfterStart) delete session.acceptEditsAfterStart;
@@ -1789,6 +1797,9 @@ function createSDKBridge(opts) {
1789
1797
  // delivered by this provider.
1790
1798
  var sessionToolDefs = getSessionToolDefs(session) || [];
1791
1799
  var queryGeneration = Number(session._sdkQueryGeneration || 0);
1800
+ var hasYouCatalog = sessionToolDefs.some(function (tool) { return tool.name === "search_user_knowledge"; });
1801
+ var recoverCodexYouTools = sessionAdapter.vendor === "codex" && !!session.cliSessionId
1802
+ && hasYouCatalog && Number(session.codexYouToolCatalogVersion || 0) < 1;
1792
1803
  var hasLinearCatalog = sessionToolDefs.some(function (tool) { return tool.name === "link_session_linear"; });
1793
1804
  var recoverCodexLinearTools = sessionAdapter.vendor === "codex" && !!session.cliSessionId
1794
1805
  && hasLinearCatalog && Number(session.codexLinearToolCatalogVersion || 0) < 1 && canUseSessionTools(session) === true;
@@ -1975,7 +1986,7 @@ function createSDKBridge(opts) {
1975
1986
  dynamicTools: sessionToolDefs,
1976
1987
  // Codex persists dynamic tools with a thread. A stale authorized Driver
1977
1988
  // gets this exact-query bridge; its handlers still reauthorize live.
1978
- sessionMcpServer: (recoverCodexIssueTools || recoverCodexQuestionTools || recoverCodexBrowserTools || recoverCodexLinearTools) ? getCodexSessionMcpServer(session, queryGeneration) : undefined,
1989
+ sessionMcpServer: (recoverCodexIssueTools || recoverCodexQuestionTools || recoverCodexBrowserTools || recoverCodexLinearTools || recoverCodexYouTools) ? getCodexSessionMcpServer(session, queryGeneration) : undefined,
1979
1990
  callDynamicTool: function (toolName, args) {
1980
1991
  var toolDef = findSessionToolDef(toolName);
1981
1992
  if (toolDef && typeof toolDef.handler === "function") {
@@ -2023,8 +2034,8 @@ function createSDKBridge(opts) {
2023
2034
  // Codex's native approval prompts are terminal-based and cannot be
2024
2035
  // relayed through Clay's web UI, causing MCP tool calls to hang.
2025
2036
  approvalPolicy: "never",
2026
- sandboxMode: codexConfig.sandbox,
2027
- webSearchMode: codexConfig.webSearch,
2037
+ sandboxMode: session.youCurator ? "read-only" : codexConfig.sandbox,
2038
+ webSearchMode: session.youCurator ? "disabled" : codexConfig.webSearch,
2028
2039
  },
2029
2040
  ACP: {
2030
2041
  mcpServers: getAcpMcpServers(session),
@@ -2194,6 +2205,7 @@ function createSDKBridge(opts) {
2194
2205
  if (requiredCatalogTools.ask_user_questions) {
2195
2206
  codexCatalogCandidate = Object.assign({}, codexCatalogCandidate || {}, { generation: queryGeneration, userInputVersion: 1 });
2196
2207
  }
2208
+ if (hasYouCatalog) codexCatalogCandidate = Object.assign({}, codexCatalogCandidate || {}, { generation: queryGeneration, youVersion: 1 });
2197
2209
  if (hasLinearCatalog) codexCatalogCandidate = Object.assign({}, codexCatalogCandidate || {}, { generation: queryGeneration, linearVersion: 1 });
2198
2210
  if (hasSharedBrowserCatalog) {
2199
2211
  codexCatalogCandidate = Object.assign({}, codexCatalogCandidate || {}, { generation: queryGeneration, sharedBrowserVersion: 5 });
@@ -6,11 +6,13 @@ var yoke = require("./yoke");
6
6
  var backgroundTaskTiming = require("./background-task-timing");
7
7
  var sessionTitlePolicy = require("./session-title-policy");
8
8
  var askUserIdentity = require("./ask-user-request-identity");
9
+ var quotaSnapshots = require("./sdk-quota-snapshot");
9
10
 
10
11
  var OVERLOAD_RETRY_LIMIT = 3;
11
12
 
12
13
  function attachMessageProcessor(ctx) {
13
14
  var sm = ctx.sm;
15
+ quotaSnapshots.attachQuotaSnapshots(sm);
14
16
  var send = ctx.send;
15
17
  var slug = ctx.slug;
16
18
  var isMate = ctx.isMate;
@@ -653,11 +655,13 @@ function attachMessageProcessor(ctx) {
653
655
  session._queuedTurnCount = 0;
654
656
  onProcessingChanged();
655
657
  }
656
- // Detect "Not logged in" scenario early for the check below
658
+ // Recognize only short, zero-cost CLI login responses, not ordinary prose.
657
659
  var previewTrimmed = (session.responsePreview || "").trim();
658
660
  var isZeroCost = !parsed.cost || parsed.cost === 0;
659
661
  var isLoginPrompt = isZeroCost && previewTrimmed.length < 100
660
- && /not logged in/i.test(previewTrimmed) && /\/login/i.test(previewTrimmed);
662
+ && ((/not logged in/i.test(previewTrimmed) && /\/login/i.test(previewTrimmed))
663
+ || ((session.vendor || "claude") === "claude"
664
+ && /^Failed to authenticate: OAuth session expired and could not be refreshed\.?$/i.test(previewTrimmed)));
661
665
  // Fetch rich context usage breakdown (fire-and-forget, non-blocking)
662
666
  if (session.queryInstance && typeof session.queryInstance.getContextUsage === "function") {
663
667
  var contextQuery = session.queryInstance;
@@ -692,7 +696,7 @@ function attachMessageProcessor(ctx) {
692
696
  if (parsed.fastModeState) {
693
697
  sendAndRecord(session, { type: "fast_mode_state", state: parsed.fastModeState });
694
698
  }
695
- // Detect "Not logged in / Please run /login" from SDK.
699
+ // Recover both missing login and expired OAuth sessions from the SDK.
696
700
  // This is a short canned response with zero cost, not actual AI output.
697
701
  if (isLoginPrompt) {
698
702
  emitAuthRequired(session);
@@ -853,6 +857,10 @@ function attachMessageProcessor(ctx) {
853
857
 
854
858
  } else if (parsed.yokeType === "rate_limit") {
855
859
  var info = parsed.rateLimitInfo;
860
+ if (info.source === "account_snapshot") {
861
+ quotaSnapshots.recordQuotaSnapshot(session, info, sendAndRecord);
862
+ return;
863
+ }
856
864
  console.log("[sdk-bridge] rate_limit_event for session " + session.localId + ": status=" + info.status + " resetsAt=" + info.resetsAt + " isUsingOverage=" + info.isUsingOverage + " isProcessing=" + session.isProcessing);
857
865
 
858
866
  // Persist the scoped reset snapshot so reconnect/history restore can reproject it.
@@ -877,7 +885,11 @@ function attachMessageProcessor(ctx) {
877
885
  resetsAt: info.resetsAt ? info.resetsAt * 1000 : null,
878
886
  rateLimitType: info.rateLimitType || null,
879
887
  utilization: info.utilization || null,
880
- isUsingOverage: info.isUsingOverage || false,
888
+ isUsingOverage: info.isUsingOverage === true || info.overageInUse === true,
889
+ overageEnabled: typeof info.overageEnabled === "boolean" ? info.overageEnabled : null,
890
+ overageStatus: info.overageStatus || null,
891
+ overageResetsAt: info.overageResetsAt ? info.overageResetsAt * 1000 : null,
892
+ overageDisabledReason: info.overageDisabledReason || null,
881
893
  });
882
894
  // Track rejection for auto-continue / scheduled message support
883
895
  if (info.status === "rejected" && info.resetsAt) {