@openma/common 0.0.0-stage → 0.9.1

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 (328) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +391 -2
  3. package/dist/acp-artifacts/binary.d.ts +35 -0
  4. package/dist/acp-artifacts/binary.d.ts.map +1 -0
  5. package/dist/acp-artifacts/binary.js +120 -0
  6. package/dist/acp-artifacts/binary.js.map +1 -0
  7. package/dist/acp-artifacts/index.d.ts +7 -0
  8. package/dist/acp-artifacts/index.d.ts.map +1 -0
  9. package/dist/acp-artifacts/index.js +7 -0
  10. package/dist/acp-artifacts/index.js.map +1 -0
  11. package/dist/acp-artifacts/node-abi.d.ts +3 -0
  12. package/dist/acp-artifacts/node-abi.d.ts.map +1 -0
  13. package/dist/acp-artifacts/node-abi.js +17 -0
  14. package/dist/acp-artifacts/node-abi.js.map +1 -0
  15. package/dist/acp-artifacts/npm-cli.d.ts +3 -0
  16. package/dist/acp-artifacts/npm-cli.d.ts.map +1 -0
  17. package/dist/acp-artifacts/npm-cli.js +9 -0
  18. package/dist/acp-artifacts/npm-cli.js.map +1 -0
  19. package/dist/acp-artifacts/npm.d.ts +37 -0
  20. package/dist/acp-artifacts/npm.d.ts.map +1 -0
  21. package/dist/acp-artifacts/npm.js +167 -0
  22. package/dist/acp-artifacts/npm.js.map +1 -0
  23. package/dist/acp-artifacts/registry.d.ts +45 -0
  24. package/dist/acp-artifacts/registry.d.ts.map +1 -0
  25. package/dist/acp-artifacts/registry.js +206 -0
  26. package/dist/acp-artifacts/registry.js.map +1 -0
  27. package/dist/acp-artifacts/shared.d.ts +45 -0
  28. package/dist/acp-artifacts/shared.d.ts.map +1 -0
  29. package/dist/acp-artifacts/shared.js +157 -0
  30. package/dist/acp-artifacts/shared.js.map +1 -0
  31. package/dist/acp-artifacts/uvx.d.ts +32 -0
  32. package/dist/acp-artifacts/uvx.d.ts.map +1 -0
  33. package/dist/acp-artifacts/uvx.js +95 -0
  34. package/dist/acp-artifacts/uvx.js.map +1 -0
  35. package/dist/acp-fork/index.d.ts +51 -0
  36. package/dist/acp-fork/index.d.ts.map +1 -0
  37. package/dist/acp-fork/index.js +116 -0
  38. package/dist/acp-fork/index.js.map +1 -0
  39. package/dist/acp-harnesses/agent-setup.d.ts +118 -0
  40. package/dist/acp-harnesses/agent-setup.d.ts.map +1 -0
  41. package/dist/acp-harnesses/agent-setup.js +717 -0
  42. package/dist/acp-harnesses/agent-setup.js.map +1 -0
  43. package/dist/acp-harnesses/custom-agents.d.ts +81 -0
  44. package/dist/acp-harnesses/custom-agents.d.ts.map +1 -0
  45. package/dist/acp-harnesses/custom-agents.js +361 -0
  46. package/dist/acp-harnesses/custom-agents.js.map +1 -0
  47. package/dist/acp-harnesses/headless-launch.d.ts +34 -0
  48. package/dist/acp-harnesses/headless-launch.d.ts.map +1 -0
  49. package/dist/acp-harnesses/headless-launch.js +67 -0
  50. package/dist/acp-harnesses/headless-launch.js.map +1 -0
  51. package/dist/acp-harnesses/index.d.ts +18 -0
  52. package/dist/acp-harnesses/index.d.ts.map +1 -0
  53. package/dist/acp-harnesses/index.js +58 -0
  54. package/dist/acp-harnesses/index.js.map +1 -0
  55. package/dist/acp-harnesses/install-state.d.ts +86 -0
  56. package/dist/acp-harnesses/install-state.d.ts.map +1 -0
  57. package/dist/acp-harnesses/install-state.js +322 -0
  58. package/dist/acp-harnesses/install-state.js.map +1 -0
  59. package/dist/acp-harnesses/installer.d.ts +145 -0
  60. package/dist/acp-harnesses/installer.d.ts.map +1 -0
  61. package/dist/acp-harnesses/installer.js +716 -0
  62. package/dist/acp-harnesses/installer.js.map +1 -0
  63. package/dist/acp-harnesses/known-agents.d.ts +154 -0
  64. package/dist/acp-harnesses/known-agents.d.ts.map +1 -0
  65. package/dist/acp-harnesses/known-agents.js +240 -0
  66. package/dist/acp-harnesses/known-agents.js.map +1 -0
  67. package/dist/acp-harnesses/launcher.d.ts +27 -0
  68. package/dist/acp-harnesses/launcher.d.ts.map +1 -0
  69. package/dist/acp-harnesses/launcher.js +64 -0
  70. package/dist/acp-harnesses/launcher.js.map +1 -0
  71. package/dist/acp-harnesses/registry-fetch.d.ts +42 -0
  72. package/dist/acp-harnesses/registry-fetch.d.ts.map +1 -0
  73. package/dist/acp-harnesses/registry-fetch.js +132 -0
  74. package/dist/acp-harnesses/registry-fetch.js.map +1 -0
  75. package/dist/acp-harnesses/registry.d.ts +36 -0
  76. package/dist/acp-harnesses/registry.d.ts.map +1 -0
  77. package/dist/acp-harnesses/registry.js +307 -0
  78. package/dist/acp-harnesses/registry.js.map +1 -0
  79. package/dist/acp-runtime/errors.d.ts +7 -0
  80. package/dist/acp-runtime/errors.d.ts.map +1 -0
  81. package/dist/acp-runtime/errors.js +17 -0
  82. package/dist/acp-runtime/errors.js.map +1 -0
  83. package/dist/acp-runtime/fork-support.d.ts +8 -0
  84. package/dist/acp-runtime/fork-support.d.ts.map +1 -0
  85. package/dist/acp-runtime/fork-support.js +20 -0
  86. package/dist/acp-runtime/fork-support.js.map +1 -0
  87. package/dist/acp-runtime/index.d.ts +11 -0
  88. package/dist/acp-runtime/index.d.ts.map +1 -0
  89. package/dist/acp-runtime/index.js +6 -0
  90. package/dist/acp-runtime/index.js.map +1 -0
  91. package/dist/acp-runtime/probe.d.ts +103 -0
  92. package/dist/acp-runtime/probe.d.ts.map +1 -0
  93. package/dist/acp-runtime/probe.js +881 -0
  94. package/dist/acp-runtime/probe.js.map +1 -0
  95. package/dist/acp-runtime/runtime.d.ts +7 -0
  96. package/dist/acp-runtime/runtime.d.ts.map +1 -0
  97. package/dist/acp-runtime/runtime.js +26 -0
  98. package/dist/acp-runtime/runtime.js.map +1 -0
  99. package/dist/acp-runtime/session.d.ts +87 -0
  100. package/dist/acp-runtime/session.d.ts.map +1 -0
  101. package/dist/acp-runtime/session.js +1071 -0
  102. package/dist/acp-runtime/session.js.map +1 -0
  103. package/dist/acp-runtime/spawners/node.d.ts +5 -0
  104. package/dist/acp-runtime/spawners/node.d.ts.map +1 -0
  105. package/dist/acp-runtime/spawners/node.js +244 -0
  106. package/dist/acp-runtime/spawners/node.js.map +1 -0
  107. package/dist/acp-runtime/types.d.ts +180 -0
  108. package/dist/acp-runtime/types.d.ts.map +1 -0
  109. package/dist/acp-runtime/types.js +2 -0
  110. package/dist/acp-runtime/types.js.map +1 -0
  111. package/dist/agent-contract/acp.d.ts +4 -0
  112. package/dist/agent-contract/acp.d.ts.map +1 -0
  113. package/dist/agent-contract/acp.js +273 -0
  114. package/dist/agent-contract/acp.js.map +1 -0
  115. package/dist/agent-contract/index.d.ts +125 -0
  116. package/dist/agent-contract/index.d.ts.map +1 -0
  117. package/dist/agent-contract/index.js +102 -0
  118. package/dist/agent-contract/index.js.map +1 -0
  119. package/dist/agent-contract/managed.d.ts +5 -0
  120. package/dist/agent-contract/managed.d.ts.map +1 -0
  121. package/dist/agent-contract/managed.js +242 -0
  122. package/dist/agent-contract/managed.js.map +1 -0
  123. package/dist/agent-ui/index.d.ts +170 -0
  124. package/dist/agent-ui/index.d.ts.map +1 -0
  125. package/dist/agent-ui/index.js +853 -0
  126. package/dist/agent-ui/index.js.map +1 -0
  127. package/dist/agent-ui/presentation.d.ts +30 -0
  128. package/dist/agent-ui/presentation.d.ts.map +1 -0
  129. package/dist/agent-ui/presentation.js +79 -0
  130. package/dist/agent-ui/presentation.js.map +1 -0
  131. package/dist/agent-ui/react.d.ts +50 -0
  132. package/dist/agent-ui/react.d.ts.map +1 -0
  133. package/dist/agent-ui/react.js +334 -0
  134. package/dist/agent-ui/react.js.map +1 -0
  135. package/dist/brand/index.d.ts +17 -0
  136. package/dist/brand/index.d.ts.map +1 -0
  137. package/dist/brand/index.js +119 -0
  138. package/dist/brand/index.js.map +1 -0
  139. package/dist/brand/openma-logo-mark.svg +7 -0
  140. package/dist/brand/tokens.css +77 -0
  141. package/dist/brand/website.css +67 -0
  142. package/dist/chat-ui/acp.d.ts +26 -0
  143. package/dist/chat-ui/acp.d.ts.map +1 -0
  144. package/dist/chat-ui/acp.js +166 -0
  145. package/dist/chat-ui/acp.js.map +1 -0
  146. package/dist/chat-ui/components.d.ts +230 -0
  147. package/dist/chat-ui/components.d.ts.map +1 -0
  148. package/dist/chat-ui/components.js +561 -0
  149. package/dist/chat-ui/components.js.map +1 -0
  150. package/dist/chat-ui/composer-drafts.d.ts +21 -0
  151. package/dist/chat-ui/composer-drafts.d.ts.map +1 -0
  152. package/dist/chat-ui/composer-drafts.js +58 -0
  153. package/dist/chat-ui/composer-drafts.js.map +1 -0
  154. package/dist/chat-ui/controller.d.ts +61 -0
  155. package/dist/chat-ui/controller.d.ts.map +1 -0
  156. package/dist/chat-ui/controller.js +218 -0
  157. package/dist/chat-ui/controller.js.map +1 -0
  158. package/dist/chat-ui/index.d.ts +8 -0
  159. package/dist/chat-ui/index.d.ts.map +1 -0
  160. package/dist/chat-ui/index.js +8 -0
  161. package/dist/chat-ui/index.js.map +1 -0
  162. package/dist/chat-ui/markdown.d.ts +37 -0
  163. package/dist/chat-ui/markdown.d.ts.map +1 -0
  164. package/dist/chat-ui/markdown.js +33 -0
  165. package/dist/chat-ui/markdown.js.map +1 -0
  166. package/dist/chat-ui/presentation.d.ts +34 -0
  167. package/dist/chat-ui/presentation.d.ts.map +1 -0
  168. package/dist/chat-ui/presentation.js +191 -0
  169. package/dist/chat-ui/presentation.js.map +1 -0
  170. package/dist/chat-ui/styles.css +815 -0
  171. package/dist/chat-ui/utils.d.ts +14 -0
  172. package/dist/chat-ui/utils.d.ts.map +1 -0
  173. package/dist/chat-ui/utils.js +71 -0
  174. package/dist/chat-ui/utils.js.map +1 -0
  175. package/dist/local-runtime/checkpoint.d.ts +28 -0
  176. package/dist/local-runtime/checkpoint.d.ts.map +1 -0
  177. package/dist/local-runtime/checkpoint.js +2 -0
  178. package/dist/local-runtime/checkpoint.js.map +1 -0
  179. package/dist/local-runtime/daemon-connection.d.ts +27 -0
  180. package/dist/local-runtime/daemon-connection.d.ts.map +1 -0
  181. package/dist/local-runtime/daemon-connection.js +161 -0
  182. package/dist/local-runtime/daemon-connection.js.map +1 -0
  183. package/dist/local-runtime/daemon-host.d.ts +39 -0
  184. package/dist/local-runtime/daemon-host.d.ts.map +1 -0
  185. package/dist/local-runtime/daemon-host.js +88 -0
  186. package/dist/local-runtime/daemon-host.js.map +1 -0
  187. package/dist/local-runtime/index.d.ts +6 -0
  188. package/dist/local-runtime/index.d.ts.map +1 -0
  189. package/dist/local-runtime/index.js +5 -0
  190. package/dist/local-runtime/index.js.map +1 -0
  191. package/dist/local-runtime/runtime.d.ts +36 -0
  192. package/dist/local-runtime/runtime.d.ts.map +1 -0
  193. package/dist/local-runtime/runtime.js +82 -0
  194. package/dist/local-runtime/runtime.js.map +1 -0
  195. package/dist/local-runtime/session-host.d.ts +62 -0
  196. package/dist/local-runtime/session-host.d.ts.map +1 -0
  197. package/dist/local-runtime/session-host.js +477 -0
  198. package/dist/local-runtime/session-host.js.map +1 -0
  199. package/dist/managed-runtime/acp-subagents.d.ts +14 -0
  200. package/dist/managed-runtime/acp-subagents.d.ts.map +1 -0
  201. package/dist/managed-runtime/acp-subagents.js +67 -0
  202. package/dist/managed-runtime/acp-subagents.js.map +1 -0
  203. package/dist/managed-runtime/claimed-environment-work.d.ts +61 -0
  204. package/dist/managed-runtime/claimed-environment-work.d.ts.map +1 -0
  205. package/dist/managed-runtime/claimed-environment-work.js +170 -0
  206. package/dist/managed-runtime/claimed-environment-work.js.map +1 -0
  207. package/dist/managed-runtime/contracts.d.ts +31 -0
  208. package/dist/managed-runtime/contracts.d.ts.map +1 -0
  209. package/dist/managed-runtime/contracts.js +2 -0
  210. package/dist/managed-runtime/contracts.js.map +1 -0
  211. package/dist/managed-runtime/http-control.d.ts +67 -0
  212. package/dist/managed-runtime/http-control.d.ts.map +1 -0
  213. package/dist/managed-runtime/http-control.js +465 -0
  214. package/dist/managed-runtime/http-control.js.map +1 -0
  215. package/dist/managed-runtime/index.d.ts +89 -0
  216. package/dist/managed-runtime/index.d.ts.map +1 -0
  217. package/dist/managed-runtime/index.js +215 -0
  218. package/dist/managed-runtime/index.js.map +1 -0
  219. package/dist/managed-runtime/input-identity.d.ts +2 -0
  220. package/dist/managed-runtime/input-identity.d.ts.map +1 -0
  221. package/dist/managed-runtime/input-identity.js +2 -0
  222. package/dist/managed-runtime/input-identity.js.map +1 -0
  223. package/dist/managed-runtime/managed-event-projector.d.ts +24 -0
  224. package/dist/managed-runtime/managed-event-projector.d.ts.map +1 -0
  225. package/dist/managed-runtime/managed-event-projector.js +333 -0
  226. package/dist/managed-runtime/managed-event-projector.js.map +1 -0
  227. package/dist/managed-runtime/semantic-recovery.d.ts +61 -0
  228. package/dist/managed-runtime/semantic-recovery.d.ts.map +1 -0
  229. package/dist/managed-runtime/semantic-recovery.js +167 -0
  230. package/dist/managed-runtime/semantic-recovery.js.map +1 -0
  231. package/dist/project-ui/CreateProjectDialog.d.ts +15 -0
  232. package/dist/project-ui/CreateProjectDialog.d.ts.map +1 -0
  233. package/dist/project-ui/CreateProjectDialog.js +87 -0
  234. package/dist/project-ui/CreateProjectDialog.js.map +1 -0
  235. package/dist/project-ui/ProjectComposer.d.ts +13 -0
  236. package/dist/project-ui/ProjectComposer.d.ts.map +1 -0
  237. package/dist/project-ui/ProjectComposer.js +70 -0
  238. package/dist/project-ui/ProjectComposer.js.map +1 -0
  239. package/dist/project-ui/ProjectConversation.d.ts +10 -0
  240. package/dist/project-ui/ProjectConversation.d.ts.map +1 -0
  241. package/dist/project-ui/ProjectConversation.js +28 -0
  242. package/dist/project-ui/ProjectConversation.js.map +1 -0
  243. package/dist/project-ui/ProjectMessageAttachments.d.ts +4 -0
  244. package/dist/project-ui/ProjectMessageAttachments.d.ts.map +1 -0
  245. package/dist/project-ui/ProjectMessageAttachments.js +28 -0
  246. package/dist/project-ui/ProjectMessageAttachments.js.map +1 -0
  247. package/dist/project-ui/ProjectSettings.d.ts +8 -0
  248. package/dist/project-ui/ProjectSettings.d.ts.map +1 -0
  249. package/dist/project-ui/ProjectSettings.js +65 -0
  250. package/dist/project-ui/ProjectSettings.js.map +1 -0
  251. package/dist/project-ui/Projects.d.ts +18 -0
  252. package/dist/project-ui/Projects.d.ts.map +1 -0
  253. package/dist/project-ui/Projects.js +377 -0
  254. package/dist/project-ui/Projects.js.map +1 -0
  255. package/dist/project-ui/client.d.ts +234 -0
  256. package/dist/project-ui/client.d.ts.map +1 -0
  257. package/dist/project-ui/client.js +42 -0
  258. package/dist/project-ui/client.js.map +1 -0
  259. package/dist/project-ui/controls.d.ts +15 -0
  260. package/dist/project-ui/controls.d.ts.map +1 -0
  261. package/dist/project-ui/controls.js +17 -0
  262. package/dist/project-ui/controls.js.map +1 -0
  263. package/dist/project-ui/index.d.ts +20 -0
  264. package/dist/project-ui/index.d.ts.map +1 -0
  265. package/dist/project-ui/index.js +17 -0
  266. package/dist/project-ui/index.js.map +1 -0
  267. package/dist/project-ui/project-coordinator.d.ts +3 -0
  268. package/dist/project-ui/project-coordinator.d.ts.map +1 -0
  269. package/dist/project-ui/project-coordinator.js +12 -0
  270. package/dist/project-ui/project-coordinator.js.map +1 -0
  271. package/dist/project-ui/project-goals.d.ts +48 -0
  272. package/dist/project-ui/project-goals.d.ts.map +1 -0
  273. package/dist/project-ui/project-goals.js +169 -0
  274. package/dist/project-ui/project-goals.js.map +1 -0
  275. package/dist/project-ui/projects-query.d.ts +19 -0
  276. package/dist/project-ui/projects-query.d.ts.map +1 -0
  277. package/dist/project-ui/projects-query.js +132 -0
  278. package/dist/project-ui/projects-query.js.map +1 -0
  279. package/dist/project-ui/styles.css +847 -0
  280. package/dist/protocol/acp/index.d.ts +52 -0
  281. package/dist/protocol/acp/index.d.ts.map +1 -0
  282. package/dist/protocol/acp/index.js +1056 -0
  283. package/dist/protocol/acp/index.js.map +1 -0
  284. package/dist/protocol/cursor-cloud/index.d.ts +74 -0
  285. package/dist/protocol/cursor-cloud/index.d.ts.map +1 -0
  286. package/dist/protocol/cursor-cloud/index.js +249 -0
  287. package/dist/protocol/cursor-cloud/index.js.map +1 -0
  288. package/dist/protocol/managed/index.d.ts +32 -0
  289. package/dist/protocol/managed/index.d.ts.map +1 -0
  290. package/dist/protocol/managed/index.js +646 -0
  291. package/dist/protocol/managed/index.js.map +1 -0
  292. package/dist/protocol/managed/input-identity.d.ts +3 -0
  293. package/dist/protocol/managed/input-identity.d.ts.map +1 -0
  294. package/dist/protocol/managed/input-identity.js +6 -0
  295. package/dist/protocol/managed/input-identity.js.map +1 -0
  296. package/dist/protocol/openai-agents/index.d.ts +102 -0
  297. package/dist/protocol/openai-agents/index.d.ts.map +1 -0
  298. package/dist/protocol/openai-agents/index.js +142 -0
  299. package/dist/protocol/openai-agents/index.js.map +1 -0
  300. package/dist/session-events/acp-system-notices.d.ts +10 -0
  301. package/dist/session-events/acp-system-notices.d.ts.map +1 -0
  302. package/dist/session-events/acp-system-notices.js +46 -0
  303. package/dist/session-events/acp-system-notices.js.map +1 -0
  304. package/dist/session-events/acp.d.ts +214 -0
  305. package/dist/session-events/acp.d.ts.map +1 -0
  306. package/dist/session-events/acp.js +956 -0
  307. package/dist/session-events/acp.js.map +1 -0
  308. package/dist/session-events/managed.d.ts +141 -0
  309. package/dist/session-events/managed.d.ts.map +1 -0
  310. package/dist/session-events/managed.js +324 -0
  311. package/dist/session-events/managed.js.map +1 -0
  312. package/dist/session-events/openma.d.ts +304 -0
  313. package/dist/session-events/openma.d.ts.map +1 -0
  314. package/dist/session-events/openma.js +438 -0
  315. package/dist/session-events/openma.js.map +1 -0
  316. package/dist/session-kernel/index.d.ts +118 -0
  317. package/dist/session-kernel/index.d.ts.map +1 -0
  318. package/dist/session-kernel/index.js +215 -0
  319. package/dist/session-kernel/index.js.map +1 -0
  320. package/dist/session-orchestrator/index.d.ts +71 -0
  321. package/dist/session-orchestrator/index.d.ts.map +1 -0
  322. package/dist/session-orchestrator/index.js +177 -0
  323. package/dist/session-orchestrator/index.js.map +1 -0
  324. package/dist/session-ui/index.d.ts +96 -0
  325. package/dist/session-ui/index.d.ts.map +1 -0
  326. package/dist/session-ui/index.js +277 -0
  327. package/dist/session-ui/index.js.map +1 -0
  328. package/package.json +222 -4
@@ -0,0 +1,716 @@
1
+ import { execFile } from "node:child_process";
2
+ import { createHash } from "node:crypto";
3
+ import { access, chmod, mkdir, readdir, readFile, rm, rename, writeFile } from "node:fs/promises";
4
+ import { basename, dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
5
+ import { promisify } from "node:util";
6
+ import { acpHarnessPinnedPackages, exactDependencyPins, latestNpmPackageVersion, npmVersionFromSpec, pinnedAcpHarnessPaths, } from "./install-state.js";
7
+ import { commandInvocation, renderWindowsLauncher } from "./launcher.js";
8
+ const execFileAsync = promisify(execFile);
9
+ export const ACP_NPM_INSTALL_TIMEOUT_MS = 10 * 60_000;
10
+ const ACP_REGISTRY_URL = "https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json";
11
+ function currentPlatformKey() {
12
+ const os = process.platform === "darwin"
13
+ ? "darwin"
14
+ : process.platform === "linux"
15
+ ? "linux"
16
+ : process.platform === "win32"
17
+ ? "windows"
18
+ : process.platform;
19
+ const arch = process.arch === "arm64"
20
+ ? "aarch64"
21
+ : process.arch === "x64"
22
+ ? "x86_64"
23
+ : process.arch;
24
+ return `${os}-${arch}`;
25
+ }
26
+ function currentDistribution(agent) {
27
+ const target = agent.distribution?.binary?.[currentPlatformKey()];
28
+ if (target) {
29
+ return {
30
+ installable: true,
31
+ ...(target.args && target.args.length > 0 ? { args: target.args } : {}),
32
+ ...(target.env && Object.keys(target.env).length > 0 ? { env: target.env } : {}),
33
+ };
34
+ }
35
+ if (agent.distribution?.npx) {
36
+ return {
37
+ installable: true,
38
+ ...(agent.distribution.npx.args && agent.distribution.npx.args.length > 0 ? { args: agent.distribution.npx.args } : {}),
39
+ ...(agent.distribution.npx.env && Object.keys(agent.distribution.npx.env).length > 0 ? { env: agent.distribution.npx.env } : {}),
40
+ };
41
+ }
42
+ if (agent.distribution?.uvx) {
43
+ return {
44
+ installable: true,
45
+ ...(agent.distribution.uvx.args && agent.distribution.uvx.args.length > 0 ? { args: agent.distribution.uvx.args } : {}),
46
+ ...(agent.distribution.uvx.env && Object.keys(agent.distribution.uvx.env).length > 0 ? { env: agent.distribution.uvx.env } : {}),
47
+ };
48
+ }
49
+ return { installable: false };
50
+ }
51
+ function sanitizePathComponent(input) {
52
+ const sanitized = input.replace(/[^a-zA-Z0-9._-]/g, "-");
53
+ return sanitized.length > 0 ? sanitized : "unknown";
54
+ }
55
+ function shellQuote(value) {
56
+ return `'${value.replace(/'/g, "'\\''")}'`;
57
+ }
58
+ function shellEnvExports(env) {
59
+ return Object.entries(env).flatMap(([key, value]) => {
60
+ if (value === undefined)
61
+ return [];
62
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
63
+ throw new Error(`Registry env key is not shell-safe: ${key}`);
64
+ }
65
+ return [`export ${key}=${shellQuote(value)}`];
66
+ });
67
+ }
68
+ function renderShellShim(commandPath, args = [], env = {}) {
69
+ return [
70
+ "#!/bin/sh",
71
+ "set -eu",
72
+ ...shellEnvExports(env),
73
+ `exec ${shellQuote(commandPath)}${args.length > 0 ? ` ${args.map(shellQuote).join(" ")}` : ""} "$@"`,
74
+ "",
75
+ ].join("\n");
76
+ }
77
+ async function writeExecutableShim(shimPath, commandPath, args = [], env = {}, windowsLauncher = false) {
78
+ await mkdir(dirname(shimPath), { recursive: true });
79
+ const stagedPath = `${shimPath}.tmp-${process.pid}-${Date.now()}`;
80
+ const render = windowsLauncher ? renderWindowsLauncher : renderShellShim;
81
+ await writeFile(stagedPath, render(commandPath, args, env), "utf8");
82
+ await chmod(stagedPath, 0o755);
83
+ await rename(stagedPath, shimPath);
84
+ }
85
+ async function fetchBytes(url, fetchImpl) {
86
+ const response = await fetchImpl(url);
87
+ if (!response.ok)
88
+ throw new Error(`Install download failed: HTTP ${response.status}`);
89
+ return Buffer.from(await response.arrayBuffer());
90
+ }
91
+ async function fetchRegistry(fetchImpl) {
92
+ const response = await fetchImpl(ACP_REGISTRY_URL);
93
+ if (!response.ok)
94
+ throw new Error(`ACP registry unavailable: HTTP ${response.status}`);
95
+ return await response.json();
96
+ }
97
+ export async function listAcpRegistryCatalog(options = {}) {
98
+ const registry = await fetchRegistry(options.fetchImpl ?? fetch);
99
+ return (registry.agents ?? [])
100
+ .filter((agent) => typeof agent.id === "string" && agent.id.length > 0)
101
+ .map((agent) => {
102
+ const distribution = currentDistribution(agent);
103
+ return {
104
+ id: agent.id,
105
+ name: agent.name ?? agent.id,
106
+ ...(agent.version ? { version: agent.version } : {}),
107
+ ...(agent.description ? { description: agent.description } : {}),
108
+ ...(agent.website ?? agent.repository ? { homepage: agent.website ?? agent.repository } : {}),
109
+ installable: distribution.installable,
110
+ ...(distribution.args ? { args: distribution.args } : {}),
111
+ ...(distribution.env ? { env: distribution.env } : {}),
112
+ };
113
+ });
114
+ }
115
+ function assertSafeRelativeCommand(cmd) {
116
+ if (isAbsolute(cmd))
117
+ throw new Error(`Registry command must be relative: ${cmd}`);
118
+ const normalized = cmd.replace(/\\/g, "/");
119
+ if (normalized.split("/").includes(".."))
120
+ throw new Error(`Registry command cannot contain '..': ${cmd}`);
121
+ return normalized.startsWith("./") ? normalized.slice(2) : normalized;
122
+ }
123
+ function archiveKind(url) {
124
+ const path = (() => {
125
+ try {
126
+ return new URL(url).pathname.toLowerCase();
127
+ }
128
+ catch {
129
+ return url.toLowerCase();
130
+ }
131
+ })();
132
+ if (path.endsWith(".zip"))
133
+ return "zip";
134
+ if (path.endsWith(".tar.gz") || path.endsWith(".tgz"))
135
+ return "tar-gz";
136
+ if (path.endsWith(".tar.bz2") || path.endsWith(".tbz2"))
137
+ return "tar-bz2";
138
+ return "raw";
139
+ }
140
+ function rawBinaryFileName(url) {
141
+ const path = (() => {
142
+ try {
143
+ return new URL(url).pathname;
144
+ }
145
+ catch {
146
+ return url;
147
+ }
148
+ })();
149
+ const name = decodeURIComponent(path.split("/").filter(Boolean).at(-1) ?? "");
150
+ if (!name || name === "." || name === ".." || name.includes("/") || name.includes("\\")) {
151
+ throw new Error(`Cannot determine binary file name from ${url}`);
152
+ }
153
+ return name;
154
+ }
155
+ function versionedInstallDir(root, registryId, version, archiveUrl) {
156
+ const versionLabel = sanitizePathComponent(version);
157
+ const hash = createHash("sha256").update(`${version}\0${archiveUrl}`).digest("hex").slice(0, 16);
158
+ return join(root, "registry", sanitizePathComponent(registryId), `v_${versionLabel}_${hash}`);
159
+ }
160
+ function requireInstallVersion(version, context) {
161
+ const trimmed = version?.trim();
162
+ if (!trimmed) {
163
+ throw new Error(`${context}: install version is required and could not be resolved`);
164
+ }
165
+ return trimmed;
166
+ }
167
+ function registryInstallMetadataPath(root, registryId) {
168
+ return join(root, "registry", sanitizePathComponent(registryId), "install.json");
169
+ }
170
+ async function writeRegistryInstallMetadata(options, metadata) {
171
+ const installRoot = options.installRoot ?? options.binDir;
172
+ if (!installRoot)
173
+ throw new Error("Install metadata requires an install root");
174
+ const metadataPath = registryInstallMetadataPath(installRoot, options.registryId);
175
+ await mkdir(dirname(metadataPath), { recursive: true });
176
+ await writeFile(metadataPath, JSON.stringify(metadata, null, 2), "utf8");
177
+ }
178
+ export async function readAcpRegistryInstallMetadata(options) {
179
+ const installRoot = options.installRoot ?? options.binDir;
180
+ try {
181
+ const parsed = JSON.parse(await readFile(registryInstallMetadataPath(installRoot, options.registryId), "utf8"));
182
+ if (parsed.source !== "registry" || parsed.registryId !== options.registryId || typeof parsed.shimName !== "string") {
183
+ return null;
184
+ }
185
+ return {
186
+ source: "registry",
187
+ registryId: parsed.registryId,
188
+ shimName: parsed.shimName,
189
+ ...(typeof parsed.version === "string" && parsed.version.length > 0 ? { version: parsed.version } : {}),
190
+ ...(isStringRecord(parsed.dependencies) ? { dependencies: parsed.dependencies } : {}),
191
+ installedAt: typeof parsed.installedAt === "string" ? parsed.installedAt : "",
192
+ };
193
+ }
194
+ catch {
195
+ return null;
196
+ }
197
+ }
198
+ /**
199
+ * Rebuild a managed shim whose installed command moved together with the ACP
200
+ * install root. The command is derived from its registry-relative suffix, so
201
+ * no previous storage location is read or treated as a fallback.
202
+ */
203
+ export async function repairRelocatedAcpRegistryShim(options) {
204
+ const installRoot = resolve(options.installRoot ?? options.binDir);
205
+ const metadata = await readAcpRegistryInstallMetadata(options);
206
+ if (!metadata || metadata.shimName !== options.shimName)
207
+ return false;
208
+ const shimPath = join(options.binDir, options.shimName);
209
+ const shim = await readFile(shimPath, "utf8").catch(() => "");
210
+ const commandMatch = shim.match(/^exec '([^'\r\n]+)'/m);
211
+ const currentCommand = commandMatch?.[1];
212
+ if (!currentCommand)
213
+ return false;
214
+ if (await access(currentCommand).then(() => true, () => false))
215
+ return false;
216
+ const registrySuffix = join("registry", sanitizePathComponent(options.registryId));
217
+ const marker = `${registrySuffix}/`;
218
+ const normalizedCommand = currentCommand.replace(/\\/g, "/");
219
+ const markerIndex = normalizedCommand.lastIndexOf(`/${marker}`);
220
+ if (markerIndex < 0)
221
+ return false;
222
+ const relativeCommand = normalizedCommand.slice(markerIndex + 1);
223
+ const repairedCommand = resolve(installRoot, relativeCommand);
224
+ const relativeToRoot = relative(installRoot, repairedCommand);
225
+ if (relativeToRoot.startsWith("..")
226
+ || isAbsolute(relativeToRoot)
227
+ || !(await access(repairedCommand).then(() => true, () => false))) {
228
+ return false;
229
+ }
230
+ const repairedShim = shim.replace(shellQuote(currentCommand), shellQuote(repairedCommand));
231
+ if (repairedShim === shim)
232
+ return false;
233
+ const stagedPath = `${shimPath}.tmp-${process.pid}-${Date.now()}`;
234
+ await writeFile(stagedPath, repairedShim, "utf8");
235
+ await chmod(stagedPath, 0o755);
236
+ await rename(stagedPath, shimPath);
237
+ return true;
238
+ }
239
+ function verifySha256(bytes, expected) {
240
+ if (!expected)
241
+ return;
242
+ const normalized = expected.startsWith("sha256:") ? expected.slice("sha256:".length) : expected;
243
+ const actual = createHash("sha256").update(bytes).digest("hex");
244
+ if (actual.toLowerCase() !== normalized.toLowerCase()) {
245
+ throw new Error(`ACP registry archive checksum mismatch: expected ${normalized}, got ${actual}`);
246
+ }
247
+ }
248
+ async function installBinaryDistribution(agent, target, options) {
249
+ const fetchImpl = options.fetchImpl ?? fetch;
250
+ const installRoot = options.installRoot ?? options.binDir;
251
+ const binaryVersion = requireInstallVersion(agent.version, `${agent.name ?? agent.id} binary install`);
252
+ const finalDir = versionedInstallDir(installRoot, options.registryId, binaryVersion, target.archive);
253
+ const commandRelativePath = assertSafeRelativeCommand(target.cmd);
254
+ const commandPath = resolve(finalDir, commandRelativePath);
255
+ const relativeCommandPath = relative(resolve(finalDir), commandPath);
256
+ if (relativeCommandPath.startsWith("..") || isAbsolute(relativeCommandPath)) {
257
+ throw new Error(`Registry command escapes install directory: ${target.cmd}`);
258
+ }
259
+ try {
260
+ await chmod(commandPath, 0o755);
261
+ }
262
+ catch {
263
+ const tmpDir = `${finalDir}.tmp-${process.pid}-${Date.now()}`;
264
+ await rm(tmpDir, { recursive: true, force: true });
265
+ await mkdir(tmpDir, { recursive: true });
266
+ const bytes = await fetchBytes(target.archive, fetchImpl);
267
+ verifySha256(bytes, target.sha256);
268
+ const kind = archiveKind(target.archive);
269
+ const archivePath = join(tmpDir, `download${kind === "zip" ? ".zip" : kind === "tar-gz" ? ".tar.gz" : kind === "tar-bz2" ? ".tar.bz2" : extname(rawBinaryFileName(target.archive))}`);
270
+ if (kind === "raw") {
271
+ await writeFile(join(tmpDir, rawBinaryFileName(target.archive)), bytes);
272
+ }
273
+ else {
274
+ await writeFile(archivePath, bytes);
275
+ if (kind === "zip") {
276
+ await execFileAsync("unzip", ["-q", archivePath, "-d", tmpDir]);
277
+ }
278
+ else if (kind === "tar-gz") {
279
+ await execFileAsync("tar", ["-xzf", archivePath, "-C", tmpDir]);
280
+ }
281
+ else {
282
+ await execFileAsync("tar", ["-xjf", archivePath, "-C", tmpDir]);
283
+ }
284
+ await rm(archivePath, { force: true });
285
+ }
286
+ await rm(finalDir, { recursive: true, force: true });
287
+ await mkdir(dirname(finalDir), { recursive: true });
288
+ await rename(tmpDir, finalDir);
289
+ await chmod(commandPath, 0o755);
290
+ }
291
+ const shimPath = join(options.binDir, options.shimName);
292
+ await writeExecutableShim(shimPath, commandPath, options.shimArgs ?? target.args ?? [], {
293
+ ...(target.env ?? {}),
294
+ ...(options.shimEnv ?? {}),
295
+ });
296
+ return { commandPath: shimPath, version: binaryVersion };
297
+ }
298
+ function packageNameFromSpec(packageSpec) {
299
+ if (packageSpec.startsWith("@")) {
300
+ const versionIndex = packageSpec.indexOf("@", 1);
301
+ return versionIndex > 0 ? packageSpec.slice(0, versionIndex) : packageSpec;
302
+ }
303
+ const versionIndex = packageSpec.lastIndexOf("@");
304
+ return versionIndex > 0 ? packageSpec.slice(0, versionIndex) : packageSpec;
305
+ }
306
+ function packagePathParts(packageName) {
307
+ return packageName.split("/").filter(Boolean);
308
+ }
309
+ function isNpmTargetMissing(error) {
310
+ const stderr = typeof error === "object" && error !== null && "stderr" in error
311
+ ? String(error.stderr ?? "")
312
+ : "";
313
+ const message = error instanceof Error ? error.message : String(error);
314
+ return /\bETARGET\b|No matching version found/i.test(`${message}\n${stderr}`);
315
+ }
316
+ async function resolvePackageVersion(prefixDir, packageSpec) {
317
+ const packageName = packageNameFromSpec(packageSpec);
318
+ const packageJsonPath = join(prefixDir, "node_modules", ...packagePathParts(packageName), "package.json");
319
+ const pkg = JSON.parse(await readFile(packageJsonPath, "utf8"));
320
+ if (typeof pkg.version === "string" && pkg.version.length > 0) {
321
+ return pkg.version;
322
+ }
323
+ throw new Error(`${packageSpec} is installed but package.json is missing a version`);
324
+ }
325
+ async function resolvePackageBin(prefixDir, packageSpec, windows) {
326
+ const packageName = packageNameFromSpec(packageSpec);
327
+ const packageJsonPath = join(prefixDir, "node_modules", ...packagePathParts(packageName), "package.json");
328
+ const pkg = JSON.parse(await readFile(packageJsonPath, "utf8"));
329
+ const unscopedName = basename(packageName);
330
+ const binName = typeof pkg.bin === "string"
331
+ ? unscopedName
332
+ : pkg.bin?.[unscopedName]
333
+ ? unscopedName
334
+ : Object.keys(pkg.bin ?? {})[0];
335
+ if (!binName)
336
+ throw new Error(`${packageSpec} does not expose an executable bin`);
337
+ return join(prefixDir, "node_modules", ".bin", windows ? `${binName}.cmd` : binName);
338
+ }
339
+ async function resolveNpmInstallVersion(packageSpec, options) {
340
+ if (options.explicitVersion?.trim())
341
+ return options.explicitVersion.trim();
342
+ const fromSpec = npmVersionFromSpec(packageSpec);
343
+ if (fromSpec)
344
+ return fromSpec;
345
+ const latest = await latestNpmPackageVersion(packageNameFromSpec(packageSpec), {
346
+ npmRegistryUrls: options.npmRegistryUrls,
347
+ fetchImpl: options.fetchImpl,
348
+ });
349
+ return requireInstallVersion(latest, `Could not resolve npm version for ${packageNameFromSpec(packageSpec)}`);
350
+ }
351
+ function isStringRecord(value) {
352
+ return value !== null
353
+ && typeof value === "object"
354
+ && !Array.isArray(value)
355
+ && Object.values(value).every((item) => typeof item === "string");
356
+ }
357
+ const WINDOWS = process.platform === "win32";
358
+ function runCommand(invocation, options) {
359
+ return execFileAsync(invocation.file, invocation.args, {
360
+ ...options,
361
+ windowsVerbatimArguments: invocation.windowsVerbatimArguments,
362
+ });
363
+ }
364
+ /**
365
+ * How a host starts a launcher this installer wrote. A POSIX launcher starts
366
+ * directly; a Windows `.cmd` launcher has to go through `cmd.exe`.
367
+ */
368
+ export function acpLauncherInvocation(commandPath, args = [], options = {}) {
369
+ return commandInvocation((options.platform ?? process.platform) === "win32", commandPath, args, options.comSpec);
370
+ }
371
+ /** npm reads `overrides` only from the package.json at the install prefix. */
372
+ async function writeOverridesManifest(prefixDir, overrides) {
373
+ if (overrides.length === 0)
374
+ return;
375
+ await mkdir(prefixDir, { recursive: true });
376
+ await writeFile(join(prefixDir, "package.json"), JSON.stringify({ private: true, overrides: Object.fromEntries(overrides) }, null, 2), "utf8");
377
+ }
378
+ async function installedOverrideVersions(prefixDir, overrides) {
379
+ const installed = {};
380
+ for (const [name, pinned] of overrides) {
381
+ const actual = await resolvePackageVersion(prefixDir, name).catch(() => undefined);
382
+ if (actual !== pinned) {
383
+ throw new Error(`${name} is pinned to ${pinned} but ${actual ?? "nothing"} is installed in ${prefixDir}`);
384
+ }
385
+ installed[name] = actual;
386
+ }
387
+ return installed;
388
+ }
389
+ async function installNpxDistribution(npx, options) {
390
+ const installRoot = options.installRoot ?? options.binDir;
391
+ const overrides = exactDependencyPins(options.npmOverrides);
392
+ const { windows } = options;
393
+ const resolvedVersion = await resolveNpmInstallVersion(npx.package, {
394
+ explicitVersion: options.version,
395
+ npmRegistryUrls: options.npmRegistryUrls,
396
+ fetchImpl: options.fetchImpl,
397
+ });
398
+ const prefixDir = versionedInstallDir(installRoot, options.registryId, resolvedVersion,
399
+ // A pinned tree and a floating tree of the same package never share a directory.
400
+ overrides.length > 0
401
+ ? `npx:${npx.package}\0overrides:${JSON.stringify(overrides)}`
402
+ : `npx:${npx.package}`);
403
+ let packageBin;
404
+ try {
405
+ packageBin = await resolvePackageBin(prefixDir, npx.package, windows);
406
+ await access(packageBin);
407
+ }
408
+ catch {
409
+ const stagedDir = `${prefixDir}.tmp-${process.pid}-${Date.now()}`;
410
+ await rm(stagedDir, { recursive: true, force: true });
411
+ try {
412
+ const npmOptions = {
413
+ env: {
414
+ ...process.env,
415
+ ...(options.env ?? {}),
416
+ ...(options.npmEnv ?? {}),
417
+ },
418
+ timeout: ACP_NPM_INSTALL_TIMEOUT_MS,
419
+ maxBuffer: 1024 * 1024,
420
+ };
421
+ const runNpm = (args) => runCommand(commandInvocation(windows, options.npmCommand ?? "npm", args, npmOptions.env.ComSpec), npmOptions);
422
+ const installArgs = [
423
+ "install",
424
+ "--prefix",
425
+ stagedDir,
426
+ "--omit=dev",
427
+ "--no-audit",
428
+ "--no-fund",
429
+ ];
430
+ const registryUrls = options.npmRegistryUrls?.length
431
+ ? options.npmRegistryUrls
432
+ : [undefined];
433
+ let installed = false;
434
+ let lastError;
435
+ for (const registryUrl of registryUrls) {
436
+ const registryArgs = registryUrl ? ["--registry", registryUrl] : [];
437
+ try {
438
+ await writeOverridesManifest(stagedDir, overrides);
439
+ await runNpm([
440
+ ...(options.npmCommandArgs ?? []),
441
+ ...installArgs,
442
+ ...registryArgs,
443
+ "--prefer-offline",
444
+ npx.package,
445
+ ]);
446
+ installed = true;
447
+ break;
448
+ }
449
+ catch (error) {
450
+ lastError = error;
451
+ if (isNpmTargetMissing(error)) {
452
+ await rm(stagedDir, { recursive: true, force: true });
453
+ try {
454
+ await writeOverridesManifest(stagedDir, overrides);
455
+ await runNpm([
456
+ ...(options.npmCommandArgs ?? []),
457
+ ...installArgs,
458
+ ...registryArgs,
459
+ "--prefer-online",
460
+ npx.package,
461
+ ]);
462
+ installed = true;
463
+ break;
464
+ }
465
+ catch (onlineError) {
466
+ lastError = onlineError;
467
+ }
468
+ }
469
+ await rm(stagedDir, { recursive: true, force: true });
470
+ }
471
+ }
472
+ if (!installed)
473
+ throw lastError;
474
+ const stagedBin = await resolvePackageBin(stagedDir, npx.package, windows);
475
+ await access(stagedBin);
476
+ await rm(prefixDir, { recursive: true, force: true });
477
+ await mkdir(dirname(prefixDir), { recursive: true });
478
+ await rename(stagedDir, prefixDir);
479
+ }
480
+ catch (error) {
481
+ await rm(stagedDir, { recursive: true, force: true });
482
+ throw error;
483
+ }
484
+ packageBin = await resolvePackageBin(prefixDir, npx.package, windows);
485
+ }
486
+ const installedVersion = await resolvePackageVersion(prefixDir, npx.package);
487
+ const dependencies = await installedOverrideVersions(prefixDir, overrides);
488
+ const shimPath = join(options.binDir, options.shimName);
489
+ await writeExecutableShim(shimPath, packageBin, options.shimArgs ?? npx.args ?? [], { ...(npx.env ?? {}), ...(options.shimEnv ?? {}) }, options.windowsLauncher);
490
+ return {
491
+ commandPath: shimPath,
492
+ version: installedVersion,
493
+ ...(overrides.length > 0 ? { dependencies } : {}),
494
+ };
495
+ }
496
+ function pythonVersionFromSpec(packageSpec) {
497
+ const name = pythonPackageNameFromSpec(packageSpec);
498
+ const remainder = packageSpec.slice(name.length).trim();
499
+ if (!remainder.startsWith("@"))
500
+ return undefined;
501
+ const version = remainder.slice(1).trim();
502
+ return version.length > 0 ? version : undefined;
503
+ }
504
+ async function readInstalledUvxVersion(toolDir, packageName) {
505
+ const normalizedName = packageName.replace(/-/g, "_").toLowerCase();
506
+ let entries;
507
+ try {
508
+ entries = await readdir(toolDir, { recursive: true });
509
+ }
510
+ catch {
511
+ return undefined;
512
+ }
513
+ for (const entry of entries) {
514
+ if (!entry.endsWith(".dist-info/METADATA") && !entry.endsWith(".dist-info\\METADATA"))
515
+ continue;
516
+ if (!entry.toLowerCase().includes(normalizedName))
517
+ continue;
518
+ try {
519
+ const metadata = await readFile(join(toolDir, entry), "utf8");
520
+ const versionLine = metadata
521
+ .split("\n")
522
+ .find((line) => line.startsWith("Version:"));
523
+ const version = versionLine?.slice("Version:".length).trim();
524
+ if (version)
525
+ return version;
526
+ }
527
+ catch {
528
+ // Keep scanning other dist-info directories.
529
+ }
530
+ }
531
+ return undefined;
532
+ }
533
+ async function installUvxDistribution(uvx, options) {
534
+ const installRoot = options.installRoot ?? options.binDir;
535
+ const packageName = pythonPackageNameFromSpec(uvx.package);
536
+ const resolvedVersion = requireInstallVersion(options.version ?? pythonVersionFromSpec(uvx.package), `${packageName} uvx install`);
537
+ const prefixDir = versionedInstallDir(installRoot, options.registryId, resolvedVersion, `uvx:${uvx.package}`);
538
+ const toolDir = join(prefixDir, "tools");
539
+ const toolBinDir = join(prefixDir, "bin");
540
+ await mkdir(toolBinDir, { recursive: true });
541
+ await execFileAsync("uv", ["tool", "install", "--force", uvx.package], {
542
+ env: {
543
+ ...process.env,
544
+ ...(options.env ?? {}),
545
+ UV_TOOL_DIR: toolDir,
546
+ UV_TOOL_BIN_DIR: toolBinDir,
547
+ },
548
+ timeout: 120_000,
549
+ maxBuffer: 1024 * 1024,
550
+ });
551
+ const packageBin = await firstExecutableInDir(toolBinDir, packageName);
552
+ const installedVersion = await readInstalledUvxVersion(toolDir, packageName) ?? resolvedVersion;
553
+ const shimPath = join(options.binDir, options.shimName);
554
+ await writeExecutableShim(shimPath, packageBin, options.shimArgs ?? uvx.args ?? [], {
555
+ ...(uvx.env ?? {}),
556
+ ...(options.shimEnv ?? {}),
557
+ });
558
+ return { commandPath: shimPath, version: installedVersion };
559
+ }
560
+ function pythonPackageNameFromSpec(packageSpec) {
561
+ return (packageSpec
562
+ .split(/[<>=!~\[]/, 1)[0]
563
+ ?? packageSpec)
564
+ .trim()
565
+ .replace(/_/g, "-");
566
+ }
567
+ async function firstExecutableInDir(binDir, preferredName) {
568
+ const entries = await readdir(binDir).catch(() => []);
569
+ const preferred = [
570
+ preferredName,
571
+ preferredName.replace(/-/g, "_"),
572
+ basename(preferredName),
573
+ ];
574
+ for (const name of [...preferred, ...entries]) {
575
+ if (!entries.includes(name))
576
+ continue;
577
+ const candidate = join(binDir, name);
578
+ try {
579
+ await access(candidate);
580
+ return candidate;
581
+ }
582
+ catch {
583
+ // Keep looking; uv may create several helper files depending on platform.
584
+ }
585
+ }
586
+ throw new Error(`uv did not expose an executable for ${preferredName}`);
587
+ }
588
+ export async function installAcpRegistryAgent(options) {
589
+ const fetchImpl = options.fetchImpl ?? fetch;
590
+ const registry = options.registryAgent ? null : await fetchRegistry(fetchImpl);
591
+ const agent = options.registryAgent ?? registry?.agents?.find((candidate) => candidate.id === options.registryId);
592
+ if (!agent)
593
+ throw new Error(`ACP registry agent not found: ${options.registryId}`);
594
+ if (agent.id !== options.registryId) {
595
+ throw new Error(`ACP registry snapshot mismatch: expected ${options.registryId}, got ${agent.id}`);
596
+ }
597
+ const platformKey = currentPlatformKey();
598
+ const target = agent.distribution?.binary?.[platformKey];
599
+ const overrideCount = Object.keys(options.npmOverrides ?? {}).length;
600
+ if (overrideCount > 0 && (target || !agent.distribution?.npx)) {
601
+ // Overrides are an npm feature. Dropping them would install an unpinned agent.
602
+ throw new Error(`${agent.name ?? agent.id} does not install from npm on ${platformKey}, so npmOverrides cannot be applied`);
603
+ }
604
+ let result;
605
+ if (target) {
606
+ result = await installBinaryDistribution(agent, target, {
607
+ registryId: options.registryId,
608
+ shimName: options.shimName,
609
+ binDir: options.binDir,
610
+ installRoot: options.installRoot,
611
+ fetchImpl,
612
+ shimArgs: options.shimArgs,
613
+ shimEnv: options.shimEnv,
614
+ });
615
+ }
616
+ else if (agent.distribution?.npx) {
617
+ result = await installNpxDistribution(agent.distribution.npx, {
618
+ registryId: options.registryId,
619
+ shimName: options.shimName,
620
+ binDir: options.binDir,
621
+ installRoot: options.installRoot,
622
+ npmCommand: options.npmCommand,
623
+ npmCommandArgs: options.npmCommandArgs,
624
+ npmEnv: options.npmEnv,
625
+ npmRegistryUrls: options.npmRegistryUrls,
626
+ fetchImpl,
627
+ env: options.env,
628
+ shimArgs: options.shimArgs,
629
+ shimEnv: options.shimEnv,
630
+ npmOverrides: options.npmOverrides,
631
+ version: agent.version,
632
+ windows: WINDOWS,
633
+ });
634
+ }
635
+ else if (agent.distribution?.uvx) {
636
+ result = await installUvxDistribution(agent.distribution.uvx, {
637
+ registryId: options.registryId,
638
+ shimName: options.shimName,
639
+ binDir: options.binDir,
640
+ installRoot: options.installRoot,
641
+ env: options.env,
642
+ shimArgs: options.shimArgs,
643
+ shimEnv: options.shimEnv,
644
+ version: agent.version,
645
+ });
646
+ }
647
+ else {
648
+ throw new Error(`${agent.name ?? agent.id} has no registry install for ${platformKey}`);
649
+ }
650
+ const installedVersion = result.version ?? agent.version;
651
+ await writeRegistryInstallMetadata(options, {
652
+ source: "registry",
653
+ registryId: options.registryId,
654
+ shimName: options.shimName,
655
+ ...(installedVersion ? { version: installedVersion } : {}),
656
+ ...(result.dependencies ? { dependencies: result.dependencies } : {}),
657
+ installedAt: new Date().toISOString(),
658
+ });
659
+ return result;
660
+ }
661
+ /**
662
+ * Installs a harness at the exact versions its registry entry pins
663
+ * (`KnownAgentEntry.pinned`), for hosts that need the same agent on every
664
+ * machine. The launcher and the install state use the names from
665
+ * `pinnedAcpHarnessPaths`, never the product install's, so both can live in
666
+ * one bin directory. On Windows the launcher is a `.cmd` file; start it with
667
+ * `acpLauncherInvocation`.
668
+ */
669
+ export async function installPinnedAcpHarness(options) {
670
+ const { entry, platform, ...install } = options;
671
+ const pins = acpHarnessPinnedPackages(entry);
672
+ const windows = (platform ?? process.platform) === "win32";
673
+ const paths = pinnedAcpHarnessPaths(entry, install.binDir, { platform });
674
+ const result = await installNpxDistribution({ package: `${pins.package.name}@${pins.package.version}` }, {
675
+ ...install,
676
+ registryId: paths.stateId,
677
+ shimName: paths.launcherName,
678
+ shimArgs: entry.spec.args,
679
+ shimEnv: entry.spec.env,
680
+ npmOverrides: Object.fromEntries(pins.dependencies),
681
+ version: pins.package.version,
682
+ windows,
683
+ windowsLauncher: windows,
684
+ });
685
+ await writeRegistryInstallMetadata({ registryId: paths.stateId, shimName: paths.launcherName, binDir: install.binDir, installRoot: install.installRoot }, {
686
+ source: "registry",
687
+ registryId: paths.stateId,
688
+ shimName: paths.launcherName,
689
+ version: result.version,
690
+ dependencies: result.dependencies,
691
+ installedAt: new Date().toISOString(),
692
+ });
693
+ return result;
694
+ }
695
+ export { readAcpHarnessInstallState, readAcpHarnessPinState, pinnedAcpHarnessPaths, acpHarnessPinnedPackages, compareCodePoints, OPENMA_NPM_HARNESS_IDS, usesOpenMaNpmLatestSource, latestNpmPackageVersion, npmPackageNameFromSpec, npmVersionFromSpec, readInstalledNpmPackageVersion, installedNpmPackageVersionFromShim, isStrictlyNewerVersion, } from "./install-state.js";
696
+ export async function installManagedAdapter(options) {
697
+ const fetchImpl = options.fetchImpl ?? fetch;
698
+ const bytes = await fetchBytes(options.downloadUrl, fetchImpl);
699
+ await mkdir(options.binDir, { recursive: true });
700
+ const commandPath = join(options.binDir, basename(options.command));
701
+ await writeFile(commandPath, bytes);
702
+ await chmod(commandPath, 0o755);
703
+ return { commandPath };
704
+ }
705
+ export async function uninstallAcpRegistryAgent(options) {
706
+ const installRoot = options.installRoot ?? options.binDir;
707
+ await rm(join(options.binDir, options.shimName), { force: true });
708
+ await rm(join(installRoot, "registry", sanitizePathComponent(options.registryId)), {
709
+ recursive: true,
710
+ force: true,
711
+ });
712
+ }
713
+ export async function uninstallManagedAdapter(options) {
714
+ await rm(join(options.binDir, basename(options.command)), { force: true });
715
+ }
716
+ //# sourceMappingURL=installer.js.map