clay-server 3.8.1 → 4.0.0-beta.10

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/lib/ask-user-mcp-server.js +5 -119
  2. package/lib/background-task-timing.js +105 -0
  3. package/lib/builtin-mates.js +6 -6
  4. package/lib/claude-hook-installer.js +15 -0
  5. package/lib/clay-history-mcp-server.js +62 -297
  6. package/lib/daemon.js +23 -1
  7. package/lib/debate-model-selection.js +119 -0
  8. package/lib/home-debate-tool-policy.js +164 -0
  9. package/lib/home-response-notifications.js +26 -0
  10. package/lib/knowledge-import.js +436 -0
  11. package/lib/knowledge-record-store.js +188 -0
  12. package/lib/knowledge-search.js +224 -0
  13. package/lib/mate-creation-mcp-server.js +55 -0
  14. package/lib/mate-knowledge-mcp-server.js +151 -0
  15. package/lib/mate-knowledge-migration.js +283 -0
  16. package/lib/mate-knowledge-service.js +488 -0
  17. package/lib/mate-knowledge-sync.js +482 -0
  18. package/lib/mate-ready-creation.js +95 -0
  19. package/lib/mates.js +2 -0
  20. package/lib/notes.js +2 -1
  21. package/lib/project-ask-user.js +64 -0
  22. package/lib/project-capsule-catalog.js +101 -0
  23. package/lib/project-connection.js +17 -0
  24. package/lib/project-debate-proposal.js +133 -17
  25. package/lib/project-debate.js +214 -110
  26. package/lib/project-delegated-follow-up.js +84 -0
  27. package/lib/project-delegated-session.js +53 -0
  28. package/lib/project-filesystem.js +7 -9
  29. package/lib/project-knowledge.js +23 -0
  30. package/lib/project-logs-comments.js +137 -0
  31. package/lib/project-logs-mcp-server.js +290 -0
  32. package/lib/project-logs-query.js +167 -0
  33. package/lib/project-logs-root.js +67 -0
  34. package/lib/project-logs-schema.js +259 -0
  35. package/lib/project-logs-service.js +357 -0
  36. package/lib/project-logs-snapshot.js +202 -0
  37. package/lib/project-logs-store.js +498 -0
  38. package/lib/project-logs-versioning.js +128 -0
  39. package/lib/project-logs.js +347 -0
  40. package/lib/project-mate-creation-proposal.js +120 -0
  41. package/lib/project-mate-interaction.js +14 -0
  42. package/lib/project-mate-knowledge.js +110 -0
  43. package/lib/project-memory.js +36 -7
  44. package/lib/project-models.js +157 -32
  45. package/lib/project-session-notes.js +2 -2
  46. package/lib/project-session-pair.js +8 -8
  47. package/lib/project-sessions.js +66 -51
  48. package/lib/project-vendor-login.js +414 -0
  49. package/lib/project-worker-proposal.js +25 -25
  50. package/lib/project-workspace-query.js +144 -0
  51. package/lib/project.js +433 -102
  52. package/lib/public/app.js +109 -48
  53. package/lib/public/css/avatar-imprints.css +0 -1
  54. package/lib/public/css/base.css +4 -0
  55. package/lib/public/css/capsule-ui.css +389 -0
  56. package/lib/public/css/command-palette.css +306 -6
  57. package/lib/public/css/home-capsule-library.css +243 -0
  58. package/lib/public/css/home-capsule-source.css +192 -0
  59. package/lib/public/css/home-debate-live.css +146 -0
  60. package/lib/public/css/home-debate-planning.css +125 -0
  61. package/lib/public/css/home-debates-archive.css +281 -0
  62. package/lib/public/css/home-hub.css +896 -405
  63. package/lib/public/css/home-mate-creation.css +34 -0
  64. package/lib/public/css/home-mate-model-picker.css +131 -0
  65. package/lib/public/css/home-mate-settings.css +344 -0
  66. package/lib/public/css/home-session-actions.css +265 -0
  67. package/lib/public/css/home-sidebar.css +667 -0
  68. package/lib/public/css/icon-strip.css +1 -2
  69. package/lib/public/css/input.css +79 -25
  70. package/lib/public/css/mates.css +7 -34
  71. package/lib/public/css/pane.css +1 -1
  72. package/lib/public/css/playbook.css +0 -80
  73. package/lib/public/css/project-logs.css +234 -0
  74. package/lib/public/css/scheduler.css +1 -1
  75. package/lib/public/css/sticky-notes.css +53 -117
  76. package/lib/public/css/tui-attention.css +0 -44
  77. package/lib/public/css/workspace-assignment.css +45 -0
  78. package/lib/public/fonts/source-serif-4/LICENSE.md +93 -0
  79. package/lib/public/fonts/source-serif-4/SourceSerif4Caption-Semibold.ttf.woff2 +0 -0
  80. package/lib/public/index.html +96 -74
  81. package/lib/public/modules/app-connection.js +100 -5
  82. package/lib/public/modules/app-dm.js +43 -160
  83. package/lib/public/modules/app-home-hub.js +328 -585
  84. package/lib/public/modules/app-message-cards.js +242 -0
  85. package/lib/public/modules/app-message-router.js +84 -0
  86. package/lib/public/modules/app-messages.js +124 -38
  87. package/lib/public/modules/app-notifications.js +8 -119
  88. package/lib/public/modules/app-panels.js +43 -2
  89. package/lib/public/modules/app-projects.js +9 -1
  90. package/lib/public/modules/app-rendering.js +21 -602
  91. package/lib/public/modules/avatar-imprint.js +11 -8
  92. package/lib/public/modules/background-tasks-ui.js +139 -16
  93. package/lib/public/modules/chat-bubble-renderer.js +152 -0
  94. package/lib/public/modules/chat-render-runtime.js +198 -0
  95. package/lib/public/modules/command-palette.js +225 -436
  96. package/lib/public/modules/dm-render.js +82 -0
  97. package/lib/public/modules/home-capsule-creation-intent.js +31 -0
  98. package/lib/public/modules/home-capsule-library.js +146 -0
  99. package/lib/public/modules/home-capsule-source.js +383 -0
  100. package/lib/public/modules/home-chat-identity.js +35 -0
  101. package/lib/public/modules/home-chat-scroll.js +77 -0
  102. package/lib/public/modules/home-chat-stream-state.js +34 -0
  103. package/lib/public/modules/home-composer-focus.js +25 -0
  104. package/lib/public/modules/home-conversations-sheet.js +179 -0
  105. package/lib/public/modules/home-debate-activity.js +48 -0
  106. package/lib/public/modules/home-debate-controls.js +295 -0
  107. package/lib/public/modules/home-debate-launch.js +41 -0
  108. package/lib/public/modules/home-debate-live.js +284 -0
  109. package/lib/public/modules/home-debate-models.js +73 -0
  110. package/lib/public/modules/home-debate-planning.js +335 -0
  111. package/lib/public/modules/home-debates-archive.js +279 -0
  112. package/lib/public/modules/home-dock-resize.js +74 -0
  113. package/lib/public/modules/home-dock.js +446 -0
  114. package/lib/public/modules/home-mate-chat.js +496 -0
  115. package/lib/public/modules/home-mate-creation.js +109 -0
  116. package/lib/public/modules/home-mate-model-picker.js +281 -0
  117. package/lib/public/modules/home-mate-selection.js +38 -0
  118. package/lib/public/modules/home-mate-settings-menu.js +131 -0
  119. package/lib/public/modules/home-mate-settings.js +383 -0
  120. package/lib/public/modules/home-session-actions.js +373 -0
  121. package/lib/public/modules/home-session-model-confirmation.js +13 -0
  122. package/lib/public/modules/home-shell.js +9 -0
  123. package/lib/public/modules/home-sidebar-chat-list.js +63 -0
  124. package/lib/public/modules/home-sidebar.js +165 -0
  125. package/lib/public/modules/home-sub-surface.js +19 -0
  126. package/lib/public/modules/home-surface-boot.js +68 -0
  127. package/lib/public/modules/home-surface.js +141 -0
  128. package/lib/public/modules/home-tools.js +271 -0
  129. package/lib/public/modules/markdown.js +50 -2
  130. package/lib/public/modules/mate-management.js +86 -0
  131. package/lib/public/modules/mate-sidebar.js +0 -8
  132. package/lib/public/modules/mate-wizard.js +0 -7
  133. package/lib/public/modules/mention.js +17 -19
  134. package/lib/public/modules/pane-bridge.js +9 -0
  135. package/lib/public/modules/profile.js +4 -5
  136. package/lib/public/modules/project-logs-ambient.js +238 -0
  137. package/lib/public/modules/project-logs-render.js +359 -0
  138. package/lib/public/modules/project-logs.js +328 -0
  139. package/lib/public/modules/project-settings.js +34 -28
  140. package/lib/public/modules/project-switcher.js +11 -5
  141. package/lib/public/modules/project-workspace-assignment.js +23 -0
  142. package/lib/public/modules/scheduler.js +17 -3
  143. package/lib/public/modules/search-clay-chat.js +402 -0
  144. package/lib/public/modules/server-settings.js +14 -12
  145. package/lib/public/modules/session-actions.js +1 -1
  146. package/lib/public/modules/sidebar-mates.js +56 -552
  147. package/lib/public/modules/sidebar-mobile.js +12 -73
  148. package/lib/public/modules/sidebar-presence.js +37 -0
  149. package/lib/public/modules/sidebar-sessions.js +25 -1
  150. package/lib/public/modules/split-pair-ui.js +13 -13
  151. package/lib/public/modules/split-view.js +7 -0
  152. package/lib/public/modules/sticky-notes.js +106 -53
  153. package/lib/public/modules/tool-input-composition.js +48 -0
  154. package/lib/public/modules/tool-llm-status.js +167 -0
  155. package/lib/public/modules/tool-palette.js +76 -4
  156. package/lib/public/modules/tool-renderer-advanced.js +285 -0
  157. package/lib/public/modules/tool-renderer-chart.js +158 -0
  158. package/lib/public/modules/tool-renderer-semantics.js +35 -0
  159. package/lib/public/modules/tool-renderer.js +464 -0
  160. package/lib/public/modules/tool-runtime.js +309 -0
  161. package/lib/public/modules/tool-ui-evaluator.js +97 -0
  162. package/lib/public/modules/tool-ui-tree.js +21 -0
  163. package/lib/public/modules/tui-attention.js +10 -0
  164. package/lib/public/modules/user-settings.js +16 -23
  165. package/lib/public/modules/vendor-login.js +287 -0
  166. package/lib/public/modules/worker-proposal.js +2 -2
  167. package/lib/public/modules/workspace-assignment-card.js +149 -0
  168. package/lib/public/modules/workspace-assignment-routing.js +4 -0
  169. package/lib/public/style.css +14 -2
  170. package/lib/runtime-env.js +65 -0
  171. package/lib/sdk-bridge.js +120 -32
  172. package/lib/sdk-message-processor.js +34 -13
  173. package/lib/server-home-capsule-creation.js +36 -0
  174. package/lib/server-home-chat-events.js +287 -0
  175. package/lib/server-home-chat.js +518 -0
  176. package/lib/server-home-clay-entry.js +65 -0
  177. package/lib/server-home-clay-session-links.js +26 -0
  178. package/lib/server-home-debate-planning.js +214 -0
  179. package/lib/server-home-debates.js +137 -0
  180. package/lib/server-home-mate-creation.js +261 -0
  181. package/lib/server-home-models.js +241 -0
  182. package/lib/server-home-preferences.js +61 -0
  183. package/lib/server-mates.js +37 -0
  184. package/lib/server-tools.js +377 -0
  185. package/lib/server.js +166 -59
  186. package/lib/session-pair-mcp-server.js +6 -6
  187. package/lib/sessions.js +22 -4
  188. package/lib/tool-capsule-source.js +142 -0
  189. package/lib/tool-control-mcp-server.js +126 -0
  190. package/lib/tool-llm.js +48 -0
  191. package/lib/tool-storage.js +77 -0
  192. package/lib/tool-ui-spec-advanced.js +82 -0
  193. package/lib/tool-ui-spec.js +261 -0
  194. package/lib/tools-registry.js +286 -0
  195. package/lib/users-home-dock-preferences.js +77 -0
  196. package/lib/users-home-surface-preferences.js +99 -0
  197. package/lib/users-preferences.js +4 -7
  198. package/lib/users.js +12 -0
  199. package/lib/whats-new-content.js +3 -3
  200. package/lib/workspace-assignment-service.js +420 -0
  201. package/lib/workspace-query-mcp-server.js +154 -0
  202. package/lib/workspace-query-service.js +492 -0
  203. package/lib/ws-schema.js +107 -12
  204. package/lib/yoke/adapters/acp.js +2 -1
  205. package/lib/yoke/adapters/antigravity.js +2 -1
  206. package/lib/yoke/adapters/claude-worker.js +11 -4
  207. package/lib/yoke/adapters/claude.js +141 -46
  208. package/lib/yoke/adapters/codex.js +79 -11
  209. package/lib/yoke/adapters/kiro.js +2 -1
  210. package/lib/yoke/claude-user-input.js +38 -0
  211. package/lib/yoke/codex-app-server.js +20 -2
  212. package/lib/yoke/codex-background-tasks.js +8 -2
  213. package/lib/yoke/codex-user-input.js +64 -0
  214. package/lib/yoke/complete-once.js +164 -0
  215. package/lib/yoke/index.js +5 -1
  216. package/lib/yoke/interface.js +19 -0
  217. package/lib/yoke/mcp-bridge-server.js +2 -6
  218. package/lib/yoke/user-input.js +254 -0
  219. package/package.json +4 -3
  220. package/lib/public/css/home-chat.css +0 -380
  221. package/lib/public/modules/home-chat.js +0 -438
  222. package/lib/server-clay-home.js +0 -245
@@ -0,0 +1,254 @@
1
+ // Provider-neutral structured user-input lifecycle for YOKE queries.
2
+
3
+ var crypto = require("crypto");
4
+ var z;
5
+ try { z = require("zod"); } catch (e) { z = null; }
6
+
7
+ var TOOL_NAME = "ask_user_questions";
8
+
9
+ function cleanText(value, field, max) {
10
+ if (typeof value !== "string" || !value.trim()) throw new Error(field + " must be a non-empty string.");
11
+ var text = value.trim();
12
+ if (text.length > max) throw new Error(field + " must be at most " + max + " characters.");
13
+ return text;
14
+ }
15
+
16
+ function normalizeOptions(options, questionIndex) {
17
+ if (options == null) return [];
18
+ if (!Array.isArray(options)) throw new Error("Question " + (questionIndex + 1) + " options must be an array.");
19
+ if (options.length === 1 || options.length > 6) {
20
+ throw new Error("Question " + (questionIndex + 1) + " must use zero options or 2-6 options.");
21
+ }
22
+ var result = [];
23
+ for (var i = 0; i < options.length; i++) {
24
+ var option = options[i] || {};
25
+ result.push({
26
+ label: cleanText(option.label || option.value, "Option label", 60),
27
+ description: typeof option.description === "string" ? option.description.trim().substring(0, 160) : "",
28
+ });
29
+ }
30
+ return result;
31
+ }
32
+
33
+ function normalizeQuestions(input) {
34
+ var source = input && Array.isArray(input.questions) ? input.questions : null;
35
+ if (!source || source.length < 1 || source.length > 3) throw new Error("Structured input requires 1-3 questions.");
36
+ var ids = {};
37
+ var questions = [];
38
+ for (var i = 0; i < source.length; i++) {
39
+ var item = source[i] || {};
40
+ var id = typeof item.id === "string" && item.id.trim() ? item.id.trim() : "question_" + (i + 1);
41
+ if (id.length > 128 || ids[id]) throw new Error("Question IDs must be unique strings of at most 128 characters.");
42
+ ids[id] = true;
43
+ questions.push({
44
+ id: id,
45
+ header: typeof item.header === "string" ? item.header.trim().substring(0, 40) : "",
46
+ question: cleanText(item.question || item.prompt, "Question", 2000),
47
+ multiSelect: item.multiSelect === true,
48
+ allowOther: item.allowOther !== false && item.isOther !== false,
49
+ secret: item.secret === true || item.isSecret === true,
50
+ options: normalizeOptions(item.options, i),
51
+ });
52
+ }
53
+ return questions;
54
+ }
55
+
56
+ function questionsFromElicitation(request) {
57
+ var schema = request && request.requestedSchema;
58
+ var properties = schema && schema.properties && typeof schema.properties === "object" ? schema.properties : null;
59
+ var questions = [];
60
+ if (properties) {
61
+ Object.keys(properties).forEach(function (id) {
62
+ var property = properties[id] || {};
63
+ var values = Array.isArray(property.enum) ? property.enum : [];
64
+ questions.push({
65
+ id: id,
66
+ header: request.serverName || "Input",
67
+ question: property.description || request.message || id,
68
+ options: values.map(function (value) { return { label: String(value), description: "" }; }),
69
+ });
70
+ });
71
+ }
72
+ if (!questions.length) questions.push({ id: "response", header: request.serverName || "Input", question: request.message || "What should the tool use?", options: [] });
73
+ return { questions: questions };
74
+ }
75
+
76
+ function answerValues(value) {
77
+ if (value && Array.isArray(value.answers)) value = value.answers;
78
+ if (!Array.isArray(value)) value = value == null ? [] : [value];
79
+ return value.map(function (entry) { return String(entry).trim(); }).filter(Boolean);
80
+ }
81
+
82
+ function normalizeAnswers(questions, raw) {
83
+ raw = raw || {};
84
+ var answers = {};
85
+ for (var i = 0; i < questions.length; i++) {
86
+ var question = questions[i];
87
+ var value = Object.prototype.hasOwnProperty.call(raw, question.id) ? raw[question.id] : raw[i];
88
+ var values = answerValues(value);
89
+ if (!values.length) throw new Error("An answer is required for " + question.id + ".");
90
+ if (!question.multiSelect && values.length > 1) throw new Error("Only one answer is allowed for " + question.id + ".");
91
+ answers[question.id] = values;
92
+ }
93
+ return answers;
94
+ }
95
+
96
+ /**
97
+ * Start one provider-neutral structured-input request.
98
+ *
99
+ * handler receives:
100
+ * request: { id, questions, source, native, provider, diagnostics }
101
+ * respond(answers): submits once; respond.cancel(reason) cancels once.
102
+ *
103
+ * The returned promise resolves to { status, answers|reason }. Provider
104
+ * adapters translate that result back to their own wire protocol. Nothing in
105
+ * this lifecycle is persisted; Clay callers may persist sanitized events.
106
+ */
107
+ function dispatchUserInput(handler, input, opts) {
108
+ opts = opts || {};
109
+ var questions;
110
+ try { questions = normalizeQuestions(input); } catch (e) { return Promise.reject(e); }
111
+ if (typeof handler !== "function") return Promise.reject(new Error("This query cannot request structured user input."));
112
+ var id = opts.requestId || (input && input.id) || "yoke_input_" + crypto.randomUUID();
113
+ var settled = false;
114
+ var abortHandler = null;
115
+ var settleListeners = [];
116
+ return new Promise(function (resolve, reject) {
117
+ function cleanup(result) {
118
+ if (opts.signal && abortHandler && typeof opts.signal.removeEventListener === "function") opts.signal.removeEventListener("abort", abortHandler);
119
+ for (var li = 0; li < settleListeners.length; li++) {
120
+ try { settleListeners[li](result); } catch (e) {}
121
+ }
122
+ }
123
+ function finish(result) {
124
+ if (settled) return false;
125
+ settled = true;
126
+ cleanup(result);
127
+ resolve(result);
128
+ return true;
129
+ }
130
+ function fail(error) {
131
+ if (settled) return false;
132
+ settled = true;
133
+ cleanup({ status: "error", error: error.message || String(error) });
134
+ reject(error);
135
+ return true;
136
+ }
137
+ var respond = function (answers) {
138
+ try { return finish({ status: "submitted", answers: normalizeAnswers(questions, answers) }); }
139
+ catch (e) { return fail(e); }
140
+ };
141
+ respond.submitContent = function (content) {
142
+ if (!content || typeof content !== "object" || Array.isArray(content)) return fail(new Error("Structured elicitation content must be an object."));
143
+ return finish({ status: "submitted", answers: {}, content: content });
144
+ };
145
+ respond.cancel = function (reason) { return finish({ status: "cancelled", reason: reason || "Cancelled" }); };
146
+ respond.isPending = function () { return !settled; };
147
+ respond.onSettle = function (listener) {
148
+ if (typeof listener === "function" && !settled) settleListeners.push(listener);
149
+ return respond;
150
+ };
151
+ abortHandler = function () { respond.cancel("Aborted"); };
152
+ if (opts.signal) {
153
+ if (opts.signal.aborted) return abortHandler();
154
+ opts.signal.addEventListener("abort", abortHandler, { once: true });
155
+ }
156
+ var request = {
157
+ id: String(id),
158
+ questions: questions,
159
+ presentation: opts.presentation || "questions",
160
+ source: opts.source || "unknown",
161
+ native: opts.native === true,
162
+ provider: opts.provider || null,
163
+ diagnostics: opts.diagnostics || null,
164
+ };
165
+ try {
166
+ var returned = handler(request, respond);
167
+ if (returned && typeof returned.then === "function") returned.catch(fail);
168
+ } catch (error) {
169
+ fail(error);
170
+ }
171
+ });
172
+ }
173
+
174
+ function claudePermissionResult(input, result) {
175
+ if (!result || result.status !== "submitted") return { behavior: "deny", message: (result && result.reason) || "Cancelled" };
176
+ var questions = normalizeQuestions(input);
177
+ var byText = {};
178
+ for (var i = 0; i < questions.length; i++) byText[questions[i].question] = result.answers[questions[i].id].join(", ");
179
+ return { behavior: "allow", updatedInput: Object.assign({}, input, { answers: byText }) };
180
+ }
181
+
182
+ function codexResponse(result) {
183
+ var answers = {};
184
+ if (result && result.status === "submitted") {
185
+ Object.keys(result.answers).forEach(function (id) { answers[id] = { answers: result.answers[id] }; });
186
+ }
187
+ return { answers: answers };
188
+ }
189
+
190
+ function elicitationResponse(result) {
191
+ if (!result || result.status !== "submitted") return { action: "reject" };
192
+ if (result.content) return { action: "accept", content: result.content };
193
+ var content = {};
194
+ Object.keys(result.answers).forEach(function (id) { content[id] = result.answers[id].length === 1 ? result.answers[id][0] : result.answers[id]; });
195
+ return { action: "accept", content: content };
196
+ }
197
+
198
+ function buildQuestionShape() {
199
+ if (!z) return {};
200
+ var option = z.object({ label: z.string().min(1).max(60), description: z.string().max(160).optional() }).passthrough();
201
+ var question = z.object({
202
+ id: z.string().max(128).optional(), header: z.string().max(40).optional(), question: z.string().min(1),
203
+ multiSelect: z.boolean().optional(), options: z.array(option).max(6).refine(function (items) { return items.length === 0 || items.length >= 2; }),
204
+ }).passthrough();
205
+ return { questions: z.array(question).min(1).max(3) };
206
+ }
207
+
208
+ function fallbackToolDefs(handler) {
209
+ return [{
210
+ name: TOOL_NAME,
211
+ description: "Ask the user 1-3 structured questions. Use zero options for freeform or 2-6 options for choices; never one option.",
212
+ inputSchema: buildQuestionShape(),
213
+ handler: function (input) {
214
+ return dispatchUserInput(handler, input, { source: "mcp_fallback", native: false }).then(function (result) {
215
+ if (result.status !== "submitted") return { content: [{ type: "text", text: "The user cancelled this question." }], isError: true };
216
+ return { content: [{ type: "text", text: JSON.stringify(result.answers) }] };
217
+ }).catch(function (error) { return { content: [{ type: "text", text: "Error: " + error.message }], isError: true }; });
218
+ },
219
+ }];
220
+ }
221
+
222
+ function capability(adapter) {
223
+ return adapter && adapter.userInputCapability ? adapter.userInputCapability : { mode: "fallback", native: false };
224
+ }
225
+
226
+ function selectMode(adapter, requestedMode) {
227
+ if (requestedMode === "fallback") return "fallback";
228
+ if (requestedMode === "native" && capability(adapter).mode !== "native") {
229
+ throw new Error("This provider does not support native structured user input.");
230
+ }
231
+ return capability(adapter).mode === "native" ? "native" : "fallback";
232
+ }
233
+
234
+ function createFallbackServer(adapter, handler) {
235
+ var opts = arguments.length > 2 && arguments[2] ? arguments[2] : {};
236
+ if (!adapter || typeof adapter.createToolServer !== "function") return null;
237
+ if (capability(adapter).mode === "native" && opts.force !== true) return null;
238
+ return adapter.createToolServer({ name: "yoke-user-input", version: "1.0.0", tools: fallbackToolDefs(handler) });
239
+ }
240
+
241
+ module.exports = {
242
+ TOOL_NAME: TOOL_NAME,
243
+ normalizeQuestions: normalizeQuestions,
244
+ questionsFromElicitation: questionsFromElicitation,
245
+ normalizeAnswers: normalizeAnswers,
246
+ dispatchUserInput: dispatchUserInput,
247
+ claudePermissionResult: claudePermissionResult,
248
+ codexResponse: codexResponse,
249
+ elicitationResponse: elicitationResponse,
250
+ fallbackToolDefs: fallbackToolDefs,
251
+ createFallbackServer: createFallbackServer,
252
+ capability: capability,
253
+ selectMode: selectMode,
254
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clay-server",
3
- "version": "3.8.1",
3
+ "version": "4.0.0-beta.10",
4
4
  "description": "Self-hosted team workspace for Claude Code and Codex. Multi-user, browser-based, with persistent AI mates.",
5
5
  "bin": {
6
6
  "clay-server": "./bin/cli.js",
@@ -49,9 +49,10 @@
49
49
  "homepage": "https://github.com/chadbyte/clay#readme",
50
50
  "author": "Chad",
51
51
  "dependencies": {
52
- "@anthropic-ai/claude-agent-sdk": "^0.3.241",
52
+ "@anthropic-ai/claude-agent-sdk": "^0.3.258",
53
53
  "@lydell/node-pty": "^1.2.0-beta.3",
54
- "@openai/codex": "^0.147.0",
54
+ "@openai/codex": "^0.152.1",
55
+ "@seald-io/nedb": "^4.1.2",
55
56
  "imapflow": "^1.3.1",
56
57
  "nodemailer": "^9.0.5",
57
58
  "qrcode-terminal": "^0.12.0",
@@ -1,380 +0,0 @@
1
- /* ==========================================================================
2
- Clay FAB + popover — phablet-style chat reachable from anywhere
3
- ==========================================================================
4
- The FAB (#clay-fab) sits at the bottom-right corner over all page
5
- content. Clicking it toggles #clay-popover, which contains the
6
- .home-chat-frame (rounded card with header / messages / input).
7
- Inspired by Vercel's persistent toolbar pattern. */
8
-
9
- /* --- FAB ---
10
- Draggable. Default position is bottom-right; user position is
11
- restored from localStorage. Inline `top`/`left` set by JS override
12
- the default `right`/`bottom`. */
13
-
14
- .clay-fab {
15
- position: fixed;
16
- right: 18px;
17
- bottom: 18px;
18
- width: 44px;
19
- height: 44px;
20
- border-radius: 50%;
21
- border: none;
22
- background: var(--bg, #fff);
23
- box-shadow: 0 4px 14px rgba(0, 0, 0, 0.16), 0 2px 4px rgba(0, 0, 0, 0.08);
24
- cursor: grab;
25
- z-index: 9000;
26
- display: flex;
27
- align-items: center;
28
- justify-content: center;
29
- padding: 0;
30
- transition: box-shadow 0.18s, opacity 0.18s, transform 0.18s cubic-bezier(.2,.7,.3,1.3);
31
- user-select: none;
32
- touch-action: none;
33
- }
34
- .clay-fab:hover {
35
- box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2), 0 3px 6px rgba(0, 0, 0, 0.10);
36
- }
37
- .clay-fab.dragging {
38
- cursor: grabbing;
39
- transition: none;
40
- box-shadow: 0 12px 28px rgba(0, 0, 0, 0.26), 0 4px 8px rgba(0, 0, 0, 0.14);
41
- }
42
- .clay-fab.open {
43
- /* Hide while popover is open — the popover X button is the close path */
44
- transform: scale(0.6);
45
- opacity: 0;
46
- pointer-events: none;
47
- }
48
-
49
- .clay-fab-icon {
50
- width: 30px;
51
- height: 30px;
52
- border-radius: 50%;
53
- object-fit: cover;
54
- pointer-events: none;
55
- }
56
-
57
- /* Subtle pulse ring to draw the eye on first paint */
58
- .clay-fab-pulse {
59
- position: absolute;
60
- inset: -2px;
61
- border-radius: 50%;
62
- border: 2px solid var(--accent);
63
- opacity: 0;
64
- pointer-events: none;
65
- animation: clay-fab-pulse 2.4s ease-out 1s 2;
66
- }
67
- @keyframes clay-fab-pulse {
68
- 0% { opacity: 0; transform: scale(1); }
69
- 20% { opacity: 0.55; }
70
- 100% { opacity: 0; transform: scale(1.6); }
71
- }
72
-
73
- /* --- Popover --- */
74
-
75
- .clay-popover {
76
- position: fixed;
77
- right: 18px;
78
- bottom: 18px;
79
- width: 320px;
80
- height: 480px;
81
- max-width: calc(100vw - 32px);
82
- max-height: calc(100vh - 40px);
83
- z-index: 9001;
84
- display: flex;
85
- transform-origin: bottom right;
86
- animation: clay-popover-in 0.18s cubic-bezier(.2,.7,.3,1.05);
87
- }
88
- .clay-popover.hidden {
89
- display: none;
90
- }
91
- @keyframes clay-popover-in {
92
- from { transform: translateY(8px) scale(0.96); opacity: 0; }
93
- to { transform: translateY(0) scale(1); opacity: 1; }
94
- }
95
-
96
- .clay-popover .home-chat-frame {
97
- width: 100%;
98
- height: 100%;
99
- display: flex;
100
- flex-direction: column;
101
- background: var(--bg-alt, var(--bg));
102
- border: 1px solid var(--border);
103
- border-radius: 18px;
104
- box-shadow: 0 14px 40px rgba(0, 0, 0, 0.22), 0 4px 10px rgba(0, 0, 0, 0.10);
105
- overflow: hidden;
106
- }
107
-
108
- /* --- Header --- */
109
-
110
- .home-chat-header {
111
- display: flex;
112
- align-items: center;
113
- gap: 10px;
114
- padding: 12px 12px 12px 14px;
115
- border-bottom: 1px solid var(--border);
116
- background: var(--bg);
117
- }
118
-
119
- .home-chat-avatar-wrap {
120
- width: 34px;
121
- height: 34px;
122
- border-radius: 50%;
123
- overflow: hidden;
124
- flex-shrink: 0;
125
- background: var(--accent);
126
- display: flex;
127
- align-items: center;
128
- justify-content: center;
129
- }
130
-
131
- .home-chat-avatar {
132
- width: 100%;
133
- height: 100%;
134
- object-fit: cover;
135
- display: block;
136
- }
137
-
138
- .home-chat-title-block {
139
- flex: 1;
140
- min-width: 0;
141
- }
142
-
143
- .home-chat-title {
144
- font-size: 14px;
145
- font-weight: 600;
146
- color: var(--text);
147
- line-height: 1.2;
148
- }
149
-
150
- .home-chat-subtitle {
151
- font-size: 11px;
152
- color: var(--text-muted, var(--text-dimmer));
153
- line-height: 1.2;
154
- margin-top: 2px;
155
- white-space: nowrap;
156
- overflow: hidden;
157
- text-overflow: ellipsis;
158
- }
159
-
160
- .home-chat-icon-btn {
161
- background: none;
162
- border: none;
163
- width: 30px;
164
- height: 30px;
165
- border-radius: 8px;
166
- display: flex;
167
- align-items: center;
168
- justify-content: center;
169
- cursor: pointer;
170
- color: var(--text-muted, var(--text-dimmer));
171
- flex-shrink: 0;
172
- }
173
- .home-chat-icon-btn:hover {
174
- background: var(--hover-bg, rgba(0,0,0,0.05));
175
- color: var(--text);
176
- }
177
- .home-chat-icon-btn .lucide {
178
- width: 16px;
179
- height: 16px;
180
- }
181
-
182
- /* --- Messages list --- */
183
-
184
- .home-chat-messages {
185
- flex: 1;
186
- overflow-y: auto;
187
- padding: 14px 12px;
188
- display: flex;
189
- flex-direction: column;
190
- gap: 8px;
191
- background: var(--input-bg, var(--bg));
192
- scroll-behavior: smooth;
193
- }
194
-
195
- .home-chat-bubble {
196
- max-width: 88%;
197
- padding: 9px 12px;
198
- border-radius: 16px;
199
- font-size: 13px;
200
- line-height: 1.5;
201
- word-wrap: break-word;
202
- white-space: pre-wrap;
203
- box-shadow: 0 1px 1px rgba(0,0,0,0.04);
204
- }
205
-
206
- .home-chat-bubble-user {
207
- align-self: flex-end;
208
- background: var(--accent);
209
- color: #fff;
210
- border-bottom-right-radius: 6px;
211
- }
212
-
213
- .home-chat-bubble-clay {
214
- align-self: flex-start;
215
- background: var(--bg);
216
- color: var(--text);
217
- border: 1px solid var(--border);
218
- border-bottom-left-radius: 6px;
219
- }
220
-
221
- .home-chat-bubble-system {
222
- align-self: center;
223
- font-size: 11px;
224
- color: var(--text-muted, var(--text-dimmer));
225
- background: transparent;
226
- padding: 4px 10px;
227
- font-style: italic;
228
- text-align: center;
229
- max-width: 100%;
230
- }
231
-
232
- .home-chat-ref {
233
- display: inline-block;
234
- background: rgba(124, 58, 237, 0.08);
235
- color: var(--accent);
236
- padding: 1px 8px;
237
- border-radius: 10px;
238
- font-family: "Roboto Mono", "Courier New", monospace;
239
- font-size: 11px;
240
- cursor: pointer;
241
- margin: 0 2px;
242
- border: 1px solid rgba(124, 58, 237, 0.18);
243
- }
244
- .home-chat-ref:hover {
245
- background: rgba(124, 58, 237, 0.16);
246
- }
247
-
248
- /* --- Typing indicator --- */
249
-
250
- .home-chat-typing {
251
- display: flex;
252
- gap: 4px;
253
- padding: 4px 16px 0;
254
- align-items: center;
255
- }
256
- .home-chat-typing.hidden { display: none; }
257
-
258
- .home-chat-typing-dot {
259
- width: 5px;
260
- height: 5px;
261
- border-radius: 50%;
262
- background: var(--text-dimmer);
263
- animation: home-chat-bounce 1.2s infinite ease-in-out;
264
- }
265
- .home-chat-typing-dot:nth-child(1) { animation-delay: 0s; }
266
- .home-chat-typing-dot:nth-child(2) { animation-delay: 0.15s; }
267
- .home-chat-typing-dot:nth-child(3) { animation-delay: 0.30s; }
268
-
269
- @keyframes home-chat-bounce {
270
- 0%, 80%, 100% { transform: translateY(0); opacity: 0.4; }
271
- 40% { transform: translateY(-4px); opacity: 1; }
272
- }
273
-
274
- /* --- Input row --- */
275
-
276
- .home-chat-input-row {
277
- display: flex;
278
- align-items: flex-end;
279
- gap: 8px;
280
- padding: 10px 10px 12px;
281
- border-top: 1px solid var(--border);
282
- background: var(--bg);
283
- }
284
-
285
- .home-chat-input {
286
- flex: 1;
287
- border: 1px solid var(--border);
288
- border-radius: 16px;
289
- padding: 9px 12px;
290
- background: var(--input-bg, var(--bg));
291
- color: var(--text);
292
- font-size: 13px;
293
- line-height: 1.5;
294
- font-family: inherit;
295
- resize: none;
296
- max-height: 120px;
297
- outline: none;
298
- transition: border-color 0.15s, box-shadow 0.15s;
299
- }
300
- .home-chat-input:focus {
301
- border-color: var(--accent);
302
- box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.18);
303
- }
304
-
305
- .home-chat-send-btn {
306
- flex-shrink: 0;
307
- width: 34px;
308
- height: 34px;
309
- border-radius: 50%;
310
- border: none;
311
- background: var(--accent);
312
- color: #fff;
313
- display: flex;
314
- align-items: center;
315
- justify-content: center;
316
- cursor: pointer;
317
- transition: opacity 0.15s, transform 0.1s;
318
- }
319
- .home-chat-send-btn:disabled {
320
- opacity: 0.4;
321
- cursor: default;
322
- }
323
- .home-chat-send-btn:not(:disabled):hover { opacity: 0.9; }
324
- .home-chat-send-btn:not(:disabled):active { transform: scale(0.95); }
325
- .home-chat-send-btn .lucide {
326
- width: 16px;
327
- height: 16px;
328
- }
329
-
330
- /* --- Mobile / narrow ---
331
- On phones the popover fills the screen edge-to-edge with a small
332
- inset, and the FAB shrinks slightly. */
333
-
334
- @media (max-width: 768px) {
335
- /* Lift the FAB above the mobile tab bar (56px + safe-bottom).
336
- Only applies when JS hasn't placed the FAB at a custom position
337
- (custom positions use inline top/left and override these defaults). */
338
- .clay-fab:not(.user-positioned) {
339
- right: 14px;
340
- bottom: calc(56px + var(--safe-bottom, 0px) + 14px);
341
- }
342
- .clay-fab {
343
- width: 44px;
344
- height: 44px;
345
- }
346
- .clay-fab-icon {
347
- width: 30px;
348
- height: 30px;
349
- }
350
- }
351
-
352
- @media (max-width: 600px) {
353
- .clay-popover {
354
- right: 8px;
355
- bottom: calc(56px + var(--safe-bottom, 0px) + 8px);
356
- left: 8px;
357
- width: auto;
358
- height: 70vh;
359
- max-height: calc(100vh - 80px - var(--safe-bottom, 0px));
360
- }
361
- .clay-popover .home-chat-frame {
362
- border-radius: 16px;
363
- }
364
- }
365
-
366
- /* When the mobile tab bar is hidden by the keyboard, drop the FAB back
367
- down so it doesn't float in dead space. */
368
- @media (max-width: 768px) {
369
- #mobile-tab-bar.keyboard-hidden ~ .clay-fab,
370
- body:has(#mobile-tab-bar.keyboard-hidden) .clay-fab {
371
- bottom: 14px;
372
- }
373
- }
374
-
375
- /* Hide FAB while user is on auth/setup pages or any modal-heavy screens.
376
- Add the class .clay-fab-suppressed on <body> when needed. */
377
- body.clay-fab-suppressed .clay-fab,
378
- body.clay-fab-suppressed .clay-popover {
379
- display: none !important;
380
- }