clay-server 3.3.2-beta.3 → 3.4.0-beta.2

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 (36) hide show
  1. package/lib/project-file-watch.js +77 -16
  2. package/lib/project-shell-command.js +160 -0
  3. package/lib/project-user-message.js +10 -0
  4. package/lib/project.js +13 -0
  5. package/lib/public/app.js +10 -0
  6. package/lib/public/css/input.css +67 -0
  7. package/lib/public/css/mates.css +1 -0
  8. package/lib/public/gemini-avatar.svg +11 -0
  9. package/lib/public/index.html +13 -0
  10. package/lib/public/modules/app-messages.js +16 -1
  11. package/lib/public/modules/app-panels.js +13 -1
  12. package/lib/public/modules/app-projects.js +2 -0
  13. package/lib/public/modules/app-rendering.js +7 -1
  14. package/lib/public/modules/input.js +58 -28
  15. package/lib/public/modules/mate-sidebar.js +9 -3
  16. package/lib/public/modules/shell-command.js +148 -0
  17. package/lib/public/modules/sidebar-mates.js +7 -1
  18. package/lib/public/modules/tools.js +7 -1
  19. package/lib/public/opencode-avatar.svg +4 -0
  20. package/lib/sdk-bridge.js +18 -2
  21. package/lib/sdk-message-processor.js +10 -1
  22. package/lib/ws-schema.js +3 -0
  23. package/lib/yoke/acp-agent-profiles.js +188 -0
  24. package/lib/yoke/acp-driver-runtime.js +50 -0
  25. package/lib/yoke/acp-event-normalizer.js +179 -0
  26. package/lib/yoke/acp-process-manager.js +264 -0
  27. package/lib/yoke/acp-query-handle.js +487 -0
  28. package/lib/yoke/adapters/acp.js +317 -0
  29. package/lib/yoke/adapters/gemini.js +7 -0
  30. package/lib/yoke/adapters/kiro.js +4 -4
  31. package/lib/yoke/adapters/opencode.js +7 -0
  32. package/lib/yoke/index.js +45 -11
  33. package/lib/yoke/interface.js +2 -0
  34. package/lib/yoke/kiro-acp-server.js +30 -276
  35. package/lib/yoke/vendor-registry.js +22 -0
  36. package/package.json +1 -1
@@ -0,0 +1,317 @@
1
+ // Shared ACP Adapter
2
+ // ------------------
3
+ // Implements the YOKE Adapter contract once for standard ACP agents.
4
+
5
+ var AcpProcessManager = require("../acp-process-manager").AcpProcessManager;
6
+ var createAcpQueryHandle = require("../acp-query-handle").createAcpQueryHandle;
7
+ var profiles = require("../acp-agent-profiles");
8
+ var driverRuntime = require("../acp-driver-runtime");
9
+ var skillDiscovery = require("../skill-discovery");
10
+
11
+ function modelValues(configOptions) {
12
+ var models = [];
13
+ var options = Array.isArray(configOptions) ? configOptions : [];
14
+ for (var i = 0; i < options.length; i++) {
15
+ var option = options[i];
16
+ if (option.category !== "model" && option.id !== "model") continue;
17
+ var values = Array.isArray(option.options) ? option.options : [];
18
+ for (var j = 0; j < values.length; j++) {
19
+ var value = values[j] && values[j].value;
20
+ if (value && models.indexOf(value) === -1) models.push(value);
21
+ }
22
+ break;
23
+ }
24
+ return models;
25
+ }
26
+
27
+ function createAcpAdapter(vendor, opts) {
28
+ opts = opts || {};
29
+ var driver = opts._profile || opts._driver || profiles.getAcpAgentDriver(vendor);
30
+ if (!driver) throw new Error("[YOKE] Unknown ACP agent driver: " + vendor);
31
+
32
+ var cwd = opts.cwd || process.cwd();
33
+ var binaryPath = opts._binaryPath || profiles.findAcpAgentPath(driver);
34
+ var ProcessManagerCtor = opts._AcpProcessManagerCtor || AcpProcessManager;
35
+ var fetchModels = opts._fetchModels || driver.fetchModels || null;
36
+ var acp = null;
37
+ var initPromise = null;
38
+ var initialized = false;
39
+ var shuttingDown = false;
40
+ var initResult = null;
41
+ var driverState = {};
42
+ var cachedModels = (driver.defaultModels || []).slice();
43
+ var defaultModel = driver.defaultModel || cachedModels[0] || "auto";
44
+ var activeHandles = [];
45
+ var lastActiveAt = Date.now();
46
+
47
+ function context(extra) {
48
+ return Object.assign({
49
+ vendor: vendor,
50
+ cwd: cwd,
51
+ driver: driver,
52
+ acp: acp,
53
+ initResult: initResult,
54
+ adapter: adapter,
55
+ binaryPath: binaryPath,
56
+ driverState: driverState,
57
+ }, extra || {});
58
+ }
59
+
60
+ function supportsSessionCapability(name) {
61
+ var capabilities = initResult && initResult.agentCapabilities;
62
+ return !!(capabilities && capabilities.sessionCapabilities && capabilities.sessionCapabilities[name]);
63
+ }
64
+
65
+ function canLoadSession() {
66
+ if (driver.sessionResume === false) return false;
67
+ return !!(initResult && initResult.agentCapabilities && initResult.agentCapabilities.loadSession);
68
+ }
69
+
70
+ function canResumeSession() {
71
+ if (driver.sessionResume === false) return false;
72
+ return supportsSessionCapability("resume");
73
+ }
74
+
75
+ function capabilities() {
76
+ var base = {
77
+ effort: false,
78
+ midSessionModelSwitch: false,
79
+ fork: false,
80
+ rollback: false,
81
+ sessionListing: false,
82
+ sessionRename: false,
83
+ thinking: true,
84
+ betas: false,
85
+ rewind: false,
86
+ sessionResume: canResumeSession() || canLoadSession(),
87
+ promptSuggestions: false,
88
+ elicitation: false,
89
+ fileCheckpointing: false,
90
+ contextCompacting: false,
91
+ skillSharing: true,
92
+ toolPolicy: ["ask", "allow-all"],
93
+ };
94
+ return driverRuntime.mergeCapabilities(driver, context(), base);
95
+ }
96
+
97
+ function readyResult() {
98
+ var skills = skillDiscovery.discoverSkills(cwd).map(function(skill) { return skill.name; });
99
+ var result = {
100
+ models: cachedModels.slice(),
101
+ defaultModel: defaultModel,
102
+ skills: skills,
103
+ slashCommands: skills,
104
+ fastModeState: null,
105
+ capabilities: capabilities(),
106
+ };
107
+ return driverRuntime.call(driver, "extendReadyResult", context({ result: result }), function() { return result; }) || result;
108
+ }
109
+
110
+ function updateModelsFromSession(sessionResult) {
111
+ var discovered = modelValues(sessionResult && sessionResult.configOptions);
112
+ if (!discovered.length) return;
113
+ cachedModels = discovered;
114
+ var configOptions = sessionResult.configOptions;
115
+ for (var i = 0; i < configOptions.length; i++) {
116
+ if (configOptions[i].category === "model" || configOptions[i].id === "model") {
117
+ defaultModel = configOptions[i].currentValue || defaultModel;
118
+ break;
119
+ }
120
+ }
121
+ }
122
+
123
+ function removeHandle(handle) {
124
+ var index = activeHandles.indexOf(handle);
125
+ if (index !== -1) activeHandles.splice(index, 1);
126
+ lastActiveAt = Date.now();
127
+ }
128
+
129
+ var adapter = {
130
+ vendor: vendor,
131
+
132
+ init: function(initOpts) {
133
+ if (shuttingDown) return Promise.reject(new Error(driver.displayName + " adapter is shutting down"));
134
+ if (initialized && acp && acp.started) return Promise.resolve(readyResult());
135
+ if (initPromise) return initPromise;
136
+
137
+ initPromise = (async function() {
138
+ if (!binaryPath) {
139
+ binaryPath = profiles.findAcpAgentPath(driver);
140
+ if (!binaryPath) throw new Error(driver.displayName + " binary not found: " + driver.binaryName);
141
+ }
142
+ var effectiveOpts = Object.assign({}, opts, initOpts || {});
143
+ var prepared = await Promise.all([
144
+ fetchModels ? fetchModels(binaryPath, cwd) : Promise.resolve([]),
145
+ driverRuntime.callAsync(driver, "prepare", context({ initOpts: effectiveOpts }), function() {}),
146
+ ]);
147
+ if (fetchModels) {
148
+ var fetched = prepared[0];
149
+ if (Array.isArray(fetched) && fetched.length) {
150
+ cachedModels = fetched;
151
+ if (cachedModels.indexOf(defaultModel) === -1) defaultModel = cachedModels[0];
152
+ }
153
+ }
154
+ if (shuttingDown) throw new Error(driver.displayName + " adapter is shutting down");
155
+
156
+ var processOptions = driverRuntime.buildParams(driver, "buildProcessOptions", context({ initOpts: effectiveOpts }), {
157
+ args: driver.args || [],
158
+ cwd: cwd,
159
+ env: effectiveOpts.env || null,
160
+ logPrefix: vendor + "-acp",
161
+ });
162
+ await driverRuntime.callAsync(driver, "validateProcessOptions", context({
163
+ initOpts: effectiveOpts,
164
+ processOptions: processOptions,
165
+ }), function() {});
166
+ if (shuttingDown) throw new Error(driver.displayName + " adapter is shutting down");
167
+ acp = new ProcessManagerCtor(binaryPath, processOptions);
168
+ await driverRuntime.callAsync(driver, "registerRequestHandlers", context({ acp: acp }), function() {});
169
+ if (shuttingDown) throw new Error(driver.displayName + " adapter is shutting down");
170
+ await acp.start();
171
+ try {
172
+ if (shuttingDown) throw new Error(driver.displayName + " adapter is shutting down");
173
+ var initializeParams = driverRuntime.buildParams(driver, "buildInitializeParams", context({ acp: acp }), {
174
+ protocolVersion: 1,
175
+ clientInfo: { name: "clay", version: "1.0.0" },
176
+ clientCapabilities: {
177
+ fs: { readTextFile: false, writeTextFile: false },
178
+ session: { configOptions: { boolean: {} } },
179
+ },
180
+ });
181
+ initResult = await acp.send("initialize", initializeParams, 30000);
182
+ await driverRuntime.callAsync(driver, "onInitialize", context({ acp: acp, initResult: initResult }), function() {});
183
+ if (shuttingDown) throw new Error(driver.displayName + " adapter is shutting down");
184
+ } catch (e) {
185
+ acp.stop();
186
+ acp = null;
187
+ throw e;
188
+ }
189
+ initialized = true;
190
+ lastActiveAt = Date.now();
191
+ return readyResult();
192
+ })().then(function(result) {
193
+ initPromise = null;
194
+ return result;
195
+ }, function(err) {
196
+ initPromise = null;
197
+ initialized = false;
198
+ throw err;
199
+ });
200
+ return initPromise;
201
+ },
202
+
203
+ supportedModels: function() {
204
+ return driverRuntime.callAsync(driver, "supportedModels", context({ models: cachedModels.slice() }), function() {
205
+ if (!fetchModels || !binaryPath) return cachedModels.slice();
206
+ return fetchModels(binaryPath, cwd).then(function(fetched) {
207
+ if (Array.isArray(fetched) && fetched.length) cachedModels = fetched;
208
+ return cachedModels.slice();
209
+ });
210
+ });
211
+ },
212
+
213
+ createToolServer: function(definition) {
214
+ return driverRuntime.call(driver, "createToolServer", context({ definition: definition }), function() { return null; });
215
+ },
216
+
217
+ createQuery: async function(queryOpts) {
218
+ queryOpts = queryOpts || {};
219
+ if (!initialized || !acp || !acp.started) await adapter.init(queryOpts);
220
+ if (shuttingDown) throw new Error(driver.displayName + " adapter is shutting down");
221
+ var controller = queryOpts.abortController || new AbortController();
222
+ var sharedSkills = skillDiscovery.discoverSkills(queryOpts.cwd || cwd);
223
+ var skillIndex = skillDiscovery.buildSkillIndex(sharedSkills);
224
+ var acpOptions = (queryOpts.adapterOptions && queryOpts.adapterOptions.ACP) || {};
225
+ var handle = null;
226
+ handle = createAcpQueryHandle(acp, {
227
+ vendor: vendor,
228
+ driver: driver,
229
+ cwd: queryOpts.cwd || cwd,
230
+ model: queryOpts.model || defaultModel,
231
+ mode: queryOpts.mode || null,
232
+ systemPrompt: queryOpts.systemPrompt || "",
233
+ appendSystemPrompt: [queryOpts.appendSystemPrompt, skillIndex].filter(function(part) { return !!part; }).join("\n\n"),
234
+ abortController: controller,
235
+ canUseTool: queryOpts.canUseTool || null,
236
+ resumeSessionId: queryOpts.resumeSessionId || null,
237
+ canLoadSession: canLoadSession(),
238
+ canResumeSession: canResumeSession(),
239
+ mcpServers: acpOptions.mcpServers || queryOpts.mcpServers || [],
240
+ onSessionReady: updateModelsFromSession,
241
+ onFinished: function() { removeHandle(handle); },
242
+ });
243
+ activeHandles.push(handle);
244
+ lastActiveAt = Date.now();
245
+ return handle;
246
+ },
247
+
248
+ generateTitle: async function(messages, titleOpts) {
249
+ if (driverRuntime.hasHook(driver, "generateTitle")) {
250
+ return driver.generateTitle(context({ messages: messages, opts: titleOpts }));
251
+ }
252
+ var prompt = "Generate a short descriptive title of 3 to 8 words. Output only the title.\n\n";
253
+ for (var i = 0; i < messages.length; i++) prompt += "User message " + (i + 1) + ": " + messages[i] + "\n";
254
+ var handle = await adapter.createQuery({
255
+ cwd: (titleOpts && titleOpts.cwd) || cwd,
256
+ systemPrompt: "You generate concise conversation titles. Output only the title.",
257
+ canUseTool: function() { return Promise.resolve({ behavior: "deny" }); },
258
+ });
259
+ handle.pushMessage(prompt);
260
+ var title = "";
261
+ try {
262
+ for await (var event of handle) {
263
+ if (event.yokeType === "text_delta" && event.text) title += event.text;
264
+ if (event.yokeType === "result") break;
265
+ }
266
+ } finally {
267
+ handle.close();
268
+ }
269
+ return title.replace(/[\r\n]+/g, " ").replace(/^["'\s]+|["'\s.]+$/g, "").trim();
270
+ },
271
+
272
+ getSessionInfo: function(sessionId, methodOpts) {
273
+ return driverRuntime.callAsync(driver, "getSessionInfo", context({ sessionId: sessionId, opts: methodOpts }), function() { return null; });
274
+ },
275
+ listSessions: function(methodOpts) {
276
+ return driverRuntime.callAsync(driver, "listSessions", context({ opts: methodOpts }), function() { return []; });
277
+ },
278
+ renameSession: function(sessionId, title, methodOpts) {
279
+ return driverRuntime.callAsync(driver, "renameSession", context({ sessionId: sessionId, title: title, opts: methodOpts }), function() {});
280
+ },
281
+ forkSession: function(sessionId, methodOpts) {
282
+ return driverRuntime.callAsync(driver, "forkSession", context({ sessionId: sessionId, opts: methodOpts }), function() { return null; });
283
+ },
284
+
285
+ shutdown: async function() {
286
+ shuttingDown = true;
287
+ var pendingInit = initPromise;
288
+ if (acp) acp.stop();
289
+ if (pendingInit) {
290
+ try { await pendingInit; } catch (e) {}
291
+ }
292
+ var handles = activeHandles.slice();
293
+ for (var i = 0; i < handles.length; i++) handles[i].abort();
294
+ activeHandles = [];
295
+ try {
296
+ if (acp) acp.stop();
297
+ await driverRuntime.callAsync(driver, "onShutdown", context(), function() {});
298
+ } finally {
299
+ acp = null;
300
+ initialized = false;
301
+ shuttingDown = false;
302
+ }
303
+ return true;
304
+ },
305
+
306
+ shutdownIfIdle: function(idleMs) {
307
+ if (!acp || activeHandles.length || Date.now() - lastActiveAt < (idleMs || 0)) return Promise.resolve(false);
308
+ return adapter.shutdown();
309
+ },
310
+ };
311
+ return adapter;
312
+ }
313
+
314
+ module.exports = {
315
+ createAcpAdapter: createAcpAdapter,
316
+ modelValues: modelValues,
317
+ };
@@ -0,0 +1,7 @@
1
+ var createAcpAdapter = require("./acp").createAcpAdapter;
2
+
3
+ function createGeminiAdapter(opts) {
4
+ return createAcpAdapter("gemini", opts);
5
+ }
6
+
7
+ module.exports = { createGeminiAdapter: createGeminiAdapter };
@@ -477,10 +477,10 @@ function createKiroQueryHandle(acp, queryOpts) {
477
477
  var method = msg.method;
478
478
  var params = msg.params || {};
479
479
 
480
- // Routing by sessionId happens in KiroAcpServer._handleMessage, which also
481
- // guarantees unroutable requests get an error response. Do not add a silent
482
- // sessionId filter here: dropping a request without calling acp.respond()
483
- // blocks kiro-cli until the session/prompt timeout.
480
+ // The shared ACP manager routes by sessionId and guarantees unroutable
481
+ // requests get an error response. Do not add a silent sessionId filter here:
482
+ // dropping a request without calling acp.respond() blocks kiro-cli until the
483
+ // session/prompt timeout.
484
484
 
485
485
  // Tool permission request (server -> client, has an id we must answer)
486
486
  if (method === "session/request_permission") {
@@ -0,0 +1,7 @@
1
+ var createAcpAdapter = require("./acp").createAcpAdapter;
2
+
3
+ function createOpenCodeAdapter(opts) {
4
+ return createAcpAdapter("opencode", opts);
5
+ }
6
+
7
+ module.exports = { createOpenCodeAdapter: createOpenCodeAdapter };
package/lib/yoke/index.js CHANGED
@@ -6,11 +6,13 @@ var instructions = require("./instructions");
6
6
  var vendorRegistry = require("./vendor-registry");
7
7
  var createClaudeAdapter = require("./adapters/claude").createClaudeAdapter;
8
8
  var createCodexAdapter = require("./adapters/codex").createCodexAdapter;
9
+ var createGeminiAdapter = require("./adapters/gemini").createGeminiAdapter;
10
+ var createOpenCodeAdapter = require("./adapters/opencode").createOpenCodeAdapter;
9
11
  var createKiroAdapter = require("./adapters/kiro").createKiroAdapter;
10
12
 
11
13
  // Keep the first session in a new project predictable. This order is also
12
14
  // used by the UI when a project has no remembered vendor yet.
13
- var DEFAULT_VENDOR_ORDER = ["claude", "codex", "kiro"];
15
+ var DEFAULT_VENDOR_ORDER = ["claude", "codex", "gemini", "opencode", "kiro"];
14
16
 
15
17
  function resolveDefaultVendor(availableVendors) {
16
18
  availableVendors = availableVendors || {};
@@ -71,6 +73,10 @@ function createAdapter(opts) {
71
73
  adapter = createClaudeAdapter(opts);
72
74
  } else if (vendor === "codex") {
73
75
  adapter = createCodexAdapter(opts);
76
+ } else if (vendor === "gemini") {
77
+ adapter = createGeminiAdapter(opts);
78
+ } else if (vendor === "opencode") {
79
+ adapter = createOpenCodeAdapter(opts);
74
80
  } else if (vendor === "kiro") {
75
81
  adapter = createKiroAdapter(opts);
76
82
  } else {
@@ -96,7 +102,7 @@ function logAuthCheck(auth) {
96
102
  if (_lastAuthLogKey === key && now - _lastAuthLogAt < 30000) return;
97
103
  _lastAuthLogKey = key;
98
104
  _lastAuthLogAt = now;
99
- console.log("[yoke] Auth check: claude=" + auth.claude + " codex=" + auth.codex + " kiro=" + auth.kiro);
105
+ console.log("[yoke] Auth check: claude=" + auth.claude + " codex=" + auth.codex + " gemini=" + auth.gemini + " opencode=" + auth.opencode + " kiro=" + auth.kiro);
100
106
  }
101
107
 
102
108
  function checkAuth() {
@@ -227,7 +233,13 @@ function checkAuth() {
227
233
  }
228
234
  }
229
235
 
230
- _authCache = { claude: checkClaude(), codex: checkCodex(), kiro: checkKiro() };
236
+ _authCache = {
237
+ claude: checkClaude(),
238
+ codex: checkCodex(),
239
+ gemini: !!lookupBinary("gemini"),
240
+ opencode: !!lookupBinary("opencode"),
241
+ kiro: checkKiro(),
242
+ };
231
243
  logAuthCheck(_authCache);
232
244
  return _authCache;
233
245
  }
@@ -249,7 +261,7 @@ function checkInstalled() {
249
261
 
250
262
  var fs = require("fs");
251
263
  var execFileSync = require("child_process").execFileSync;
252
- var result = { claude: false, codex: false, kiro: false };
264
+ var result = { claude: false, codex: false, gemini: false, opencode: false, kiro: false };
253
265
  try {
254
266
  if (process.platform === "win32") execFileSync("where", ["claude"], { timeout: 3000, stdio: ["pipe", "pipe", "pipe"] });
255
267
  else execFileSync("which", ["claude"], { timeout: 3000, stdio: ["pipe", "pipe", "pipe"] });
@@ -267,15 +279,20 @@ function checkInstalled() {
267
279
  codexBin = findCodexPath();
268
280
  if (codexBin && fs.existsSync(codexBin)) {
269
281
  result.codex = true;
270
- _installedCache = result;
271
- return result;
272
282
  }
273
283
  } catch (e) {}
274
284
 
275
- var whichOut = process.platform === "win32"
276
- ? execFileSync("where", ["codex"], { timeout: 3000, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] })
277
- : execFileSync("which", ["codex"], { timeout: 3000, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] });
278
- if (whichOut.trim()) result.codex = true;
285
+ if (!result.codex) {
286
+ var whichOut = process.platform === "win32"
287
+ ? execFileSync("where", ["codex"], { timeout: 3000, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] })
288
+ : execFileSync("which", ["codex"], { timeout: 3000, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] });
289
+ if (whichOut.trim()) result.codex = true;
290
+ }
291
+ } catch (e) {}
292
+ try {
293
+ var acpProfiles = require("./acp-agent-profiles");
294
+ result.gemini = !!acpProfiles.findAcpAgentPath(acpProfiles.getAcpAgentProfile("gemini"));
295
+ result.opencode = !!acpProfiles.findAcpAgentPath(acpProfiles.getAcpAgentProfile("opencode"));
279
296
  } catch (e) {}
280
297
  _installedCache = result;
281
298
  return result;
@@ -301,7 +318,7 @@ function createAdapters(opts) {
301
318
  // that `claude auth status` does not always detect. Runtime auth failures are
302
319
  // handled downstream via query-level error detection.
303
320
  var installed = checkInstalled();
304
- var auth = { claude: false, codex: false, kiro: false };
321
+ var auth = { claude: false, codex: false, gemini: false, opencode: false, kiro: false };
305
322
  var adapters = {};
306
323
 
307
324
  function supportsConfiguredIsolation(vendor) {
@@ -336,6 +353,23 @@ function createAdapters(opts) {
336
353
  }
337
354
  }
338
355
 
356
+ var acpVendors = ["gemini", "opencode"];
357
+ for (var acpIndex = 0; acpIndex < acpVendors.length; acpIndex++) {
358
+ var acpVendor = acpVendors[acpIndex];
359
+ var acpInfo = vendorRegistry.getVendorInfo(acpVendor);
360
+ if (installed[acpVendor] && supportsConfiguredIsolation(acpVendor)) {
361
+ try {
362
+ adapters[acpVendor] = createAdapter({ vendor: acpVendor, cwd: opts.cwd, slug: opts.slug });
363
+ auth[acpVendor] = true;
364
+ console.log("[yoke] Adapter created: " + acpVendor);
365
+ } catch (e) {
366
+ console.error("[yoke] Failed to create adapter for " + acpVendor + ":", e.message);
367
+ }
368
+ } else if (installed[acpVendor] && opts.osUsers) {
369
+ console.log("[yoke] " + acpInfo.displayName + " adapter disabled: OS-user isolation requires per-user spawning");
370
+ }
371
+ }
372
+
339
373
  var kiroInfo = vendorRegistry.getVendorInfo("kiro");
340
374
  if (installed.kiro && supportsConfiguredIsolation("kiro")) {
341
375
  try {
@@ -41,6 +41,7 @@ var TOOL_POLICIES = ["ask", "allow-all"];
41
41
  * .setToolPolicy(policy) - "ask" | "allow-all"
42
42
  * .stopTask(taskId)
43
43
  * .getContextUsage() - Promise<object|null>
44
+ * .endInput() - stop accepting turns after queued input drains
44
45
  * .abort()
45
46
  * .close()
46
47
  */
@@ -59,6 +60,7 @@ var QUERY_HANDLE_METHODS = [
59
60
  "setToolPolicy",
60
61
  "stopTask",
61
62
  "getContextUsage",
63
+ "endInput",
62
64
  "abort",
63
65
  "close",
64
66
  ];