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.
- package/lib/ask-user-mcp-server.js +5 -119
- package/lib/background-task-timing.js +105 -0
- package/lib/builtin-mates.js +6 -6
- package/lib/claude-hook-installer.js +15 -0
- package/lib/clay-history-mcp-server.js +62 -297
- package/lib/daemon.js +23 -1
- package/lib/debate-model-selection.js +119 -0
- package/lib/home-debate-tool-policy.js +164 -0
- package/lib/home-response-notifications.js +26 -0
- package/lib/knowledge-import.js +436 -0
- package/lib/knowledge-record-store.js +188 -0
- package/lib/knowledge-search.js +224 -0
- package/lib/mate-creation-mcp-server.js +55 -0
- package/lib/mate-knowledge-mcp-server.js +151 -0
- package/lib/mate-knowledge-migration.js +283 -0
- package/lib/mate-knowledge-service.js +488 -0
- package/lib/mate-knowledge-sync.js +482 -0
- package/lib/mate-ready-creation.js +95 -0
- package/lib/mates.js +2 -0
- package/lib/notes.js +2 -1
- package/lib/project-ask-user.js +64 -0
- package/lib/project-capsule-catalog.js +101 -0
- package/lib/project-connection.js +17 -0
- package/lib/project-debate-proposal.js +133 -17
- package/lib/project-debate.js +214 -110
- package/lib/project-delegated-follow-up.js +84 -0
- package/lib/project-delegated-session.js +53 -0
- package/lib/project-filesystem.js +7 -9
- package/lib/project-knowledge.js +23 -0
- package/lib/project-logs-comments.js +137 -0
- package/lib/project-logs-mcp-server.js +290 -0
- package/lib/project-logs-query.js +167 -0
- package/lib/project-logs-root.js +67 -0
- package/lib/project-logs-schema.js +259 -0
- package/lib/project-logs-service.js +357 -0
- package/lib/project-logs-snapshot.js +202 -0
- package/lib/project-logs-store.js +498 -0
- package/lib/project-logs-versioning.js +128 -0
- package/lib/project-logs.js +347 -0
- package/lib/project-mate-creation-proposal.js +120 -0
- package/lib/project-mate-interaction.js +14 -0
- package/lib/project-mate-knowledge.js +110 -0
- package/lib/project-memory.js +36 -7
- package/lib/project-models.js +157 -32
- package/lib/project-session-notes.js +2 -2
- package/lib/project-session-pair.js +8 -8
- package/lib/project-sessions.js +66 -51
- package/lib/project-vendor-login.js +414 -0
- package/lib/project-worker-proposal.js +25 -25
- package/lib/project-workspace-query.js +144 -0
- package/lib/project.js +433 -102
- package/lib/public/app.js +109 -48
- package/lib/public/css/avatar-imprints.css +0 -1
- package/lib/public/css/base.css +4 -0
- package/lib/public/css/capsule-ui.css +389 -0
- package/lib/public/css/command-palette.css +306 -6
- package/lib/public/css/home-capsule-library.css +243 -0
- package/lib/public/css/home-capsule-source.css +192 -0
- package/lib/public/css/home-debate-live.css +146 -0
- package/lib/public/css/home-debate-planning.css +125 -0
- package/lib/public/css/home-debates-archive.css +281 -0
- package/lib/public/css/home-hub.css +896 -405
- package/lib/public/css/home-mate-creation.css +34 -0
- package/lib/public/css/home-mate-model-picker.css +131 -0
- package/lib/public/css/home-mate-settings.css +344 -0
- package/lib/public/css/home-session-actions.css +265 -0
- package/lib/public/css/home-sidebar.css +667 -0
- package/lib/public/css/icon-strip.css +1 -2
- package/lib/public/css/input.css +79 -25
- package/lib/public/css/mates.css +7 -34
- package/lib/public/css/pane.css +1 -1
- package/lib/public/css/playbook.css +0 -80
- package/lib/public/css/project-logs.css +234 -0
- package/lib/public/css/scheduler.css +1 -1
- package/lib/public/css/sticky-notes.css +53 -117
- package/lib/public/css/tui-attention.css +0 -44
- package/lib/public/css/workspace-assignment.css +45 -0
- package/lib/public/fonts/source-serif-4/LICENSE.md +93 -0
- package/lib/public/fonts/source-serif-4/SourceSerif4Caption-Semibold.ttf.woff2 +0 -0
- package/lib/public/index.html +96 -74
- package/lib/public/modules/app-connection.js +100 -5
- package/lib/public/modules/app-dm.js +43 -160
- package/lib/public/modules/app-home-hub.js +328 -585
- package/lib/public/modules/app-message-cards.js +242 -0
- package/lib/public/modules/app-message-router.js +84 -0
- package/lib/public/modules/app-messages.js +124 -38
- package/lib/public/modules/app-notifications.js +8 -119
- package/lib/public/modules/app-panels.js +43 -2
- package/lib/public/modules/app-projects.js +9 -1
- package/lib/public/modules/app-rendering.js +21 -602
- package/lib/public/modules/avatar-imprint.js +11 -8
- package/lib/public/modules/background-tasks-ui.js +139 -16
- package/lib/public/modules/chat-bubble-renderer.js +152 -0
- package/lib/public/modules/chat-render-runtime.js +198 -0
- package/lib/public/modules/command-palette.js +225 -436
- package/lib/public/modules/dm-render.js +82 -0
- package/lib/public/modules/home-capsule-creation-intent.js +31 -0
- package/lib/public/modules/home-capsule-library.js +146 -0
- package/lib/public/modules/home-capsule-source.js +383 -0
- package/lib/public/modules/home-chat-identity.js +35 -0
- package/lib/public/modules/home-chat-scroll.js +77 -0
- package/lib/public/modules/home-chat-stream-state.js +34 -0
- package/lib/public/modules/home-composer-focus.js +25 -0
- package/lib/public/modules/home-conversations-sheet.js +179 -0
- package/lib/public/modules/home-debate-activity.js +48 -0
- package/lib/public/modules/home-debate-controls.js +295 -0
- package/lib/public/modules/home-debate-launch.js +41 -0
- package/lib/public/modules/home-debate-live.js +284 -0
- package/lib/public/modules/home-debate-models.js +73 -0
- package/lib/public/modules/home-debate-planning.js +335 -0
- package/lib/public/modules/home-debates-archive.js +279 -0
- package/lib/public/modules/home-dock-resize.js +74 -0
- package/lib/public/modules/home-dock.js +446 -0
- package/lib/public/modules/home-mate-chat.js +496 -0
- package/lib/public/modules/home-mate-creation.js +109 -0
- package/lib/public/modules/home-mate-model-picker.js +281 -0
- package/lib/public/modules/home-mate-selection.js +38 -0
- package/lib/public/modules/home-mate-settings-menu.js +131 -0
- package/lib/public/modules/home-mate-settings.js +383 -0
- package/lib/public/modules/home-session-actions.js +373 -0
- package/lib/public/modules/home-session-model-confirmation.js +13 -0
- package/lib/public/modules/home-shell.js +9 -0
- package/lib/public/modules/home-sidebar-chat-list.js +63 -0
- package/lib/public/modules/home-sidebar.js +165 -0
- package/lib/public/modules/home-sub-surface.js +19 -0
- package/lib/public/modules/home-surface-boot.js +68 -0
- package/lib/public/modules/home-surface.js +141 -0
- package/lib/public/modules/home-tools.js +271 -0
- package/lib/public/modules/markdown.js +50 -2
- package/lib/public/modules/mate-management.js +86 -0
- package/lib/public/modules/mate-sidebar.js +0 -8
- package/lib/public/modules/mate-wizard.js +0 -7
- package/lib/public/modules/mention.js +17 -19
- package/lib/public/modules/pane-bridge.js +9 -0
- package/lib/public/modules/profile.js +4 -5
- package/lib/public/modules/project-logs-ambient.js +238 -0
- package/lib/public/modules/project-logs-render.js +359 -0
- package/lib/public/modules/project-logs.js +328 -0
- package/lib/public/modules/project-settings.js +34 -28
- package/lib/public/modules/project-switcher.js +11 -5
- package/lib/public/modules/project-workspace-assignment.js +23 -0
- package/lib/public/modules/scheduler.js +17 -3
- package/lib/public/modules/search-clay-chat.js +402 -0
- package/lib/public/modules/server-settings.js +14 -12
- package/lib/public/modules/session-actions.js +1 -1
- package/lib/public/modules/sidebar-mates.js +56 -552
- package/lib/public/modules/sidebar-mobile.js +12 -73
- package/lib/public/modules/sidebar-presence.js +37 -0
- package/lib/public/modules/sidebar-sessions.js +25 -1
- package/lib/public/modules/split-pair-ui.js +13 -13
- package/lib/public/modules/split-view.js +7 -0
- package/lib/public/modules/sticky-notes.js +106 -53
- package/lib/public/modules/tool-input-composition.js +48 -0
- package/lib/public/modules/tool-llm-status.js +167 -0
- package/lib/public/modules/tool-palette.js +76 -4
- package/lib/public/modules/tool-renderer-advanced.js +285 -0
- package/lib/public/modules/tool-renderer-chart.js +158 -0
- package/lib/public/modules/tool-renderer-semantics.js +35 -0
- package/lib/public/modules/tool-renderer.js +464 -0
- package/lib/public/modules/tool-runtime.js +309 -0
- package/lib/public/modules/tool-ui-evaluator.js +97 -0
- package/lib/public/modules/tool-ui-tree.js +21 -0
- package/lib/public/modules/tui-attention.js +10 -0
- package/lib/public/modules/user-settings.js +16 -23
- package/lib/public/modules/vendor-login.js +287 -0
- package/lib/public/modules/worker-proposal.js +2 -2
- package/lib/public/modules/workspace-assignment-card.js +149 -0
- package/lib/public/modules/workspace-assignment-routing.js +4 -0
- package/lib/public/style.css +14 -2
- package/lib/runtime-env.js +65 -0
- package/lib/sdk-bridge.js +120 -32
- package/lib/sdk-message-processor.js +34 -13
- package/lib/server-home-capsule-creation.js +36 -0
- package/lib/server-home-chat-events.js +287 -0
- package/lib/server-home-chat.js +518 -0
- package/lib/server-home-clay-entry.js +65 -0
- package/lib/server-home-clay-session-links.js +26 -0
- package/lib/server-home-debate-planning.js +214 -0
- package/lib/server-home-debates.js +137 -0
- package/lib/server-home-mate-creation.js +261 -0
- package/lib/server-home-models.js +241 -0
- package/lib/server-home-preferences.js +61 -0
- package/lib/server-mates.js +37 -0
- package/lib/server-tools.js +377 -0
- package/lib/server.js +166 -59
- package/lib/session-pair-mcp-server.js +6 -6
- package/lib/sessions.js +22 -4
- package/lib/tool-capsule-source.js +142 -0
- package/lib/tool-control-mcp-server.js +126 -0
- package/lib/tool-llm.js +48 -0
- package/lib/tool-storage.js +77 -0
- package/lib/tool-ui-spec-advanced.js +82 -0
- package/lib/tool-ui-spec.js +261 -0
- package/lib/tools-registry.js +286 -0
- package/lib/users-home-dock-preferences.js +77 -0
- package/lib/users-home-surface-preferences.js +99 -0
- package/lib/users-preferences.js +4 -7
- package/lib/users.js +12 -0
- package/lib/whats-new-content.js +3 -3
- package/lib/workspace-assignment-service.js +420 -0
- package/lib/workspace-query-mcp-server.js +154 -0
- package/lib/workspace-query-service.js +492 -0
- package/lib/ws-schema.js +107 -12
- package/lib/yoke/adapters/acp.js +2 -1
- package/lib/yoke/adapters/antigravity.js +2 -1
- package/lib/yoke/adapters/claude-worker.js +11 -4
- package/lib/yoke/adapters/claude.js +141 -46
- package/lib/yoke/adapters/codex.js +79 -11
- package/lib/yoke/adapters/kiro.js +2 -1
- package/lib/yoke/claude-user-input.js +38 -0
- package/lib/yoke/codex-app-server.js +20 -2
- package/lib/yoke/codex-background-tasks.js +8 -2
- package/lib/yoke/codex-user-input.js +64 -0
- package/lib/yoke/complete-once.js +164 -0
- package/lib/yoke/index.js +5 -1
- package/lib/yoke/interface.js +19 -0
- package/lib/yoke/mcp-bridge-server.js +2 -6
- package/lib/yoke/user-input.js +254 -0
- package/package.json +4 -3
- package/lib/public/css/home-chat.css +0 -380
- package/lib/public/modules/home-chat.js +0 -438
- package/lib/server-clay-home.js +0 -245
|
@@ -10,6 +10,24 @@ var INITIALIZE_TIMEOUT_MS = require("../interface").INITIALIZE_TIMEOUT_MS;
|
|
|
10
10
|
var skillDiscovery = require("../skill-discovery");
|
|
11
11
|
var { resolveOsUserInfo } = require("../../os-users");
|
|
12
12
|
var backgroundTasks = require("../codex-background-tasks");
|
|
13
|
+
var codexUserInput = require("../codex-user-input");
|
|
14
|
+
|
|
15
|
+
// --- Reasoning defaults ---
|
|
16
|
+
// Reasoning summaries are the only readable thinking channel Codex offers:
|
|
17
|
+
// raw reasoning content is encrypted for ChatGPT-authenticated models, so the
|
|
18
|
+
// item/reasoning/* events this adapter already maps to thinking only carry
|
|
19
|
+
// text when the app-server is asked for summaries. The CLI default
|
|
20
|
+
// (`model_reasoning_summary = "auto"`) frequently produces none at all, and the
|
|
21
|
+
// app-server otherwise inherits whatever is in the user's ~/.codex/config.toml,
|
|
22
|
+
// so Clay asks for detailed summaries explicitly.
|
|
23
|
+
//
|
|
24
|
+
// `show_raw_agent_reasoning` is deliberately absent: it is encrypted on
|
|
25
|
+
// ChatGPT-auth models and noisy elsewhere, so it stays a user opt-in.
|
|
26
|
+
// Everything here is overridable via adapterOptions.CODEX.config.
|
|
27
|
+
var CODEX_REASONING_DEFAULTS = {
|
|
28
|
+
model_reasoning_summary: "detailed",
|
|
29
|
+
model_supports_reasoning_summaries: true,
|
|
30
|
+
};
|
|
13
31
|
|
|
14
32
|
// --- Event flattening ---
|
|
15
33
|
// Converts app-server JSON-RPC notifications into flat objects with a yokeType field.
|
|
@@ -726,6 +744,7 @@ function createCodexQueryHandle(appServer, queryOpts) {
|
|
|
726
744
|
var canUseTool = queryOpts.canUseTool || null;
|
|
727
745
|
var callDynamicTool = queryOpts.callDynamicTool || null;
|
|
728
746
|
var onElicitation = queryOpts.onElicitation || null;
|
|
747
|
+
var onUserInputRequest = queryOpts.onUserInputRequest || null;
|
|
729
748
|
var onFinished = queryOpts.onFinished || null;
|
|
730
749
|
|
|
731
750
|
// Check if the query was cancelled (either via handle.abort() or direct signal abort)
|
|
@@ -925,12 +944,23 @@ function createCodexQueryHandle(appServer, queryOpts) {
|
|
|
925
944
|
return;
|
|
926
945
|
}
|
|
927
946
|
|
|
928
|
-
|
|
929
|
-
|
|
947
|
+
if (method === "item/tool/requestUserInput") {
|
|
948
|
+
if (!onUserInputRequest) {
|
|
949
|
+
appServer.respondError(msg.id, -32002, "This query cannot request structured user input.");
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
952
|
+
codexUserInput.handleNative(appServer, msg, onUserInputRequest, state.threadId, abortController && abortController.signal);
|
|
953
|
+
return;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
// MCP elicitation shares the YOKE user-input lifecycle when available.
|
|
957
|
+
if (method === "mcpServer/elicitation/request") {
|
|
930
958
|
var mcpParams = msg.params || {};
|
|
931
959
|
var mcpMeta = mcpParams._meta || {};
|
|
932
960
|
console.log("[yoke/codex] MCP approval request:", (mcpMeta.tool || "?"), "server=" + (mcpParams.serverName || "?"));
|
|
933
|
-
if (
|
|
961
|
+
if (onUserInputRequest) {
|
|
962
|
+
codexUserInput.handleElicitation(appServer, msg, onUserInputRequest, abortController && abortController.signal);
|
|
963
|
+
} else if (onElicitation) {
|
|
934
964
|
var request = {
|
|
935
965
|
serverName: mcpParams.serverName || (mcpMeta.tool || "Tool"),
|
|
936
966
|
message: mcpParams.message || mcpParams.prompt || "",
|
|
@@ -1049,6 +1079,7 @@ function createCodexQueryHandle(appServer, queryOpts) {
|
|
|
1049
1079
|
cwd: queryOpts.cwd,
|
|
1050
1080
|
skipGitRepoCheck: true,
|
|
1051
1081
|
};
|
|
1082
|
+
if (queryOpts.ephemeral === true) threadParams.ephemeral = true;
|
|
1052
1083
|
if (queryOpts.modelReasoningEffort) {
|
|
1053
1084
|
threadParams.modelReasoningEffort = queryOpts.modelReasoningEffort;
|
|
1054
1085
|
}
|
|
@@ -1079,6 +1110,11 @@ function createCodexQueryHandle(appServer, queryOpts) {
|
|
|
1079
1110
|
threadResult = await appServer.send("thread/start", threadParams, 60000);
|
|
1080
1111
|
}
|
|
1081
1112
|
|
|
1113
|
+
if (queryOpts.ephemeral === true
|
|
1114
|
+
&& (!threadResult || !threadResult.thread || threadResult.thread.ephemeral !== true)) {
|
|
1115
|
+
throw new Error("Codex did not confirm an ephemeral one-shot thread.");
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1082
1118
|
if (threadResult && threadResult.thread) {
|
|
1083
1119
|
state.threadId = threadResult.thread.id;
|
|
1084
1120
|
handlerEntry.threadId = state.threadId;
|
|
@@ -1110,7 +1146,7 @@ function createCodexQueryHandle(appServer, queryOpts) {
|
|
|
1110
1146
|
|
|
1111
1147
|
// Explicit references use Codex's native skill input item regardless of
|
|
1112
1148
|
// which vendor owns the SKILL.md file.
|
|
1113
|
-
var availableSkills = skillDiscovery.discoverSkills(queryOpts.cwd);
|
|
1149
|
+
var availableSkills = queryOpts.skipSkills ? [] : skillDiscovery.discoverSkills(queryOpts.cwd);
|
|
1114
1150
|
var skillItemsToInject = [];
|
|
1115
1151
|
var injected = {};
|
|
1116
1152
|
for (var ii = 0; ii < input.length; ii++) {
|
|
@@ -1293,15 +1329,14 @@ function createCodexAdapter(opts) {
|
|
|
1293
1329
|
// model listing must not depend on a successful app-server init — otherwise a
|
|
1294
1330
|
// slow/failed `initialize` leaves the picker empty and the chip shows the
|
|
1295
1331
|
// previous vendor's model.
|
|
1332
|
+
// Kept in sync with what `model/list` reports for the bundled codex build
|
|
1333
|
+
// (0.152.1). Models the CLI no longer offers are rejected at turn/start, so
|
|
1334
|
+
// listing them would only surface a runtime failure in the model picker.
|
|
1296
1335
|
var CODEX_MODELS = [
|
|
1297
1336
|
"gpt-5.6-terra",
|
|
1298
1337
|
"gpt-5.6-sol",
|
|
1299
1338
|
"gpt-5.6-luna",
|
|
1300
1339
|
"gpt-5.5",
|
|
1301
|
-
"gpt-5.4",
|
|
1302
|
-
"gpt-5.4-mini",
|
|
1303
|
-
"gpt-5.3-codex",
|
|
1304
|
-
"gpt-5.3-codex-spark",
|
|
1305
1340
|
"gpt-5.2",
|
|
1306
1341
|
];
|
|
1307
1342
|
var _cachedModels = CODEX_MODELS.slice();
|
|
@@ -1516,6 +1551,7 @@ function createCodexAdapter(opts) {
|
|
|
1516
1551
|
|
|
1517
1552
|
var adapter = {
|
|
1518
1553
|
vendor: "codex",
|
|
1554
|
+
userInputCapability: { mode: "native", native: true, transport: "item/tool/requestUserInput" },
|
|
1519
1555
|
|
|
1520
1556
|
init: function(initOpts) {
|
|
1521
1557
|
var requestedLinuxUser = initOpts && initOpts.linuxUser;
|
|
@@ -1543,17 +1579,21 @@ function createCodexAdapter(opts) {
|
|
|
1543
1579
|
if (_initPromise) return _initPromise;
|
|
1544
1580
|
|
|
1545
1581
|
_initPromise = (async function() {
|
|
1546
|
-
var serverOpts = { cwd: _cwd };
|
|
1582
|
+
var serverOpts = { cwd: _cwd, env: effectiveInitOpts.env || null };
|
|
1547
1583
|
if (_runtimeLinuxUser) {
|
|
1548
1584
|
serverOpts.osUserInfo = _resolveOsUserInfo(_runtimeLinuxUser);
|
|
1549
1585
|
}
|
|
1550
1586
|
|
|
1587
|
+
// Clay's config defaults go in first so any user-supplied
|
|
1588
|
+
// adapterOptions.CODEX.config key of the same name overrides them.
|
|
1589
|
+
serverOpts.config = Object.assign({}, CODEX_REASONING_DEFAULTS);
|
|
1590
|
+
|
|
1551
1591
|
// Extract adapter options
|
|
1552
1592
|
if (effectiveInitOpts && effectiveInitOpts.adapterOptions && effectiveInitOpts.adapterOptions.CODEX) {
|
|
1553
1593
|
var co = effectiveInitOpts.adapterOptions.CODEX;
|
|
1554
1594
|
if (co.apiKey) serverOpts.env = Object.assign({}, serverOpts.env || {}, { OPENAI_API_KEY: co.apiKey });
|
|
1555
1595
|
if (co.baseUrl) serverOpts.env = Object.assign({}, serverOpts.env || {}, { OPENAI_BASE_URL: co.baseUrl });
|
|
1556
|
-
if (co.config) serverOpts.config = co.config;
|
|
1596
|
+
if (co.config) serverOpts.config = Object.assign(serverOpts.config, co.config);
|
|
1557
1597
|
}
|
|
1558
1598
|
|
|
1559
1599
|
// Track 1: Read local MCP server definitions from ~/.clay/mcp.json
|
|
@@ -1749,9 +1789,11 @@ function createCodexAdapter(opts) {
|
|
|
1749
1789
|
callDynamicTool: queryOpts.callDynamicTool || null,
|
|
1750
1790
|
abortController: ac,
|
|
1751
1791
|
canUseTool: queryOpts.canUseTool || null,
|
|
1752
|
-
onElicitation: queryOpts.onElicitation || null,
|
|
1792
|
+
onElicitation: queryOpts.userInputMode === "fallback" ? null : (queryOpts.onElicitation || null),
|
|
1793
|
+
onUserInputRequest: queryOpts.userInputMode === "fallback" ? null : (queryOpts.onUserInputRequest || null),
|
|
1753
1794
|
resumeSessionId: queryOpts.resumeSessionId || null,
|
|
1754
1795
|
registerBackgroundTaskReset: registerBackgroundTaskReset,
|
|
1796
|
+
ephemeral: queryOpts.ephemeral === true,
|
|
1755
1797
|
};
|
|
1756
1798
|
|
|
1757
1799
|
// Reasoning effort
|
|
@@ -1806,6 +1848,14 @@ function createCodexAdapter(opts) {
|
|
|
1806
1848
|
return handle;
|
|
1807
1849
|
},
|
|
1808
1850
|
|
|
1851
|
+
createOneShotQuery: async function(queryOpts) {
|
|
1852
|
+
var handle = await adapter.createQuery(Object.assign({}, queryOpts || {}, {
|
|
1853
|
+
ephemeral: true,
|
|
1854
|
+
resumeSessionId: null,
|
|
1855
|
+
}));
|
|
1856
|
+
return { handle: handle, backendPersistence: "ephemeral" };
|
|
1857
|
+
},
|
|
1858
|
+
|
|
1809
1859
|
// --- Title generation ---
|
|
1810
1860
|
generateTitle: async function(messages, opts) {
|
|
1811
1861
|
var requestedLinuxUser = opts && opts.linuxUser;
|
|
@@ -1823,6 +1873,7 @@ function createCodexAdapter(opts) {
|
|
|
1823
1873
|
var ac = new AbortController();
|
|
1824
1874
|
var handle = await adapter.createQuery({
|
|
1825
1875
|
cwd: (opts && opts.cwd) || _cwd,
|
|
1876
|
+
env: opts && opts.env,
|
|
1826
1877
|
systemPrompt: systemPrompt,
|
|
1827
1878
|
model: "gpt-5.4-mini",
|
|
1828
1879
|
abortController: ac,
|
|
@@ -1892,6 +1943,23 @@ function createCodexAdapter(opts) {
|
|
|
1892
1943
|
]).then(function() { return true; });
|
|
1893
1944
|
},
|
|
1894
1945
|
|
|
1946
|
+
// A device login writes credentials for one OS identity. Refresh only
|
|
1947
|
+
// that identity in OS-isolated deployments; single-user projects restart
|
|
1948
|
+
// their sole app-server.
|
|
1949
|
+
refreshAuthIdentity: function(linuxUser) {
|
|
1950
|
+
if (!_runtimeLinuxUser && linuxUser) {
|
|
1951
|
+
var userRuntime = _userRuntimes[linuxUser];
|
|
1952
|
+
if (!userRuntime) return Promise.resolve(false);
|
|
1953
|
+
return userRuntime.shutdown().then(function() {
|
|
1954
|
+
delete _userRuntimes[linuxUser];
|
|
1955
|
+
return true;
|
|
1956
|
+
});
|
|
1957
|
+
}
|
|
1958
|
+
if (_runtimeLinuxUser && linuxUser !== _runtimeLinuxUser) return Promise.resolve(false);
|
|
1959
|
+
if (_requiresLinuxUser) return Promise.resolve(false);
|
|
1960
|
+
return adapter.shutdown();
|
|
1961
|
+
},
|
|
1962
|
+
|
|
1895
1963
|
shutdownIfIdle: function(idleMs) {
|
|
1896
1964
|
if (!_runtimeLinuxUser && Object.keys(_userRuntimes).length > 0) {
|
|
1897
1965
|
return shutdownUserRuntimes("shutdownIfIdle", idleMs).then(function(results) {
|
|
@@ -1065,7 +1065,7 @@ function createKiroAdapter(opts) {
|
|
|
1065
1065
|
var model = queryOpts.model || _defaultModel || "auto";
|
|
1066
1066
|
var ac = queryOpts.abortController || new AbortController();
|
|
1067
1067
|
var kiroOpts = (queryOpts.adapterOptions && queryOpts.adapterOptions.KIRO) || {};
|
|
1068
|
-
var sharedSkills = skillDiscovery.discoverSkills(queryOpts.cwd || _cwd);
|
|
1068
|
+
var sharedSkills = queryOpts.skipSkills ? [] : skillDiscovery.discoverSkills(queryOpts.cwd || _cwd);
|
|
1069
1069
|
var skillIndex = skillDiscovery.buildSkillIndex(sharedSkills);
|
|
1070
1070
|
|
|
1071
1071
|
var activeEntry = { abort: function() { try { ac.abort(); } catch (e) {} } };
|
|
@@ -1123,6 +1123,7 @@ function createKiroAdapter(opts) {
|
|
|
1123
1123
|
var ac = new AbortController();
|
|
1124
1124
|
var handle = await adapter.createQuery({
|
|
1125
1125
|
cwd: (opts && opts.cwd) || _cwd,
|
|
1126
|
+
env: opts && opts.env,
|
|
1126
1127
|
systemPrompt: systemPrompt,
|
|
1127
1128
|
model: "auto",
|
|
1128
1129
|
abortController: ac,
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Claude SDK mappings for YOKE structured user input.
|
|
2
|
+
var userInput = require("./user-input");
|
|
3
|
+
|
|
4
|
+
function ask(handler, input, opts) {
|
|
5
|
+
opts = opts || {};
|
|
6
|
+
return userInput.dispatchUserInput(handler, input, {
|
|
7
|
+
requestId: opts.toolUseID || opts.requestId,
|
|
8
|
+
signal: opts.signal,
|
|
9
|
+
source: "claude_ask_user_question",
|
|
10
|
+
native: true,
|
|
11
|
+
provider: "claude",
|
|
12
|
+
}).then(function (result) { return userInput.claudePermissionResult(input, result); });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function elicitation(handler, request, opts) {
|
|
16
|
+
opts = opts || {};
|
|
17
|
+
return userInput.dispatchUserInput(handler, userInput.questionsFromElicitation(request), {
|
|
18
|
+
requestId: opts.requestId || request.elicitationId,
|
|
19
|
+
signal: opts.signal,
|
|
20
|
+
source: "claude_elicitation",
|
|
21
|
+
native: true,
|
|
22
|
+
provider: "claude",
|
|
23
|
+
presentation: "elicitation",
|
|
24
|
+
diagnostics: { elicitation: request },
|
|
25
|
+
}).then(userInput.elicitationResponse);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function canUseTool(queryOpts) {
|
|
29
|
+
var original = queryOpts.canUseTool;
|
|
30
|
+
return function (toolName, input, opts) {
|
|
31
|
+
if (toolName === "AskUserQuestion" && typeof queryOpts.onUserInputRequest === "function") return ask(queryOpts.onUserInputRequest, input, opts);
|
|
32
|
+
if (toolName === "AskUserQuestion") return Promise.resolve({ behavior: "deny", message: "Use the query's structured input fallback tool." });
|
|
33
|
+
if (original) return original(toolName, input, opts);
|
|
34
|
+
return Promise.resolve({ behavior: "deny", message: "No tool permission handler is available." });
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = { ask: ask, elicitation: elicitation, canUseTool: canUseTool };
|
|
@@ -13,7 +13,13 @@ var { buildUserEnv } = require("../build-user-env");
|
|
|
13
13
|
var { wrapSpawnAsUser } = require("../os-users");
|
|
14
14
|
|
|
15
15
|
// --- Find the codex binary path ---
|
|
16
|
-
// Mirrors the logic from @openai/codex-sdk findCodexPath()
|
|
16
|
+
// Mirrors the logic from @openai/codex-sdk findCodexPath().
|
|
17
|
+
//
|
|
18
|
+
// The bundled @openai/codex platform package is the default. Set the
|
|
19
|
+
// CLAY_CODEX_PATH env var to an existing executable to run a different codex
|
|
20
|
+
// build (local dev build, system install, pinned older release); the chosen
|
|
21
|
+
// binary is logged on every resolution. An unset or non-existent
|
|
22
|
+
// CLAY_CODEX_PATH silently falls back to the bundled resolution.
|
|
17
23
|
|
|
18
24
|
var PLATFORM_PACKAGE_BY_TARGET = {
|
|
19
25
|
"aarch64-apple-darwin": "@openai/codex-darwin-arm64",
|
|
@@ -39,6 +45,15 @@ function getTargetTriple() {
|
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
function findCodexPath() {
|
|
48
|
+
var override = process.env.CLAY_CODEX_PATH;
|
|
49
|
+
if (override) {
|
|
50
|
+
if (fs.existsSync(override)) {
|
|
51
|
+
console.log("[codex-app-server] Using CLAY_CODEX_PATH binary:", override);
|
|
52
|
+
return override;
|
|
53
|
+
}
|
|
54
|
+
console.warn("[codex-app-server] CLAY_CODEX_PATH does not exist, falling back to bundled codex:", override);
|
|
55
|
+
}
|
|
56
|
+
|
|
42
57
|
var triple = getTargetTriple();
|
|
43
58
|
if (!triple) throw new Error("Unsupported platform: " + process.platform + "/" + process.arch);
|
|
44
59
|
|
|
@@ -59,7 +74,10 @@ function findCodexPath() {
|
|
|
59
74
|
path.join(vendorRoot, triple, "codex", binaryName),
|
|
60
75
|
];
|
|
61
76
|
for (var i = 0; i < candidates.length; i++) {
|
|
62
|
-
if (fs.existsSync(candidates[i]))
|
|
77
|
+
if (fs.existsSync(candidates[i])) {
|
|
78
|
+
console.log("[codex-app-server] Using bundled codex binary:", candidates[i]);
|
|
79
|
+
return candidates[i];
|
|
80
|
+
}
|
|
63
81
|
}
|
|
64
82
|
throw new Error("codex binary not found in any known layout under " + path.join(vendorRoot, triple));
|
|
65
83
|
} catch (e) {
|
|
@@ -19,11 +19,17 @@ function mapTerminals(result) {
|
|
|
19
19
|
var terminal = terminals[i] || {};
|
|
20
20
|
var taskId = terminal.id || terminal.terminalId || terminal.taskId || "";
|
|
21
21
|
if (!taskId || !isLiveTerminal(terminal)) continue;
|
|
22
|
-
|
|
22
|
+
var task = {
|
|
23
23
|
task_id: String(taskId),
|
|
24
24
|
task_type: "shell",
|
|
25
25
|
description: terminal.commandLine || terminal.command || terminal.name || "",
|
|
26
|
-
}
|
|
26
|
+
};
|
|
27
|
+
// Forward the terminal's own start time when the app-server reports one,
|
|
28
|
+
// so elapsed time survives a Clay restart. Falls back to first-seen
|
|
29
|
+
// stamping in background-task-timing.js when absent.
|
|
30
|
+
var startedAt = terminal.startedAt || terminal.started_at || terminal.createdAt || terminal.created_at;
|
|
31
|
+
if (startedAt) task.started_at = startedAt;
|
|
32
|
+
tasks.push(task);
|
|
27
33
|
}
|
|
28
34
|
return tasks;
|
|
29
35
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Codex app-server 0.147 structured user-input protocol mapping.
|
|
2
|
+
var userInput = require("./user-input");
|
|
3
|
+
|
|
4
|
+
function nativeInput(params) {
|
|
5
|
+
return {
|
|
6
|
+
questions: (params.questions || []).map(function (question) {
|
|
7
|
+
return {
|
|
8
|
+
id: question.id,
|
|
9
|
+
header: question.header || "",
|
|
10
|
+
question: question.question,
|
|
11
|
+
allowOther: question.isOther !== false,
|
|
12
|
+
secret: question.isSecret === true,
|
|
13
|
+
options: Array.isArray(question.options) ? question.options : [],
|
|
14
|
+
};
|
|
15
|
+
}),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function handleNative(appServer, msg, handler, expectedThreadId, signal) {
|
|
20
|
+
var params = msg.params || {};
|
|
21
|
+
if (!params.threadId || (expectedThreadId && params.threadId !== expectedThreadId)) {
|
|
22
|
+
appServer.respondError(msg.id, -32001, "Structured input request does not belong to this query thread.");
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
userInput.dispatchUserInput(handler, nativeInput(params), {
|
|
26
|
+
requestId: params.itemId || String(msg.id),
|
|
27
|
+
signal: signal,
|
|
28
|
+
source: "codex_request_user_input",
|
|
29
|
+
native: true,
|
|
30
|
+
provider: "codex",
|
|
31
|
+
diagnostics: { threadId: params.threadId, turnId: params.turnId || null, itemId: params.itemId || null },
|
|
32
|
+
}).then(function (result) {
|
|
33
|
+
appServer.respond(msg.id, userInput.codexResponse(result));
|
|
34
|
+
}).catch(function (error) {
|
|
35
|
+
appServer.respondError(msg.id, -32602, error.message);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function handleElicitation(appServer, msg, handler, signal) {
|
|
40
|
+
var params = msg.params || {};
|
|
41
|
+
var request = {
|
|
42
|
+
serverName: params.serverName || (params._meta && params._meta.tool) || "Tool",
|
|
43
|
+
message: params.message || params.prompt || "",
|
|
44
|
+
url: params.url || null,
|
|
45
|
+
elicitationId: params.elicitationId || null,
|
|
46
|
+
requestedSchema: params.requestedSchema || null,
|
|
47
|
+
};
|
|
48
|
+
var input = Array.isArray(params.questions) ? nativeInput(params) : userInput.questionsFromElicitation(request);
|
|
49
|
+
userInput.dispatchUserInput(handler, input, {
|
|
50
|
+
requestId: request.elicitationId || String(msg.id),
|
|
51
|
+
signal: signal,
|
|
52
|
+
source: "codex_mcp_elicitation",
|
|
53
|
+
native: true,
|
|
54
|
+
provider: "codex",
|
|
55
|
+
presentation: "elicitation",
|
|
56
|
+
diagnostics: { threadId: params.threadId || null, elicitation: request },
|
|
57
|
+
}).then(function (result) {
|
|
58
|
+
appServer.respond(msg.id, userInput.elicitationResponse(result));
|
|
59
|
+
}).catch(function (error) {
|
|
60
|
+
appServer.respondError(msg.id, -32602, error.message);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
module.exports = { nativeInput: nativeInput, handleNative: handleNative, handleElicitation: handleElicitation };
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// Canonical single-turn completion lifecycle for YOKE adapters.
|
|
2
|
+
|
|
3
|
+
function assistantMessageText(event) {
|
|
4
|
+
if (!event || event.yokeType !== "message" || event.messageRole !== "assistant") return "";
|
|
5
|
+
if (!Array.isArray(event.content)) return "";
|
|
6
|
+
var text = "";
|
|
7
|
+
for (var i = 0; i < event.content.length; i++) {
|
|
8
|
+
if (event.content[i] && event.content[i].type === "text" && event.content[i].text) {
|
|
9
|
+
text += event.content[i].text;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return text;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function normalizedText(streamedText, finalText) {
|
|
16
|
+
if (!streamedText) return finalText;
|
|
17
|
+
if (!finalText) return streamedText;
|
|
18
|
+
if (finalText.indexOf(streamedText) === 0) return finalText;
|
|
19
|
+
if (streamedText.indexOf(finalText) === 0) return streamedText;
|
|
20
|
+
return streamedText;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function oneShotError(event) {
|
|
24
|
+
if (!event) return null;
|
|
25
|
+
if (event.yokeType === "error") return new Error(event.text || "One-shot completion failed.");
|
|
26
|
+
if (event.yokeType === "auth_required") {
|
|
27
|
+
return new Error("The " + (event.vendor || "selected") + " provider requires sign-in.");
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function createOneShot(adapter, queryOpts, allowUnknownPersistence) {
|
|
33
|
+
if (typeof adapter.createOneShotQuery === "function") {
|
|
34
|
+
var created = await adapter.createOneShotQuery(queryOpts);
|
|
35
|
+
if (!created || !created.handle) throw new Error("YOKE adapter returned an invalid one-shot query.");
|
|
36
|
+
if (created.backendPersistence !== "ephemeral") {
|
|
37
|
+
if (!allowUnknownPersistence) {
|
|
38
|
+
if (typeof created.handle.abort === "function") created.handle.abort();
|
|
39
|
+
if (typeof created.handle.close === "function") created.handle.close();
|
|
40
|
+
throw new Error("The " + adapter.vendor + " adapter did not confirm ephemeral one-shot execution.");
|
|
41
|
+
}
|
|
42
|
+
created.backendPersistence = "unknown";
|
|
43
|
+
}
|
|
44
|
+
return created;
|
|
45
|
+
}
|
|
46
|
+
if (!allowUnknownPersistence) {
|
|
47
|
+
throw new Error("The " + adapter.vendor + " adapter does not guarantee ephemeral one-shot execution.");
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
handle: await adapter.createQuery(Object.assign({}, queryOpts, { persistSession: false })),
|
|
51
|
+
backendPersistence: "unknown",
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function completeOnce(adapter, opts) {
|
|
56
|
+
opts = opts || {};
|
|
57
|
+
if (!adapter || typeof adapter.createQuery !== "function") throw new Error("A YOKE adapter is required.");
|
|
58
|
+
if (typeof opts.prompt !== "string" || !opts.prompt.trim()) throw new Error("A one-shot prompt is required.");
|
|
59
|
+
|
|
60
|
+
var timeoutMs = opts.timeoutMs || 60000;
|
|
61
|
+
var controller = new AbortController();
|
|
62
|
+
var handle = null;
|
|
63
|
+
var timedOut = false;
|
|
64
|
+
var externallyAborted = false;
|
|
65
|
+
var timer = null;
|
|
66
|
+
var externalSignal = opts.signal || null;
|
|
67
|
+
var abortHandle = function() {
|
|
68
|
+
controller.abort();
|
|
69
|
+
if (handle && typeof handle.abort === "function") handle.abort();
|
|
70
|
+
};
|
|
71
|
+
var onExternalAbort = function() {
|
|
72
|
+
externallyAborted = true;
|
|
73
|
+
abortHandle();
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
if (externalSignal) {
|
|
77
|
+
if (externalSignal.aborted) onExternalAbort();
|
|
78
|
+
else externalSignal.addEventListener("abort", onExternalAbort, { once: true });
|
|
79
|
+
}
|
|
80
|
+
timer = setTimeout(function() {
|
|
81
|
+
timedOut = true;
|
|
82
|
+
abortHandle();
|
|
83
|
+
}, timeoutMs);
|
|
84
|
+
|
|
85
|
+
var streamedText = "";
|
|
86
|
+
var finalText = "";
|
|
87
|
+
var resultEvent = null;
|
|
88
|
+
var interactiveRequested = false;
|
|
89
|
+
var created;
|
|
90
|
+
try {
|
|
91
|
+
var queryOpts = Object.assign({}, opts.query || {}, {
|
|
92
|
+
cwd: opts.cwd,
|
|
93
|
+
model: opts.model,
|
|
94
|
+
systemPrompt: opts.systemPrompt,
|
|
95
|
+
abortController: controller,
|
|
96
|
+
onUserInputRequest: function (request, respond) {
|
|
97
|
+
interactiveRequested = true;
|
|
98
|
+
respond.cancel("One-shot completions cannot request interactive user input.");
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
var creationFinished = false;
|
|
102
|
+
var rejectCreation;
|
|
103
|
+
var creationAbort = new Promise(function(resolve, reject) { rejectCreation = reject; });
|
|
104
|
+
var onCreationAbort = function() { rejectCreation(new Error("One-shot completion aborted.")); };
|
|
105
|
+
controller.signal.addEventListener("abort", onCreationAbort, { once: true });
|
|
106
|
+
var creation = createOneShot(adapter, queryOpts, !!opts.allowUnknownBackendPersistence);
|
|
107
|
+
creation.then(function(lateCreated) {
|
|
108
|
+
if (!creationFinished && controller.signal.aborted && lateCreated && lateCreated.handle) {
|
|
109
|
+
if (typeof lateCreated.handle.abort === "function") lateCreated.handle.abort();
|
|
110
|
+
if (typeof lateCreated.handle.close === "function") lateCreated.handle.close();
|
|
111
|
+
}
|
|
112
|
+
}).catch(function() {});
|
|
113
|
+
try {
|
|
114
|
+
created = await Promise.race([creation, creationAbort]);
|
|
115
|
+
creationFinished = true;
|
|
116
|
+
} finally {
|
|
117
|
+
controller.signal.removeEventListener("abort", onCreationAbort);
|
|
118
|
+
}
|
|
119
|
+
handle = created.handle;
|
|
120
|
+
if (controller.signal.aborted) {
|
|
121
|
+
if (typeof handle.abort === "function") handle.abort();
|
|
122
|
+
throw new Error("One-shot completion aborted.");
|
|
123
|
+
}
|
|
124
|
+
if (handle.pushMessage(opts.prompt) !== true) {
|
|
125
|
+
throw new Error("YOKE one-shot query rejected its prompt.");
|
|
126
|
+
}
|
|
127
|
+
handle.endInput();
|
|
128
|
+
|
|
129
|
+
for await (var event of handle) {
|
|
130
|
+
var eventError = oneShotError(event);
|
|
131
|
+
if (eventError) throw eventError;
|
|
132
|
+
if (event.yokeType === "text_delta" && event.text) streamedText += event.text;
|
|
133
|
+
var messageText = assistantMessageText(event);
|
|
134
|
+
if (messageText) finalText = messageText;
|
|
135
|
+
if (event.yokeType === "result") {
|
|
136
|
+
resultEvent = event;
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (timedOut) throw new Error("YOKE one-shot timed out after " + timeoutMs + " ms.");
|
|
141
|
+
if (externallyAborted) throw new Error("YOKE one-shot was aborted.");
|
|
142
|
+
if (interactiveRequested) throw new Error("YOKE one-shot completion requested interactive user input.");
|
|
143
|
+
return {
|
|
144
|
+
text: normalizedText(streamedText, finalText).trim(),
|
|
145
|
+
backendPersistence: created.backendPersistence || "unknown",
|
|
146
|
+
vendor: adapter.vendor,
|
|
147
|
+
model: opts.model || null,
|
|
148
|
+
result: resultEvent,
|
|
149
|
+
};
|
|
150
|
+
} catch (error) {
|
|
151
|
+
if (timedOut) throw new Error("YOKE one-shot timed out after " + timeoutMs + " ms.");
|
|
152
|
+
if (externallyAborted) throw new Error("YOKE one-shot was aborted.");
|
|
153
|
+
throw error;
|
|
154
|
+
} finally {
|
|
155
|
+
clearTimeout(timer);
|
|
156
|
+
if (externalSignal) externalSignal.removeEventListener("abort", onExternalAbort);
|
|
157
|
+
if (handle && typeof handle.close === "function") handle.close();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
module.exports = {
|
|
162
|
+
completeOnce: completeOnce,
|
|
163
|
+
normalizedText: normalizedText,
|
|
164
|
+
};
|
package/lib/yoke/index.js
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
var iface = require("./interface");
|
|
5
5
|
var instructions = require("./instructions");
|
|
6
6
|
var vendorRegistry = require("./vendor-registry");
|
|
7
|
+
var completeOnce = require("./complete-once").completeOnce;
|
|
8
|
+
var userInput = require("./user-input");
|
|
7
9
|
var createClaudeAdapter = require("./adapters/claude").createClaudeAdapter;
|
|
8
10
|
var createCodexAdapter = require("./adapters/codex").createCodexAdapter;
|
|
9
11
|
var createAntigravityAdapter = require("./adapters/antigravity").createAntigravityAdapter;
|
|
@@ -47,7 +49,7 @@ function wrapCreateQuery(adapter, defaultCwd) {
|
|
|
47
49
|
adapter.createQuery = function(queryOpts) {
|
|
48
50
|
queryOpts = queryOpts || {};
|
|
49
51
|
var projectDir = (queryOpts && queryOpts.cwd) || defaultCwd;
|
|
50
|
-
var merged = instructions.scanAndMerge(projectDir, adapter.vendor);
|
|
52
|
+
var merged = queryOpts.skipProjectInstructions ? "" : instructions.scanAndMerge(projectDir, adapter.vendor);
|
|
51
53
|
|
|
52
54
|
if (merged) {
|
|
53
55
|
var parts = [];
|
|
@@ -473,4 +475,6 @@ module.exports = {
|
|
|
473
475
|
TOOL_POLICIES: iface.TOOL_POLICIES,
|
|
474
476
|
validateAdapter: iface.validateAdapter,
|
|
475
477
|
validateQueryHandle: iface.validateQueryHandle,
|
|
478
|
+
completeOnce: completeOnce,
|
|
479
|
+
userInput: userInput,
|
|
476
480
|
};
|
package/lib/yoke/interface.js
CHANGED
|
@@ -40,6 +40,25 @@ var INITIALIZE_TIMEOUT_MS = 90000;
|
|
|
40
40
|
* .createToolServer(def): ToolServer (opaque)
|
|
41
41
|
* .createQuery(opts): QueryHandle
|
|
42
42
|
*
|
|
43
|
+
* Optional one-shot capability:
|
|
44
|
+
* .createOneShotQuery(opts): Promise<{ handle, backendPersistence }>
|
|
45
|
+
* backendPersistence is "ephemeral" only when the adapter can verify the
|
|
46
|
+
* provider does not materialize the backend conversation. Adapters without
|
|
47
|
+
* this method may only use completeOnce's explicit unknown-persistence path.
|
|
48
|
+
*
|
|
49
|
+
* Optional structured user-input capability:
|
|
50
|
+
* .userInputCapability: { mode: "native"|"fallback", native: boolean, transport: string }
|
|
51
|
+
* createQuery({ userInputMode: "auto"|"native"|"fallback",
|
|
52
|
+
* onUserInputRequest(request, respond) })
|
|
53
|
+
* request.presentation is "questions" or "elicitation";
|
|
54
|
+
* request.questions contain 1-3 { id, header, question, multiSelect,
|
|
55
|
+
* allowOther, secret, options }; options contain zero or 2-6 safe
|
|
56
|
+
* { label, description } entries. respond(answerMap),
|
|
57
|
+
* respond.submitContent(typedMap), and respond.cancel(reason) settle
|
|
58
|
+
* exactly once. submitContent preserves typed MCP elicitation forms.
|
|
59
|
+
* Adapters with mode "native" translate their provider protocol directly.
|
|
60
|
+
* Other adapters use createFallbackServer() from yoke/user-input.
|
|
61
|
+
*
|
|
43
62
|
* Lightweight utilities:
|
|
44
63
|
* .generateTitle(messages, opts) : Promise<string> - generate a short session title
|
|
45
64
|
* messages: string[] - user messages to derive the title from
|
|
@@ -102,12 +102,8 @@ function postJson(urlPath, body) {
|
|
|
102
102
|
reject(err);
|
|
103
103
|
});
|
|
104
104
|
|
|
105
|
-
// 10 min safety ceiling.
|
|
106
|
-
//
|
|
107
|
-
// user message), so no tool call should legitimately block long.
|
|
108
|
-
// The generous ceiling is just a belt-and-suspenders against slow
|
|
109
|
-
// browser automation or external MCP servers, not the primary
|
|
110
|
-
// mechanism for human-in-the-loop tools.
|
|
105
|
+
// 10 min safety ceiling. Structured user input may legitimately wait
|
|
106
|
+
// for a person, while other tools normally return much sooner.
|
|
111
107
|
req.setTimeout(600000, function () {
|
|
112
108
|
req.destroy(new Error("Request timed out"));
|
|
113
109
|
});
|