@xyagent/cli 0.0.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 (385) hide show
  1. package/README.md +860 -0
  2. package/bin/agentlink +8585 -0
  3. package/bin/agentlink-agent +7 -0
  4. package/bin/agentlink-mcp-stdio +173 -0
  5. package/docs/LOGGING.md +159 -0
  6. package/package.json +38 -0
  7. package/src/core.mjs +320 -0
  8. package/src/tunnel.mjs +291 -0
  9. package/src/tunnel_proxy.mjs +913 -0
  10. package/src/tunnel_service.mjs +699 -0
  11. package/src/tunnel_state.mjs +301 -0
  12. package/src/unified_producer.mjs +259 -0
  13. package/src-ext/README.md +75 -0
  14. package/src-ext/bin.mjs +128 -0
  15. package/src-ext/commands/agent.mjs +66 -0
  16. package/src-ext/commands/help.mjs +31 -0
  17. package/src-ext/commands/pair.mjs +455 -0
  18. package/src-ext/commands/reload.mjs +78 -0
  19. package/src-ext/commands/service.mjs +64 -0
  20. package/src-ext/core/accountResolver.mjs +137 -0
  21. package/src-ext/core/activeRuns.mjs +76 -0
  22. package/src-ext/core/agentlinkToolsBootstrap.mjs +75 -0
  23. package/src-ext/core/agentlinkToolsRegistry.mjs +323 -0
  24. package/src-ext/core/agentlinkToolsServer.mjs +109 -0
  25. package/src-ext/core/approvalGateway.mjs +132 -0
  26. package/src-ext/core/attachAuditLog.mjs +79 -0
  27. package/src-ext/core/attachDenylist.mjs +128 -0
  28. package/src-ext/core/autoTunnelDetector.mjs +98 -0
  29. package/src-ext/core/autoTunnelGateway.mjs +393 -0
  30. package/src-ext/core/autoTunnelWiring.mjs +184 -0
  31. package/src-ext/core/boundedMap.mjs +98 -0
  32. package/src-ext/core/bridgeAttachAutoScanner.mjs +237 -0
  33. package/src-ext/core/bridgeHooks.mjs +168 -0
  34. package/src-ext/core/bridgeSelfUninstall.mjs +133 -0
  35. package/src-ext/core/claudeTrust.mjs +74 -0
  36. package/src-ext/core/codexTrust.mjs +77 -0
  37. package/src-ext/core/cosUploadClient.mjs +326 -0
  38. package/src-ext/core/createWorkspace.mjs +170 -0
  39. package/src-ext/core/daemonRestart.mjs +49 -0
  40. package/src-ext/core/defaultWorkspace.mjs +65 -0
  41. package/src-ext/core/ensureGitRepo.mjs +57 -0
  42. package/src-ext/core/hermesProfile.mjs +75 -0
  43. package/src-ext/core/interruptGateway.mjs +119 -0
  44. package/src-ext/core/interruptRunListener.mjs +106 -0
  45. package/src-ext/core/mcpRuntimeFanout.mjs +236 -0
  46. package/src-ext/core/mcpStdioClient.mjs +316 -0
  47. package/src-ext/core/openclawGatewayClient.mjs +230 -0
  48. package/src-ext/core/pairCodeClient.mjs +331 -0
  49. package/src-ext/core/pairInventory.mjs +59 -0
  50. package/src-ext/core/pathExpand.mjs +34 -0
  51. package/src-ext/core/preprocessAttachments.mjs +113 -0
  52. package/src-ext/core/relayWorker.mjs +284 -0
  53. package/src-ext/core/relayWorkerHttp.mjs +58 -0
  54. package/src-ext/core/scanWorkspaces.mjs +842 -0
  55. package/src-ext/core/sessionSlot.mjs +70 -0
  56. package/src-ext/core/stateMachine.mjs +85 -0
  57. package/src-ext/core/toolsServerLifecycle.mjs +169 -0
  58. package/src-ext/core/unifiedDispatchHandler.mjs +439 -0
  59. package/src-ext/core/usageReporter.mjs +207 -0
  60. package/src-ext/openclaw-plugin/envelope-builder.cjs +619 -0
  61. package/src-ext/openclaw-plugin/index.cjs +1919 -0
  62. package/src-ext/openclaw-plugin/openclaw.plugin.json +20 -0
  63. package/src-ext/openclaw-plugin/package.json +12 -0
  64. package/src-ext/openclaw-plugin/relay-defaults.json +3 -0
  65. package/src-ext/openclaw-plugin/todoTranslatorUtils.cjs +101 -0
  66. package/src-ext/runtime/_shared/cliExec.mjs +138 -0
  67. package/src-ext/runtime/_shared/cosTextRefs.mjs +120 -0
  68. package/src-ext/runtime/_shared/fetchAndBase64Encode.mjs +52 -0
  69. package/src-ext/runtime/_shared/relayObjectToBlock.mjs +307 -0
  70. package/src-ext/runtime/_shared/sessionPicker.mjs +418 -0
  71. package/src-ext/runtime/_shared/slashCommandRouter.mjs +1346 -0
  72. package/src-ext/runtime/_shared/todoTranslatorUtils.mjs +94 -0
  73. package/src-ext/runtime/claude/askUserQuestionTranslator.mjs +241 -0
  74. package/src-ext/runtime/claude/customCommandsCollector.mjs +132 -0
  75. package/src-ext/runtime/claude/handleRequest.mjs +1418 -0
  76. package/src-ext/runtime/claude/index.mjs +160 -0
  77. package/src-ext/runtime/claude/internalCommandNames.mjs +58 -0
  78. package/src-ext/runtime/claude/launcher.mjs +313 -0
  79. package/src-ext/runtime/claude/mcpConfigAdapter.mjs +174 -0
  80. package/src-ext/runtime/claude/mcpConfigWriter.mjs +57 -0
  81. package/src-ext/runtime/claude/modelContextWindow.mjs +30 -0
  82. package/src-ext/runtime/claude/modelScanner.mjs +257 -0
  83. package/src-ext/runtime/claude/permissionInterruptBlock.mjs +86 -0
  84. package/src-ext/runtime/claude/permissionPromptServer.mjs +170 -0
  85. package/src-ext/runtime/claude/permissionPromptServerWorker.mjs +214 -0
  86. package/src-ext/runtime/claude/preflight.mjs +62 -0
  87. package/src-ext/runtime/claude/stdoutParser.mjs +365 -0
  88. package/src-ext/runtime/claude/todoTranslator.mjs +66 -0
  89. package/src-ext/runtime/claude/usageProbe.mjs +576 -0
  90. package/src-ext/runtime/claude/usageProbeStrip.mjs +14 -0
  91. package/src-ext/runtime/codex/codexCustomCommandsCollector.mjs +87 -0
  92. package/src-ext/runtime/codex/elicitationHandler.mjs +91 -0
  93. package/src-ext/runtime/codex/eventMapper.mjs +154 -0
  94. package/src-ext/runtime/codex/handleRequest.mjs +1152 -0
  95. package/src-ext/runtime/codex/index.mjs +142 -0
  96. package/src-ext/runtime/codex/mcpConfigAdapter.mjs +155 -0
  97. package/src-ext/runtime/codex/modelScanner.mjs +305 -0
  98. package/src-ext/runtime/codex/planNotificationHandler.mjs +61 -0
  99. package/src-ext/runtime/codex/preflight.mjs +67 -0
  100. package/src-ext/runtime/hermes/commandBackend.mjs +117 -0
  101. package/src-ext/runtime/hermes/envSetup.mjs +229 -0
  102. package/src-ext/runtime/hermes/gatewayManager.mjs +625 -0
  103. package/src-ext/runtime/hermes/handleRequest.mjs +1257 -0
  104. package/src-ext/runtime/hermes/httpBackend.mjs +219 -0
  105. package/src-ext/runtime/hermes/index.mjs +196 -0
  106. package/src-ext/runtime/hermes/mcpConfigAdapter.mjs +189 -0
  107. package/src-ext/runtime/hermes/preflight.mjs +359 -0
  108. package/src-ext/runtime/hermes/responsesBackend.mjs +276 -0
  109. package/src-ext/runtime/hermes/sessionStore.mjs +78 -0
  110. package/src-ext/runtime/hermes/todoTranslator.mjs +90 -0
  111. package/src-ext/runtime/hermes/workspaceRpc.mjs +124 -0
  112. package/src-ext/runtime/openclaw/buildOpenclawDaemonInput.mjs +143 -0
  113. package/src-ext/runtime/openclaw/mcpConfigAdapter.mjs +91 -0
  114. package/src-ext/runtime/openclaw/openclawConfig.mjs +145 -0
  115. package/src-ext/runtime/picoclaw/constants.mjs +39 -0
  116. package/src-ext/runtime/picoclaw/handleRequest.mjs +289 -0
  117. package/src-ext/runtime/picoclaw/index.mjs +314 -0
  118. package/src-ext/runtime/picoclaw/pairFlow.mjs +224 -0
  119. package/src-ext/runtime/picoclaw/state.mjs +78 -0
  120. package/src-ext/runtime/picoclaw/todoTranslator.mjs +67 -0
  121. package/src-ext/runtime/picoclaw/translator.mjs +272 -0
  122. package/src-ext/runtime/picoclaw/wsClient.mjs +129 -0
  123. package/src-ext/service/serviceManager.mjs +521 -0
  124. package/src-shared/README.md +44 -0
  125. package/src-shared/chat_push_normalizer.mjs +113 -0
  126. package/src-shared/correlation.mjs +25 -0
  127. package/src-shared/envelope_builder.mjs +612 -0
  128. package/src-shared/logger.mjs +167 -0
  129. package/src-shared/relay-defaults.json +3 -0
  130. package/src-shared/relay_revoke.mjs +46 -0
  131. package/src-shared/vendor/README.md +60 -0
  132. package/src-shared/vendor/smol-toml/LICENSE +24 -0
  133. package/src-shared/vendor/smol-toml/README.md +236 -0
  134. package/src-shared/vendor/smol-toml/VENDORED.md +37 -0
  135. package/src-shared/vendor/smol-toml/dist/date.d.ts +41 -0
  136. package/src-shared/vendor/smol-toml/dist/date.js +127 -0
  137. package/src-shared/vendor/smol-toml/dist/error.d.ts +38 -0
  138. package/src-shared/vendor/smol-toml/dist/error.js +63 -0
  139. package/src-shared/vendor/smol-toml/dist/extract.d.ts +30 -0
  140. package/src-shared/vendor/smol-toml/dist/extract.js +109 -0
  141. package/src-shared/vendor/smol-toml/dist/index.cjs +900 -0
  142. package/src-shared/vendor/smol-toml/dist/index.d.ts +43 -0
  143. package/src-shared/vendor/smol-toml/dist/index.js +33 -0
  144. package/src-shared/vendor/smol-toml/dist/parse.d.ts +37 -0
  145. package/src-shared/vendor/smol-toml/dist/parse.js +148 -0
  146. package/src-shared/vendor/smol-toml/dist/primitive.d.ts +31 -0
  147. package/src-shared/vendor/smol-toml/dist/primitive.js +178 -0
  148. package/src-shared/vendor/smol-toml/dist/stringify.d.ts +31 -0
  149. package/src-shared/vendor/smol-toml/dist/stringify.js +163 -0
  150. package/src-shared/vendor/smol-toml/dist/struct.d.ts +32 -0
  151. package/src-shared/vendor/smol-toml/dist/struct.js +194 -0
  152. package/src-shared/vendor/smol-toml/dist/util.d.ts +42 -0
  153. package/src-shared/vendor/smol-toml/dist/util.js +100 -0
  154. package/src-shared/vendor/smol-toml/package.json +54 -0
  155. package/src-shared/vendor/yaml/LICENSE +13 -0
  156. package/src-shared/vendor/yaml/README.md +155 -0
  157. package/src-shared/vendor/yaml/VENDORED.md +29 -0
  158. package/src-shared/vendor/yaml/bin.mjs +11 -0
  159. package/src-shared/vendor/yaml/browser/dist/compose/compose-collection.js +88 -0
  160. package/src-shared/vendor/yaml/browser/dist/compose/compose-doc.js +42 -0
  161. package/src-shared/vendor/yaml/browser/dist/compose/compose-node.js +92 -0
  162. package/src-shared/vendor/yaml/browser/dist/compose/compose-scalar.js +80 -0
  163. package/src-shared/vendor/yaml/browser/dist/compose/composer.js +217 -0
  164. package/src-shared/vendor/yaml/browser/dist/compose/resolve-block-map.js +113 -0
  165. package/src-shared/vendor/yaml/browser/dist/compose/resolve-block-scalar.js +198 -0
  166. package/src-shared/vendor/yaml/browser/dist/compose/resolve-block-seq.js +47 -0
  167. package/src-shared/vendor/yaml/browser/dist/compose/resolve-end.js +37 -0
  168. package/src-shared/vendor/yaml/browser/dist/compose/resolve-flow-collection.js +203 -0
  169. package/src-shared/vendor/yaml/browser/dist/compose/resolve-flow-scalar.js +223 -0
  170. package/src-shared/vendor/yaml/browser/dist/compose/resolve-props.js +148 -0
  171. package/src-shared/vendor/yaml/browser/dist/compose/util-contains-newline.js +34 -0
  172. package/src-shared/vendor/yaml/browser/dist/compose/util-empty-scalar-position.js +27 -0
  173. package/src-shared/vendor/yaml/browser/dist/compose/util-flow-indent-check.js +15 -0
  174. package/src-shared/vendor/yaml/browser/dist/compose/util-map-includes.js +17 -0
  175. package/src-shared/vendor/yaml/browser/dist/doc/Document.js +334 -0
  176. package/src-shared/vendor/yaml/browser/dist/doc/anchors.js +72 -0
  177. package/src-shared/vendor/yaml/browser/dist/doc/applyReviver.js +55 -0
  178. package/src-shared/vendor/yaml/browser/dist/doc/createNode.js +89 -0
  179. package/src-shared/vendor/yaml/browser/dist/doc/directives.js +176 -0
  180. package/src-shared/vendor/yaml/browser/dist/errors.js +57 -0
  181. package/src-shared/vendor/yaml/browser/dist/index.js +17 -0
  182. package/src-shared/vendor/yaml/browser/dist/log.js +14 -0
  183. package/src-shared/vendor/yaml/browser/dist/nodes/Alias.js +101 -0
  184. package/src-shared/vendor/yaml/browser/dist/nodes/Collection.js +147 -0
  185. package/src-shared/vendor/yaml/browser/dist/nodes/Node.js +38 -0
  186. package/src-shared/vendor/yaml/browser/dist/nodes/Pair.js +36 -0
  187. package/src-shared/vendor/yaml/browser/dist/nodes/Scalar.js +24 -0
  188. package/src-shared/vendor/yaml/browser/dist/nodes/YAMLMap.js +144 -0
  189. package/src-shared/vendor/yaml/browser/dist/nodes/YAMLSeq.js +113 -0
  190. package/src-shared/vendor/yaml/browser/dist/nodes/addPairToJSMap.js +104 -0
  191. package/src-shared/vendor/yaml/browser/dist/nodes/identity.js +36 -0
  192. package/src-shared/vendor/yaml/browser/dist/nodes/toJS.js +37 -0
  193. package/src-shared/vendor/yaml/browser/dist/parse/cst-scalar.js +214 -0
  194. package/src-shared/vendor/yaml/browser/dist/parse/cst-stringify.js +61 -0
  195. package/src-shared/vendor/yaml/browser/dist/parse/cst-visit.js +97 -0
  196. package/src-shared/vendor/yaml/browser/dist/parse/cst.js +98 -0
  197. package/src-shared/vendor/yaml/browser/dist/parse/lexer.js +717 -0
  198. package/src-shared/vendor/yaml/browser/dist/parse/line-counter.js +39 -0
  199. package/src-shared/vendor/yaml/browser/dist/parse/parser.js +954 -0
  200. package/src-shared/vendor/yaml/browser/dist/public-api.js +99 -0
  201. package/src-shared/vendor/yaml/browser/dist/schema/Schema.js +38 -0
  202. package/src-shared/vendor/yaml/browser/dist/schema/common/map.js +17 -0
  203. package/src-shared/vendor/yaml/browser/dist/schema/common/null.js +15 -0
  204. package/src-shared/vendor/yaml/browser/dist/schema/common/seq.js +17 -0
  205. package/src-shared/vendor/yaml/browser/dist/schema/common/string.js +14 -0
  206. package/src-shared/vendor/yaml/browser/dist/schema/core/bool.js +19 -0
  207. package/src-shared/vendor/yaml/browser/dist/schema/core/float.js +43 -0
  208. package/src-shared/vendor/yaml/browser/dist/schema/core/int.js +38 -0
  209. package/src-shared/vendor/yaml/browser/dist/schema/core/schema.js +23 -0
  210. package/src-shared/vendor/yaml/browser/dist/schema/json/schema.js +62 -0
  211. package/src-shared/vendor/yaml/browser/dist/schema/tags.js +83 -0
  212. package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/binary.js +66 -0
  213. package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/bool.js +26 -0
  214. package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/float.js +46 -0
  215. package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/int.js +71 -0
  216. package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/omap.js +74 -0
  217. package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/pairs.js +78 -0
  218. package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/schema.js +37 -0
  219. package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/set.js +93 -0
  220. package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/timestamp.js +101 -0
  221. package/src-shared/vendor/yaml/browser/dist/stringify/foldFlowLines.js +146 -0
  222. package/src-shared/vendor/yaml/browser/dist/stringify/stringify.js +124 -0
  223. package/src-shared/vendor/yaml/browser/dist/stringify/stringifyCollection.js +143 -0
  224. package/src-shared/vendor/yaml/browser/dist/stringify/stringifyComment.js +20 -0
  225. package/src-shared/vendor/yaml/browser/dist/stringify/stringifyDocument.js +85 -0
  226. package/src-shared/vendor/yaml/browser/dist/stringify/stringifyNumber.js +24 -0
  227. package/src-shared/vendor/yaml/browser/dist/stringify/stringifyPair.js +150 -0
  228. package/src-shared/vendor/yaml/browser/dist/stringify/stringifyString.js +328 -0
  229. package/src-shared/vendor/yaml/browser/dist/util.js +11 -0
  230. package/src-shared/vendor/yaml/browser/dist/visit.js +233 -0
  231. package/src-shared/vendor/yaml/browser/index.js +5 -0
  232. package/src-shared/vendor/yaml/browser/package.json +3 -0
  233. package/src-shared/vendor/yaml/dist/cli.d.ts +8 -0
  234. package/src-shared/vendor/yaml/dist/cli.mjs +199 -0
  235. package/src-shared/vendor/yaml/dist/compose/compose-collection.d.ts +11 -0
  236. package/src-shared/vendor/yaml/dist/compose/compose-collection.js +90 -0
  237. package/src-shared/vendor/yaml/dist/compose/compose-doc.d.ts +7 -0
  238. package/src-shared/vendor/yaml/dist/compose/compose-doc.js +44 -0
  239. package/src-shared/vendor/yaml/dist/compose/compose-node.d.ts +28 -0
  240. package/src-shared/vendor/yaml/dist/compose/compose-node.js +95 -0
  241. package/src-shared/vendor/yaml/dist/compose/compose-scalar.d.ts +5 -0
  242. package/src-shared/vendor/yaml/dist/compose/compose-scalar.js +82 -0
  243. package/src-shared/vendor/yaml/dist/compose/composer.d.ts +62 -0
  244. package/src-shared/vendor/yaml/dist/compose/composer.js +221 -0
  245. package/src-shared/vendor/yaml/dist/compose/resolve-block-map.d.ts +6 -0
  246. package/src-shared/vendor/yaml/dist/compose/resolve-block-map.js +115 -0
  247. package/src-shared/vendor/yaml/dist/compose/resolve-block-scalar.d.ts +11 -0
  248. package/src-shared/vendor/yaml/dist/compose/resolve-block-scalar.js +200 -0
  249. package/src-shared/vendor/yaml/dist/compose/resolve-block-seq.d.ts +6 -0
  250. package/src-shared/vendor/yaml/dist/compose/resolve-block-seq.js +49 -0
  251. package/src-shared/vendor/yaml/dist/compose/resolve-end.d.ts +6 -0
  252. package/src-shared/vendor/yaml/dist/compose/resolve-end.js +39 -0
  253. package/src-shared/vendor/yaml/dist/compose/resolve-flow-collection.d.ts +7 -0
  254. package/src-shared/vendor/yaml/dist/compose/resolve-flow-collection.js +205 -0
  255. package/src-shared/vendor/yaml/dist/compose/resolve-flow-scalar.d.ts +10 -0
  256. package/src-shared/vendor/yaml/dist/compose/resolve-flow-scalar.js +225 -0
  257. package/src-shared/vendor/yaml/dist/compose/resolve-props.d.ts +23 -0
  258. package/src-shared/vendor/yaml/dist/compose/resolve-props.js +150 -0
  259. package/src-shared/vendor/yaml/dist/compose/util-contains-newline.d.ts +2 -0
  260. package/src-shared/vendor/yaml/dist/compose/util-contains-newline.js +36 -0
  261. package/src-shared/vendor/yaml/dist/compose/util-empty-scalar-position.d.ts +2 -0
  262. package/src-shared/vendor/yaml/dist/compose/util-empty-scalar-position.js +29 -0
  263. package/src-shared/vendor/yaml/dist/compose/util-flow-indent-check.d.ts +3 -0
  264. package/src-shared/vendor/yaml/dist/compose/util-flow-indent-check.js +17 -0
  265. package/src-shared/vendor/yaml/dist/compose/util-map-includes.d.ts +4 -0
  266. package/src-shared/vendor/yaml/dist/compose/util-map-includes.js +19 -0
  267. package/src-shared/vendor/yaml/dist/doc/Document.d.ts +141 -0
  268. package/src-shared/vendor/yaml/dist/doc/Document.js +336 -0
  269. package/src-shared/vendor/yaml/dist/doc/anchors.d.ts +24 -0
  270. package/src-shared/vendor/yaml/dist/doc/anchors.js +77 -0
  271. package/src-shared/vendor/yaml/dist/doc/applyReviver.d.ts +9 -0
  272. package/src-shared/vendor/yaml/dist/doc/applyReviver.js +57 -0
  273. package/src-shared/vendor/yaml/dist/doc/createNode.d.ts +17 -0
  274. package/src-shared/vendor/yaml/dist/doc/createNode.js +91 -0
  275. package/src-shared/vendor/yaml/dist/doc/directives.d.ts +49 -0
  276. package/src-shared/vendor/yaml/dist/doc/directives.js +178 -0
  277. package/src-shared/vendor/yaml/dist/errors.d.ts +21 -0
  278. package/src-shared/vendor/yaml/dist/errors.js +62 -0
  279. package/src-shared/vendor/yaml/dist/index.d.ts +22 -0
  280. package/src-shared/vendor/yaml/dist/index.js +50 -0
  281. package/src-shared/vendor/yaml/dist/log.d.ts +3 -0
  282. package/src-shared/vendor/yaml/dist/log.js +17 -0
  283. package/src-shared/vendor/yaml/dist/nodes/Alias.d.ts +28 -0
  284. package/src-shared/vendor/yaml/dist/nodes/Alias.js +103 -0
  285. package/src-shared/vendor/yaml/dist/nodes/Collection.d.ts +73 -0
  286. package/src-shared/vendor/yaml/dist/nodes/Collection.js +151 -0
  287. package/src-shared/vendor/yaml/dist/nodes/Node.d.ts +47 -0
  288. package/src-shared/vendor/yaml/dist/nodes/Node.js +40 -0
  289. package/src-shared/vendor/yaml/dist/nodes/Pair.d.ts +21 -0
  290. package/src-shared/vendor/yaml/dist/nodes/Pair.js +39 -0
  291. package/src-shared/vendor/yaml/dist/nodes/Scalar.d.ts +42 -0
  292. package/src-shared/vendor/yaml/dist/nodes/Scalar.js +27 -0
  293. package/src-shared/vendor/yaml/dist/nodes/YAMLMap.d.ts +53 -0
  294. package/src-shared/vendor/yaml/dist/nodes/YAMLMap.js +147 -0
  295. package/src-shared/vendor/yaml/dist/nodes/YAMLSeq.d.ts +60 -0
  296. package/src-shared/vendor/yaml/dist/nodes/YAMLSeq.js +115 -0
  297. package/src-shared/vendor/yaml/dist/nodes/addPairToJSMap.d.ts +4 -0
  298. package/src-shared/vendor/yaml/dist/nodes/addPairToJSMap.js +106 -0
  299. package/src-shared/vendor/yaml/dist/nodes/identity.d.ts +23 -0
  300. package/src-shared/vendor/yaml/dist/nodes/identity.js +53 -0
  301. package/src-shared/vendor/yaml/dist/nodes/toJS.d.ts +27 -0
  302. package/src-shared/vendor/yaml/dist/nodes/toJS.js +39 -0
  303. package/src-shared/vendor/yaml/dist/options.d.ts +338 -0
  304. package/src-shared/vendor/yaml/dist/parse/cst-scalar.d.ts +64 -0
  305. package/src-shared/vendor/yaml/dist/parse/cst-scalar.js +218 -0
  306. package/src-shared/vendor/yaml/dist/parse/cst-stringify.d.ts +8 -0
  307. package/src-shared/vendor/yaml/dist/parse/cst-stringify.js +63 -0
  308. package/src-shared/vendor/yaml/dist/parse/cst-visit.d.ts +39 -0
  309. package/src-shared/vendor/yaml/dist/parse/cst-visit.js +99 -0
  310. package/src-shared/vendor/yaml/dist/parse/cst.d.ts +108 -0
  311. package/src-shared/vendor/yaml/dist/parse/cst.js +112 -0
  312. package/src-shared/vendor/yaml/dist/parse/lexer.d.ts +87 -0
  313. package/src-shared/vendor/yaml/dist/parse/lexer.js +719 -0
  314. package/src-shared/vendor/yaml/dist/parse/line-counter.d.ts +22 -0
  315. package/src-shared/vendor/yaml/dist/parse/line-counter.js +41 -0
  316. package/src-shared/vendor/yaml/dist/parse/parser.d.ts +84 -0
  317. package/src-shared/vendor/yaml/dist/parse/parser.js +958 -0
  318. package/src-shared/vendor/yaml/dist/public-api.d.ts +43 -0
  319. package/src-shared/vendor/yaml/dist/public-api.js +104 -0
  320. package/src-shared/vendor/yaml/dist/schema/Schema.d.ts +18 -0
  321. package/src-shared/vendor/yaml/dist/schema/Schema.js +40 -0
  322. package/src-shared/vendor/yaml/dist/schema/common/map.d.ts +2 -0
  323. package/src-shared/vendor/yaml/dist/schema/common/map.js +19 -0
  324. package/src-shared/vendor/yaml/dist/schema/common/null.d.ts +4 -0
  325. package/src-shared/vendor/yaml/dist/schema/common/null.js +17 -0
  326. package/src-shared/vendor/yaml/dist/schema/common/seq.d.ts +2 -0
  327. package/src-shared/vendor/yaml/dist/schema/common/seq.js +19 -0
  328. package/src-shared/vendor/yaml/dist/schema/common/string.d.ts +2 -0
  329. package/src-shared/vendor/yaml/dist/schema/common/string.js +16 -0
  330. package/src-shared/vendor/yaml/dist/schema/core/bool.d.ts +4 -0
  331. package/src-shared/vendor/yaml/dist/schema/core/bool.js +21 -0
  332. package/src-shared/vendor/yaml/dist/schema/core/float.d.ts +4 -0
  333. package/src-shared/vendor/yaml/dist/schema/core/float.js +47 -0
  334. package/src-shared/vendor/yaml/dist/schema/core/int.d.ts +4 -0
  335. package/src-shared/vendor/yaml/dist/schema/core/int.js +42 -0
  336. package/src-shared/vendor/yaml/dist/schema/core/schema.d.ts +1 -0
  337. package/src-shared/vendor/yaml/dist/schema/core/schema.js +25 -0
  338. package/src-shared/vendor/yaml/dist/schema/json/schema.d.ts +2 -0
  339. package/src-shared/vendor/yaml/dist/schema/json/schema.js +64 -0
  340. package/src-shared/vendor/yaml/dist/schema/json-schema.d.ts +69 -0
  341. package/src-shared/vendor/yaml/dist/schema/tags.d.ts +40 -0
  342. package/src-shared/vendor/yaml/dist/schema/tags.js +86 -0
  343. package/src-shared/vendor/yaml/dist/schema/types.d.ts +90 -0
  344. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/binary.d.ts +2 -0
  345. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/binary.js +68 -0
  346. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/bool.d.ts +7 -0
  347. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/bool.js +29 -0
  348. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/float.d.ts +4 -0
  349. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/float.js +50 -0
  350. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/int.d.ts +5 -0
  351. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/int.js +76 -0
  352. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/omap.d.ts +28 -0
  353. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/omap.js +77 -0
  354. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/pairs.d.ts +10 -0
  355. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/pairs.js +82 -0
  356. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/schema.d.ts +1 -0
  357. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/schema.js +39 -0
  358. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/set.d.ts +28 -0
  359. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/set.js +96 -0
  360. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/timestamp.d.ts +6 -0
  361. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/timestamp.js +105 -0
  362. package/src-shared/vendor/yaml/dist/stringify/foldFlowLines.d.ts +34 -0
  363. package/src-shared/vendor/yaml/dist/stringify/foldFlowLines.js +151 -0
  364. package/src-shared/vendor/yaml/dist/stringify/stringify.d.ts +21 -0
  365. package/src-shared/vendor/yaml/dist/stringify/stringify.js +127 -0
  366. package/src-shared/vendor/yaml/dist/stringify/stringifyCollection.d.ts +17 -0
  367. package/src-shared/vendor/yaml/dist/stringify/stringifyCollection.js +145 -0
  368. package/src-shared/vendor/yaml/dist/stringify/stringifyComment.d.ts +10 -0
  369. package/src-shared/vendor/yaml/dist/stringify/stringifyComment.js +24 -0
  370. package/src-shared/vendor/yaml/dist/stringify/stringifyDocument.d.ts +4 -0
  371. package/src-shared/vendor/yaml/dist/stringify/stringifyDocument.js +87 -0
  372. package/src-shared/vendor/yaml/dist/stringify/stringifyNumber.d.ts +2 -0
  373. package/src-shared/vendor/yaml/dist/stringify/stringifyNumber.js +26 -0
  374. package/src-shared/vendor/yaml/dist/stringify/stringifyPair.d.ts +3 -0
  375. package/src-shared/vendor/yaml/dist/stringify/stringifyPair.js +152 -0
  376. package/src-shared/vendor/yaml/dist/stringify/stringifyString.d.ts +9 -0
  377. package/src-shared/vendor/yaml/dist/stringify/stringifyString.js +330 -0
  378. package/src-shared/vendor/yaml/dist/test-events.d.ts +4 -0
  379. package/src-shared/vendor/yaml/dist/test-events.js +134 -0
  380. package/src-shared/vendor/yaml/dist/util.d.ts +12 -0
  381. package/src-shared/vendor/yaml/dist/util.js +28 -0
  382. package/src-shared/vendor/yaml/dist/visit.d.ts +102 -0
  383. package/src-shared/vendor/yaml/dist/visit.js +236 -0
  384. package/src-shared/vendor/yaml/package.json +96 -0
  385. package/src-shared/vendor/yaml/util.js +2 -0
@@ -0,0 +1,236 @@
1
+ // mcpRuntimeFanout.mjs — 把 `agentlink` MCP server 注册到各 runtime 的 MCP
2
+ // 配置里的统一入口。
3
+ //
4
+ // 设计要点(见 spec cli-tools-mcp-fanout/spec.md 和 design.md D9–D14):
5
+ // 1. idempotent: 同样输入跑 N 次产物一致
6
+ // 2. non-destructive: 用户其它 MCP server entry 一字不动
7
+ // 3. versioned: 写入的 args 含 `--agentlink-version <X>`,升级时识别旧条目
8
+ // 自动替换
9
+ // 4. traceable: 写入前的 config 内容备份到 ~/.agentlink/fanout-history/
10
+ // <runtime>-<ISO>.<ext>,保留最近 10 份
11
+ // 5. 4 个 runtime 走 4 条不同适配:
12
+ // - claude: JSON (stdlib)
13
+ // - codex: TOML (vendored smol-toml)
14
+ // - hermes: YAML (vendored yaml)
15
+ // - openclaw: 走 plugin 路径(本模块仅 stub 返回 "plugin_managed",真正
16
+ // 的 tool injection 在 openclaw-plugin/index.cjs)
17
+ //
18
+ // 入口:
19
+ // await register("claude", { projectCwd }) → { ok, mode?, reason? }
20
+ // await deregister("claude", { projectCwd }) → { ok, reason? }
21
+ // await status() → 4-runtime 状态汇总,给 `agentlink mcp list` 用
22
+ //
23
+ // 每个 adapter 必须实现 register / deregister / read,签名一致。
24
+
25
+ import path from "node:path";
26
+ import fs from "node:fs/promises";
27
+ import { getAgentlinkDir } from "./attachAuditLog.mjs";
28
+ import { getDiscoveryPath } from "./toolsServerLifecycle.mjs";
29
+
30
+ import * as claudeAdapter from "../runtime/claude/mcpConfigAdapter.mjs";
31
+ import * as codexAdapter from "../runtime/codex/mcpConfigAdapter.mjs";
32
+ import * as hermesAdapter from "../runtime/hermes/mcpConfigAdapter.mjs";
33
+ import * as openclawAdapter from "../runtime/openclaw/mcpConfigAdapter.mjs";
34
+
35
+ const ADAPTERS = {
36
+ claude: claudeAdapter,
37
+ codex: codexAdapter,
38
+ hermes: hermesAdapter,
39
+ openclaw: openclawAdapter,
40
+ };
41
+
42
+ const HISTORY_DIR = () => path.join(getAgentlinkDir(), "fanout-history");
43
+ const HISTORY_KEEP = 10;
44
+
45
+ /**
46
+ * 拼出所有 adapter 共用的 args 数组(写到 MCP server entry 里)。
47
+ *
48
+ * @param {object} opts
49
+ * @param {string} opts.binPath agentlink-mcp-stdio 的绝对路径
50
+ * @param {string} opts.discoveryPath ~/.agentlink/tools-server.json 路径
51
+ * @param {string} opts.version npm_cli 包版本(用于 fanout 版本漂移检测)
52
+ * @returns {string[]}
53
+ */
54
+ export function buildArgs({ binPath, discoveryPath, version }) {
55
+ return [
56
+ binPath,
57
+ "--discovery", discoveryPath,
58
+ "--agentlink-version", String(version || "unknown"),
59
+ ];
60
+ }
61
+
62
+ /**
63
+ * 给某个 runtime 注册 agentlink MCP server。idempotent + 可逆。
64
+ *
65
+ * @param {"claude"|"codex"|"hermes"|"openclaw"} runtime
66
+ * @param {object} [opts]
67
+ * @param {string} [opts.projectCwd] Claude 适用,选用项目级配置写哪里
68
+ * @param {string} [opts.binPath] agentlink-mcp-stdio 绝对路径,默认从 process.argv 推断
69
+ * @param {string} [opts.version] npm_cli 版本
70
+ * @param {object} [opts.log]
71
+ * @returns {Promise<{ ok: boolean, reason?: string, mode?: string, changed?: boolean }>}
72
+ */
73
+ export async function register(runtime, opts = {}) {
74
+ const adapter = ADAPTERS[runtime];
75
+ if (!adapter) {
76
+ return { ok: false, reason: "unknown_runtime" };
77
+ }
78
+ const log = opts.log || console;
79
+ const binPath = opts.binPath || defaultBinPath();
80
+ const discoveryPath = getDiscoveryPath();
81
+ const version = opts.version || "unknown";
82
+ const args = buildArgs({ binPath, discoveryPath, version });
83
+
84
+ // openclaw adapter 是 plugin-managed, no-op stub.
85
+ if (runtime === "openclaw") {
86
+ return await adapter.register({ args, log });
87
+ }
88
+
89
+ // 1) 读现有配置(可能 ENOENT,adapter 自己 handle)
90
+ let beforeRaw;
91
+ try {
92
+ beforeRaw = await adapter.read({ projectCwd: opts.projectCwd });
93
+ } catch (err) {
94
+ // not_installed (来自 hermes adapter 显式标记) → 视为致命,该 runtime 没装
95
+ if (err?.kind === "not_installed") {
96
+ return { ok: false, reason: err.reason || "not_installed" };
97
+ }
98
+ // ENOENT 仅代表"配置文件不存在",对 claude/codex 是合法初次注册场景,
99
+ // 不阻塞 register —— 留给 adapter 的 register() 自己 create。
100
+ if (err?.code !== "ENOENT") {
101
+ log.warn?.("mcp.fanout.read_failed", `read existing config failed: ${err?.message}`);
102
+ }
103
+ }
104
+
105
+ // 2) 备份(只在内容非空时备份,避免无意义 0 字节)
106
+ if (beforeRaw && typeof beforeRaw === "string" && beforeRaw.length > 0) {
107
+ try {
108
+ await backupConfig(runtime, beforeRaw, adapter.fileExtension);
109
+ } catch (err) {
110
+ log.warn?.("mcp.fanout.backup_failed",
111
+ `backup before write failed (non-fatal): ${err?.message}`);
112
+ }
113
+ }
114
+
115
+ // 3) 让 adapter 处理 idempotent merge + write
116
+ try {
117
+ const result = await adapter.register({
118
+ projectCwd: opts.projectCwd,
119
+ args,
120
+ log,
121
+ });
122
+ log.info?.("mcp.fanout.register",
123
+ `registered agentlink MCP server in ${runtime}`, { runtime, ...result });
124
+ return { ok: true, ...result };
125
+ } catch (err) {
126
+ log.error?.("mcp.fanout.register_failed",
127
+ `register ${runtime} failed: ${err?.message}`);
128
+ return { ok: false, reason: "write_failed", error: err?.message };
129
+ }
130
+ }
131
+
132
+ /**
133
+ * 给某个 runtime 取消注册 agentlink MCP server。
134
+ *
135
+ * @param {"claude"|"codex"|"hermes"|"openclaw"} runtime
136
+ * @param {object} [opts]
137
+ */
138
+ export async function deregister(runtime, opts = {}) {
139
+ const adapter = ADAPTERS[runtime];
140
+ if (!adapter) {
141
+ return { ok: false, reason: "unknown_runtime" };
142
+ }
143
+ const log = opts.log || console;
144
+
145
+ if (runtime === "openclaw") {
146
+ return await adapter.deregister({ log });
147
+ }
148
+
149
+ let beforeRaw;
150
+ try {
151
+ beforeRaw = await adapter.read({ projectCwd: opts.projectCwd });
152
+ } catch (err) {
153
+ if (err?.code === "ENOENT" || err?.kind === "not_installed") {
154
+ // 配置不存在 → 自然「未注册」状态,no-op success
155
+ return { ok: true, mode: "noop_no_config" };
156
+ }
157
+ }
158
+
159
+ if (beforeRaw && typeof beforeRaw === "string" && beforeRaw.length > 0) {
160
+ try {
161
+ await backupConfig(runtime, beforeRaw, adapter.fileExtension);
162
+ } catch { /* swallow */ }
163
+ }
164
+
165
+ try {
166
+ const result = await adapter.deregister({
167
+ projectCwd: opts.projectCwd,
168
+ log,
169
+ });
170
+ log.info?.("mcp.fanout.deregister",
171
+ `deregistered agentlink MCP server from ${runtime}`, { runtime, ...result });
172
+ return { ok: true, ...result };
173
+ } catch (err) {
174
+ return { ok: false, reason: "write_failed", error: err?.message };
175
+ }
176
+ }
177
+
178
+ /**
179
+ * 汇总 4 个 runtime 的当前状态(给 `agentlink mcp list` 用)。
180
+ *
181
+ * @returns {Promise<Array<{ runtime, installed, registered, version?, error? }>>}
182
+ */
183
+ export async function status(opts = {}) {
184
+ const out = [];
185
+ for (const runtime of Object.keys(ADAPTERS)) {
186
+ const adapter = ADAPTERS[runtime];
187
+ try {
188
+ const s = await adapter.status({ projectCwd: opts.projectCwd });
189
+ out.push({ runtime, ...s });
190
+ } catch (err) {
191
+ out.push({ runtime, installed: false, registered: false, error: err?.message });
192
+ }
193
+ }
194
+ return out;
195
+ }
196
+
197
+ /**
198
+ * 调试用:列出所有 4 个 adapter 模块。
199
+ */
200
+ export function listAdapters() {
201
+ return Object.keys(ADAPTERS);
202
+ }
203
+
204
+ /**
205
+ * 推断 agentlink-mcp-stdio 二进制位置。如果不在 process.argv[1] 同目录,
206
+ * 退到 node_modules/.bin/agentlink-mcp-stdio。fanout 写入前用绝对路径,
207
+ * 否则 MCP 客户端 spawn 时找不到。
208
+ */
209
+ function defaultBinPath() {
210
+ const argv1 = process.argv[1] || "";
211
+ const argv1Dir = path.dirname(argv1);
212
+ // npm_cli/bin/agentlink-mcp-stdio 跟 agentlink-agent / agentlink 同目录
213
+ const candidate = path.join(argv1Dir, "agentlink-mcp-stdio");
214
+ return candidate;
215
+ }
216
+
217
+ /**
218
+ * 写备份。文件名 <runtime>-<ISO8601>.<ext>;ext 从 adapter 拿(json/toml/yaml)。
219
+ * 保留最近 10 份,旧的删。
220
+ */
221
+ async function backupConfig(runtime, content, ext) {
222
+ const dir = HISTORY_DIR();
223
+ await fs.mkdir(dir, { recursive: true, mode: 0o700 });
224
+ const stamp = new Date().toISOString().replace(/[:.]/g, "-");
225
+ const dst = path.join(dir, `${runtime}-${stamp}.${ext || "txt"}`);
226
+ await fs.writeFile(dst, content, { mode: 0o600 });
227
+ // 删旧
228
+ const entries = await fs.readdir(dir);
229
+ const mine = entries
230
+ .filter((n) => n.startsWith(`${runtime}-`) && n.endsWith(`.${ext || "txt"}`))
231
+ .sort()
232
+ .reverse();
233
+ for (const old of mine.slice(HISTORY_KEEP)) {
234
+ try { await fs.unlink(path.join(dir, old)); } catch { /* swallow */ }
235
+ }
236
+ }
@@ -0,0 +1,316 @@
1
+ // 极简 MCP over stdio 客户端。
2
+ //
3
+ // 为什么手写:
4
+ // - 只用到 initialize / tools/call / notifications 三类报文
5
+ // - @modelcontextprotocol/sdk 对我们来说是黑盒,多一层版本风险
6
+ // - 手写 + 类型松校验 = 未来 codex 升级协议时只需改这里
7
+ //
8
+ // 设计:
9
+ // - 给定 command + args 启动子进程
10
+ // - 所有出站报文 → `{ "jsonrpc":"2.0", ... }\n`
11
+ // - 入站按 `\n` 分片 → JSON.parse → 路由到请求回调 / 通知监听器
12
+ // - call(method, params, { timeoutMs }) → Promise,超时 reject
13
+ // - onNotification(method, cb)
14
+ // - onRequest(method, cb) —— 用于服务端反向调用(P5 elicitation 用)
15
+
16
+ import { spawn } from "node:child_process";
17
+
18
+ const DEFAULT_CALL_TIMEOUT_MS = 600_000; // codex 工具调用可能长达数分钟
19
+
20
+ export function createMcpStdioClient({
21
+ command,
22
+ args = [],
23
+ env,
24
+ cwd,
25
+ log,
26
+ clientInfo = { name: "agentlink-agent", version: "p4" },
27
+ signal,
28
+ }) {
29
+ if (!command) throw new Error("mcp: command required");
30
+ if (!log) throw new Error("mcp: log required");
31
+
32
+ const cLog = log.child({ comp: "mcp" });
33
+
34
+ const mergedEnv = { ...process.env, ...(env || {}) };
35
+ const proc = spawn(command, args, {
36
+ env: mergedEnv,
37
+ cwd,
38
+ stdio: ["pipe", "pipe", "pipe"],
39
+ windowsHide: true,
40
+ shell: process.platform === "win32",
41
+ });
42
+
43
+ cLog.info("mcp.spawn", "mcp server spawned", {
44
+ command, args: args.join(" "), pid: proc.pid,
45
+ });
46
+
47
+ // 外部 signal → kill child
48
+ if (signal) {
49
+ if (signal.aborted) safeKill(proc, cLog, "aborted-before-spawn");
50
+ else signal.addEventListener("abort", () => safeKill(proc, cLog, "signal-abort"), { once: true });
51
+ }
52
+
53
+ const stderrRing = createRing(4096);
54
+ proc.stderr.on("data", (buf) => stderrRing.push(buf.toString("utf8")));
55
+
56
+ let exitHandler = null;
57
+ proc.once("exit", (code, sig) => {
58
+ cLog.info("mcp.exit", "mcp server exited", {
59
+ code, signal: sig, stderr_tail: stderrRing.tail(1000),
60
+ });
61
+ if (exitHandler) exitHandler({ code, signal: sig });
62
+ });
63
+ proc.once("error", (err) => {
64
+ cLog.error("mcp.error", "mcp server emit error", { err: err?.message || String(err) });
65
+ });
66
+
67
+ let idCounter = 0;
68
+ const pending = new Map(); // id → { resolve, reject, method, timer }
69
+ const notifHandlers = new Map(); // method → [cb]
70
+ const reqHandlers = new Map(); // method → cb (returns result or Promise)
71
+
72
+ let initialized = false;
73
+
74
+ // ---- stdin (outgoing) ----
75
+ function sendRaw(obj) {
76
+ const line = JSON.stringify(obj) + "\n";
77
+ return new Promise((resolve, reject) => {
78
+ if (proc.stdin.destroyed) return reject(new Error("stdin destroyed"));
79
+ proc.stdin.write(line, (err) => (err ? reject(err) : resolve()));
80
+ });
81
+ }
82
+
83
+ // ---- stdout (incoming) ----
84
+ const decoder = new TextDecoder("utf-8");
85
+ let buf = "";
86
+ proc.stdout.on("data", (chunk) => {
87
+ buf += typeof chunk === "string" ? chunk : decoder.decode(chunk, { stream: true });
88
+ if (buf.length > 8 << 20) {
89
+ cLog.warn("mcp.stdout.overflow", "buffer exceeded 8MB; truncating", { size: buf.length });
90
+ buf = buf.slice(-(4 << 20));
91
+ }
92
+ let idx;
93
+ while ((idx = buf.indexOf("\n")) >= 0) {
94
+ const line = buf.slice(0, idx);
95
+ buf = buf.slice(idx + 1);
96
+ handleLine(line);
97
+ }
98
+ });
99
+
100
+ function handleLine(rawLine) {
101
+ const line = rawLine.replace(/\r$/, "").trim();
102
+ if (!line) return;
103
+ let msg;
104
+ try { msg = JSON.parse(line); }
105
+ catch (err) {
106
+ cLog.warn("mcp.stdout.parse.failed", "non-json line", {
107
+ err: err?.message, sample: line.slice(0, 200),
108
+ });
109
+ return;
110
+ }
111
+ if (!msg || typeof msg !== "object") return;
112
+
113
+ // Response(有 id + result/error)
114
+ if (Object.prototype.hasOwnProperty.call(msg, "id") && (msg.result !== undefined || msg.error !== undefined)) {
115
+ const entry = pending.get(msg.id);
116
+ if (!entry) {
117
+ cLog.warn("mcp.response.orphan", "no pending request for id", { id: msg.id });
118
+ return;
119
+ }
120
+ pending.delete(msg.id);
121
+ clearTimeout(entry.timer);
122
+ if (msg.error) {
123
+ const err = new Error(`mcp call ${entry.method} failed: ${msg.error.message || "unknown"}`);
124
+ err.code = msg.error.code;
125
+ err.data = msg.error.data;
126
+ entry.reject(err);
127
+ } else {
128
+ entry.resolve(msg.result);
129
+ }
130
+ return;
131
+ }
132
+ // Request from server (has id + method) —— P5 会用(elicitation)
133
+ if (msg.method && Object.prototype.hasOwnProperty.call(msg, "id")) {
134
+ const handler = reqHandlers.get(msg.method);
135
+ const id = msg.id;
136
+ if (!handler) {
137
+ cLog.warn("mcp.request.unhandled", "no handler for server request", { method: msg.method });
138
+ void sendRaw({ jsonrpc: "2.0", id, error: { code: -32601, message: "method not supported" } });
139
+ return;
140
+ }
141
+ Promise.resolve().then(() => handler(msg.params)).then(
142
+ (result) => sendRaw({ jsonrpc: "2.0", id, result: result ?? {} }),
143
+ (err) => sendRaw({
144
+ jsonrpc: "2.0", id,
145
+ error: { code: -32603, message: err?.message || String(err) },
146
+ }),
147
+ );
148
+ return;
149
+ }
150
+ // Notification(有 method 无 id)
151
+ if (msg.method && !Object.prototype.hasOwnProperty.call(msg, "id")) {
152
+ const cbs = notifHandlers.get(msg.method);
153
+ if (!cbs || cbs.length === 0) {
154
+ cLog.debug("mcp.notif.unhandled", "no handler for notification", { method: msg.method });
155
+ return;
156
+ }
157
+ for (const cb of cbs) {
158
+ try { cb(msg.params); }
159
+ catch (err) {
160
+ cLog.error("error.caught", "notification handler threw", {
161
+ where: "mcpStdioClient.notif", method: msg.method,
162
+ err: err?.message || String(err),
163
+ });
164
+ }
165
+ }
166
+ return;
167
+ }
168
+ cLog.warn("mcp.stdout.unknown_shape", "message dropped", { sample: line.slice(0, 200) });
169
+ }
170
+
171
+ // ---- public API ----
172
+
173
+ /**
174
+ * callWithId(method, params, opts) → { promise, requestId }
175
+ *
176
+ * 与 call() 行为完全相同,但同时返回本次分配的 JSON-RPC requestId,
177
+ * 供调用方后续 cancel(requestId) 取消 in-flight 请求。
178
+ * call() 改为 callWithId().promise,保持向后兼容。
179
+ */
180
+ function callWithId(method, params, { timeoutMs } = {}) {
181
+ const id = ++idCounter;
182
+ const promise = new Promise((resolve, reject) => {
183
+ const timer = setTimeout(() => {
184
+ if (pending.delete(id)) {
185
+ reject(new Error(`mcp call ${method} timed out after ${timeoutMs || DEFAULT_CALL_TIMEOUT_MS}ms`));
186
+ }
187
+ }, timeoutMs || DEFAULT_CALL_TIMEOUT_MS);
188
+ pending.set(id, { resolve, reject, method, timer });
189
+ cLog.debug("mcp.call", "outgoing request", { id, method });
190
+ sendRaw({ jsonrpc: "2.0", id, method, params: params ?? {} }).catch((err) => {
191
+ if (pending.delete(id)) {
192
+ clearTimeout(timer);
193
+ reject(err);
194
+ }
195
+ });
196
+ });
197
+ return { promise, requestId: id };
198
+ }
199
+
200
+ function call(method, params, opts) {
201
+ return callWithId(method, params, opts).promise;
202
+ }
203
+
204
+ /**
205
+ * cancel(requestId) — 取消 in-flight 请求。
206
+ *
207
+ * 1. 向 server 发 notifications/cancelled { requestId }(MCP 协议取消通知)。
208
+ * 2. 主动清理该 requestId 的 pending entry(clearTimeout + reject + delete),
209
+ * 避免 codex 不回复时 orphaned 响应挂到 600s 超时。
210
+ * 清除后若 server 仍发回 response,会走 mcp.response.orphan warn 路径,不触发 reject。
211
+ *
212
+ * 对不存在的 requestId 调用是 no-op(不抛异常)。
213
+ */
214
+ async function cancel(requestId) {
215
+ // 主动清理 pending entry(先清后发 notify,避免 notify 回传 response 时 pending 还在)
216
+ const entry = pending.get(requestId);
217
+ if (entry) {
218
+ pending.delete(requestId);
219
+ clearTimeout(entry.timer);
220
+ entry.reject(new Error(`mcp call ${entry.method} cancelled (requestId=${requestId})`));
221
+ cLog.debug("mcp.cancel", "pending entry cleared", { requestId, method: entry.method });
222
+ }
223
+ // 发 MCP notifications/cancelled 通知 server 停止处理
224
+ await notify("notifications/cancelled", { requestId });
225
+ }
226
+
227
+ function notify(method, params) {
228
+ return sendRaw({ jsonrpc: "2.0", method, params: params ?? {} });
229
+ }
230
+
231
+ function onNotification(method, cb) {
232
+ const arr = notifHandlers.get(method) || [];
233
+ arr.push(cb);
234
+ notifHandlers.set(method, arr);
235
+ return () => {
236
+ const a = notifHandlers.get(method) || [];
237
+ const i = a.indexOf(cb);
238
+ if (i >= 0) a.splice(i, 1);
239
+ };
240
+ }
241
+
242
+ function onRequest(method, cb) {
243
+ reqHandlers.set(method, cb);
244
+ return () => reqHandlers.delete(method);
245
+ }
246
+
247
+ async function initialize({ capabilities = {}, protocolVersion = "2024-11-05" } = {}) {
248
+ if (initialized) return;
249
+ const result = await call("initialize", {
250
+ protocolVersion,
251
+ capabilities,
252
+ clientInfo,
253
+ }, { timeoutMs: 30_000 });
254
+ await notify("notifications/initialized", {});
255
+ initialized = true;
256
+ cLog.info("mcp.initialized", "handshake complete", {
257
+ server: result?.serverInfo, version: result?.protocolVersion,
258
+ });
259
+ return result;
260
+ }
261
+
262
+ function setExitHandler(cb) {
263
+ exitHandler = cb;
264
+ }
265
+
266
+ async function close(reason = "manual") {
267
+ cLog.info("mcp.close", "closing mcp client", { reason });
268
+ safeKill(proc, cLog, reason);
269
+ // 让所有 pending 失败
270
+ for (const [id, entry] of pending.entries()) {
271
+ clearTimeout(entry.timer);
272
+ entry.reject(new Error(`mcp closing: ${reason}`));
273
+ pending.delete(id);
274
+ }
275
+ }
276
+
277
+ return {
278
+ proc,
279
+ call,
280
+ callWithId,
281
+ cancel,
282
+ notify,
283
+ onNotification,
284
+ onRequest,
285
+ initialize,
286
+ setExitHandler,
287
+ close,
288
+ get pendingCount() { return pending.size; },
289
+ getStderrTail: (n = 1000) => stderrRing.tail(n),
290
+ };
291
+ }
292
+
293
+ function safeKill(child, log, reason) {
294
+ if (!child || child.killed) return;
295
+ try {
296
+ log.info("mcp.kill.term", "sending SIGTERM", { reason });
297
+ child.kill("SIGTERM");
298
+ } catch (err) {
299
+ log.warn("mcp.kill.term.failed", "SIGTERM failed", { err: err?.message });
300
+ }
301
+ const deadline = setTimeout(() => {
302
+ if (child.exitCode === null && !child.killed) {
303
+ log.warn("mcp.kill.force", "SIGKILL after timeout", { reason });
304
+ try { child.kill("SIGKILL"); } catch {}
305
+ }
306
+ }, 2000);
307
+ deadline.unref?.();
308
+ }
309
+
310
+ function createRing(capacity) {
311
+ let buf = "";
312
+ return {
313
+ push(s) { buf += s; if (buf.length > capacity) buf = buf.slice(-capacity); },
314
+ tail(n) { return buf.slice(-n); },
315
+ };
316
+ }