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
@@ -21,6 +21,25 @@ var INITIALIZE_TIMEOUT_MS = 90000;
21
21
 
22
22
  /*
23
23
  * Optional adapter event contract:
24
+ * { yokeType: "turn_activity", phase: "waiting" | "running" | "background", turnId?, disposition? }
25
+ * Waiting reports a pending submission/acknowledged queue, never model
26
+ * reasoning. Running requires an observed native start. Background means the
27
+ * foreground yielded while real terminals remain pending. These presentation
28
+ * facts never settle a turn or authorize tools; human decision surfaces take
29
+ * precedence. Common processing records them for live/replayed progress UI.
30
+ *
31
+ * { yokeType: "foreground_available" }
32
+ * Observed next-message admission while background work retains its real
33
+ * terminal. Offers one queue admission bound to this exact live query. Does
34
+ * not emit result/done, clear processing, settle reviews or complete tasks.
35
+ * Common processing persists an assistant_boundary presentation event before
36
+ * offering admission. Live/replayed clients flush the current assistant bubble
37
+ * at this boundary without treating it as a terminal or completing tools.
38
+ * Stop, paused delivery and query replacement invalidate the admission.
39
+ * A later successful result may carry backgroundOnly: true when its earlier
40
+ * foreground yielded to a newer accepted message. It accounts for that send
41
+ * without settling the newer turn's reviews or user-work completion callbacks.
42
+ *
24
43
  * { yokeType: "background_tasks_changed", tasks: [{ task_id, task_type, description }] }
25
44
  *
26
45
  * Each event replaces the complete live set. An adapter that emits this event
@@ -29,6 +48,25 @@ var INITIALIZE_TIMEOUT_MS = 90000;
29
48
  * and adapters that emit nothing simply have no background-task indicator.
30
49
  */
31
50
 
51
+ /*
52
+ * Optional image output event (independent of image input or invocation APIs):
53
+ * { yokeType: "generated_image", toolId, blockId, data, mediaType,
54
+ * prompt, savedPath, transparentBackground, isError, status }
55
+ * data is base64 image bytes (the common processor also accepts data URLs).
56
+ * toolId identifies this output; blockId associates any existing tool display.
57
+ * prompt is optional observed prompt text; savedPath is optional provenance,
58
+ * never authority to open a provider path. transparentBackground is true/false
59
+ * only when observed, otherwise null. Failed output sets isError and carries
60
+ * no successful image bytes. Common processing saves bytes, persists imageRefs
61
+ * and sends authenticated project URLs; failed saves become tool errors.
62
+ * The historical name covers provider-produced image artifacts, not proof of
63
+ * model generation. Emit only observed bytes, never an input echo, guessed
64
+ * filename or opaque artifact reference. Codex normalizes imageGeneration;
65
+ * Muse can read an explicitly typed raster outputRef through item/readOutput.
66
+ * This optional event does not imply pushMessage image-input support, an
67
+ * always-available model tool, or a dedicated adapter.generateImage() method.
68
+ */
69
+
32
70
  /**
33
71
  * Validate that an adapter object implements all required methods.
34
72
  * Throws if any are missing. Development-time safety net only.
@@ -40,6 +78,84 @@ var INITIALIZE_TIMEOUT_MS = 90000;
40
78
  * .createToolServer(def): ToolServer (opaque)
41
79
  * .createQuery(opts): QueryHandle
42
80
  *
81
+ * Optional query orchestration contract (.queryContract):
82
+ * toolTransport: "sdk-mcp" | "dynamic" | "stdio-mcp" (absent: unsupported)
83
+ * catalogLifetime: "query" | "conversation"
84
+ * externalToolTransport?: "dynamic" for remotely discovered definitions
85
+ * defaultUserInputMode?: "fallback" | "native" (auto otherwise)
86
+ * questionGuidance?(): string; provider-specific protocol guidance
87
+ * permissionModes?: string[]; implemented native modes, e.g. "auto"
88
+ * mcpPermissionOverrides?: true only for a working handle override setter
89
+ * interruptionMessage?: string; truthful feedback after Stop
90
+ * catalogVersion?(session, family): number
91
+ * recordCatalog?(session, versions): void
92
+ * staleCatalogReason?: string
93
+ *
94
+ * Conversation catalogs are immutable on resume. The host uses semantic tool
95
+ * families (schedules, questions, browser, issues, knowledge, linear) and their
96
+ * required revisions to request an exact-query recovery bridge. Adapter-owned
97
+ * mapping reads/writes persisted provider fields, including legacy names. A
98
+ * missing reader means unknown catalog; a missing writer never records success.
99
+ * Writers run only after a matching session_started event on the same live
100
+ * session/query generation. Creating a handle alone is not catalog confirmation.
101
+ * SDK transports must actually mount createToolServer output; dynamic transports
102
+ * must dispatch dynamicTools/callDynamicTool and deliver sessionMcpServer on
103
+ * resume or reject startup truthfully. These declarations never authorize tools:
104
+ * owner/foreign checks, target/review authority and live generation checks remain
105
+ * in common services. Stop cancels pending input/effects immediately; uncertain
106
+ * effects must not replay automatically. Provider protocols stay adapter-side.
107
+ * Init-free contracts live beside adapters and are also exposed by the registry
108
+ * for product controls before adapter initialization. Other providers retain
109
+ * their existing declared stdio transport or default to unsupported.
110
+ *
111
+ * Init-free provider services (adapter.providerContract or registry entry):
112
+ * mapQueryOptions(intent): object. Translates validated common intent to SDK
113
+ * namespaces; host never builds CLAUDE/CODEX/ACP/KIRO envelopes. Intent
114
+ * includes settings, thinking, nativePermissionMode/nativeBypass, readOnly,
115
+ * isolation, resumeAt, instructionSources, betas and start time. readOnly
116
+ * must dominate bypass, sandbox and search options. Unknown providers have
117
+ * no extra options; declared invalid/missing implementations must not imply
118
+ * success. Legacy persisted names remain accepted through provider codecs.
119
+ * configuration: serializable permission/thinking/approval/sandbox/search
120
+ * descriptions. These describe supported controls, never authorization.
121
+ * settings: defaults(), messages(settings), change(message, settings) returns
122
+ * a validated patch and response; host owns persistence and socket access.
123
+ * normalizeContext(value): { usedTokens, windowTokens, measurement, source }.
124
+ * measurement is observed, estimated or unavailable. Zero is a measurement;
125
+ * unknown is null. Billing totals are not context occupancy. YOKE usage
126
+ * projects result/account-quota history to the same client contract.
127
+ * authenticationReply(text), classifyError(text): protocol interpretation.
128
+ * Host handles authenticationRequired and classified errors, preserving
129
+ * identity, user-visible failure and explicit resumption requirements.
130
+ * resolveExecutable(options): path|null; discovery never runs the provider.
131
+ * Explicit supported overrides win; mapped users cannot inherit daemon
132
+ * credentials/installations. Errors or missing resolvers mean unavailable.
133
+ * login command/host metadata: only known validated token-only operations;
134
+ * OAuth URLs require exact hosts, PKCE, state and a loopback callback.
135
+ * Host still authorizes the exact owner/terminal and async flow revision.
136
+ * prepareIsolation, processControl: provider filesystem/PID protocol. Host
137
+ * authorizes identity and the exact process target before effects; absent
138
+ * verification refuses termination. No arbitrary shell/API dispatch.
139
+ * recoveryFactory(ctx): actual begin/enqueue/event/progress/cancel/current/
140
+ * valid/stopping/dispose implementation. Only the implemented confirmed
141
+ * termination protocol may retry; never replay uncertain delivery. Bindings
142
+ * retain the original service for immediate Stop and reject replacement
143
+ * providers. Unsupported providers receive no synthesized watchdog/retry.
144
+ * readSessionHistory(home, cwd, sessionId): actual provider fork-history
145
+ * reader. Local-history forks bypass file reading. Missing/nonfunction
146
+ * readers refuse; the host must not assume another provider's format.
147
+ * supportsLegacyGuiResume(session): implements the actual terminal format;
148
+ * the host retains idle/Stop/identity admission and persistence authority.
149
+ * notificationHooks, maintenance, provisionUser, credentialDirectories:
150
+ * bounded provider services; host owns provisioning and cleanup policy.
151
+ *
152
+ * publicInfo() sends only an explicit serializable field allowlist. Executable
153
+ * callbacks/services, OAuth internals and factories are never client metadata.
154
+ * Unknown/unsupported transports normalize to none. Declared SDK MCP transport
155
+ * with requested definitions must have a callable factory and non-null result;
156
+ * errors fail startup before admission. Capability data never grants canonical
157
+ * registry/query-generation authority, owner permissions or human review.
158
+ *
43
159
  * Optional one-shot capability:
44
160
  * .createOneShotQuery(opts): Promise<{ handle, backendPersistence }>
45
161
  * backendPersistence is "ephemeral" only when the adapter can verify the
@@ -8,9 +8,9 @@ var fs = require("fs");
8
8
  var { AcpProcessManager } = require("./acp-process-manager");
9
9
 
10
10
  function findKiroPath() {
11
- if (process.env.KIRO_CLI_PATH && fs.existsSync(process.env.KIRO_CLI_PATH)) {
12
- return process.env.KIRO_CLI_PATH;
13
- }
11
+ var discovery = require("./discovery");
12
+ var explicit = discovery.explicitEntry(process.env, "KIRO_CLI_PATH", false);
13
+ if (explicit !== undefined) return explicit;
14
14
 
15
15
  var binName = process.platform === "win32" ? "kiro-cli.exe" : "kiro-cli";
16
16
  var realHome;
@@ -23,7 +23,7 @@ function findKiroPath() {
23
23
  "/opt/homebrew/bin/" + binName,
24
24
  ];
25
25
  for (var i = 0; i < candidates.length; i++) {
26
- if (candidates[i] && fs.existsSync(candidates[i])) return candidates[i];
26
+ if (discovery.validEntry(candidates[i], false)) return candidates[i];
27
27
  }
28
28
 
29
29
  try {
@@ -32,7 +32,7 @@ function findKiroPath() {
32
32
  ? execFileSync("where", [binName], { timeout: 3000, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] })
33
33
  : execFileSync("which", ["kiro-cli"], { timeout: 3000, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] });
34
34
  var resolved = out.trim().split(/\r?\n/)[0];
35
- if (resolved) return resolved;
35
+ if (discovery.validEntry(resolved, false)) return resolved;
36
36
  } catch (e) {}
37
37
 
38
38
  throw new Error("Could not find kiro-cli binary (looked in ~/.local/bin, PATH, KIRO_CLI_PATH)");
@@ -0,0 +1,89 @@
1
+ // The existing imported terminal format. Product session creation/deletion
2
+ // remains in the host; these are provider file/grammar projections only.
3
+ var fs = require("fs"), path = require("path");
4
+ var hygiene = require("./claude-transcript-hygiene");
5
+ function directory(home, cwd) { return path.join(home, ".claude", "projects", require("../utils").encodeCwd(cwd)); }
6
+ function readHead(filePath) {
7
+ var MAX_READ = 64 * 1024;
8
+ try {
9
+ var stat = fs.statSync(filePath);
10
+ var fd = fs.openSync(filePath, "r");
11
+ var bytesToRead = Math.min(stat.size, MAX_READ);
12
+ var buf = Buffer.alloc(bytesToRead);
13
+ fs.readSync(fd, buf, 0, bytesToRead, 0);
14
+ fs.closeSync(fd);
15
+ var lines = buf.toString("utf8").split("\n");
16
+ var events = [];
17
+ for (var i = 0; i < lines.length; i++) {
18
+ if (!lines[i]) continue;
19
+ try {
20
+ var event = JSON.parse(lines[i]);
21
+ if (event && typeof event === "object") events.push(event);
22
+ } catch (e) {}
23
+ }
24
+ return events;
25
+ } catch (e) {
26
+ return null;
27
+ }
28
+ }
29
+
30
+ function metadata(events, fp) {
31
+ var userCount = 0;
32
+ var firstUserText = null;
33
+ var createdAtIso = null;
34
+ for (var li = 0; li < events.length; li++) {
35
+ var ev = events[li];
36
+ if (ev.type === "user" && ev.message && ev.message.role === "user") {
37
+ userCount++;
38
+ if (firstUserText == null) {
39
+ var c = ev.message.content;
40
+ if (typeof c === "string") {
41
+ firstUserText = c;
42
+ } else if (Array.isArray(c)) {
43
+ var parts = [];
44
+ for (var ci = 0; ci < c.length; ci++) {
45
+ if (c[ci] && c[ci].type === "text" && typeof c[ci].text === "string") parts.push(c[ci].text);
46
+ }
47
+ firstUserText = parts.join("");
48
+ }
49
+ if (ev.timestamp && !createdAtIso) createdAtIso = ev.timestamp;
50
+ }
51
+ }
52
+ }
53
+
54
+ if (userCount === 0) return null;
55
+ // Defensive warmup skip (daemon also cleans these)
56
+ if (hygiene.isClaudeWarmupTranscript(events)) return null;
57
+
58
+ // Title: first user message trimmed/truncated. Fall back to a
59
+ // neutral label so the sidebar entry is identifiable.
60
+ var title = (firstUserText || "").trim().replace(/\s+/g, " ");
61
+ if (title.length > 60) title = title.slice(0, 57) + "...";
62
+ if (!title) title = "Imported CLI session";
63
+
64
+ var createdAt = Date.now();
65
+ if (createdAtIso) {
66
+ var t = Date.parse(createdAtIso);
67
+ if (!isNaN(t)) createdAt = t;
68
+ }
69
+ var lastActivity = createdAt;
70
+ try { lastActivity = fs.statSync(fp).mtimeMs; } catch (e) {}
71
+
72
+ return { title: title, createdAt: createdAt, lastActivity: lastActivity };
73
+ }
74
+ function candidates(dir, known, deleted) {
75
+ var files;
76
+ try { files = fs.readdirSync(dir); } catch (error) { return []; }
77
+ return files.filter(function(file) { return file.endsWith(".jsonl"); }).flatMap(function(file) {
78
+ var id = file.slice(0, -6);
79
+ if (known.has(id) || deleted.has(id)) return [];
80
+ var filename = path.join(dir, file), events = readHead(filename);
81
+ var value = events && metadata(events, filename);
82
+ return value ? [Object.assign({ id: id, vendor: "claude" }, value)] : [];
83
+ });
84
+ }
85
+ function obsolete(dir, session) {
86
+ var filename = path.join(dir, session.cliSessionId + ".jsonl"), events = readHead(filename);
87
+ return !fs.existsSync(filename) && (!session.history || session.history.length === 0) || events && hygiene.isClaudeWarmupTranscript(events);
88
+ }
89
+ module.exports = { candidates: candidates, obsolete: obsolete, directory: directory, readHead: readHead, metadata: metadata, isWarmup: hygiene.isClaudeWarmupTranscript };
@@ -0,0 +1,25 @@
1
+ // Known provider login operations and output grammar; never accepts a command
2
+ // from model/client input. Identity and terminal permission stay in the host.
3
+ var PATTERNS = [/successfully logged in(?![ \t]+to[ \t]+mcp)/i, /logged in successfully/i, /login successful/i,
4
+ /successfully authenticated/i, /authentication successful/i, /signed in successfully/i,
5
+ /signed in with your [a-z ]+ account/i, /you(?:'re| are) (?:now )?(?:logged|signed) in/i];
6
+ function stripAnsi(text) { return String(text).replace(/\x1b\[[0-9;?]*[ -\/]*[@-~]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\r/g, ''); }
7
+ function successful(text) { return PATTERNS.some(function(pattern) { return pattern.test(text); }); }
8
+ function command(vendor, browser) {
9
+ var info = require('./provider-contract').resolve(vendor);
10
+ var operation = browser ? info.browserLoginCommand : info.terminalLoginCommand || info.loginCommand;
11
+ if (typeof operation !== 'string' || !/^[a-zA-Z0-9_.-]+(?: [a-zA-Z0-9_.-]+)*$/.test(operation)) throw new Error('Provider sign-in is unavailable.');
12
+ return operation;
13
+ }
14
+ function loginUrl(value, provider) {
15
+ try {
16
+ var hosts = require('./provider-contract').resolve(provider).oauthHosts || [];
17
+ var url = new URL(value);
18
+ if (url.protocol !== 'https:' || url.username || url.password || hosts.indexOf(url.hostname) < 0) return null;
19
+ if (!url.searchParams.get('state') || !url.searchParams.get('code_challenge')) return null;
20
+ var callback = new URL(url.searchParams.get('redirect_uri'));
21
+ if (callback.protocol !== 'http:' || ['localhost', '127.0.0.1', '[::1]'].indexOf(callback.hostname) < 0) return null;
22
+ return url.href;
23
+ } catch (error) { return null; }
24
+ }
25
+ module.exports = { stripAnsi: stripAnsi, successful: successful, command: command, loginUrl: loginUrl };
@@ -0,0 +1,12 @@
1
+ function cleanup(home) {
2
+ var registry = require("./vendor-registry").VENDOR_REGISTRY;
3
+ Object.keys(registry).forEach(function(vendor) {
4
+ var service = registry[vendor].maintenance;
5
+ if (service && typeof service.cleanup === "function") service.cleanup(home);
6
+ });
7
+ }
8
+ function credentialPaths(home) {
9
+ var registry = require("./vendor-registry").VENDOR_REGISTRY, path = require("path");
10
+ return Object.keys(registry).flatMap(function(vendor) { return (registry[vendor].credentialDirectories || []).map(function(name) { return path.join(home, name); }); });
11
+ }
12
+ module.exports = { cleanup: cleanup, credentialPaths: credentialPaths };
@@ -0,0 +1,32 @@
1
+ // Preserve the server's JSON Schema across SDK and stdio projections.
2
+ function validateDefinitions(definitions) {
3
+ var z = require('zod');
4
+ var names = new Set();
5
+ return definitions.map(function (definition) {
6
+ if (!definition || !/^[a-zA-Z0-9_.-]{1,128}$/.test(definition.name) || names.has(definition.name) || Object.prototype.hasOwnProperty.call(Object.prototype, definition.name)) throw new Error('Unsupported MCP tool catalog.');
7
+ names.add(definition.name);
8
+ var parsed = z.fromJSONSchema(definition.inputSchema || { type: 'object', properties: {} });
9
+ if (!parsed.shape) throw new Error('MCP tools must accept an object.');
10
+ return parsed;
11
+ });
12
+ }
13
+ function createProxy(name, definitions, invoke) {
14
+ var sdk = require('@anthropic-ai/claude-agent-sdk');
15
+ var schemas = validateDefinitions(definitions);
16
+ var tools = definitions.map(function (definition, index) {
17
+ return sdk.tool(definition.name, definition.description || definition.name, schemas[index].shape, function (args) { return invoke(definition.name, args); });
18
+ });
19
+ var server = sdk.createSdkMcpServer({ name: name, version: '1.0.0', tools: tools });
20
+ definitions.forEach(function (definition, index) {
21
+ var tool = server.instance._registeredTools[definition.name];
22
+ tool.inputSchema = schemas[index];
23
+ tool._clayInputSchema = definition.inputSchema || { type: 'object', properties: {} };
24
+ });
25
+ server.instance.server.setRequestHandler(require('@modelcontextprotocol/sdk/types.js').ListToolsRequestSchema, function () {
26
+ return { tools: definitions.map(function (definition) {
27
+ return { name: definition.name, description: definition.description, inputSchema: definition.inputSchema || { type: 'object', properties: {} } };
28
+ }) };
29
+ });
30
+ return server;
31
+ }
32
+ module.exports = { createProxy: createProxy, validateDefinitions: validateDefinitions };
@@ -0,0 +1,91 @@
1
+ // File-only adapters. Discovery never loads vendor code, plugins, or OAuth stores.
2
+ var path = require('path');
3
+ var toml = require('@iarna/toml');
4
+ var jsonc = require('jsonc-parser');
5
+ var yaml = require('yaml');
6
+ var network = require('../mcp-network');
7
+ var crypto = require('crypto');
8
+ var ADAPTERS = {
9
+ claude: { user: ['.claude.json'], project: ['.mcp.json'], key: 'mcpServers' },
10
+ codex: { user: ['.codex/config.toml'], project: ['.codex/config.toml'], key: 'mcp_servers' },
11
+ kiro: { user: ['.kiro/settings/mcp.json', '.kiro/mcp.json'], project: ['.kiro/settings/mcp.json', '.kiro/mcp.json'], key: 'mcpServers', agents: '.kiro/agents' },
12
+ opencode: { user: ['.config/opencode/opencode.json', '.config/opencode/opencode.jsonc'], project: ['opencode.json', 'opencode.jsonc'], key: 'mcp' },
13
+ kimi: { user: ['.kimi-code/mcp.json', '.kimi/mcp.json'], project: ['.kimi-code/mcp.json'], key: 'mcpServers' },
14
+ copilot: { user: ['.copilot/mcp-config.json'], project: ['.mcp.json', '.github/mcp.json'], key: 'mcpServers' },
15
+ qwen: { user: ['.qwen/settings.json'], project: ['.qwen/settings.json'], key: 'mcpServers' },
16
+ junie: { user: ['.junie/mcp/mcp.json'], project: ['.junie/mcp/mcp.json'], key: 'mcpServers' },
17
+ grok: { user: ['.grok/config.toml'], project: ['.grok/config.toml'], key: 'mcp_servers' },
18
+ antigravity: { user: ['.gemini/config/mcp_config.json', '.gemini/antigravity-cli/mcp_config.json'], project: ['.agents/mcp_config.json'], key: 'mcpServers', plugins: '.gemini/antigravity-cli/plugins' },
19
+ acp: { user: [], project: [], key: 'mcpServers' },
20
+ };
21
+ function parse(file, content) {
22
+ if (file.endsWith('.md')) {
23
+ var match = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(content);
24
+ if (!match) throw new Error('Agent profile requires YAML frontmatter.');
25
+ var document = yaml.parseDocument(match[1]);
26
+ if (document.errors.length) throw new Error('Invalid agent frontmatter.');
27
+ return document.toJS({ maxAliasCount: 50 });
28
+ }
29
+ if (file.endsWith('.toml')) return toml.parse(content);
30
+ var errors = [], value = jsonc.parse(content, errors, { allowTrailingComma: true });
31
+ if (errors.length || !value || typeof value !== 'object' || Array.isArray(value)) throw new Error('Invalid MCP source format.');
32
+ return value;
33
+ }
34
+ function stringMap(value) {
35
+ if (!value) return {};
36
+ if (Array.isArray(value)) {
37
+ var map = {}; value.forEach(function (entry) { if (!entry || typeof entry.name !== 'string' || typeof entry.value !== 'string') throw new Error('Invalid name/value field.'); map[entry.name] = entry.value; });
38
+ return map;
39
+ }
40
+ if (typeof value !== 'object') throw new Error('Invalid environment or headers.');
41
+ Object.keys(value).forEach(function (name) { if (typeof value[name] !== 'string') throw new Error('Invalid environment or headers.'); });
42
+ return Object.assign({}, value);
43
+ }
44
+ function normalize(vendor, name, value, source) {
45
+ if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('Invalid server definition.');
46
+ ['enabled', 'disabled'].forEach(function (key) { if (value[key] !== undefined && typeof value[key] !== 'boolean') throw new Error('Invalid source enablement: ' + key); });
47
+ if (value.oauth !== undefined && value.oauth !== true) throw new Error('Vendor OAuth policy requires reviewed Clay-owned authentication setup.');
48
+ var command = value.command, args = value.args || [];
49
+ if (vendor === 'opencode' && Array.isArray(command)) { args = command.slice(1); command = command[0]; }
50
+ var url = value.url || value.httpUrl || value.serverUrl;
51
+ if (command && url) throw new Error('Conflicting stdio and remote transport definitions.');
52
+ var type = value.type || value.transport || (url ? vendor === 'qwen' && !value.httpUrl ? 'sse' : 'http' : 'stdio');
53
+ if (type === 'local') type = 'stdio'; if (type === 'remote' || type === 'streamable-http') type = 'http';
54
+ if (['stdio', 'http', 'sse'].indexOf(type) < 0) throw new Error('Unsupported transport. Clay supports stdio, HTTP and SSE.');
55
+ if (value.headersHelper || value.oauth && (value.oauth.clientSecret || value.oauth.clientId)) throw new Error('Vendor authentication helper requires Clay-owned credential setup.');
56
+ var policy = require('../mcp-tool-policy').normalize(vendor, value);
57
+ var config = { transport: type, enabled: false, label: name, source: type === 'stdio' ? 'local' : 'url',
58
+ provenance: source, sourceEnabled: value.enabled === false || value.disabled === true ? false : source.scope.indexOf('plugin') === 0 ? null : true };
59
+ if (type === 'stdio') {
60
+ if (typeof command !== 'string' || !command || command.includes('\0') || !Array.isArray(args) || args.some(function (arg) { return typeof arg !== 'string' || arg.includes('\0'); })) throw new Error('Invalid stdio command or arguments.');
61
+ config.command = command; config.args = args; config.env = stringMap(value.env || value.environment); config.cwd = value.cwd || source.cwd;
62
+ if (typeof config.cwd !== 'string' || !path.isAbsolute(config.cwd)) throw new Error('Stdio working directory must be absolute.');
63
+ } else {
64
+ // Do not expand credential references during inspection.
65
+ config.url = network.remoteUrl(url).href; config.headers = stringMap(value.headers || value.http_headers);
66
+ config.envHeaders = stringMap(value.env_http_headers);
67
+ var bearer = value.bearer_token_env_var || value.bearerTokenEnvVar;
68
+ if (bearer) { config.bearerTokenEnv = bearer; config.envHeaders.Authorization = bearer; }
69
+ }
70
+ config.environmentNames = (value.env_vars || []).concat(Object.keys(config.env || {}));
71
+ if (value.env_vars !== undefined && !Array.isArray(value.env_vars)) throw new Error('Invalid environment allowlist.');
72
+ Object.assign(config, policy);
73
+ if (source.sourceEnabled !== undefined) config.sourceEnabled = config.sourceEnabled === false || source.sourceEnabled === false ? false : source.sourceEnabled;
74
+ var references = JSON.stringify([config.command, config.args, config.env, config.headers, config.url]).match(/\$\{[A-Za-z_][A-Za-z0-9_]*(?::-[^}]*)?\}|\$[A-Z_][A-Z0-9_]*|\{env:[^}]+\}|\{file:[^}]+\}|\{\{[^}]+\}\}/g) || [];
75
+ config.references = Array.from(new Set(references.concat(Object.values(config.envHeaders || {})).concat(value.env_vars || [])));
76
+ // Plugins may reference their own installed directory without reading any credential file.
77
+ if (source.pluginRoot) {
78
+ function pluginValue(value) {
79
+ if (typeof value === 'string') return value.replace(/\$\{CLAUDE_PLUGIN_ROOT\}/g, function () { return source.pluginRoot; }).replace(/\$\{CLAUDE_PROJECT_DIR\}/g, function () { return source.cwd; });
80
+ if (Array.isArray(value)) return value.map(pluginValue);
81
+ if (value && typeof value === 'object') { var next = {}; Object.keys(value).forEach(function (key) { next[key] = pluginValue(value[key]); }); return next; }
82
+ return value;
83
+ }
84
+ config = pluginValue(config); config.references = config.references.filter(function (ref) { return ref !== source.pluginRoot && ref !== source.cwd; });
85
+ }
86
+ return config;
87
+ }
88
+ function signature(config) {
89
+ return crypto.createHash('sha256').update(JSON.stringify([config.transport, config.url, config.command, config.args, config.env, config.headers, config.envHeaders, config.cwd, config.disabledTools, config.enabledTools, config.toolPatterns, config.toolPrefix, config.references])).digest('hex');
90
+ }
91
+ module.exports = { adapters: ADAPTERS, parse: parse, normalize: normalize, signature: signature };
@@ -0,0 +1,42 @@
1
+ var path = require('path');
2
+ var crypto = require('crypto');
3
+ var adapters = require('./mcp-source-adapters').adapters;
4
+ var KEYS = ['CODEX_HOME', 'CLAUDE_CONFIG_DIR', 'OPENCODE_CONFIG', 'OPENCODE_CONFIG_DIR', 'OPENCODE_CONFIG_CONTENT', 'XDG_CONFIG_HOME', 'KIMI_CODE_HOME', 'COPILOT_HOME', 'GROK_HOME', 'QWEN_HOME', 'QWEN_CODE_SYSTEM_SETTINGS_PATH', 'QWEN_CODE_SYSTEM_DEFAULTS_PATH'];
5
+ function resolve(ctx, owner, ws, home, identity) {
6
+ // Only the production runtime resolver may supply mapped-user overrides.
7
+ var env = ctx.runtimeEnv ? ctx.runtimeEnv(owner, ws) : identity ? {} : ctx.home ? {} : process.env;
8
+ var selected = {};
9
+ KEYS.forEach(function (key) { if (env[key] !== undefined) selected[key] = env[key]; });
10
+ function qwenRoot(value) { if (!value) return path.join(home, '.qwen'); return path.resolve(ctx.cwd, value.replace(/^~(?=\/|$)/, home)); }
11
+ var roots = { copilot: path.resolve(home, env.COPILOT_HOME || '.copilot'), grok: path.resolve(home, env.GROK_HOME || '.grok'), qwen: qwenRoot(env.QWEN_HOME), codex: path.resolve(home, env.CODEX_HOME || '.codex'), claude: path.resolve(home, env.CLAUDE_CONFIG_DIR || '.claude'),
12
+ opencode: path.resolve(home, env.XDG_CONFIG_HOME || '.config', 'opencode'), kimi: path.resolve(home, env.KIMI_CODE_HOME || '.kimi-code') };
13
+ var sources = [];
14
+ function add(vendor, file, scope, extra) { sources.push(Object.assign({ vendor: vendor, file: file, scope: scope, cwd: ctx.cwd }, extra)); }
15
+ Object.keys(adapters).forEach(function (vendor) {
16
+ var files = adapters[vendor].user;
17
+ if (vendor === 'codex') files = [path.join(roots.codex, 'config.toml')];
18
+ if (vendor === 'claude') files = [env.CLAUDE_CONFIG_DIR ? path.join(roots.claude, '.claude.json') : path.join(home, '.claude.json')];
19
+ if (vendor === 'opencode') files = ['opencode.json', 'opencode.jsonc'].map(function (file) { return path.join(roots.opencode, file); });
20
+ if (vendor === 'copilot') files = [path.join(roots.copilot, 'mcp-config.json')];
21
+ if (vendor === 'grok') files = [path.join(roots.grok, 'config.toml')];
22
+ if (vendor === 'qwen') files = [path.join(roots.qwen, 'settings.json')];
23
+ if (vendor === 'kimi' && env.KIMI_CODE_HOME) files = [path.join(roots.kimi, 'mcp.json')];
24
+ files.forEach(function (file) { add(vendor, path.resolve(home, file), 'user'); });
25
+ adapters[vendor].project.forEach(function (file) { add(vendor, path.join(ctx.cwd, file), 'project'); });
26
+ });
27
+ ['opencode.json', 'opencode.jsonc'].forEach(function (file) { add('opencode', path.join(ctx.cwd, '.opencode', file), 'runtime', { configDirectory: true }); });
28
+ if (env.OPENCODE_CONFIG) add('opencode', path.resolve(ctx.cwd, env.OPENCODE_CONFIG), 'runtime');
29
+ if (env.OPENCODE_CONFIG_DIR) ['opencode.json', 'opencode.jsonc'].forEach(function (file) { add('opencode', path.resolve(ctx.cwd, env.OPENCODE_CONFIG_DIR, file), 'runtime', { configDirectory: true }); });
30
+ if (env.OPENCODE_CONFIG_CONTENT) add('opencode', 'runtime:OPENCODE_CONFIG_CONTENT', 'runtime-inline', { inline: env.OPENCODE_CONFIG_CONTENT });
31
+ return { roots: roots, policyPaths: { qwenSettings: env.QWEN_CODE_SYSTEM_SETTINGS_PATH && path.resolve(ctx.cwd, env.QWEN_CODE_SYSTEM_SETTINGS_PATH), qwenDefaults: env.QWEN_CODE_SYSTEM_DEFAULTS_PATH && path.resolve(ctx.cwd, env.QWEN_CODE_SYSTEM_DEFAULTS_PATH) }, sources: sources, fingerprint: crypto.createHash('sha256').update(JSON.stringify(selected)).digest('hex') };
32
+ }
33
+ function priority(source) {
34
+ if (source.scope === 'runtime-inline') return 80;
35
+ if (source.scope === 'configured') return 70;
36
+ if (source.scope === 'runtime') return source.configDirectory ? 65 : 30;
37
+ if (source.scope === 'local') return 60;
38
+ if (source.scope === 'project') return 50 + (source.vendor === 'copilot' && path.basename(source.file) === '.mcp.json' ? 1 : 0);
39
+ if (source.scope === 'project-ancestor') return 40 + source.file.split(path.sep).length * 0.01 + (path.basename(source.file) === '.mcp.json' ? 0.001 : 0);
40
+ return source.scope.indexOf('plugin') === 0 ? 10 : 20;
41
+ }
42
+ module.exports = { resolve: resolve, priority: priority };