clay-server 2.33.0-beta.2 → 2.33.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.
- package/lib/project-connection.js +1 -0
- package/lib/project-sessions.js +12 -0
- package/lib/project.js +38 -5
- package/lib/public/css/debate.css +0 -29
- package/lib/public/css/mobile-nav.css +17 -0
- package/lib/public/css/notifications-center.css +30 -17
- package/lib/public/css/overlays.css +7 -1
- package/lib/public/css/sidebar.css +65 -39
- package/lib/public/index.html +0 -2
- package/lib/public/modules/app-messages.js +11 -1
- package/lib/public/modules/app-panels.js +1 -1
- package/lib/public/modules/app-rate-limit.js +33 -6
- package/lib/public/modules/sidebar-mobile.js +41 -3
- package/lib/public/modules/sidebar-sessions.js +68 -4
- package/lib/public/modules/sidebar.js +7 -4
- package/lib/public/modules/tool-palette.js +3 -1
- package/lib/public/modules/tools.js +47 -26
- package/lib/sdk-bridge.js +58 -6
- package/lib/sdk-message-processor.js +55 -1
- package/lib/sessions.js +15 -0
- package/lib/ws-schema.js +1 -0
- package/lib/yoke/adapters/codex.js +145 -9
- package/lib/yoke/index.js +5 -1
- package/package.json +1 -1
|
@@ -89,6 +89,23 @@ function generateUuid() {
|
|
|
89
89
|
return "codex-" + ts + "-" + cnt + "-" + rnd;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
function normalizePlanStatus(status) {
|
|
93
|
+
if (status === "inProgress") return "in_progress";
|
|
94
|
+
if (status === "completed") return "completed";
|
|
95
|
+
return "pending";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function extractPromptSuggestion(params) {
|
|
99
|
+
if (!params) return "";
|
|
100
|
+
if (typeof params.suggestion === "string") return params.suggestion;
|
|
101
|
+
if (typeof params.promptSuggestion === "string") return params.promptSuggestion;
|
|
102
|
+
if (typeof params.suggestedPrompt === "string") return params.suggestedPrompt;
|
|
103
|
+
if (Array.isArray(params.suggestions) && typeof params.suggestions[0] === "string") return params.suggestions[0];
|
|
104
|
+
if (Array.isArray(params.promptSuggestions) && typeof params.promptSuggestions[0] === "string") return params.promptSuggestions[0];
|
|
105
|
+
if (Array.isArray(params.followUpSuggestions) && typeof params.followUpSuggestions[0] === "string") return params.followUpSuggestions[0];
|
|
106
|
+
return "";
|
|
107
|
+
}
|
|
108
|
+
|
|
92
109
|
function flattenEvent(notification, state) {
|
|
93
110
|
var events = [];
|
|
94
111
|
var method = notification.method;
|
|
@@ -142,6 +159,21 @@ function flattenEvent(notification, state) {
|
|
|
142
159
|
return events;
|
|
143
160
|
}
|
|
144
161
|
|
|
162
|
+
if (method === "turn/plan/updated") {
|
|
163
|
+
events.push({
|
|
164
|
+
yokeType: "plan_updated",
|
|
165
|
+
turnId: params.turnId || null,
|
|
166
|
+
explanation: params.explanation || "",
|
|
167
|
+
plan: Array.isArray(params.plan) ? params.plan.map(function(step) {
|
|
168
|
+
return {
|
|
169
|
+
step: step && step.step ? step.step : "",
|
|
170
|
+
status: normalizePlanStatus(step && step.status),
|
|
171
|
+
};
|
|
172
|
+
}) : [],
|
|
173
|
+
});
|
|
174
|
+
return events;
|
|
175
|
+
}
|
|
176
|
+
|
|
145
177
|
if (method === "turn/failed") {
|
|
146
178
|
events.push({
|
|
147
179
|
yokeType: "error",
|
|
@@ -202,6 +234,20 @@ function flattenEvent(notification, state) {
|
|
|
202
234
|
return events;
|
|
203
235
|
}
|
|
204
236
|
|
|
237
|
+
if (method === "item/plan/delta") {
|
|
238
|
+
var planDeltaItemId = params.itemId || params.id;
|
|
239
|
+
var nextPlanText = (state.planTexts[planDeltaItemId] || "") + (params.delta || "");
|
|
240
|
+
if (planDeltaItemId) state.planTexts[planDeltaItemId] = nextPlanText;
|
|
241
|
+
if (nextPlanText) {
|
|
242
|
+
events.push({
|
|
243
|
+
yokeType: "plan_content",
|
|
244
|
+
content: nextPlanText,
|
|
245
|
+
itemId: planDeltaItemId || null,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
return events;
|
|
249
|
+
}
|
|
250
|
+
|
|
205
251
|
// serverRequest/resolved - confirmation that an approval was processed
|
|
206
252
|
if (method === "serverRequest/resolved") {
|
|
207
253
|
return events; // no-op, approval already handled
|
|
@@ -214,6 +260,27 @@ function flattenEvent(notification, state) {
|
|
|
214
260
|
|
|
215
261
|
var evtPhase = method.split("/")[1]; // "started", "updated", "completed"
|
|
216
262
|
|
|
263
|
+
if (item.type === "plan") {
|
|
264
|
+
if (typeof item.text === "string") {
|
|
265
|
+
state.planTexts[item.id] = item.text;
|
|
266
|
+
events.push({
|
|
267
|
+
yokeType: "plan_content",
|
|
268
|
+
content: item.text,
|
|
269
|
+
itemId: item.id,
|
|
270
|
+
final: evtPhase === "completed",
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
return events;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (item.type === "contextCompaction" || item.type === "context_compaction") {
|
|
277
|
+
events.push({
|
|
278
|
+
yokeType: "status",
|
|
279
|
+
status: evtPhase === "completed" ? "processing" : "compacting",
|
|
280
|
+
});
|
|
281
|
+
return events;
|
|
282
|
+
}
|
|
283
|
+
|
|
217
284
|
// Agent message (text response)
|
|
218
285
|
if (item.type === "agentMessage" || item.type === "agent_message") {
|
|
219
286
|
if (!state.textBlocks[item.id]) {
|
|
@@ -262,6 +329,8 @@ function flattenEvent(notification, state) {
|
|
|
262
329
|
|
|
263
330
|
// Command execution (bash/shell)
|
|
264
331
|
if (item.type === "commandExecution" || item.type === "command_execution") {
|
|
332
|
+
var commandText = item.command || state.commandInputs[item.id] || "";
|
|
333
|
+
if (commandText) state.commandInputs[item.id] = commandText;
|
|
265
334
|
if (!state.toolBlocks[item.id]) {
|
|
266
335
|
state.blockCounter++;
|
|
267
336
|
state.toolBlocks[item.id] = "blk_" + state.blockCounter;
|
|
@@ -277,7 +346,7 @@ function flattenEvent(notification, state) {
|
|
|
277
346
|
blockId: toolBlockId,
|
|
278
347
|
toolId: item.id,
|
|
279
348
|
toolName: "Bash",
|
|
280
|
-
input: { command:
|
|
349
|
+
input: { command: commandText },
|
|
281
350
|
});
|
|
282
351
|
}
|
|
283
352
|
if (evtPhase === "completed") {
|
|
@@ -294,6 +363,9 @@ function flattenEvent(notification, state) {
|
|
|
294
363
|
|
|
295
364
|
// File change
|
|
296
365
|
if (item.type === "fileChange" || item.type === "file_change") {
|
|
366
|
+
var changes = item.changes || [];
|
|
367
|
+
var changeDesc = changes.map(function(c) { return c.kind + " " + c.path; }).join(", ");
|
|
368
|
+
var primaryPath = changes.length === 1 ? (changes[0].path || "") : "";
|
|
297
369
|
if (!state.toolBlocks[item.id]) {
|
|
298
370
|
state.blockCounter++;
|
|
299
371
|
state.toolBlocks[item.id] = "blk_" + state.blockCounter;
|
|
@@ -304,21 +376,26 @@ function flattenEvent(notification, state) {
|
|
|
304
376
|
toolId: item.id,
|
|
305
377
|
toolName: "Edit",
|
|
306
378
|
});
|
|
307
|
-
var changeDesc = (item.changes || []).map(function(c) { return c.kind + " " + c.path; }).join(", ");
|
|
308
379
|
events.push({
|
|
309
380
|
yokeType: "tool_executing",
|
|
310
381
|
blockId: fcBlockId,
|
|
311
382
|
toolId: item.id,
|
|
312
383
|
toolName: "Edit",
|
|
313
|
-
input: {
|
|
384
|
+
input: {
|
|
385
|
+
changes: changeDesc,
|
|
386
|
+
file_path: primaryPath || undefined,
|
|
387
|
+
},
|
|
314
388
|
});
|
|
315
389
|
}
|
|
316
390
|
if (evtPhase === "completed") {
|
|
391
|
+
var diffText = changes.map(function(c) {
|
|
392
|
+
return c && c.diff ? c.diff : "";
|
|
393
|
+
}).filter(Boolean).join("\n\n");
|
|
317
394
|
events.push({
|
|
318
395
|
yokeType: "tool_result",
|
|
319
396
|
toolId: item.id,
|
|
320
397
|
blockId: state.toolBlocks[item.id],
|
|
321
|
-
content: item.status === "completed" ? "Changes applied" : "Changes failed",
|
|
398
|
+
content: diffText || (item.status === "completed" ? "Changes applied" : "Changes failed"),
|
|
322
399
|
isError: item.status === "failed",
|
|
323
400
|
});
|
|
324
401
|
}
|
|
@@ -397,6 +474,15 @@ function flattenEvent(notification, state) {
|
|
|
397
474
|
return events;
|
|
398
475
|
}
|
|
399
476
|
|
|
477
|
+
var promptSuggestion = extractPromptSuggestion(params);
|
|
478
|
+
if (promptSuggestion) {
|
|
479
|
+
events.push({
|
|
480
|
+
yokeType: "prompt_suggestion",
|
|
481
|
+
suggestion: promptSuggestion,
|
|
482
|
+
});
|
|
483
|
+
return events;
|
|
484
|
+
}
|
|
485
|
+
|
|
400
486
|
// Unknown event type - pass through
|
|
401
487
|
console.log("[yoke/codex] UNHANDLED event:", method, JSON.stringify(params).substring(0, 200));
|
|
402
488
|
events.push({
|
|
@@ -415,6 +501,7 @@ function createCodexQueryHandle(appServer, queryOpts) {
|
|
|
415
501
|
var abortController = queryOpts.abortController;
|
|
416
502
|
var systemPrompt = queryOpts.systemPrompt || "";
|
|
417
503
|
var canUseTool = queryOpts.canUseTool || null;
|
|
504
|
+
var onElicitation = queryOpts.onElicitation || null;
|
|
418
505
|
|
|
419
506
|
// Check if the query was cancelled (either via handle.abort() or direct signal abort)
|
|
420
507
|
function isCancelled() {
|
|
@@ -437,6 +524,8 @@ function createCodexQueryHandle(appServer, queryOpts) {
|
|
|
437
524
|
thinkingBlocks: {}, // itemId -> blockId
|
|
438
525
|
thinkingLengths: {}, // itemId -> last sent length
|
|
439
526
|
toolBlocks: {}, // itemId -> blockId (for tool_start dedup)
|
|
527
|
+
commandInputs: {}, // itemId -> command captured from approval/start events
|
|
528
|
+
planTexts: {}, // itemId -> streamed plan text
|
|
440
529
|
};
|
|
441
530
|
|
|
442
531
|
// Internal event buffer for async iterator
|
|
@@ -512,6 +601,9 @@ function createCodexQueryHandle(appServer, queryOpts) {
|
|
|
512
601
|
// Command approval request
|
|
513
602
|
if (method === "item/commandExecution/requestApproval") {
|
|
514
603
|
var cmdParams = msg.params || {};
|
|
604
|
+
if (cmdParams.itemId && cmdParams.command) {
|
|
605
|
+
state.commandInputs[cmdParams.itemId] = cmdParams.command;
|
|
606
|
+
}
|
|
515
607
|
if (canUseTool) {
|
|
516
608
|
canUseTool("Bash", { command: cmdParams.command }, {}).then(function(decision) {
|
|
517
609
|
var approved = isApproved(decision);
|
|
@@ -549,7 +641,45 @@ function createCodexQueryHandle(appServer, queryOpts) {
|
|
|
549
641
|
var mcpParams = msg.params || {};
|
|
550
642
|
var mcpMeta = mcpParams._meta || {};
|
|
551
643
|
console.log("[yoke/codex] MCP approval request:", (mcpMeta.tool || "?"), "server=" + (mcpParams.serverName || "?"));
|
|
552
|
-
if (
|
|
644
|
+
if (onElicitation) {
|
|
645
|
+
var request = {
|
|
646
|
+
serverName: mcpParams.serverName || (mcpMeta.tool || "Tool"),
|
|
647
|
+
message: mcpParams.message || mcpParams.prompt || "",
|
|
648
|
+
mode: mcpParams.url ? "url" : "form",
|
|
649
|
+
url: mcpParams.url || null,
|
|
650
|
+
elicitationId: mcpParams.elicitationId || null,
|
|
651
|
+
requestedSchema: mcpParams.requestedSchema || null,
|
|
652
|
+
};
|
|
653
|
+
if (!request.requestedSchema && Array.isArray(mcpParams.questions) && mcpParams.questions.length > 0) {
|
|
654
|
+
var schema = { type: "object", properties: {}, required: [] };
|
|
655
|
+
for (var qi = 0; qi < mcpParams.questions.length; qi++) {
|
|
656
|
+
var q = mcpParams.questions[qi];
|
|
657
|
+
var qid = q.id || ("question_" + (qi + 1));
|
|
658
|
+
schema.required.push(qid);
|
|
659
|
+
if (Array.isArray(q.options) && q.options.length > 0) {
|
|
660
|
+
schema.properties[qid] = {
|
|
661
|
+
type: "string",
|
|
662
|
+
description: q.question || q.prompt || qid,
|
|
663
|
+
enum: q.options.map(function(opt) { return opt && (opt.value || opt.label) ? (opt.value || opt.label) : ""; }).filter(Boolean),
|
|
664
|
+
};
|
|
665
|
+
} else {
|
|
666
|
+
schema.properties[qid] = {
|
|
667
|
+
type: "string",
|
|
668
|
+
description: q.question || q.prompt || qid,
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
request.requestedSchema = schema;
|
|
673
|
+
}
|
|
674
|
+
onElicitation(request, {
|
|
675
|
+
signal: { addEventListener: function() {} },
|
|
676
|
+
}).then(function(result) {
|
|
677
|
+
appServer.respond(msg.id, result || { action: "reject" });
|
|
678
|
+
}).catch(function(err) {
|
|
679
|
+
console.error("[yoke/codex] elicitation_response send failed:", err.message || err);
|
|
680
|
+
appServer.respond(msg.id, { action: "reject" });
|
|
681
|
+
});
|
|
682
|
+
} else if (canUseTool) {
|
|
553
683
|
canUseTool("mcp__" + (mcpParams.serverName || "unknown") + "__" + (mcpMeta.tool || "call"), mcpParams, {}).then(function(decision) {
|
|
554
684
|
appServer.respond(msg.id, { action: isApproved(decision) ? "accept" : "decline" });
|
|
555
685
|
}).catch(function(err) {
|
|
@@ -592,9 +722,9 @@ function createCodexQueryHandle(appServer, queryOpts) {
|
|
|
592
722
|
// Start or resume thread
|
|
593
723
|
var threadParams = {
|
|
594
724
|
model: queryOpts.model || "gpt-5.4",
|
|
595
|
-
|
|
725
|
+
sandbox: queryOpts.sandboxMode || "workspace-write",
|
|
596
726
|
approvalPolicy: queryOpts.approvalPolicy || "on-failure",
|
|
597
|
-
|
|
727
|
+
cwd: queryOpts.cwd,
|
|
598
728
|
skipGitRepoCheck: true,
|
|
599
729
|
};
|
|
600
730
|
if (queryOpts.modelReasoningEffort) {
|
|
@@ -609,6 +739,9 @@ function createCodexQueryHandle(appServer, queryOpts) {
|
|
|
609
739
|
threadResult = await appServer.send("thread/resume", {
|
|
610
740
|
threadId: queryOpts.resumeSessionId,
|
|
611
741
|
model: threadParams.model,
|
|
742
|
+
sandbox: threadParams.sandbox,
|
|
743
|
+
approvalPolicy: threadParams.approvalPolicy,
|
|
744
|
+
cwd: threadParams.cwd,
|
|
612
745
|
}, 60000);
|
|
613
746
|
} else {
|
|
614
747
|
threadResult = await appServer.send("thread/start", threadParams, 60000);
|
|
@@ -626,6 +759,8 @@ function createCodexQueryHandle(appServer, queryOpts) {
|
|
|
626
759
|
state.thinkingBlocks = {};
|
|
627
760
|
state.thinkingLengths = {};
|
|
628
761
|
state.toolBlocks = {};
|
|
762
|
+
state.commandInputs = {};
|
|
763
|
+
state.planTexts = {};
|
|
629
764
|
|
|
630
765
|
// Start turn
|
|
631
766
|
var turnPromise = new Promise(function(resolve) { turnResolve = resolve; });
|
|
@@ -822,7 +957,7 @@ function createCodexAdapter(opts) {
|
|
|
822
957
|
betas: false,
|
|
823
958
|
rewind: false,
|
|
824
959
|
sessionResume: true,
|
|
825
|
-
promptSuggestions:
|
|
960
|
+
promptSuggestions: true,
|
|
826
961
|
elicitation: true,
|
|
827
962
|
fileCheckpointing: false,
|
|
828
963
|
contextCompacting: false,
|
|
@@ -974,7 +1109,7 @@ function createCodexAdapter(opts) {
|
|
|
974
1109
|
betas: false,
|
|
975
1110
|
rewind: false,
|
|
976
1111
|
sessionResume: true,
|
|
977
|
-
promptSuggestions:
|
|
1112
|
+
promptSuggestions: true,
|
|
978
1113
|
elicitation: true,
|
|
979
1114
|
fileCheckpointing: false,
|
|
980
1115
|
contextCompacting: false,
|
|
@@ -1014,6 +1149,7 @@ function createCodexAdapter(opts) {
|
|
|
1014
1149
|
systemPrompt: queryOpts.systemPrompt || "",
|
|
1015
1150
|
abortController: ac,
|
|
1016
1151
|
canUseTool: queryOpts.canUseTool || null,
|
|
1152
|
+
onElicitation: queryOpts.onElicitation || null,
|
|
1017
1153
|
resumeSessionId: queryOpts.resumeSessionId || null,
|
|
1018
1154
|
};
|
|
1019
1155
|
|
package/lib/yoke/index.js
CHANGED
|
@@ -162,7 +162,7 @@ function createAdapters(opts) {
|
|
|
162
162
|
* Re-checks auth, creates adapter if now logged in.
|
|
163
163
|
* Returns the adapter or null.
|
|
164
164
|
*/
|
|
165
|
-
function lazyCreateAdapter(adapters, vendor, opts) {
|
|
165
|
+
async function lazyCreateAdapter(adapters, vendor, opts) {
|
|
166
166
|
if (_sharedAdapters && _sharedAdapters[vendor]) {
|
|
167
167
|
adapters[vendor] = _sharedAdapters[vendor];
|
|
168
168
|
return adapters[vendor];
|
|
@@ -177,8 +177,12 @@ function lazyCreateAdapter(adapters, vendor, opts) {
|
|
|
177
177
|
|
|
178
178
|
try {
|
|
179
179
|
var ad = createAdapter({ vendor: vendor, cwd: opts.cwd });
|
|
180
|
+
if (typeof ad.init === "function") {
|
|
181
|
+
await ad.init(opts || {});
|
|
182
|
+
}
|
|
180
183
|
console.log("[yoke] Lazy adapter created: " + vendor);
|
|
181
184
|
if (_sharedAdapters) _sharedAdapters[vendor] = ad;
|
|
185
|
+
if (_sharedAuth) _sharedAuth[vendor] = true;
|
|
182
186
|
adapters[vendor] = ad;
|
|
183
187
|
return ad;
|
|
184
188
|
} catch (e) {
|