clay-server 5.2.0-beta.4 → 5.2.0-beta.6

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 (301) hide show
  1. package/lib/account-auth-socket.js +1 -0
  2. package/lib/builtin-mates.js +17 -14
  3. package/lib/canonical-clay-record-authority.js +15 -0
  4. package/lib/canonical-clay-scheduling-authority.js +19 -0
  5. package/lib/claude-hook-installer.js +1 -239
  6. package/lib/claude-jsonl-watcher.js +1 -204
  7. package/lib/clay-mate-chat-receipts.js +26 -0
  8. package/lib/clay-mate-chat.js +87 -0
  9. package/lib/clay-mate-knowledge-input.js +26 -0
  10. package/lib/clay-mate-knowledge.js +95 -0
  11. package/lib/clay-mate-lifecycle.js +95 -0
  12. package/lib/clay-product-control-input.js +33 -0
  13. package/lib/clay-product-control-tools.js +51 -0
  14. package/lib/clay-product-control.js +237 -0
  15. package/lib/clay-project-lifecycle.js +154 -0
  16. package/lib/clay-project-record-input.js +44 -0
  17. package/lib/clay-project-records.js +83 -0
  18. package/lib/clay-scheduling-input.js +21 -0
  19. package/lib/clay-scheduling-receipts.js +26 -0
  20. package/lib/clay-scheduling.js +119 -0
  21. package/lib/clay-screen-controls.js +96 -0
  22. package/lib/clay-skill-install.js +1 -33
  23. package/lib/clay-workspace-controls.js +83 -0
  24. package/lib/clay-workspace-input.js +17 -0
  25. package/lib/clay-workspace-receipts.js +26 -0
  26. package/lib/cli-sessions.js +1 -300
  27. package/lib/codex-defaults.js +1 -28
  28. package/lib/context-usage.js +3 -2
  29. package/lib/daemon-project-access.js +11 -0
  30. package/lib/daemon-project-lifecycle-callbacks.js +15 -0
  31. package/lib/daemon-project-lifecycle.js +262 -0
  32. package/lib/daemon-projects.js +1 -1
  33. package/lib/daemon.js +78 -276
  34. package/lib/default-ai-runtime.js +4 -8
  35. package/lib/email-mcp-server.js +1 -1
  36. package/lib/issues-service.js +29 -15
  37. package/lib/kiro-defaults.js +1 -22
  38. package/lib/knowledge-db-import.js +5 -4
  39. package/lib/knowledge-db-service.js +9 -6
  40. package/lib/knowledge-document-index.js +2 -1
  41. package/lib/knowledge-product-operations.js +46 -0
  42. package/lib/mate-creation-mcp-server.js +2 -0
  43. package/lib/mate-knowledge-canonical-access.js +10 -0
  44. package/lib/mate-knowledge-service.js +7 -4
  45. package/lib/mate-lifecycle-service.js +94 -0
  46. package/lib/mate-message-delivery.js +43 -0
  47. package/lib/mate-ready-creation.js +9 -1
  48. package/lib/mate-schedule-input.js +29 -0
  49. package/lib/mate-schedule-lifecycle.js +151 -0
  50. package/lib/mate-scheduling.js +103 -0
  51. package/lib/mates.js +4 -3
  52. package/lib/mcp-proxy.js +2 -32
  53. package/lib/mcp-query-bridge.js +1 -1
  54. package/lib/mcp-source-adapters.js +1 -91
  55. package/lib/mcp-source-context.js +1 -42
  56. package/lib/mcp-source-discovery.js +1 -169
  57. package/lib/mcp-source-plugins.js +1 -68
  58. package/lib/mcp-source-restrictions.js +1 -47
  59. package/lib/mcp-tool-policy.js +1 -26
  60. package/lib/notes-checklist.js +50 -0
  61. package/lib/notes.js +49 -3
  62. package/lib/os-user-diagnostics.js +2 -4
  63. package/lib/os-users.js +24 -70
  64. package/lib/project-admin-overview.js +51 -0
  65. package/lib/project-ask-user.js +4 -2
  66. package/lib/project-connection.js +8 -7
  67. package/lib/project-delegated-follow-up.js +2 -1
  68. package/lib/project-directory-claim.js +65 -0
  69. package/lib/project-file-operations.js +61 -0
  70. package/lib/project-filesystem.js +13 -87
  71. package/lib/project-full-access.js +23 -2
  72. package/lib/project-http.js +4 -4
  73. package/lib/project-knowledge.js +32 -18
  74. package/lib/project-lifecycle-operations.js +98 -0
  75. package/lib/project-lifecycle-process-witness.js +32 -0
  76. package/lib/project-lifecycle-runtime.js +50 -0
  77. package/lib/project-linux-access.js +22 -0
  78. package/lib/project-logs-canonical-clay.js +27 -0
  79. package/lib/project-logs-clay-query.js +16 -0
  80. package/lib/project-logs-schema.js +4 -2
  81. package/lib/project-logs-service.js +8 -7
  82. package/lib/project-logs.js +1 -0
  83. package/lib/project-loop.js +1 -0
  84. package/lib/project-mate-chat-control.js +55 -0
  85. package/lib/project-mate-creation-proposal.js +18 -3
  86. package/lib/project-mcp.js +2 -2
  87. package/lib/project-models.js +14 -31
  88. package/lib/project-notifications.js +74 -16
  89. package/lib/project-ownership.js +77 -0
  90. package/lib/project-pair-result-delivery.js +14 -3
  91. package/lib/project-pair-usage.js +12 -13
  92. package/lib/project-pending-message-queue.js +4 -1
  93. package/lib/project-product-control.js +87 -0
  94. package/lib/project-product-session-queue.js +46 -0
  95. package/lib/project-push-access.js +28 -0
  96. package/lib/project-scheduled-message-queue.js +30 -0
  97. package/lib/project-scheduled-messages.js +63 -64
  98. package/lib/project-scheduled-task-control.js +83 -0
  99. package/lib/project-scheduled-tasks.js +13 -2
  100. package/lib/project-scheduling-access.js +10 -0
  101. package/lib/project-session-actions.js +65 -0
  102. package/lib/project-session-delete.js +8 -1
  103. package/lib/project-session-github.js +47 -12
  104. package/lib/project-session-history-actions.js +167 -0
  105. package/lib/project-session-pair.js +1 -1
  106. package/lib/project-session-runtime-actions.js +64 -0
  107. package/lib/project-session-spawn.js +2 -3
  108. package/lib/project-session-vendor.js +55 -0
  109. package/lib/project-sessions.js +82 -267
  110. package/lib/project-user-message.js +31 -1
  111. package/lib/project-vendor-login.js +6 -36
  112. package/lib/project-workspace-operations.js +126 -0
  113. package/lib/project-workspace-query.js +9 -2
  114. package/lib/project.js +95 -3
  115. package/lib/public/app.js +1 -0
  116. package/lib/public/css/clay-tool-activity.css +51 -0
  117. package/lib/public/css/home-mate-creation.css +5 -0
  118. package/lib/public/css/messages.css +6 -2
  119. package/lib/public/css/overlays.css +4 -2
  120. package/lib/public/css/project-admin-overview.css +13 -0
  121. package/lib/public/css/session-folders.css +11 -0
  122. package/lib/public/css/session-github.css +3 -0
  123. package/lib/public/css/sticky-notes.css +61 -1
  124. package/lib/public/index.html +1 -1
  125. package/lib/public/modules/admin-settings-projects.js +6 -2
  126. package/lib/public/modules/app-connection.js +8 -1
  127. package/lib/public/modules/app-favicon.js +11 -2
  128. package/lib/public/modules/app-header.js +4 -2
  129. package/lib/public/modules/app-loop-ui.js +2 -0
  130. package/lib/public/modules/app-message-router.js +1 -1
  131. package/lib/public/modules/app-messages.js +54 -8
  132. package/lib/public/modules/app-notifications.js +1 -2
  133. package/lib/public/modules/app-panels.js +61 -123
  134. package/lib/public/modules/app-projects.js +5 -0
  135. package/lib/public/modules/app-rate-limit.js +7 -27
  136. package/lib/public/modules/chat-render-runtime.js +3 -0
  137. package/lib/public/modules/clay-owner-navigation.js +27 -0
  138. package/lib/public/modules/clay-tool-activity.js +140 -0
  139. package/lib/public/modules/clay-tool-presentation.js +338 -0
  140. package/lib/public/modules/command-palette.js +1 -1
  141. package/lib/public/modules/default-ai.js +11 -3
  142. package/lib/public/modules/home-debate-planning.js +5 -5
  143. package/lib/public/modules/home-mate-chat.js +8 -6
  144. package/lib/public/modules/home-mate-creation.js +73 -1
  145. package/lib/public/modules/mcp-connection-view.js +1 -1
  146. package/lib/public/modules/permission-control.js +5 -4
  147. package/lib/public/modules/personal-settings-dialog.js +7 -1
  148. package/lib/public/modules/project-access-recovery.js +17 -0
  149. package/lib/public/modules/project-admin-overview.js +21 -0
  150. package/lib/public/modules/scheduler.js +2 -0
  151. package/lib/public/modules/session-create-form.js +10 -10
  152. package/lib/public/modules/session-folder-layout.js +1 -1
  153. package/lib/public/modules/session-folder-view-menu.js +9 -0
  154. package/lib/public/modules/session-github.js +65 -8
  155. package/lib/public/modules/settings-defaults.js +27 -28
  156. package/lib/public/modules/sidebar-session-folders-ui.js +1 -1
  157. package/lib/public/modules/sticky-note-markdown.js +72 -6
  158. package/lib/public/modules/sticky-notes-actions.js +30 -0
  159. package/lib/public/modules/sticky-notes-browser.js +9 -2
  160. package/lib/public/modules/sticky-notes-card.js +23 -7
  161. package/lib/public/modules/sticky-notes-checklist.js +71 -0
  162. package/lib/public/modules/sticky-notes-editor.js +108 -44
  163. package/lib/public/modules/sticky-notes-shared.js +50 -2
  164. package/lib/public/modules/sticky-notes-state.js +66 -0
  165. package/lib/public/modules/sticky-notes.js +34 -51
  166. package/lib/public/modules/thinking-lifecycle.js +33 -3
  167. package/lib/public/modules/thinking-view.js +23 -1
  168. package/lib/public/modules/tools.js +36 -7
  169. package/lib/public/modules/tui-grab.js +1 -2
  170. package/lib/public/modules/user-settings-appearance.js +10 -3
  171. package/lib/public/modules/user-settings-editors.js +1 -1
  172. package/lib/public/modules/user-settings-layout.js +11 -2
  173. package/lib/public/modules/user-settings-preferences.js +6 -2
  174. package/lib/public/modules/user-settings-profile.js +12 -2
  175. package/lib/public/modules/user-settings.js +3 -2
  176. package/lib/public/modules/vendor-login-browser.js +5 -3
  177. package/lib/public/modules/vendor-login.js +2 -2
  178. package/lib/public/modules/vendor-priority.js +15 -1
  179. package/lib/public/muse-avatar.svg +4 -0
  180. package/lib/public/style.css +2 -0
  181. package/lib/safe-bash-commands.js +3 -45
  182. package/lib/scheduled-task-records.js +3 -1
  183. package/lib/scheduler.js +2 -0
  184. package/lib/sdk-bridge.js +334 -403
  185. package/lib/sdk-foreground-admission.js +16 -0
  186. package/lib/sdk-mcp-descriptors.js +2 -37
  187. package/lib/sdk-message-processor.js +52 -17
  188. package/lib/sdk-quota-snapshot.js +1 -1
  189. package/lib/sdk-response-recovery.js +1 -0
  190. package/lib/sdk-worker.js +2 -677
  191. package/lib/server-admin.js +63 -16
  192. package/lib/server-dm.js +1 -1
  193. package/lib/server-global-ws.js +10 -20
  194. package/lib/server-home-chat-events.js +7 -3
  195. package/lib/server-home-chat.js +4 -16
  196. package/lib/server-home-mate-creation.js +1 -0
  197. package/lib/server-home-mcp-consent.js +3 -3
  198. package/lib/server-mates.js +25 -67
  199. package/lib/server-owner-ui.js +77 -0
  200. package/lib/server-path-access.js +38 -0
  201. package/lib/server-project-removal.js +22 -0
  202. package/lib/server.js +100 -30
  203. package/lib/session-config-transition.js +45 -0
  204. package/lib/session-folders.js +7 -2
  205. package/lib/session-fork-history.js +21 -0
  206. package/lib/session-github.js +9 -2
  207. package/lib/session-hygiene.js +3 -35
  208. package/lib/session-permission-mode.js +4 -3
  209. package/lib/session-skill-scope.js +11 -0
  210. package/lib/session-visibility.js +5 -2
  211. package/lib/sessions.js +27 -89
  212. package/lib/terminal-manager.js +52 -0
  213. package/lib/tool-llm.js +1 -1
  214. package/lib/tui-transcript-index.js +1 -132
  215. package/lib/users-permissions.js +2 -8
  216. package/lib/users.js +4 -0
  217. package/lib/vendor-login-browser.js +1 -11
  218. package/lib/workspace-query-access.js +4 -1
  219. package/lib/ws-schema.js +8 -2
  220. package/lib/yoke/acp-agent-profiles.js +5 -3
  221. package/lib/yoke/adapters/antigravity.js +3 -14
  222. package/lib/yoke/adapters/claude-query-contract.js +9 -0
  223. package/lib/yoke/adapters/claude.js +54 -50
  224. package/lib/yoke/adapters/codex-query-contract.js +24 -0
  225. package/lib/yoke/adapters/codex.js +53 -111
  226. package/lib/yoke/adapters/kiro.js +3 -1
  227. package/lib/yoke/adapters/muse-query-contract.js +7 -0
  228. package/lib/yoke/adapters/muse.js +122 -0
  229. package/lib/yoke/auth-events.js +17 -0
  230. package/lib/yoke/claude-hook-installer.js +267 -0
  231. package/lib/yoke/claude-jsonl-watcher.js +204 -0
  232. package/lib/yoke/claude-maintenance.js +55 -0
  233. package/lib/yoke/claude-permission-patterns.js +53 -0
  234. package/lib/yoke/claude-response-recovery.js +155 -0
  235. package/lib/yoke/claude-transcript-hygiene.js +34 -0
  236. package/lib/yoke/claude-worker-startup.js +28 -0
  237. package/lib/yoke/clay-skill-install.js +33 -0
  238. package/lib/yoke/cli-sessions.js +300 -0
  239. package/lib/yoke/codex-app-server.js +7 -12
  240. package/lib/yoke/codex-idle-recovery.js +81 -1
  241. package/lib/yoke/codex-recovery-admission.js +164 -0
  242. package/lib/yoke/configuration.js +13 -0
  243. package/lib/yoke/discovery.js +70 -0
  244. package/lib/yoke/errors.js +8 -0
  245. package/lib/yoke/host-environment.js +7 -0
  246. package/lib/yoke/index.js +9 -51
  247. package/lib/yoke/interface.js +116 -0
  248. package/lib/yoke/kiro-acp-server.js +5 -5
  249. package/lib/yoke/legacy-sessions.js +89 -0
  250. package/lib/yoke/login-protocol.js +25 -0
  251. package/lib/yoke/maintenance.js +12 -0
  252. package/lib/yoke/mcp-proxy.js +32 -0
  253. package/lib/yoke/mcp-source-adapters.js +91 -0
  254. package/lib/yoke/mcp-source-context.js +42 -0
  255. package/lib/yoke/mcp-source-discovery.js +169 -0
  256. package/lib/yoke/mcp-source-plugins.js +68 -0
  257. package/lib/yoke/mcp-source-restrictions.js +47 -0
  258. package/lib/yoke/mcp-tool-policy-normalize.js +28 -0
  259. package/lib/yoke/model-preferences.js +6 -0
  260. package/lib/yoke/muse-artifacts.js +36 -0
  261. package/lib/yoke/muse-controls.js +50 -0
  262. package/lib/yoke/muse-input.js +64 -0
  263. package/lib/yoke/muse-items.js +157 -0
  264. package/lib/yoke/muse-policy.js +52 -0
  265. package/lib/yoke/muse-query.js +428 -0
  266. package/lib/yoke/muse-runtime.js +211 -0
  267. package/lib/yoke/muse-services.js +79 -0
  268. package/lib/yoke/muse-skills.js +79 -0
  269. package/lib/yoke/muse-turns.js +71 -0
  270. package/lib/yoke/options/acp.js +2 -0
  271. package/lib/yoke/options/antigravity.js +2 -0
  272. package/lib/yoke/options/claude.js +21 -0
  273. package/lib/yoke/options/codex-defaults.js +29 -0
  274. package/lib/yoke/options/codex-settings.js +21 -0
  275. package/lib/yoke/options/codex.js +6 -0
  276. package/lib/yoke/options/kiro-defaults.js +22 -0
  277. package/lib/yoke/options/kiro.js +5 -0
  278. package/lib/yoke/options/muse.js +5 -0
  279. package/lib/yoke/provider-contract.js +5 -0
  280. package/lib/yoke/providers/antigravity-executable.js +8 -0
  281. package/lib/yoke/providers/claude-executable.js +40 -0
  282. package/lib/yoke/providers/claude-model-descriptions.js +14 -0
  283. package/lib/yoke/providers/claude-process.js +97 -0
  284. package/lib/yoke/providers/claude-provision.js +75 -0
  285. package/lib/yoke/providers/codex-errors.js +8 -0
  286. package/lib/yoke/providers/muse-executable.js +17 -0
  287. package/lib/yoke/provisioning.js +6 -0
  288. package/lib/yoke/query-options.js +10 -0
  289. package/lib/yoke/response-recovery.js +41 -0
  290. package/lib/yoke/sdk-mcp-descriptors.js +37 -0
  291. package/lib/yoke/sdk-server-factory.js +7 -0
  292. package/lib/yoke/session-history.js +8 -0
  293. package/lib/yoke/session-tool-transport.js +34 -13
  294. package/lib/yoke/settings.js +23 -0
  295. package/lib/yoke/source-locations.js +4 -0
  296. package/lib/yoke/title-query.js +18 -7
  297. package/lib/yoke/tui-transcript-index.js +132 -0
  298. package/lib/yoke/usage.js +48 -0
  299. package/lib/yoke/user-input.js +13 -0
  300. package/lib/yoke/vendor-registry.js +81 -1
  301. package/package.json +3 -2
@@ -0,0 +1,10 @@
1
+ // Translate common execution intent at the provider implementation boundary.
2
+ function map(provider, intent) {
3
+ var info = provider && Object.prototype.hasOwnProperty.call(provider, "mapQueryOptions") ? provider : require("./provider-contract").resolve(provider);
4
+ if (info.mapQueryOptions === undefined) return {};
5
+ if (typeof info.mapQueryOptions !== "function") throw new Error("Provider option mapping is unavailable.");
6
+ var options = info.mapQueryOptions(intent || {});
7
+ if (!options || typeof options !== "object" || Array.isArray(options)) throw new Error("Invalid provider option mapping.");
8
+ return options;
9
+ }
10
+ module.exports = { map: map };
@@ -0,0 +1,41 @@
1
+ // Explicit provider implementation, with a live binding to the implementation
2
+ // selected for this session. Stop always reaches the originally bound service.
3
+ function attachResponseRecovery(ctx) {
4
+ var managers = new Map(), bindings = new WeakMap();
5
+ function policy(session) {
6
+ return require('./provider-contract').resolve(ctx.getProvider ? ctx.getProvider(session) : session.vendor || 'claude');
7
+ }
8
+ function manager(session, create) {
9
+ if (!create) return bindings.get(session) || null;
10
+ var factory = policy(session).recoveryFactory;
11
+ var previous = bindings.get(session);
12
+ if (factory === undefined) {
13
+ if (previous) previous.cancel(session);
14
+ bindings.delete(session);
15
+ return null;
16
+ }
17
+ if (typeof factory !== 'function') throw new Error('Provider recovery implementation is unavailable.');
18
+ if (!managers.has(factory)) {
19
+ var context = Object.assign({}, ctx, { isCurrentProvider: function(target) { return policy(target).recoveryFactory === factory; } });
20
+ var service = factory(context);
21
+ ['begin', 'enqueue', 'event', 'progress', 'cancel', 'current', 'valid', 'stopping', 'dispose'].forEach(function(name) {
22
+ if (!service || typeof service[name] !== 'function') throw new Error('Provider recovery implementation is missing ' + name + '.');
23
+ });
24
+ managers.set(factory, service);
25
+ }
26
+ var selected = managers.get(factory);
27
+ if (previous && previous !== selected) previous.cancel(session);
28
+ bindings.set(session, selected);
29
+ return selected;
30
+ }
31
+ var api = {};
32
+ ['begin', 'enqueue', 'event', 'progress', 'cancel', 'current', 'valid', 'stopping'].forEach(function(name) {
33
+ api[name] = function(session) {
34
+ var service = manager(session, name === 'begin' || name === 'enqueue');
35
+ return service ? service[name].apply(service, arguments) : name === 'stopping' || name === 'valid' ? false : null;
36
+ };
37
+ });
38
+ api.dispose = function() { managers.forEach(function(service) { service.dispose(); }); managers.clear(); bindings = new WeakMap(); };
39
+ return api;
40
+ }
41
+ module.exports = { attachResponseRecovery: attachResponseRecovery };
@@ -0,0 +1,37 @@
1
+ // Extract serializable tool descriptors from MCP server instances.
2
+ // Used for IPC to worker processes (McpSdkServerConfigWithInstance is not serializable).
3
+ function extractMcpDescriptors(mcpServers) {
4
+ if (!mcpServers) return null;
5
+ // Claude's adapter uses Zod v3 for JSON Schema tools; other servers use v4.
6
+ // Use the MCP SDK's version-aware converter for both kinds of registered tool.
7
+ var toJSONSchema = require("@modelcontextprotocol/sdk/server/zod-json-schema-compat.js").toJsonSchemaCompat;
8
+ var descriptors = [];
9
+ var names = Object.keys(mcpServers);
10
+ for (var i = 0; i < names.length; i++) {
11
+ var serverName = names[i];
12
+ var server = mcpServers[serverName];
13
+ if (!server || !server.instance || !server.instance._registeredTools) continue;
14
+ var tools = [];
15
+ var toolNames = Object.keys(server.instance._registeredTools);
16
+ for (var j = 0; j < toolNames.length; j++) {
17
+ var toolName = toolNames[j];
18
+ var toolDef = server.instance._registeredTools[toolName];
19
+ var inputSchema = { type: "object", properties: {} };
20
+ try {
21
+ if (toolDef._clayInputSchema) inputSchema = toolDef._clayInputSchema;
22
+ else if (toolDef.inputSchema) inputSchema = toJSONSchema(toolDef.inputSchema);
23
+ } catch (e) {
24
+ throw new Error("Cannot serialize MCP tool schema " + serverName + "/" + toolName + ": " + e.message);
25
+ }
26
+ tools.push({
27
+ name: toolName,
28
+ description: toolDef.description || toolName,
29
+ inputSchema: inputSchema,
30
+ });
31
+ }
32
+ if (tools.length > 0) descriptors.push({ serverName: serverName, tools: tools });
33
+ }
34
+ return descriptors.length > 0 ? descriptors : null;
35
+ }
36
+
37
+ module.exports = { extractMcpDescriptors: extractMcpDescriptors };
@@ -0,0 +1,7 @@
1
+ // Shared SDK server envelope; transport projection remains inside YOKE.
2
+ function load() {
3
+ var sdk = require("@anthropic-ai/claude-agent-sdk");
4
+ if (typeof sdk.createSdkMcpServer !== "function" || typeof sdk.tool !== "function") throw new Error("SDK tool server implementation is unavailable.");
5
+ return { createSdkMcpServer: sdk.createSdkMcpServer, tool: sdk.tool };
6
+ }
7
+ module.exports = { load: load };
@@ -0,0 +1,8 @@
1
+ // A provider fork may return local history or require a provider-owned reader.
2
+ // Absence is an unsupported operation, never an empty successful transcript.
3
+ function read(provider, home, cwd, sessionId) {
4
+ var reader = require("./provider-contract").resolve(provider).readSessionHistory;
5
+ if (typeof reader !== "function") throw new Error("Provider session history reading is unavailable.");
6
+ return reader(home, cwd, sessionId);
7
+ }
8
+ module.exports = { read: read };
@@ -1,23 +1,39 @@
1
1
  // Shared production transport facts for query-bound Clay tools.
2
2
 
3
3
  var vendorRegistry = require("./vendor-registry");
4
- var CODEX_CATALOG_VERSION = 5;
4
+ var SCHEDULE_CATALOG_VERSION = 5;
5
+ var MATE_SCHEDULE_TOOLS = ["begin_mate_schedule_interview", "propose_mate_schedule", "list_mate_schedules", "read_mate_schedule", "update_mate_schedule", "cancel_mate_schedule"];
5
6
  var SCHEDULE_TOOLS = ["begin_scheduled_task_interview", "propose_scheduled_task", "list_scheduled_tasks", "read_scheduled_task", "update_scheduled_task", "report_scheduled_task_outcome"];
6
7
 
7
- function capability(vendor) {
8
- if (vendor === "claude") return { supported: true, kind: "sdk-mcp" };
9
- if (vendor === "codex") return { supported: true, kind: "dynamic" };
10
- var info = vendorRegistry.getVendorInfo(vendor);
11
- if (info && info.sessionBoundTools === true) return { supported: true, kind: "stdio-mcp" };
12
- return { supported: false, kind: "none" };
8
+ // Accept an adapter as well as a registry key. Live adapters can implement the
9
+ // same semantics independently of their name; unknown providers fail closed.
10
+ function contract(provider) {
11
+ if (provider && typeof provider === "object" && provider.queryContract) return provider.queryContract;
12
+ var info = vendorRegistry.getVendorInfo(typeof provider === "string" ? provider : provider && provider.vendor);
13
+ if (info && info.queryContract) return info.queryContract;
14
+ return info && info.sessionBoundTools === true ? { toolTransport: "stdio-mcp", catalogLifetime: "query" } : {};
15
+ }
16
+
17
+ function capability(provider) {
18
+ var kind = contract(provider).toolTransport || "none";
19
+ if (["sdk-mcp", "dynamic", "stdio-mcp"].indexOf(kind) === -1) kind = "none";
20
+ return { supported: kind !== "none", kind: kind };
21
+ }
22
+
23
+ function needsRecovery(provider, session, family, version) {
24
+ var policy = contract(provider);
25
+ if (!session.cliSessionId || policy.catalogLifetime !== "conversation") return false;
26
+ if (!family) return true;
27
+ if (typeof policy.catalogVersion !== "function") return true;
28
+ var recorded = policy.catalogVersion(session, family);
29
+ return !Number.isFinite(recorded) || recorded < version;
13
30
  }
14
31
 
15
32
  function availableForSession(session) {
16
- var vendor = session && (session.vendor || "claude");
17
- var transport = capability(vendor);
18
- if (!transport.supported) return { available: false, reason: "This provider's current Clay adapter does not deliver custom session tools." };
19
- if (vendor === "codex" && session.cliSessionId && Number(session.codexDynamicToolCatalogVersion || 0) < CODEX_CATALOG_VERSION) {
20
- return { available: false, reason: "This Codex conversation predates Clay's scheduled-task tool catalog. Start a new conversation to use the assisted interview; manual task creation remains available here." };
33
+ var provider = session && (session.vendor || "claude");
34
+ if (!capability(provider).supported) return { available: false, reason: "This provider's current Clay adapter does not deliver custom session tools." };
35
+ if (needsRecovery(provider, session, "schedules", SCHEDULE_CATALOG_VERSION)) {
36
+ return { available: false, reason: contract(provider).staleCatalogReason || "This conversation's persisted tool catalog is outdated. Start a new conversation to use the assisted interview." };
21
37
  }
22
38
  return { available: true, reason: null };
23
39
  }
@@ -38,16 +54,21 @@ function questionToolName(vendor) {
38
54
 
39
55
  function bridgeServerForTool(name) {
40
56
  if (name === "ask_user_questions") return "yoke-user-input";
57
+ if (MATE_SCHEDULE_TOOLS.indexOf(name) !== -1) return "clay-mate-schedules";
41
58
  if (SCHEDULE_TOOLS.indexOf(name) !== -1) return "clay-scheduled-tasks";
42
59
  return null;
43
60
  }
44
61
 
45
62
  module.exports = {
63
+ contract: contract,
64
+ needsRecovery: needsRecovery,
46
65
  capability: capability,
47
66
  availableForSession: availableForSession,
48
- CODEX_CATALOG_VERSION: CODEX_CATALOG_VERSION,
67
+ SCHEDULE_CATALOG_VERSION: SCHEDULE_CATALOG_VERSION,
68
+ CODEX_CATALOG_VERSION: SCHEDULE_CATALOG_VERSION, // Legacy export for existing consumers.
49
69
  scheduleToolName: scheduleToolName,
50
70
  questionToolName: questionToolName,
51
71
  bridgeServerForTool: bridgeServerForTool,
52
72
  SCHEDULE_TOOLS: SCHEDULE_TOOLS,
73
+ MATE_SCHEDULE_TOOLS: MATE_SCHEDULE_TOOLS,
53
74
  };
@@ -0,0 +1,23 @@
1
+ function implementations(provider) {
2
+ if (provider) { var policy = require("./provider-contract").resolve(provider); return policy.settings ? [policy.settings] : []; }
3
+ var registry = require("./vendor-registry").VENDOR_REGISTRY;
4
+ return Array.from(new Set(Object.keys(registry).map(function(vendor) { return registry[vendor].settings; }).filter(Boolean)));
5
+ }
6
+ function defaults() {
7
+ var result = {};
8
+ implementations().forEach(function(service) { Object.assign(result, service.defaults()); });
9
+ return result;
10
+ }
11
+ function messages(settings) {
12
+ return implementations().flatMap(function(service) { return service.messages(settings); });
13
+ }
14
+ function change(message, settings, provider) {
15
+ var services = implementations(provider);
16
+ for (var i = 0; i < services.length; i++) {
17
+ if (typeof services[i].change !== "function") throw new Error("Provider settings implementation is unavailable.");
18
+ var result = services[i].change(message, settings);
19
+ if (result) return result;
20
+ }
21
+ return null;
22
+ }
23
+ module.exports = { defaults: defaults, messages: messages, change: change };
@@ -0,0 +1,4 @@
1
+ var path = require("path");
2
+ // Legacy imported skill format; Clay-only skills use their own private root.
3
+ function legacySkillRoot(base) { return path.join(base, ".claude", "skills"); }
4
+ module.exports = { legacySkillRoot: legacySkillRoot };
@@ -25,12 +25,14 @@ async function generateTitle(adapter, messages, opts, queryOptions) {
25
25
  opts = opts || {};
26
26
  var controller = new AbortController();
27
27
  var handle;
28
- var closed = false;
28
+ var closing;
29
29
  function close() {
30
- if (handle && !closed) {
31
- closed = true;
32
- try { handle.close(); } catch (error) { controller.abort(); }
30
+ if (handle && !closing) {
31
+ try { closing = Promise.resolve(handle.close()); }
32
+ catch (error) { closing = Promise.reject(error); }
33
+ closing.catch(function () { controller.abort(); });
33
34
  }
35
+ return closing;
34
36
  }
35
37
  var rejectAbort;
36
38
  var cancelled = new Promise(function (resolve, reject) { rejectAbort = reject; });
@@ -39,7 +41,7 @@ async function generateTitle(adapter, messages, opts, queryOptions) {
39
41
  rejectAbort(new Error("Title request aborted or timed out"));
40
42
  close();
41
43
  }
42
- var timer = setTimeout(abort, 30000);
44
+ var timer = setTimeout(abort, opts.timeoutMs || 30000);
43
45
  if (opts.signal) opts.signal.addEventListener("abort", abort, { once: true });
44
46
  var request = Promise.resolve().then(async function () {
45
47
  if (opts.signal && opts.signal.aborted) { abort(); throw new Error("Title request aborted"); }
@@ -69,12 +71,21 @@ async function generateTitle(adapter, messages, opts, queryOptions) {
69
71
  }
70
72
  throw new Error("Title request ended without a successful result");
71
73
  });
74
+ var title;
75
+ var failure;
72
76
  try {
73
- return await Promise.race([request, cancelled]);
77
+ try { title = await Promise.race([request, cancelled]); }
78
+ catch (error) { failure = error; }
79
+ // Keep the overall deadline armed while cleanup is pending. A late handle
80
+ // still initiates close through the request continuation, with rejection
81
+ // observed by close(), even after this caller has been released.
82
+ try { await Promise.race([close(), cancelled]); }
83
+ catch (error) { if (!failure) failure = error; }
84
+ if (failure) throw failure;
85
+ return title;
74
86
  } finally {
75
87
  clearTimeout(timer);
76
88
  if (opts.signal) opts.signal.removeEventListener("abort", abort);
77
- close();
78
89
  }
79
90
  }
80
91
 
@@ -0,0 +1,132 @@
1
+ // tui-transcript-index.js
2
+ //
3
+ // Build a per-session index of assistant text messages from a Claude Code
4
+ // TUI transcript (~/.claude/projects/{encoded-cwd}/{cliSessionId}.jsonl).
5
+ //
6
+ // The TUI message-grab feature uses this index on the client to map a
7
+ // hovered xterm region back to its original markdown source. We only
8
+ // extract assistant text blocks. Tool calls and tool results render in
9
+ // the terminal in a shape that's quite different from their JSONL form,
10
+ // so matching them would be noisy and not particularly useful.
11
+ //
12
+ // Codex sessions don't write transcripts at all; callers should skip
13
+ // indexing for non-claude vendors.
14
+
15
+ var fs = require("fs");
16
+ var path = require("path");
17
+ var utils = require("../utils");
18
+ var { REAL_HOME } = require("../config");
19
+
20
+ var encodeCwd = utils.encodeCwd;
21
+
22
+ // Min length of a normalized assistant message to bother indexing.
23
+ // Anything shorter ("ok", "sure", "yes") would generate too many false
24
+ // positives when matched against a hovered terminal block.
25
+ var MIN_MATCH_LEN = 20;
26
+
27
+ // Claude Code writes its JSONL under the *running user's* home, which
28
+ // is not the daemon's home in OS-isolation mode (where each Clay user
29
+ // gets a real Linux account like /home/clay-name). Callers from the
30
+ // project context resolve the session owner's home and pass it in;
31
+ // when no home is provided we fall back to REAL_HOME for single-user
32
+ // installs.
33
+ function transcriptFilePath(home, cwd, cliSessionId) {
34
+ if (!cwd || !cliSessionId) return null;
35
+ var base = home || REAL_HOME;
36
+ return path.join(base, ".claude", "projects", encodeCwd(cwd), cliSessionId + ".jsonl");
37
+ }
38
+
39
+ // matchKey is just whitespace-normalized raw markdown. We intentionally
40
+ // do NOT strip markdown decoration here.
41
+ //
42
+ // Reasoning: TUI rendering drops markdown markers (**bold** -> bold,
43
+ // `code` -> code, [text](url) -> text, etc.) and the visible text is
44
+ // therefore always a substring of the JSONL source's character stream.
45
+ // If we strip server-side we risk getting the rules wrong on corner
46
+ // cases (double-backtick code spans, list-bullet rendering quirks,
47
+ // nested formatting) and the resulting matchKey diverges from both
48
+ // sides at once. Leaving the source alone and letting the client do a
49
+ // multi-offset substring probe against block text is more robust and
50
+ // much less code.
51
+ function normalizeForMatch(s) {
52
+ if (!s) return "";
53
+ return s.replace(/\s+/g, " ").trim();
54
+ }
55
+
56
+ // Stable per-message id. Claude's JSONL usually carries one of these but
57
+ // fall back to the parsed line index so the client always has a handle.
58
+ function messageId(obj, index) {
59
+ if (obj && obj.uuid) return String(obj.uuid);
60
+ if (obj && obj.message && obj.message.id) return String(obj.message.id);
61
+ return "msg-" + index;
62
+ }
63
+
64
+ // Parse a single JSONL line into one assistant-text record, or null
65
+ // when the line isn't one we index (user prompts, tool_use blocks,
66
+ // tool_result records, etc.). Text-only assistant blocks get joined
67
+ // in order so a multi-block response surfaces as a single grabbable
68
+ // message.
69
+ function parseAssistantTextLine(line, index) {
70
+ var obj;
71
+ try { obj = JSON.parse(line); } catch (e) { return null; }
72
+ if (!obj || !obj.message) return null;
73
+ if (obj.message.role !== "assistant") return null;
74
+ if (!Array.isArray(obj.message.content)) return null;
75
+
76
+ var text = "";
77
+ for (var i = 0; i < obj.message.content.length; i++) {
78
+ var block = obj.message.content[i];
79
+ if (block && block.type === "text" && typeof block.text === "string") {
80
+ text += block.text;
81
+ }
82
+ }
83
+ text = text.trim();
84
+ if (!text) return null;
85
+
86
+ var normalized = normalizeForMatch(text);
87
+ if (normalized.length < MIN_MATCH_LEN) return null;
88
+
89
+ return {
90
+ id: messageId(obj, index),
91
+ text: text,
92
+ matchKey: normalized,
93
+ };
94
+ }
95
+
96
+ // Read the whole transcript and return the assistant text index. The
97
+ // transcripts are small enough (KB to a few MB) that a sync read on
98
+ // session open or on a watcher-driven update is fine. We also return
99
+ // the mtime/size so callers can short-circuit re-reads when nothing
100
+ // changed.
101
+ function readAssistantIndex(home, cwd, cliSessionId) {
102
+ var file = transcriptFilePath(home, cwd, cliSessionId);
103
+ if (!file) return { messages: [], mtimeMs: 0, byteLength: 0 };
104
+ var raw;
105
+ var stat;
106
+ try {
107
+ raw = fs.readFileSync(file, "utf8");
108
+ stat = fs.statSync(file);
109
+ } catch (e) {
110
+ return { messages: [], mtimeMs: 0, byteLength: 0 };
111
+ }
112
+ var lines = raw.split("\n");
113
+ var messages = [];
114
+ for (var i = 0; i < lines.length; i++) {
115
+ if (!lines[i]) continue;
116
+ var entry = parseAssistantTextLine(lines[i], i);
117
+ if (entry) messages.push(entry);
118
+ }
119
+ return {
120
+ messages: messages,
121
+ mtimeMs: stat.mtimeMs || 0,
122
+ byteLength: stat.size || raw.length,
123
+ };
124
+ }
125
+
126
+ module.exports = {
127
+ MIN_MATCH_LEN: MIN_MATCH_LEN,
128
+ transcriptFilePath: transcriptFilePath,
129
+ readAssistantIndex: readAssistantIndex,
130
+ parseAssistantTextLine: parseAssistantTextLine,
131
+ normalizeForMatch: normalizeForMatch,
132
+ };
@@ -0,0 +1,48 @@
1
+ function number() {
2
+ for (var i = 0; i < arguments.length; i++) if (typeof arguments[i] === 'number' && Number.isFinite(arguments[i]) && arguments[i] >= 0) return arguments[i];
3
+ return null;
4
+ }
5
+ function accounting(value) {
6
+ if (!value) return null;
7
+ return Object.assign({}, value, { inputTokens: number(value.inputTokens, value.input_tokens), outputTokens: number(value.outputTokens, value.output_tokens),
8
+ cacheReadInputTokens: number(value.cacheReadInputTokens, value.cache_read_input_tokens), cacheCreationInputTokens: number(value.cacheCreationInputTokens, value.cache_creation_input_tokens) });
9
+ }
10
+ function validateProjection(value) {
11
+ value = value || {};
12
+ var used = number(value.usedTokens), window = number(value.windowTokens);
13
+ var measurement = ['observed', 'estimated', 'unavailable'].indexOf(value.measurement) >= 0 ? value.measurement : 'unavailable';
14
+ var inflated = used !== null && window !== null && used > window;
15
+ if (inflated || used === null || measurement === 'unavailable') { used = null; measurement = 'unavailable'; }
16
+ return { usedTokens: used, windowTokens: window, measurement: measurement, source: inflated || measurement === 'unavailable' && window === null ? 'unavailable' : typeof value.source === 'string' ? value.source : 'unavailable' };
17
+ }
18
+ function context(value, provider) {
19
+ if (!value) return null;
20
+ if (value.context && value.context.measurement) return Object.assign({}, value, { context: validateProjection(value.context) });
21
+ var policy = require('./provider-contract').resolve(provider);
22
+ var projection = typeof policy.normalizeContext === 'function' ? policy.normalizeContext(value) : { usedTokens: null, windowTokens: null, measurement: 'unavailable', source: 'unavailable' };
23
+ return Object.assign({}, value, { context: validateProjection(projection) });
24
+ }
25
+ function sdkContext(value) { return { usedTokens: number(value.totalTokens), windowTokens: number(value.maxTokens), measurement: value.unavailable ? 'unavailable' : value.measurement === 'estimated' ? 'estimated' : 'observed', source: 'claude_sdk_context_usage' }; }
26
+ function tokenContext(value) { return { usedTokens: number(value.input_tokens), windowTokens: number(value.contextWindow), measurement: value.unavailable ? 'unavailable' : value.measurement === 'estimated' ? 'estimated' : 'observed', source: 'adapter_context_usage' }; }
27
+ function turnContext(event) {
28
+ var models = event.modelUsage || {}, entries = Object.keys(models);
29
+ var result = { usedTokens: null, windowTokens: null, measurement: 'unavailable', source: 'unavailable' };
30
+ for (var i = 0; i < entries.length; i++) {
31
+ var value = models[entries[i]], snapshot = value.contextSnapshot;
32
+ if (snapshot) return { usedTokens: snapshot.valid === true ? number(snapshot.inputTokens) : null, windowTokens: number(snapshot.contextWindow, value.contextWindow), measurement: snapshot.valid === true ? 'observed' : 'unavailable', source: 'last_turn' };
33
+ result.windowTokens = number(value.contextWindow, result.windowTokens);
34
+ }
35
+ // Per-query accounting can contain many API calls. Never use its sum as
36
+ // current occupancy. Only an actual last-call measurement is a valid estimate.
37
+ result.usedTokens = number(event.lastStreamInputTokens);
38
+ if (result.usedTokens !== null) { result.measurement = 'estimated'; result.source = 'last_call'; }
39
+ return result;
40
+ }
41
+ function clientEvent(event, provider) {
42
+ if (!event) return event;
43
+ var info = require('./provider-contract').resolve(provider);
44
+ if ((event.type === 'rate_limit' || event.type === 'rate_limit_usage') && !event.source && info.requiresQuotaSource) return Object.assign({}, event, { ignored: true });
45
+ if (event.type !== 'result') return event;
46
+ return Object.assign({}, event, { usage: accounting(event.usage), context: validateProjection(event.context || turnContext(event)) });
47
+ }
48
+ module.exports = { number: number, accounting: accounting, context: context, sdkContext: sdkContext, tokenContext: tokenContext, turnContext: turnContext, clientEvent: clientEvent };
@@ -246,6 +246,7 @@ function capability(adapter) {
246
246
  }
247
247
 
248
248
  function selectMode(adapter, requestedMode) {
249
+ if (requestedMode !== undefined && ["auto", "native", "fallback"].indexOf(requestedMode) < 0) throw new Error("Unsupported structured input mode.");
249
250
  if (requestedMode === "fallback") return "fallback";
250
251
  if (requestedMode === "native" && capability(adapter).mode !== "native") {
251
252
  throw new Error("This provider does not support native structured user input.");
@@ -260,7 +261,19 @@ function createFallbackServer(adapter, handler) {
260
261
  return adapter.createToolServer({ name: "yoke-user-input", version: "1.0.0", tools: fallbackToolDefs(handler, opts) });
261
262
  }
262
263
 
264
+ // AskUserQuestion is also the normalized legacy question-tool identity in
265
+ // stored Clay transcripts. Adapters may translate another native shape.
266
+ function toolQuestions(adapter, name, input) {
267
+ var contract = require("./session-tool-transport").contract(adapter);
268
+ if (typeof contract.questionInput === "function") {
269
+ var nativeInput = contract.questionInput(name, input);
270
+ if (nativeInput) return nativeInput;
271
+ }
272
+ return name === "AskUserQuestion" || name === TOOL_NAME ? input : null;
273
+ }
274
+
263
275
  module.exports = {
276
+ toolQuestions: toolQuestions,
264
277
  TOOL_NAME: TOOL_NAME,
265
278
  normalizeQuestions: normalizeQuestions,
266
279
  questionsFromElicitation: questionsFromElicitation,
@@ -1,6 +1,6 @@
1
1
  // Static, init-free facts about each vendor YOKE supports. Host code that
2
2
  // needs metadata before adapter initialization should read it from here.
3
- // Do not import adapters into this module.
3
+ // Only init-free contract data may be imported here; never runtime adapters.
4
4
 
5
5
  // Canonical effort ordering used to clamp a level onto a vendor that does
6
6
  // not support it (e.g. codex "minimal" -> claude "low", claude "max" ->
@@ -10,6 +10,26 @@ var EFFORT_ORDER = ["minimal", "low", "medium", "high", "xhigh", "max"];
10
10
  // sessionBoundTools gates whether per-session MCP tool mounting reaches a vendor's process.
11
11
  var VENDOR_REGISTRY = {
12
12
  claude: {
13
+ readSessionHistory: require("./cli-sessions").readCliSessionHistory,
14
+ terminalResumeCommand: "claude --resume",
15
+ planPathSegments: [".claude/plans/"],
16
+ notificationHooks: require("./claude-hook-installer"),
17
+ maintenance: require("./claude-maintenance"),
18
+ credentialDirectories: [".claude"],
19
+ preferredModelFamilies: ["opus", "sonnet", "haiku"],
20
+ provisionUser: require("./providers/claude-provision").attachProvisioning,
21
+ configuration: require("./configuration").claude,
22
+ normalizeContext: require("./usage").sdkContext, authenticationReply: require("./auth-events").authenticationReply,
23
+ rateLimitScheduling: true, acceptsUnstampedQuota: true,
24
+ terminalLoginCommand: "claude auth login", browserLoginCommand: "claude auth login",
25
+ oauthHosts: ["claude.ai", "claude.com", "console.anthropic.com", "platform.claude.com"],
26
+ resolveExecutable: require("./discovery").bundledResolver(function() { return require("./providers/claude-executable").resolve(); }, "claude"),
27
+ processControl: require("./providers/claude-process"),
28
+ prepareIsolation: require("./providers/claude-process").prepareIsolation,
29
+ recoveryFactory: require("./claude-response-recovery").attachResponseRecovery,
30
+ supportsLegacyGuiResume: function(session) { return !!session.cliSessionId; },
31
+ mapQueryOptions: require("./options/claude").map,
32
+ queryContract: require("./adapters/claude-query-contract"),
13
33
  displayName: "Claude Code",
14
34
  loginCommand: "claude login",
15
35
  binaryName: "claude",
@@ -27,6 +47,16 @@ var VENDOR_REGISTRY = {
27
47
  rateLimitTracking: true,
28
48
  },
29
49
  codex: {
50
+ credentialDirectories: [".codex"],
51
+ preferredModelFamilies: ["astra", "sol", "gpt", "o"],
52
+ classifyError: require("./providers/codex-errors").classify,
53
+ settings: require("./options/codex-settings"),
54
+ configuration: require("./configuration").codex,
55
+ normalizeContext: require("./usage").tokenContext, requiresQuotaSource: true,
56
+ browserLoginCommand: "codex login", oauthHosts: ["auth.openai.com"],
57
+ resolveExecutable: require("./discovery").bundledResolver(function() { return require("./codex-app-server").findCodexPath(); }, "codex"),
58
+ mapQueryOptions: require("./options/codex").map,
59
+ queryContract: require("./adapters/codex-query-contract"),
30
60
  displayName: "Codex",
31
61
  loginCommand: "codex login --device-auth",
32
62
  binaryName: "codex",
@@ -43,7 +73,27 @@ var VENDOR_REGISTRY = {
43
73
  },
44
74
  rateLimitTracking: true,
45
75
  },
76
+ muse: {
77
+ displayName: "Muse Code",
78
+ loginCommand: "muse",
79
+ binaryName: "muse",
80
+ avatar: "/muse-avatar.svg",
81
+ sessionModes: ["gui"],
82
+ effortLevels: ["none", "minimal", "low", "medium", "high", "xhigh", "max", "ultra"],
83
+ osUserIsolation: false,
84
+ sessionBoundTools: true,
85
+ usageDashboard: null,
86
+ rateLimitTracking: false,
87
+ forkHistoryBoundary: "completed-turn-inclusive",
88
+ resolveExecutable: require("./providers/muse-executable").resolve,
89
+ mapQueryOptions: require("./options/muse").map,
90
+ queryContract: require("./adapters/muse-query-contract"),
91
+ normalizeContext: require("./usage").tokenContext,
92
+ configuration: { auto: true, permissionModes: [{ value: "default", label: "Ask" }] },
93
+ },
46
94
  antigravity: {
95
+ resolveExecutable: require("./providers/antigravity-executable").resolve,
96
+ mapQueryOptions: require("./options/antigravity").map,
47
97
  displayName: "Antigravity CLI",
48
98
  loginCommand: "agy",
49
99
  binaryName: "agy",
@@ -56,6 +106,8 @@ var VENDOR_REGISTRY = {
56
106
  rateLimitTracking: false,
57
107
  },
58
108
  opencode: {
109
+ resolveExecutable: require("./discovery").acpResolver("opencode"),
110
+ mapQueryOptions: require("./options/acp").map,
59
111
  displayName: "OpenCode",
60
112
  loginCommand: "opencode auth login",
61
113
  binaryName: "opencode",
@@ -68,6 +120,8 @@ var VENDOR_REGISTRY = {
68
120
  rateLimitTracking: false,
69
121
  },
70
122
  kimi: {
123
+ resolveExecutable: require("./discovery").acpResolver("kimi"),
124
+ mapQueryOptions: require("./options/acp").map,
71
125
  displayName: "Kimi Code",
72
126
  loginCommand: "kimi login",
73
127
  binaryName: "kimi",
@@ -80,6 +134,8 @@ var VENDOR_REGISTRY = {
80
134
  rateLimitTracking: false,
81
135
  },
82
136
  grok: {
137
+ resolveExecutable: require("./discovery").acpResolver("grok"),
138
+ mapQueryOptions: require("./options/acp").map,
83
139
  displayName: "Grok Build",
84
140
  loginCommand: "grok login --device-auth",
85
141
  binaryName: "grok",
@@ -92,6 +148,8 @@ var VENDOR_REGISTRY = {
92
148
  rateLimitTracking: false,
93
149
  },
94
150
  copilot: {
151
+ resolveExecutable: require("./discovery").acpResolver("copilot"),
152
+ mapQueryOptions: require("./options/acp").map,
95
153
  displayName: "GitHub Copilot CLI",
96
154
  loginCommand: "copilot login",
97
155
  binaryName: "copilot",
@@ -104,6 +162,8 @@ var VENDOR_REGISTRY = {
104
162
  rateLimitTracking: false,
105
163
  },
106
164
  qwen: {
165
+ resolveExecutable: require("./discovery").acpResolver("qwen"),
166
+ mapQueryOptions: require("./options/acp").map,
107
167
  displayName: "Qwen Code",
108
168
  loginCommand: "qwen",
109
169
  binaryName: "qwen",
@@ -116,6 +176,8 @@ var VENDOR_REGISTRY = {
116
176
  rateLimitTracking: false,
117
177
  },
118
178
  junie: {
179
+ resolveExecutable: require("./discovery").acpResolver("junie"),
180
+ mapQueryOptions: require("./options/acp").map,
119
181
  displayName: "Junie CLI",
120
182
  loginCommand: "junie",
121
183
  binaryName: "junie",
@@ -128,6 +190,9 @@ var VENDOR_REGISTRY = {
128
190
  rateLimitTracking: false,
129
191
  },
130
192
  kiro: {
193
+ normalizeContext: require("./usage").tokenContext,
194
+ resolveExecutable: require("./discovery").bundledResolver(function() { return require("./kiro-acp-server").findKiroPath(); }, "kiro-cli"),
195
+ mapQueryOptions: require("./options/kiro").map,
131
196
  displayName: "Kiro CLI",
132
197
  loginCommand: "kiro-cli login",
133
198
  binaryName: "kiro-cli",
@@ -169,7 +234,22 @@ function clampEffort(vendor, effort) {
169
234
  return nearest;
170
235
  }
171
236
 
237
+ // Publish only serializable product descriptions, never backend services.
238
+ function publicInfo() {
239
+ var result = {};
240
+ Object.keys(VENDOR_REGISTRY).forEach(function(vendor) {
241
+ var info = VENDOR_REGISTRY[vendor], entry = {};
242
+ ["displayName", "terminalResumeCommand", "planPathSegments", "loginCommand", "binaryName", "avatar", "sessionModes", "effortLevels", "osUserIsolation", "sessionBoundTools", "usageDashboard", "rateLimitTracking", "rateLimitScheduling", "acceptsUnstampedQuota", "configuration"].forEach(function(key) {
243
+ if (info[key] !== undefined) entry[key] = info[key];
244
+ });
245
+ entry.browserLoginSupported = typeof info.browserLoginCommand === "string" && Array.isArray(info.oauthHosts) && info.oauthHosts.length > 0;
246
+ result[vendor] = entry;
247
+ });
248
+ return result;
249
+ }
250
+
172
251
  module.exports = {
252
+ publicInfo: publicInfo,
173
253
  VENDOR_REGISTRY: VENDOR_REGISTRY,
174
254
  getVendorInfo: getVendorInfo,
175
255
  clampEffort: clampEffort,