clay-server 5.2.0-beta.5 → 5.2.0-beta.7

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 (246) hide show
  1. package/lib/claude-hook-installer.js +1 -267
  2. package/lib/claude-jsonl-watcher.js +1 -204
  3. package/lib/clay-control-presentation-binding.js +96 -0
  4. package/lib/clay-control-presentation.js +128 -0
  5. package/lib/clay-control-target-projection.js +26 -0
  6. package/lib/clay-mate-chat.js +1 -0
  7. package/lib/clay-mate-knowledge.js +1 -1
  8. package/lib/clay-product-control-tools.js +1 -1
  9. package/lib/clay-product-control.js +22 -12
  10. package/lib/clay-project-records.js +2 -1
  11. package/lib/clay-scheduling.js +1 -1
  12. package/lib/clay-screen-controls.js +13 -5
  13. package/lib/clay-skill-install.js +1 -33
  14. package/lib/clay-workspace-controls.js +2 -1
  15. package/lib/cli-sessions.js +1 -300
  16. package/lib/codex-defaults.js +1 -28
  17. package/lib/context-usage.js +3 -2
  18. package/lib/contextual-screen-snapshot.js +38 -0
  19. package/lib/daemon.js +5 -55
  20. package/lib/default-ai-runtime.js +4 -8
  21. package/lib/email-mcp-server.js +1 -1
  22. package/lib/kiro-defaults.js +1 -22
  23. package/lib/mate-context-service.js +138 -0
  24. package/lib/mate-context-tools.js +21 -0
  25. package/lib/mcp-proxy.js +2 -32
  26. package/lib/mcp-query-bridge.js +1 -1
  27. package/lib/mcp-source-adapters.js +1 -91
  28. package/lib/mcp-source-context.js +1 -42
  29. package/lib/mcp-source-discovery.js +1 -169
  30. package/lib/mcp-source-plugins.js +1 -68
  31. package/lib/mcp-source-restrictions.js +1 -47
  32. package/lib/mcp-tool-policy.js +1 -26
  33. package/lib/os-user-diagnostics.js +2 -4
  34. package/lib/os-users.js +4 -65
  35. package/lib/project-connection.js +14 -10
  36. package/lib/project-control-git-view.js +12 -0
  37. package/lib/project-filesystem.js +5 -1
  38. package/lib/project-http.js +7 -4
  39. package/lib/project-mcp.js +2 -2
  40. package/lib/project-notifications.js +5 -4
  41. package/lib/project-pair-result-delivery.js +2 -2
  42. package/lib/project-pair-usage.js +12 -13
  43. package/lib/project-pending-message-queue.js +3 -1
  44. package/lib/project-product-control.js +3 -1
  45. package/lib/project-scheduled-messages.js +4 -4
  46. package/lib/project-scheduled-task-control.js +1 -1
  47. package/lib/project-session-document.js +20 -5
  48. package/lib/project-session-history-actions.js +5 -3
  49. package/lib/project-session-pair.js +1 -1
  50. package/lib/project-session-runtime-actions.js +2 -1
  51. package/lib/project-session-spawn.js +2 -3
  52. package/lib/project-session-vendor.js +2 -1
  53. package/lib/project-sessions.js +18 -26
  54. package/lib/project-shared-browser.js +22 -5
  55. package/lib/project-studio-presentation.js +58 -0
  56. package/lib/project-user-message.js +37 -0
  57. package/lib/project-vendor-login.js +6 -36
  58. package/lib/project-workspace-query.js +11 -1
  59. package/lib/project.js +24 -7
  60. package/lib/public/app.js +25 -0
  61. package/lib/public/appearance-bootstrap.js +2 -0
  62. package/lib/public/css/contextual-clay.css +240 -0
  63. package/lib/public/css/messages.css +6 -2
  64. package/lib/public/modules/app-favicon.js +18 -9
  65. package/lib/public/modules/app-header.js +4 -2
  66. package/lib/public/modules/app-loop-ui.js +2 -0
  67. package/lib/public/modules/app-message-router.js +5 -1
  68. package/lib/public/modules/app-messages.js +50 -6
  69. package/lib/public/modules/app-notifications.js +11 -5
  70. package/lib/public/modules/app-panels.js +61 -123
  71. package/lib/public/modules/app-projects.js +3 -0
  72. package/lib/public/modules/app-rate-limit.js +7 -27
  73. package/lib/public/modules/chat-render-runtime.js +3 -0
  74. package/lib/public/modules/clay-control-activity.js +214 -0
  75. package/lib/public/modules/clay-control-copy.js +36 -0
  76. package/lib/public/modules/clay-control-detail-targets.js +44 -0
  77. package/lib/public/modules/clay-control-object-targets.js +52 -0
  78. package/lib/public/modules/clay-control-target-visibility.js +12 -0
  79. package/lib/public/modules/clay-control-targets.js +44 -0
  80. package/lib/public/modules/clay-navigation-render.js +52 -0
  81. package/lib/public/modules/clay-owner-navigation.js +11 -2
  82. package/lib/public/modules/clay-session-links.js +31 -0
  83. package/lib/public/modules/clay-studio-bridge.js +20 -0
  84. package/lib/public/modules/clay-studio-document.js +67 -0
  85. package/lib/public/modules/clay-studio-render.js +144 -0
  86. package/lib/public/modules/clay-tool-presentation.js +4 -0
  87. package/lib/public/modules/command-palette.js +26 -31
  88. package/lib/public/modules/contextual-ask-session.js +26 -0
  89. package/lib/public/modules/contextual-clay-geometry.js +155 -0
  90. package/lib/public/modules/contextual-clay-session.js +130 -0
  91. package/lib/public/modules/contextual-clay-workspace.js +157 -0
  92. package/lib/public/modules/contextual-clay.js +237 -0
  93. package/lib/public/modules/contextual-composer.js +91 -0
  94. package/lib/public/modules/contextual-mate-context.js +115 -0
  95. package/lib/public/modules/contextual-mate-hint.js +40 -0
  96. package/lib/public/modules/contextual-mate-identity.js +23 -0
  97. package/lib/public/modules/contextual-mate-sessions.js +134 -0
  98. package/lib/public/modules/contextual-search.js +137 -0
  99. package/lib/public/modules/contextual-session-citations.js +58 -0
  100. package/lib/public/modules/filebrowser.js +20 -1
  101. package/lib/public/modules/generation-stop.js +8 -5
  102. package/lib/public/modules/git-panel.js +3 -1
  103. package/lib/public/modules/icon-strip-tooltip.js +2 -1
  104. package/lib/public/modules/input.js +35 -1
  105. package/lib/public/modules/issues-render.js +3 -2
  106. package/lib/public/modules/knowledge-db-workbench.js +4 -4
  107. package/lib/public/modules/markdown.js +2 -34
  108. package/lib/public/modules/mate-knowledge-workbench.js +1 -1
  109. package/lib/public/modules/mcp-connection-view.js +1 -1
  110. package/lib/public/modules/message-delivery.js +10 -0
  111. package/lib/public/modules/pane-bridge.js +2 -2
  112. package/lib/public/modules/pending-message-queue.js +1 -0
  113. package/lib/public/modules/permission-control.js +5 -4
  114. package/lib/public/modules/product-review.js +26 -0
  115. package/lib/public/modules/project-chat-identity.js +13 -4
  116. package/lib/public/modules/project-logs-render.js +3 -0
  117. package/lib/public/modules/project-mate-navigation.js +58 -21
  118. package/lib/public/modules/scheduled-tasks.js +2 -0
  119. package/lib/public/modules/scheduler.js +2 -0
  120. package/lib/public/modules/search-clay-chat.js +5 -454
  121. package/lib/public/modules/session-create-form.js +10 -10
  122. package/lib/public/modules/settings-defaults.js +27 -28
  123. package/lib/public/modules/shared-browser.js +2 -0
  124. package/lib/public/modules/sidebar-mobile.js +4 -3
  125. package/lib/public/modules/sidebar-projects.js +1 -0
  126. package/lib/public/modules/sidebar-sessions.js +1 -0
  127. package/lib/public/modules/split-view.js +7 -16
  128. package/lib/public/modules/terminal.js +9 -0
  129. package/lib/public/modules/tools.js +6 -2
  130. package/lib/public/modules/tui-grab.js +1 -2
  131. package/lib/public/modules/vendor-login-browser.js +5 -3
  132. package/lib/public/modules/vendor-login.js +2 -2
  133. package/lib/public/modules/vendor-priority.js +15 -1
  134. package/lib/public/modules/wireframe-workbench.js +5 -2
  135. package/lib/public/muse-avatar.svg +4 -0
  136. package/lib/public/style.css +2 -0
  137. package/lib/safe-bash-commands.js +3 -45
  138. package/lib/sdk-bridge.js +131 -395
  139. package/lib/sdk-foreground-admission.js +16 -0
  140. package/lib/sdk-mcp-descriptors.js +2 -37
  141. package/lib/sdk-message-processor.js +50 -17
  142. package/lib/sdk-quota-snapshot.js +1 -1
  143. package/lib/sdk-response-recovery.js +1 -155
  144. package/lib/sdk-worker.js +2 -677
  145. package/lib/server-contextual-clay-settings.js +40 -0
  146. package/lib/server-contextual-mate-sessions.js +70 -0
  147. package/lib/server-home-chat.js +7 -1
  148. package/lib/server-home-clay-entry.js +23 -4
  149. package/lib/server-home-clay-session-links.js +12 -0
  150. package/lib/server-owner-ui.js +49 -8
  151. package/lib/server-settings.js +2 -0
  152. package/lib/server.js +18 -1
  153. package/lib/session-fork-history.js +21 -0
  154. package/lib/session-hygiene.js +3 -35
  155. package/lib/session-permission-mode.js +4 -3
  156. package/lib/session-skill-scope.js +11 -0
  157. package/lib/sessions.js +24 -89
  158. package/lib/terminal-manager.js +18 -11
  159. package/lib/tool-llm.js +1 -1
  160. package/lib/tui-transcript-index.js +1 -132
  161. package/lib/users-contextual-clay-preferences.js +31 -0
  162. package/lib/users.js +3 -0
  163. package/lib/vendor-login-browser.js +1 -11
  164. package/lib/workspace-assignment-service.js +25 -0
  165. package/lib/workspace-query-mcp-server.js +1 -1
  166. package/lib/ws-request.js +1 -0
  167. package/lib/ws-schema.js +10 -0
  168. package/lib/yoke/acp-agent-profiles.js +5 -3
  169. package/lib/yoke/adapters/antigravity.js +3 -14
  170. package/lib/yoke/adapters/claude-query-contract.js +9 -0
  171. package/lib/yoke/adapters/claude.js +7 -42
  172. package/lib/yoke/adapters/codex-query-contract.js +24 -0
  173. package/lib/yoke/adapters/codex.js +1 -0
  174. package/lib/yoke/adapters/kiro.js +3 -1
  175. package/lib/yoke/adapters/muse-query-contract.js +7 -0
  176. package/lib/yoke/adapters/muse.js +122 -0
  177. package/lib/yoke/auth-events.js +17 -0
  178. package/lib/yoke/claude-hook-installer.js +271 -0
  179. package/lib/yoke/claude-jsonl-watcher.js +204 -0
  180. package/lib/yoke/claude-maintenance.js +55 -0
  181. package/lib/yoke/claude-permission-patterns.js +53 -0
  182. package/lib/yoke/claude-response-recovery.js +155 -0
  183. package/lib/yoke/claude-transcript-hygiene.js +34 -0
  184. package/lib/yoke/clay-skill-install.js +33 -0
  185. package/lib/yoke/cli-sessions.js +300 -0
  186. package/lib/yoke/codex-app-server.js +7 -12
  187. package/lib/yoke/configuration.js +13 -0
  188. package/lib/yoke/discovery.js +70 -0
  189. package/lib/yoke/errors.js +8 -0
  190. package/lib/yoke/host-environment.js +7 -0
  191. package/lib/yoke/index.js +9 -51
  192. package/lib/yoke/interface.js +116 -0
  193. package/lib/yoke/kiro-acp-server.js +5 -5
  194. package/lib/yoke/legacy-sessions.js +89 -0
  195. package/lib/yoke/login-protocol.js +25 -0
  196. package/lib/yoke/maintenance.js +12 -0
  197. package/lib/yoke/mcp-proxy.js +32 -0
  198. package/lib/yoke/mcp-source-adapters.js +91 -0
  199. package/lib/yoke/mcp-source-context.js +42 -0
  200. package/lib/yoke/mcp-source-discovery.js +169 -0
  201. package/lib/yoke/mcp-source-plugins.js +68 -0
  202. package/lib/yoke/mcp-source-restrictions.js +47 -0
  203. package/lib/yoke/mcp-tool-policy-normalize.js +28 -0
  204. package/lib/yoke/model-preferences.js +6 -0
  205. package/lib/yoke/muse-artifacts.js +36 -0
  206. package/lib/yoke/muse-controls.js +50 -0
  207. package/lib/yoke/muse-input.js +64 -0
  208. package/lib/yoke/muse-items.js +157 -0
  209. package/lib/yoke/muse-policy.js +52 -0
  210. package/lib/yoke/muse-query.js +428 -0
  211. package/lib/yoke/muse-runtime.js +211 -0
  212. package/lib/yoke/muse-services.js +79 -0
  213. package/lib/yoke/muse-skills.js +79 -0
  214. package/lib/yoke/muse-turns.js +71 -0
  215. package/lib/yoke/options/acp.js +2 -0
  216. package/lib/yoke/options/antigravity.js +2 -0
  217. package/lib/yoke/options/claude.js +21 -0
  218. package/lib/yoke/options/codex-defaults.js +29 -0
  219. package/lib/yoke/options/codex-settings.js +21 -0
  220. package/lib/yoke/options/codex.js +6 -0
  221. package/lib/yoke/options/kiro-defaults.js +22 -0
  222. package/lib/yoke/options/kiro.js +5 -0
  223. package/lib/yoke/options/muse.js +5 -0
  224. package/lib/yoke/provider-contract.js +5 -0
  225. package/lib/yoke/providers/antigravity-executable.js +8 -0
  226. package/lib/yoke/providers/claude-executable.js +40 -0
  227. package/lib/yoke/providers/claude-model-descriptions.js +14 -0
  228. package/lib/yoke/providers/claude-process.js +97 -0
  229. package/lib/yoke/providers/claude-provision.js +75 -0
  230. package/lib/yoke/providers/codex-errors.js +8 -0
  231. package/lib/yoke/providers/muse-executable.js +17 -0
  232. package/lib/yoke/provisioning.js +6 -0
  233. package/lib/yoke/query-options.js +10 -0
  234. package/lib/yoke/response-recovery.js +41 -0
  235. package/lib/yoke/sdk-mcp-descriptors.js +37 -0
  236. package/lib/yoke/sdk-server-factory.js +7 -0
  237. package/lib/yoke/session-history.js +8 -0
  238. package/lib/yoke/session-tool-transport.js +31 -13
  239. package/lib/yoke/settings.js +23 -0
  240. package/lib/yoke/source-locations.js +4 -0
  241. package/lib/yoke/title-query.js +18 -7
  242. package/lib/yoke/tui-transcript-index.js +132 -0
  243. package/lib/yoke/usage.js +48 -0
  244. package/lib/yoke/user-input.js +13 -0
  245. package/lib/yoke/vendor-registry.js +81 -1
  246. package/package.json +3 -2
@@ -0,0 +1,52 @@
1
+ var itemInput = require("./muse-items").itemInput;
2
+
3
+ function normalizeMcpServers(servers) {
4
+ var config = {};
5
+ if (servers == null) return config;
6
+ if (!Array.isArray(servers)) throw new Error("Invalid Muse session MCP servers");
7
+ for (var i = 0; i < servers.length; i++) {
8
+ var server = servers[i] || {};
9
+ if (!server.name || !server.command || typeof server.name !== "string" || typeof server.command !== "string" || !Array.isArray(server.args || [])) throw new Error("Invalid Muse session MCP server");
10
+ if (["__proto__", "constructor", "prototype"].includes(server.name) || Object.prototype.hasOwnProperty.call(config, server.name)) throw new Error("Invalid or duplicate Muse MCP server name");
11
+ var env = {};
12
+ var entries = Array.isArray(server.env) ? server.env : [];
13
+ for (var j = 0; j < entries.length; j++) if (entries[j] && entries[j].name) env[entries[j].name] = String(entries[j].value == null ? "" : entries[j].value);
14
+ config[server.name] = {
15
+ transport: "stdio",
16
+ command: server.command,
17
+ args: server.args || [],
18
+ env: env,
19
+ mode: "required"
20
+ };
21
+ }
22
+ return config;
23
+ }
24
+
25
+ function chooseApprovalDecision(request, canUseTool, signal) {
26
+ var choices = Array.isArray(request && request.availableChoices) ? request.availableChoices : [];
27
+ if (!choices.length || typeof canUseTool !== "function") return Promise.reject(new Error("Muse approval cannot be decided safely"));
28
+ if (signal && signal.aborted) return Promise.reject(new Error("Muse approval cancelled"));
29
+ return Promise.resolve(canUseTool(request.toolName || "Tool", itemInput({
30
+ args: request.rawArgs
31
+ }), {
32
+ request: request,
33
+ signal: signal
34
+ })).then(function(result) {
35
+ if (signal && signal.aborted) throw new Error("Muse approval cancelled");
36
+ var allowed = result && result.behavior === "allow";
37
+ if (!allowed && !(result && result.behavior === "deny")) throw new Error("Muse approval returned an unsupported decision");
38
+ for (var i = 0; i < choices.length; i++) if (choices[i].scope === "once" && (choices[i].decision === (allowed ? "approved" : "denied") || !allowed && choices[i].decision === "abort")) {
39
+ var decision = {
40
+ choiceId: choices[i].choiceId
41
+ };
42
+ if (choices[i].acceptsFeedback && result.message) decision.feedback = result.message;
43
+ return decision;
44
+ }
45
+ throw new Error("Muse approval has no matching safe choice");
46
+ });
47
+ }
48
+
49
+ module.exports = {
50
+ normalizeMcpServers: normalizeMcpServers,
51
+ chooseApprovalDecision: chooseApprovalDecision
52
+ };
@@ -0,0 +1,428 @@
1
+ var queryAbort = require("./query-abort");
2
+
3
+ var runtimeTools = require("./muse-runtime");
4
+
5
+ var policy = require("./muse-policy");
6
+
7
+ function createMuseQueryHandle(adapter, queryOpts) {
8
+ var state = {
9
+ client: null,
10
+ connection: null,
11
+ session: null,
12
+ sessionId: queryOpts.resumeSessionId || null,
13
+ model: queryOpts.model || null,
14
+ effort: queryOpts.effort || null,
15
+ toolPolicy: "ask",
16
+ messages: [],
17
+ messageSequence: 0,
18
+ active: false,
19
+ ended: false,
20
+ inputEnded: false,
21
+ stopped: false,
22
+ events: [],
23
+ waiter: null,
24
+ textBlocks: {},
25
+ thinkingBlocks: {},
26
+ toolBlocks: {},
27
+ activeTurn: null,
28
+ liveTurnIds: new Set(),
29
+ abortController: queryOpts.abortController || new AbortController(),
30
+ started: false
31
+ };
32
+ var removeAbort = function() {};
33
+ var handle;
34
+ var failure = null;
35
+ var cleanup = null;
36
+ var runtime = null;
37
+ var itemFrames = [];
38
+ var skillDelivery = require("./muse-skills").create(Object.assign({}, queryOpts, { cwd: queryOpts.cwd || adapter.cwd }), function() { return runtime; }, push, assertLive);
39
+ var emitArtifact = require("./muse-artifacts").create(function() { return runtime; }, push);
40
+ var renderer = require("./muse-items").createRenderer(state, push);
41
+ var turns = require("./muse-turns").create({ state: state, renderer: renderer, emitArtifact: emitArtifact,
42
+ runtime: function() { return runtime; }, ready: flushFrames, push: push, outcomeEvent: outcomeEvent, fail: fail, close: function() { return handle.close(); } });
43
+ function push(event) {
44
+ if (state.stopped || state.ended) return;
45
+ if (state.waiter) {
46
+ var resolve = state.waiter;
47
+ state.waiter = null;
48
+ resolve({
49
+ value: event,
50
+ done: false
51
+ });
52
+ } else state.events.push(event);
53
+ }
54
+ function finish() {
55
+ if (state.waiter) {
56
+ var resolve = state.waiter;
57
+ state.waiter = null;
58
+ resolve({
59
+ value: undefined,
60
+ done: true
61
+ });
62
+ }
63
+ }
64
+ function assertLive() {
65
+ if (state.stopped || state.ended || adapter.shuttingDown) throw new Error("Muse Code query was stopped");
66
+ }
67
+ function activateTurn(turn) {
68
+ state.activeTurn = turn;
69
+ }
70
+ function flushFrames() {
71
+ var frames = itemFrames.splice(0);
72
+ for (var i = 0; i < frames.length; i++) renderer.renderFrame(frames[i]);
73
+ }
74
+ function chooseApproval(request) {
75
+ if (state.stopped || state.abortController.signal.aborted) return Promise.reject(new Error("Muse approval cancelled"));
76
+ return runtime.wait(policy.chooseApprovalDecision(request, queryOpts.canUseTool, state.abortController.signal));
77
+ }
78
+ function fail(error) {
79
+ if (state.stopped || failure) return;
80
+ failure = error;
81
+ state.messages = [];
82
+ push(runtimeTools.isAuthError(error) ? {
83
+ yokeType: "auth_required",
84
+ vendor: "muse"
85
+ } : {
86
+ yokeType: "error",
87
+ text: error.message || String(error)
88
+ });
89
+ handle.close().catch(function(closeError) {
90
+ adapter.lastCloseError = closeError;
91
+ });
92
+ }
93
+ async function selectModel(model) {
94
+ if (!model) return null;
95
+ if (!adapter.catalog.some(function(row) {
96
+ return row.value === model;
97
+ })) {
98
+ var result = await runtime.waitRequest(state.connection.request("model/list", {}));
99
+ adapter.catalog = runtimeTools.normalizeCatalog(result);
100
+ }
101
+ assertLive();
102
+ return runtimeTools.modelSelection(adapter.catalog, model);
103
+ }
104
+ function validateEffort(effort) {
105
+ var vocabulary = [ "none", "minimal", "low", "medium", "high", "xhigh", "max", "ultra" ];
106
+ if (!vocabulary.includes(effort)) throw new Error("Unsupported Muse reasoning effort: " + effort);
107
+ var row = adapter.catalog.find(function(model) {
108
+ return model.value === state.model;
109
+ });
110
+ if (row && !row.effortUnknown && !row.supportedEffortLevels.includes(effort)) {
111
+ throw new Error("Muse model does not support reasoning effort: " + effort);
112
+ }
113
+ }
114
+ async function ensureSession() {
115
+ assertLive();
116
+ if (state.session) return state.session;
117
+ var sdk = await adapter.loadSdk();
118
+ assertLive();
119
+ runtime = runtimeTools.createRuntime(adapter, sdk, {
120
+ command: adapter.binaryPath,
121
+ args: [ "serve" ],
122
+ cwd: queryOpts.cwd || adapter.cwd,
123
+ userInputDialogs: queryOpts.userInputMode !== "fallback" && typeof queryOpts.onUserInputRequest === "function",
124
+ env: Object.assign({}, process.env, queryOpts.env || {})
125
+ });
126
+ runtime.fail = fail;
127
+ runtime.onUserInput = require("./muse-input").createRouter(runtime, queryOpts, state.abortController.signal);
128
+ runtime.onFrame = function(frame) {
129
+ turns.onFrame(frame);
130
+ if (frame.method.indexOf("item/") === 0) {
131
+ if (!renderer.renderFrame(frame)) itemFrames.push(frame);
132
+ }
133
+ if (frame.method === "session/modelChanged") {
134
+ var previousModel = state.model;
135
+ state.model = frame.params.modelId;
136
+ if (typeof queryOpts.onModelSwitch === "function" && previousModel && previousModel !== state.model) queryOpts.onModelSwitch({ fromModel: previousModel, toModel: state.model, source: frame.params.source });
137
+ }
138
+ if (frame.method === "userInput/settled") runtime.onUserInput.settle(frame.params.userInputId);
139
+ if (frame.method === "userInput/requested") runtime.onUserInput(frame.params).catch(fail);
140
+ if (frame.method === "usage/changed") {
141
+ var quota = require("./muse-services").quotaEvent(frame.params);
142
+ if (quota) push(quota);
143
+ }
144
+ if (frame.method === "session/contextUsage") state.contextUsage = frame.params;
145
+ if (frame.method === "approval/requested" && queryOpts.resumeSessionId && !state.started) {
146
+ state.resumedTurnId = state.resumedTurnId || frame.params.turnId;
147
+ }
148
+ };
149
+ var spawned = await runtime.initialize();
150
+ assertLive();
151
+ state.connection = spawned.connection;
152
+ var museOpts = queryOpts.adapterOptions && queryOpts.adapterOptions.MUSE || {};
153
+ var mcpServers = policy.normalizeMcpServers(museOpts.mcpServers);
154
+ var hasMcp = Object.keys(mcpServers).length > 0;
155
+ var config = hasMcp ? {
156
+ mcpServers: mcpServers
157
+ } : undefined;
158
+ if (hasMcp && !(spawned.initializeResult.grantedCapabilities || []).includes("sessionMcp")) {
159
+ throw new Error("Muse host does not support the required sessionMcp capability");
160
+ }
161
+ var selection = await selectModel(state.model);
162
+ if (state.effort) validateEffort(state.effort);
163
+ var verb = state.sessionId ? "session/resume" : "session/start";
164
+ var params = state.sessionId ? {
165
+ sessionId: state.sessionId,
166
+ config: config,
167
+ history: "inline"
168
+ } : {
169
+ workspaceRoot: queryOpts.cwd || adapter.cwd,
170
+ config: config,
171
+ approvalMode: museOpts.readOnly ? "denyUnmatched" : "onRequest"
172
+ };
173
+ if (selection && verb === "session/start") {
174
+ params.modelId = selection.modelId;
175
+ if (selection.providerId) params.providerId = selection.providerId;
176
+ }
177
+ var result = await runtime.waitRequest(state.connection.command(verb, params));
178
+ assertLive();
179
+ state.sessionId = result.session.sessionId;
180
+ var opening = {
181
+ verb: verb,
182
+ result: result
183
+ };
184
+ state.session = new sdk.Session({
185
+ connection: state.connection,
186
+ durability: sdk.readSessionDurability(spawned.initializeResult),
187
+ opening: opening,
188
+ sessionId: state.sessionId
189
+ });
190
+ runtime.session = state.session;
191
+ state.session.onApproval(chooseApproval);
192
+ state.session.onApprovalError(function(problem) {
193
+ fail(problem.error || new Error("Muse approval failed: " + problem.kind));
194
+ });
195
+ state.session.onGapError(function(problem) {
196
+ fail(problem.error || new Error("Muse view gap could not be filled"));
197
+ });
198
+ runtimeTools.seedHistory(state.session, opening, runtime.onFrame);
199
+ state.resumedTurnId = state.session.fold.activeTurnId;
200
+ state.contextUsage = result.history && result.history.snapshot && result.history.snapshot.state.contextUsage || null;
201
+ runtime.opening = false;
202
+ var held = runtime.held.splice(0);
203
+ for (var i = 0; i < held.length; i++) runtime.apply(held[i]);
204
+ assertLive();
205
+ if (runtime.dead) throw new Error("Muse host exited while opening the session");
206
+ if (verb === "session/resume") {
207
+ await runtime.waitRequest(state.connection.command("session/setApprovalMode", {
208
+ sessionId: state.sessionId,
209
+ mode: museOpts.readOnly ? "denyUnmatched" : "onRequest"
210
+ }));
211
+ if (selection) await runtime.waitRequest(state.connection.command("session/setModel", {
212
+ sessionId: state.sessionId,
213
+ model: selection
214
+ }));
215
+ }
216
+ assertLive();
217
+ if (verb === "session/resume") {
218
+ state.resumedTurnId = state.resumedTurnId || result.session.activeTurnId || state.session.fold.activeTurnId;
219
+ if ((result.pendingRequests || []).length) {
220
+ var pending = await runtime.waitRequest(state.connection.request("approval/listPending", {
221
+ sessionId: state.sessionId
222
+ }));
223
+ for (var promptIndex = 0; promptIndex < (pending.userInputs || []).length; promptIndex++) {
224
+ var promptRequest = pending.userInputs[promptIndex];
225
+ state.resumedTurnId = state.resumedTurnId || promptRequest.turnId;
226
+ runtime.onUserInput(promptRequest).catch(fail);
227
+ }
228
+ for (var pendingIndex = 0; pendingIndex < (pending.approvals || []).length; pendingIndex++) {
229
+ var approval = pending.approvals[pendingIndex];
230
+ state.resumedTurnId = state.resumedTurnId || approval.turnId;
231
+ runtime.apply({
232
+ method: "approval/requested",
233
+ params: approval
234
+ });
235
+ }
236
+ }
237
+ }
238
+ assertLive();
239
+ push({
240
+ yokeType: "session_started",
241
+ sessionId: state.sessionId
242
+ });
243
+ return state.session;
244
+ }
245
+ function outcomeEvent(outcome) {
246
+ if (!outcome || outcome.kind === "unqueued" || outcome.kind === "completed" && outcome.params && (outcome.params.terminal === "cancelled" || outcome.params.terminal === "cancelledByUser")) return {
247
+ yokeType: "interrupted"
248
+ };
249
+ if (outcome.kind === "terminalUnknown") return {
250
+ yokeType: "error",
251
+ text: "Muse host exited before the turn outcome was known"
252
+ };
253
+ var params = outcome.params || {};
254
+ if (params.terminal === "failed") return params.error && params.error.kind === "authRequired" ? {
255
+ yokeType: "auth_required",
256
+ vendor: "muse"
257
+ } : {
258
+ yokeType: "error",
259
+ text: params.error && params.error.message || params.reason || "Muse Code turn failed."
260
+ };
261
+ if (params.terminal !== "completed") return {
262
+ yokeType: "error",
263
+ text: "Unknown Muse turn outcome: " + params.terminal
264
+ };
265
+ return {
266
+ yokeType: "result",
267
+ messageType: "assistant",
268
+ sessionId: state.sessionId,
269
+ usage: params.usage ? {
270
+ input_tokens: params.usage.inputTokens,
271
+ output_tokens: params.usage.outputTokens,
272
+ cache_read_input_tokens: params.usage.cacheReadTokens == null ? params.usage.cachedTokens : params.usage.cacheReadTokens,
273
+ cache_creation_input_tokens: params.usage.cacheWriteTokens || 0
274
+ } : null,
275
+ cost: null,
276
+ duration: params.durationMs || null
277
+ };
278
+ }
279
+ async function runMessage(text, images, skill, sequence) {
280
+ state.active = true;
281
+ try {
282
+ var session = await ensureSession();
283
+ assertLive();
284
+ if (state.resumedTurnId) {
285
+ var resumed = session.turn(state.resumedTurnId);
286
+ state.resumedTurnId = null;
287
+ activateTurn(resumed);
288
+ var resumedBoundary = await turns.follow(resumed, false);
289
+ assertLive();
290
+ if (resumedBoundary.kind === "failed" || resumedBoundary.event && resumedBoundary.event.yokeType !== "result") return;
291
+ push({ yokeType: "runtime_specific", vendor: "muse",
292
+ eventType: resumedBoundary.kind === "foreground" ? "resumed_foreground_completed" : "resumed_turn_completed", raw: resumedBoundary.outcome });
293
+ }
294
+ var prepared = await skillDelivery.prepare(text || "", skill);
295
+ assertLive();
296
+ skill = prepared.skill;
297
+ var prompt = prepared.text;
298
+ if (!state.started) {
299
+ state.started = true;
300
+ prompt = [ queryOpts.systemPrompt, queryOpts.appendSystemPrompt, prompt ].filter(function(part) {
301
+ return !!part;
302
+ }).join("\n\n");
303
+ }
304
+ state.activeTurn = null;
305
+ if (prepared.scoped) skillDelivery.check();
306
+ push({ yokeType: "turn_activity", phase: "waiting" });
307
+ var turn = await runtime.wait(session.sendUserTurn({
308
+ input: require("./muse-input").inputParts(prompt, images).concat(skill ? [{ type: "skill", selector: skill.selector, arguments: skill.arguments }] : []),
309
+ reasoningEffort: state.effort || undefined
310
+ }));
311
+ assertLive();
312
+ activateTurn(turn);
313
+ await turns.follow(turn, true, sequence);
314
+ } catch (e) {
315
+ fail(e);
316
+ } finally {
317
+ state.active = false;
318
+ state.activeTurn = null;
319
+ if (state.messages.length && !state.stopped) {
320
+ var next = state.messages.shift();
321
+ runMessage(next.text, next.images, next.skill, next.sequence).catch(function(error) {
322
+ adapter.lastCloseError = error;
323
+ });
324
+ } else if (state.inputEnded && !turns.pending()) await handle.close();
325
+ else if (!state.stopped && turns.background()) push({ yokeType: "foreground_available" });
326
+ }
327
+ }
328
+ handle = {
329
+ [Symbol.asyncIterator]: function() {
330
+ return {
331
+ next: function() {
332
+ if (state.events.length) return Promise.resolve({
333
+ value: state.events.shift(),
334
+ done: false
335
+ });
336
+ if (state.ended) return Promise.resolve({
337
+ value: undefined,
338
+ done: true
339
+ });
340
+ return new Promise(function(resolve) {
341
+ state.waiter = resolve;
342
+ });
343
+ }
344
+ };
345
+ },
346
+ pushMessage: function(text, images, skill) {
347
+ if (state.stopped || state.ended || state.inputEnded) return false;
348
+ state.messages.push({
349
+ text: text, sequence: ++state.messageSequence,
350
+ images: images, skill: skill
351
+ });
352
+ if (!state.active) {
353
+ var next = state.messages.shift();
354
+ runMessage(next.text, next.images, next.skill, next.sequence).catch(function(error) {
355
+ adapter.lastCloseError = error;
356
+ });
357
+ }
358
+ return true;
359
+ },
360
+ // Clay's callback remains the authority even when its UI permits all tools.
361
+ setToolPolicy: async function(value) {
362
+ assertLive();
363
+ if (["ask", "allow-all"].indexOf(value) < 0) throw new Error("Unsupported Muse tool policy: " + value);
364
+ state.toolPolicy = value;
365
+ return { policy: value, nativeApprovalMode: "onRequest", authority: "canUseTool" };
366
+ },
367
+ stopTask: async function(taskId) {
368
+ assertLive();
369
+ if (!taskId) return handle.abort();
370
+ if (!state.connection || !state.session) throw new Error("Muse task stop requires an opened session");
371
+ await runtime.waitRequest(state.connection.command("task/stop", {
372
+ sessionId: state.sessionId,
373
+ taskId: taskId
374
+ }));
375
+ },
376
+ getContextUsage: function() {
377
+ var context = state.contextUsage;
378
+ return Promise.resolve(context ? {
379
+ input_tokens: context.usedTokens,
380
+ contextWindow: context.windowTokens
381
+ } : null);
382
+ },
383
+ endInput: function() {
384
+ state.inputEnded = true;
385
+ if (!state.active && !state.messages.length && !turns.pending()) handle.close().catch(function(error) {
386
+ adapter.lastCloseError = error;
387
+ });
388
+ },
389
+ abort: function() {
390
+ if (state.ended || state.stopped) return cleanup;
391
+ state.events = [];
392
+ var liveTurns = new Set(state.liveTurnIds);
393
+ if (state.activeTurn) liveTurns.add(state.activeTurn.turnId);
394
+ if (state.connection) liveTurns.forEach(function(turnId) {
395
+ state.connection.command("turn/cancel", { sessionId: state.sessionId, turnId: turnId }).catch(function(error) {
396
+ adapter.lastCancelError = error;
397
+ });
398
+ });
399
+ push({
400
+ yokeType: "interrupted"
401
+ });
402
+ return handle.close();
403
+ },
404
+ close: function() {
405
+ if (cleanup) return cleanup;
406
+ state.stopped = true;
407
+ state.inputEnded = true;
408
+ state.messages = [];
409
+ state.ended = true;
410
+ removeAbort();
411
+ state.abortController.abort();
412
+ finish();
413
+ adapter.handles.delete(handle);
414
+ cleanup = runtime ? runtime.close() : Promise.resolve();
415
+ return cleanup;
416
+ }
417
+ };
418
+ Object.assign(handle, require("./muse-controls").create({ state: state, assertLive: assertLive, selectModel: selectModel, validateEffort: validateEffort, skills: skillDelivery, runtime: function() { return runtime; }, handle: handle }));
419
+ adapter.handles.add(handle);
420
+ removeAbort = queryAbort.bindAbort(state.abortController, function() {
421
+ handle.abort();
422
+ });
423
+ return handle;
424
+ }
425
+
426
+ module.exports = {
427
+ createMuseQueryHandle: createMuseQueryHandle
428
+ };
@@ -0,0 +1,211 @@
1
+ var queryAbort = require("./query-abort");
2
+
3
+ var initializeTimeoutMs = require("./interface").INITIALIZE_TIMEOUT_MS;
4
+
5
+ function isAuthError(error) {
6
+ var kind = error && (error.kind || error.data && error.data.kind);
7
+ return kind === "authRequired" || /authentication|not authenticated|sign[ -]?in|log[ -]?in|credential|unauthorized|forbidden|api.?key|401/i.test(String(error && error.message || error || ""));
8
+ }
9
+
10
+ function closeResource(resource) {
11
+ if (!resource || typeof resource.close !== "function") return Promise.resolve();
12
+ return Promise.resolve().then(function() {
13
+ return resource.close();
14
+ });
15
+ }
16
+ // Own the process before initialize starts, including callers still opening a session.
17
+
18
+ function createRuntime(adapter, sdk, options) {
19
+ var scope = queryAbort.createAbortScope();
20
+ var handshake = sdk.spawnMspConnection(Object.assign({}, options, {
21
+ shutdownTimeoutMs: adapter.shutdownTimeoutMs
22
+ }));
23
+ var closing = null;
24
+ var runtime = {
25
+ handshake: handshake,
26
+ spawned: null,
27
+ connection: null,
28
+ session: null,
29
+ held: [],
30
+ opening: true,
31
+ dead: false,
32
+ wait: scope.wait,
33
+ check: scope.check,
34
+ waitRequest: async function(promise, timeoutMs) {
35
+ var timer;
36
+ try {
37
+ return await scope.wait(Promise.race([ promise, new Promise(function(resolve, reject) {
38
+ timer = setTimeout(function() {
39
+ reject(new Error("Muse Code request timed out"));
40
+ }, timeoutMs || adapter.requestTimeoutMs);
41
+ }) ]));
42
+ } finally {
43
+ clearTimeout(timer);
44
+ }
45
+ },
46
+ fail: function(error) {},
47
+ onFrame: function(frame) {},
48
+ apply: function(frame) {
49
+ if (!runtime.session || scope.stopped()) return;
50
+ var named = frame.params && frame.params.sessionId;
51
+ if (named !== runtime.session.sessionId) return;
52
+ if (frame.method === "view/gap") {
53
+ runtime.fail(new Error("Muse view stream has a gap; Stop retired this attempt. Resume explicitly to reconcile the session."));
54
+ return;
55
+ }
56
+ try {
57
+ var applied = runtime.session.apply(frame);
58
+ if (applied.fold.kind !== "item" || applied.fold.outcome.kind !== "ignoredStaleRevision") runtime.onFrame(frame);
59
+ } catch (error) {
60
+ runtime.fail(error);
61
+ }
62
+ },
63
+ close: function() {
64
+ if (closing) return closing;
65
+ scope.stop();
66
+ if (runtime.session) runtime.session.hostExited({
67
+ kind: "transportEof"
68
+ });
69
+ closing = closeResource(handshake).finally(function() {
70
+ adapter.clients.delete(runtime);
71
+ });
72
+ return closing;
73
+ },
74
+ initialize: async function() {
75
+ try {
76
+ runtime.spawned = await runtime.waitRequest(handshake.initialize({
77
+ clientInfo: {
78
+ name: "clay",
79
+ title: "Clay",
80
+ version: "1.0.0"
81
+ },
82
+ capabilities: {
83
+ requestedCapabilities: [ "sessionMcp" ],
84
+ userInputDialogs: options.userInputDialogs === true
85
+ }
86
+ }), initializeTimeoutMs);
87
+ runtime.connection = runtime.spawned.connection;
88
+ runtime.connection.onProtocolError(function(error) {
89
+ runtime.fail(error);
90
+ });
91
+ runtime.connection.closed.then(function() {
92
+ if (scope.stopped()) return;
93
+ runtime.dead = true;
94
+ if (runtime.session) runtime.session.hostExited({
95
+ kind: "transportEof"
96
+ });
97
+ runtime.fail(new Error("Muse Code transport closed unexpectedly"));
98
+ });
99
+ return runtime.spawned;
100
+ } catch (error) {
101
+ await runtime.close();
102
+ throw error;
103
+ }
104
+ }
105
+ };
106
+ function route(frame) {
107
+ if (scope.stopped()) return;
108
+ if (frame.method === "usage/changed") { runtime.onFrame(frame); return; }
109
+ if (runtime.opening) runtime.held.push(frame); else runtime.apply(frame);
110
+ }
111
+ handshake.onServerRequest(async function(request) {
112
+ if (request.method === "approval/request") {
113
+ route({
114
+ method: "approval/requested",
115
+ params: request.params
116
+ });
117
+ return {};
118
+ }
119
+ if (request.method === "userInput/request" && typeof runtime.onUserInput === "function") {
120
+ route({ method: "userInput/requested", params: request.params });
121
+ return {};
122
+ }
123
+ var error = new Error("Muse host requested an unsupported client dialog: " + request.method);
124
+ runtime.fail(error);
125
+ throw error;
126
+ });
127
+ adapter.clients.add(runtime);
128
+ handshake.onNotification(route);
129
+ if (typeof handshake.onProtocolError === "function") handshake.onProtocolError(function(error) {
130
+ runtime.fail(error);
131
+ });
132
+ if (handshake.child && handshake.child.exit) handshake.child.exit.then(function(exit) {
133
+ runtime.dead = true;
134
+ if (runtime.session) runtime.session.hostExited(exit);
135
+ if (!scope.stopped()) runtime.fail(new Error("Muse Code host exited: " + exit.kind));
136
+ }, function(error) {
137
+ if (!scope.stopped()) runtime.fail(error);
138
+ });
139
+ return runtime;
140
+ }
141
+
142
+ function normalizeCatalog(result) {
143
+ return (result.models || []).map(function(model) {
144
+ return {
145
+ value: model.modelId,
146
+ displayName: model.displayLabel || model.modelId,
147
+ description: model.description || "",
148
+ supportedEffortLevels: Array.isArray(model.variants) ? model.variants.filter(function(tier) {
149
+ return ["none", "minimal", "low", "medium", "high", "xhigh", "max", "ultra"].includes(tier);
150
+ }) : [],
151
+ providerId: model.providerId || result.providerId,
152
+ profileId: model.profileId == null ? result.profileId : model.profileId,
153
+ defaultReasoningEffort: model.defaultReasoningEffort,
154
+ isDefault: model.isDefault === true,
155
+ effortUnknown: !Array.isArray(model.variants),
156
+ catalogSource: result.source
157
+ };
158
+ });
159
+ }
160
+
161
+ function modelSelection(catalog, model) {
162
+ for (var i = 0; i < catalog.length; i++) {
163
+ if (catalog[i].value !== model) continue;
164
+ var selection = {
165
+ modelId: model,
166
+ displayLabel: catalog[i].displayName
167
+ };
168
+ if (catalog[i].providerId) selection.providerId = catalog[i].providerId;
169
+ if (catalog[i].profileId != null) selection.profileId = catalog[i].profileId;
170
+ return selection;
171
+ }
172
+ throw new Error("Muse model is not in the live model catalog: " + model);
173
+ }
174
+ // SDK 1.4.7 retains opening metadata but does not ingest its history. Seed once,
175
+ // before the buffered live suffix; pending pointers await the host's full reissue.
176
+
177
+ function seedHistory(session, opening, onFrame) {
178
+ if (opening.verb !== "session/resume") return;
179
+ var history = opening.result.history || {};
180
+ var snapshot = history.snapshot;
181
+ if (snapshot && snapshot.schemaVersion !== 1) throw new Error("Unsupported Muse snapshot schema version");
182
+ var items = history.items || snapshot && snapshot.state.items || [];
183
+ for (var i = 0; i < items.length; i++) {
184
+ var frame = {
185
+ method: "item/updated",
186
+ params: {
187
+ sessionId: session.sessionId,
188
+ item: items[i],
189
+ viewCursor: opening.result.viewCursor
190
+ }
191
+ };
192
+ session.apply(frame);
193
+ if (onFrame) onFrame(frame);
194
+ }
195
+ var active = snapshot && snapshot.state.activeTurn;
196
+ if (active) session.apply({
197
+ method: "turn/started",
198
+ params: Object.assign({}, active, {
199
+ sessionId: session.sessionId,
200
+ viewCursor: snapshot.viewCursor
201
+ })
202
+ });
203
+ }
204
+
205
+ module.exports = {
206
+ isAuthError: isAuthError,
207
+ createRuntime: createRuntime,
208
+ normalizeCatalog: normalizeCatalog,
209
+ modelSelection: modelSelection,
210
+ seedHistory: seedHistory
211
+ };