@animalabs/agent-framework 0.23.2 → 0.24.0

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 (338) hide show
  1. package/README.md +212 -42
  2. package/dist/src/agent.d.ts +60 -9
  3. package/dist/src/agent.d.ts.map +1 -1
  4. package/dist/src/agent.js +92 -12
  5. package/dist/src/agent.js.map +1 -1
  6. package/dist/src/api/server.d.ts.map +1 -1
  7. package/dist/src/api/server.js +14 -12
  8. package/dist/src/api/server.js.map +1 -1
  9. package/dist/src/code-execution/engine.d.ts +177 -0
  10. package/dist/src/code-execution/engine.d.ts.map +1 -0
  11. package/dist/src/code-execution/engine.js +494 -0
  12. package/dist/src/code-execution/engine.js.map +1 -0
  13. package/dist/src/code-execution/index.d.ts +5 -10
  14. package/dist/src/code-execution/index.d.ts.map +1 -1
  15. package/dist/src/code-execution/index.js +5 -9
  16. package/dist/src/code-execution/index.js.map +1 -1
  17. package/dist/src/code-execution/isolate/calls.d.ts +114 -0
  18. package/dist/src/code-execution/isolate/calls.d.ts.map +1 -0
  19. package/dist/src/code-execution/isolate/calls.js +145 -0
  20. package/dist/src/code-execution/isolate/calls.js.map +1 -0
  21. package/dist/src/code-execution/isolate/child-entry.d.ts +2 -0
  22. package/dist/src/code-execution/isolate/child-entry.d.ts.map +1 -0
  23. package/dist/src/code-execution/isolate/child-entry.js +5 -0
  24. package/dist/src/code-execution/isolate/child-entry.js.map +1 -0
  25. package/dist/src/code-execution/isolate/child-main.d.ts +26 -0
  26. package/dist/src/code-execution/isolate/child-main.d.ts.map +1 -0
  27. package/dist/src/code-execution/isolate/child-main.js +132 -0
  28. package/dist/src/code-execution/isolate/child-main.js.map +1 -0
  29. package/dist/src/code-execution/isolate/child.d.ts +44 -0
  30. package/dist/src/code-execution/isolate/child.d.ts.map +1 -0
  31. package/dist/src/code-execution/isolate/child.js +315 -0
  32. package/dist/src/code-execution/isolate/child.js.map +1 -0
  33. package/dist/src/code-execution/isolate/frames.d.ts +80 -0
  34. package/dist/src/code-execution/isolate/frames.d.ts.map +1 -0
  35. package/dist/src/code-execution/isolate/frames.js +210 -0
  36. package/dist/src/code-execution/isolate/frames.js.map +1 -0
  37. package/dist/src/code-execution/isolate/output.d.ts +68 -0
  38. package/dist/src/code-execution/isolate/output.d.ts.map +1 -0
  39. package/dist/src/code-execution/isolate/output.js +143 -0
  40. package/dist/src/code-execution/isolate/output.js.map +1 -0
  41. package/dist/src/code-execution/isolate/prelude.d.ts +109 -0
  42. package/dist/src/code-execution/isolate/prelude.d.ts.map +1 -0
  43. package/dist/src/code-execution/isolate/prelude.js +401 -0
  44. package/dist/src/code-execution/isolate/prelude.js.map +1 -0
  45. package/dist/src/code-execution/isolate/protocol.d.ts +151 -0
  46. package/dist/src/code-execution/isolate/protocol.d.ts.map +1 -0
  47. package/dist/src/code-execution/isolate/protocol.js +150 -0
  48. package/dist/src/code-execution/isolate/protocol.js.map +1 -0
  49. package/dist/src/code-execution/isolate/render.d.ts +57 -0
  50. package/dist/src/code-execution/isolate/render.d.ts.map +1 -0
  51. package/dist/src/code-execution/isolate/render.js +214 -0
  52. package/dist/src/code-execution/isolate/render.js.map +1 -0
  53. package/dist/src/code-execution/isolate/runner.d.ts +250 -0
  54. package/dist/src/code-execution/isolate/runner.d.ts.map +1 -0
  55. package/dist/src/code-execution/isolate/runner.js +854 -0
  56. package/dist/src/code-execution/isolate/runner.js.map +1 -0
  57. package/dist/src/code-execution/isolate/scripts.d.ts +175 -0
  58. package/dist/src/code-execution/isolate/scripts.d.ts.map +1 -0
  59. package/dist/src/code-execution/isolate/scripts.js +357 -0
  60. package/dist/src/code-execution/isolate/scripts.js.map +1 -0
  61. package/dist/src/code-execution/quickjs.wasm +0 -0
  62. package/dist/src/code-execution/tool-definition.d.ts +93 -43
  63. package/dist/src/code-execution/tool-definition.d.ts.map +1 -1
  64. package/dist/src/code-execution/tool-definition.js +176 -142
  65. package/dist/src/code-execution/tool-definition.js.map +1 -1
  66. package/dist/src/deadline-timer.d.ts +3 -0
  67. package/dist/src/deadline-timer.d.ts.map +1 -1
  68. package/dist/src/deadline-timer.js +1 -1
  69. package/dist/src/deadline-timer.js.map +1 -1
  70. package/dist/src/framework.d.ts +1027 -440
  71. package/dist/src/framework.d.ts.map +1 -1
  72. package/dist/src/framework.js +4093 -2238
  73. package/dist/src/framework.js.map +1 -1
  74. package/dist/src/gate/event-gate.d.ts +28 -1
  75. package/dist/src/gate/event-gate.d.ts.map +1 -1
  76. package/dist/src/gate/event-gate.js +88 -10
  77. package/dist/src/gate/event-gate.js.map +1 -1
  78. package/dist/src/held-writes.d.ts +16 -3
  79. package/dist/src/held-writes.d.ts.map +1 -1
  80. package/dist/src/held-writes.js +16 -3
  81. package/dist/src/held-writes.js.map +1 -1
  82. package/dist/src/index.d.ts +6 -6
  83. package/dist/src/index.d.ts.map +1 -1
  84. package/dist/src/index.js +9 -8
  85. package/dist/src/index.js.map +1 -1
  86. package/dist/src/mcpl/channel-registry.d.ts +471 -75
  87. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  88. package/dist/src/mcpl/channel-registry.js +1673 -337
  89. package/dist/src/mcpl/channel-registry.js.map +1 -1
  90. package/dist/src/mcpl/conversation-router.d.ts +12 -7
  91. package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
  92. package/dist/src/mcpl/conversation-router.js +12 -7
  93. package/dist/src/mcpl/conversation-router.js.map +1 -1
  94. package/dist/src/mcpl/convert-block.d.ts.map +1 -1
  95. package/dist/src/mcpl/convert-block.js +9 -5
  96. package/dist/src/mcpl/convert-block.js.map +1 -1
  97. package/dist/src/mcpl/inbound-source.d.ts +50 -0
  98. package/dist/src/mcpl/inbound-source.d.ts.map +1 -1
  99. package/dist/src/mcpl/inbound-source.js +130 -0
  100. package/dist/src/mcpl/inbound-source.js.map +1 -1
  101. package/dist/src/mcpl/index.d.ts +2 -1
  102. package/dist/src/mcpl/index.d.ts.map +1 -1
  103. package/dist/src/mcpl/index.js +3 -2
  104. package/dist/src/mcpl/index.js.map +1 -1
  105. package/dist/src/mcpl/log-value.d.ts +6 -0
  106. package/dist/src/mcpl/log-value.d.ts.map +1 -1
  107. package/dist/src/mcpl/log-value.js +8 -0
  108. package/dist/src/mcpl/log-value.js.map +1 -1
  109. package/dist/src/mcpl/modern-connection.d.ts +15 -6
  110. package/dist/src/mcpl/modern-connection.d.ts.map +1 -1
  111. package/dist/src/mcpl/modern-connection.js +168 -53
  112. package/dist/src/mcpl/modern-connection.js.map +1 -1
  113. package/dist/src/mcpl/prose-grammar.d.ts +4 -5
  114. package/dist/src/mcpl/prose-grammar.d.ts.map +1 -1
  115. package/dist/src/mcpl/prose-grammar.js +4 -5
  116. package/dist/src/mcpl/prose-grammar.js.map +1 -1
  117. package/dist/src/mcpl/protocol-family.d.ts +97 -10
  118. package/dist/src/mcpl/protocol-family.d.ts.map +1 -1
  119. package/dist/src/mcpl/protocol-family.js +173 -16
  120. package/dist/src/mcpl/protocol-family.js.map +1 -1
  121. package/dist/src/mcpl/push-coalescer.d.ts +132 -14
  122. package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
  123. package/dist/src/mcpl/push-coalescer.js +227 -50
  124. package/dist/src/mcpl/push-coalescer.js.map +1 -1
  125. package/dist/src/mcpl/push-handler.d.ts +6 -1
  126. package/dist/src/mcpl/push-handler.d.ts.map +1 -1
  127. package/dist/src/mcpl/push-handler.js +4 -1
  128. package/dist/src/mcpl/push-handler.js.map +1 -1
  129. package/dist/src/mcpl/reference-fetcher.d.ts +2 -2
  130. package/dist/src/mcpl/reference-fetcher.d.ts.map +1 -1
  131. package/dist/src/mcpl/reference-fetcher.js +4 -4
  132. package/dist/src/mcpl/reference-fetcher.js.map +1 -1
  133. package/dist/src/mcpl/server-connection.d.ts +50 -21
  134. package/dist/src/mcpl/server-connection.d.ts.map +1 -1
  135. package/dist/src/mcpl/server-connection.js +158 -74
  136. package/dist/src/mcpl/server-connection.js.map +1 -1
  137. package/dist/src/mcpl/tags.d.ts +24 -0
  138. package/dist/src/mcpl/tags.d.ts.map +1 -1
  139. package/dist/src/mcpl/tags.js +33 -0
  140. package/dist/src/mcpl/tags.js.map +1 -1
  141. package/dist/src/mcpl/tool-result-normalize.d.ts +2 -1
  142. package/dist/src/mcpl/tool-result-normalize.d.ts.map +1 -1
  143. package/dist/src/mcpl/tool-result-normalize.js.map +1 -1
  144. package/dist/src/mcpl/transport.d.ts +55 -7
  145. package/dist/src/mcpl/transport.d.ts.map +1 -1
  146. package/dist/src/mcpl/transport.js +163 -34
  147. package/dist/src/mcpl/transport.js.map +1 -1
  148. package/dist/src/mcpl/types.d.ts +22 -6
  149. package/dist/src/mcpl/types.d.ts.map +1 -1
  150. package/dist/src/mcpl/types.js.map +1 -1
  151. package/dist/src/module-registry.d.ts +4 -2
  152. package/dist/src/module-registry.d.ts.map +1 -1
  153. package/dist/src/module-registry.js +100 -13
  154. package/dist/src/module-registry.js.map +1 -1
  155. package/dist/src/modules/discord/index.d.ts.map +1 -1
  156. package/dist/src/modules/discord/index.js +8 -13
  157. package/dist/src/modules/discord/index.js.map +1 -1
  158. package/dist/src/modules/history/index.d.ts.map +1 -1
  159. package/dist/src/modules/history/index.js +27 -4
  160. package/dist/src/modules/history/index.js.map +1 -1
  161. package/dist/src/modules/history/semantic.d.ts +15 -3
  162. package/dist/src/modules/history/semantic.d.ts.map +1 -1
  163. package/dist/src/modules/history/semantic.js +27 -5
  164. package/dist/src/modules/history/semantic.js.map +1 -1
  165. package/dist/src/modules/index.d.ts +1 -1
  166. package/dist/src/modules/index.d.ts.map +1 -1
  167. package/dist/src/modules/index.js.map +1 -1
  168. package/dist/src/modules/unknown-tool.d.ts +4 -1
  169. package/dist/src/modules/unknown-tool.d.ts.map +1 -1
  170. package/dist/src/modules/unknown-tool.js +4 -1
  171. package/dist/src/modules/unknown-tool.js.map +1 -1
  172. package/dist/src/modules/workspace/branch-intent.d.ts +3 -1
  173. package/dist/src/modules/workspace/branch-intent.d.ts.map +1 -1
  174. package/dist/src/modules/workspace/branch-intent.js +3 -1
  175. package/dist/src/modules/workspace/branch-intent.js.map +1 -1
  176. package/dist/src/modules/workspace/edit-plan.d.ts +265 -0
  177. package/dist/src/modules/workspace/edit-plan.d.ts.map +1 -0
  178. package/dist/src/modules/workspace/edit-plan.js +794 -0
  179. package/dist/src/modules/workspace/edit-plan.js.map +1 -0
  180. package/dist/src/modules/workspace/edit-text.d.ts +117 -0
  181. package/dist/src/modules/workspace/edit-text.d.ts.map +1 -0
  182. package/dist/src/modules/workspace/edit-text.js +584 -0
  183. package/dist/src/modules/workspace/edit-text.js.map +1 -0
  184. package/dist/src/modules/workspace/effects.d.ts +5 -4
  185. package/dist/src/modules/workspace/effects.d.ts.map +1 -1
  186. package/dist/src/modules/workspace/effects.js +78 -25
  187. package/dist/src/modules/workspace/effects.js.map +1 -1
  188. package/dist/src/modules/workspace/index.d.ts +484 -61
  189. package/dist/src/modules/workspace/index.d.ts.map +1 -1
  190. package/dist/src/modules/workspace/index.js +2173 -645
  191. package/dist/src/modules/workspace/index.js.map +1 -1
  192. package/dist/src/modules/workspace/observe.d.ts +213 -38
  193. package/dist/src/modules/workspace/observe.d.ts.map +1 -1
  194. package/dist/src/modules/workspace/observe.js +416 -36
  195. package/dist/src/modules/workspace/observe.js.map +1 -1
  196. package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
  197. package/dist/src/modules/workspace/reconcile.js +15 -8
  198. package/dist/src/modules/workspace/reconcile.js.map +1 -1
  199. package/dist/src/modules/workspace/text.d.ts +32 -0
  200. package/dist/src/modules/workspace/text.d.ts.map +1 -0
  201. package/dist/src/modules/workspace/text.js +67 -0
  202. package/dist/src/modules/workspace/text.js.map +1 -0
  203. package/dist/src/modules/workspace/types.d.ts +210 -6
  204. package/dist/src/modules/workspace/types.d.ts.map +1 -1
  205. package/dist/src/modules/workspace/types.js.map +1 -1
  206. package/dist/src/modules/workspace/watcher.d.ts +3 -2
  207. package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
  208. package/dist/src/modules/workspace/watcher.js.map +1 -1
  209. package/dist/src/operator-log.d.ts +52 -24
  210. package/dist/src/operator-log.d.ts.map +1 -1
  211. package/dist/src/operator-log.js.map +1 -1
  212. package/dist/src/recovery/discord-awareness-outbox.d.ts +496 -72
  213. package/dist/src/recovery/discord-awareness-outbox.d.ts.map +1 -1
  214. package/dist/src/recovery/discord-awareness-outbox.js +1196 -289
  215. package/dist/src/recovery/discord-awareness-outbox.js.map +1 -1
  216. package/dist/src/recovery/offline-branch.d.ts +26 -1
  217. package/dist/src/recovery/offline-branch.d.ts.map +1 -1
  218. package/dist/src/recovery/offline-branch.js +164 -39
  219. package/dist/src/recovery/offline-branch.js.map +1 -1
  220. package/dist/src/recovery/recover-cli.js +23 -4
  221. package/dist/src/recovery/recover-cli.js.map +1 -1
  222. package/dist/src/send-tools.d.ts +11 -0
  223. package/dist/src/send-tools.d.ts.map +1 -0
  224. package/dist/src/send-tools.js +11 -0
  225. package/dist/src/send-tools.js.map +1 -0
  226. package/dist/src/tool-result-guard.d.ts +4 -3
  227. package/dist/src/tool-result-guard.d.ts.map +1 -1
  228. package/dist/src/tool-result-guard.js +5 -4
  229. package/dist/src/tool-result-guard.js.map +1 -1
  230. package/dist/src/tool-result-history.d.ts +1 -1
  231. package/dist/src/tool-result-history.js +1 -1
  232. package/dist/src/tune-out/coordinator.d.ts +21 -0
  233. package/dist/src/tune-out/coordinator.d.ts.map +1 -1
  234. package/dist/src/tune-out/coordinator.js +139 -37
  235. package/dist/src/tune-out/coordinator.js.map +1 -1
  236. package/dist/src/types/agent.d.ts +4 -0
  237. package/dist/src/types/agent.d.ts.map +1 -1
  238. package/dist/src/types/events.d.ts +62 -9
  239. package/dist/src/types/events.d.ts.map +1 -1
  240. package/dist/src/types/framework.d.ts +62 -58
  241. package/dist/src/types/framework.d.ts.map +1 -1
  242. package/dist/src/types/module.d.ts +40 -8
  243. package/dist/src/types/module.d.ts.map +1 -1
  244. package/dist/src/types/trace.d.ts +111 -10
  245. package/dist/src/types/trace.d.ts.map +1 -1
  246. package/dist/src/usage/types.d.ts +16 -0
  247. package/dist/src/usage/types.d.ts.map +1 -1
  248. package/dist/src/usage/usage-tracker.d.ts +14 -1
  249. package/dist/src/usage/usage-tracker.d.ts.map +1 -1
  250. package/dist/src/usage/usage-tracker.js +81 -41
  251. package/dist/src/usage/usage-tracker.js.map +1 -1
  252. package/package.json +6 -5
  253. package/src/agent.ts +93 -12
  254. package/src/api/server.ts +14 -12
  255. package/src/code-execution/engine.ts +595 -0
  256. package/src/code-execution/index.ts +5 -17
  257. package/src/code-execution/isolate/calls.ts +199 -0
  258. package/src/code-execution/isolate/child-entry.ts +5 -0
  259. package/src/code-execution/isolate/child-main.ts +132 -0
  260. package/src/code-execution/isolate/child.ts +327 -0
  261. package/src/code-execution/isolate/frames.ts +209 -0
  262. package/src/code-execution/isolate/output.ts +161 -0
  263. package/src/code-execution/isolate/prelude.ts +409 -0
  264. package/src/code-execution/isolate/protocol.ts +240 -0
  265. package/src/code-execution/isolate/render.ts +230 -0
  266. package/src/code-execution/isolate/runner.ts +911 -0
  267. package/src/code-execution/isolate/scripts.ts +479 -0
  268. package/src/code-execution/quickjs.wasm +0 -0
  269. package/src/code-execution/quickjs.wasm.LICENSES +149 -0
  270. package/src/code-execution/tool-definition.ts +236 -167
  271. package/src/deadline-timer.ts +1 -1
  272. package/src/framework.ts +4468 -2418
  273. package/src/gate/event-gate.ts +78 -11
  274. package/src/held-writes.ts +17 -3
  275. package/src/index.ts +30 -22
  276. package/src/mcpl/channel-registry.ts +1825 -368
  277. package/src/mcpl/conversation-router.ts +12 -7
  278. package/src/mcpl/convert-block.ts +9 -5
  279. package/src/mcpl/inbound-source.ts +131 -0
  280. package/src/mcpl/index.ts +4 -2
  281. package/src/mcpl/log-value.ts +9 -0
  282. package/src/mcpl/modern-connection.ts +162 -53
  283. package/src/mcpl/prose-grammar.ts +4 -5
  284. package/src/mcpl/protocol-family.ts +199 -21
  285. package/src/mcpl/push-coalescer.ts +306 -62
  286. package/src/mcpl/push-handler.ts +10 -2
  287. package/src/mcpl/reference-fetcher.ts +4 -4
  288. package/src/mcpl/server-connection.ts +180 -79
  289. package/src/mcpl/tags.ts +36 -0
  290. package/src/mcpl/tool-result-normalize.ts +2 -1
  291. package/src/mcpl/transport.ts +162 -33
  292. package/src/mcpl/types.ts +23 -6
  293. package/src/module-registry.ts +92 -13
  294. package/src/modules/discord/index.ts +8 -13
  295. package/src/modules/history/index.ts +25 -3
  296. package/src/modules/history/semantic.ts +29 -6
  297. package/src/modules/index.ts +1 -0
  298. package/src/modules/unknown-tool.ts +4 -1
  299. package/src/modules/workspace/branch-intent.ts +3 -1
  300. package/src/modules/workspace/edit-plan.ts +954 -0
  301. package/src/modules/workspace/edit-text.ts +618 -0
  302. package/src/modules/workspace/effects.ts +70 -19
  303. package/src/modules/workspace/index.ts +2247 -642
  304. package/src/modules/workspace/observe.ts +465 -56
  305. package/src/modules/workspace/reconcile.ts +14 -7
  306. package/src/modules/workspace/text.ts +68 -0
  307. package/src/modules/workspace/types.ts +211 -6
  308. package/src/modules/workspace/watcher.ts +3 -2
  309. package/src/operator-log.ts +47 -19
  310. package/src/recovery/discord-awareness-outbox.ts +1500 -356
  311. package/src/recovery/offline-branch.ts +189 -55
  312. package/src/recovery/recover-cli.ts +25 -4
  313. package/src/send-tools.ts +11 -0
  314. package/src/tool-result-guard.ts +6 -5
  315. package/src/tool-result-history.ts +1 -1
  316. package/src/tune-out/coordinator.ts +163 -42
  317. package/src/types/agent.ts +4 -0
  318. package/src/types/events.ts +62 -9
  319. package/src/types/framework.ts +62 -58
  320. package/src/types/module.ts +40 -8
  321. package/src/types/trace.ts +121 -15
  322. package/src/usage/types.ts +16 -0
  323. package/src/usage/usage-tracker.ts +86 -43
  324. package/dist/src/code-execution/py-runner.d.ts +0 -191
  325. package/dist/src/code-execution/py-runner.d.ts.map +0 -1
  326. package/dist/src/code-execution/py-runner.js +0 -655
  327. package/dist/src/code-execution/py-runner.js.map +0 -1
  328. package/dist/src/code-execution/runtime-py.d.ts +0 -50
  329. package/dist/src/code-execution/runtime-py.d.ts.map +0 -1
  330. package/dist/src/code-execution/runtime-py.js +0 -677
  331. package/dist/src/code-execution/runtime-py.js.map +0 -1
  332. package/dist/src/mcpl/prose-stream-router.d.ts +0 -88
  333. package/dist/src/mcpl/prose-stream-router.d.ts.map +0 -1
  334. package/dist/src/mcpl/prose-stream-router.js +0 -291
  335. package/dist/src/mcpl/prose-stream-router.js.map +0 -1
  336. package/src/code-execution/py-runner.ts +0 -791
  337. package/src/code-execution/runtime-py.ts +0 -677
  338. package/src/mcpl/prose-stream-router.ts +0 -268
@@ -13,23 +13,35 @@ import { openTransport, STDERR_END_WAIT_MS } from './transport.js';
13
13
  import { maskNegotiatedCapabilities } from './capability-mask.js';
14
14
  import { CapabilityGrant, expandAdvertisementShorthand } from './capability-grant.js';
15
15
  import { CAPABILITY_DISABLED, boundedForLog, describeCause } from './errors.js';
16
- import { logDetail, logValue, logValueRedacted } from './log-value.js';
17
- import { LEGACY_MCP_PROTOCOL_VERSION, MODERN_MCP_PROTOCOL_VERSION, checkServerConfig, redactServerText, } from './protocol-family.js';
16
+ import { logDetail, logValue, logValueRedacted, loggedCode } from './log-value.js';
17
+ import { LEGACY_MCP_PROTOCOL_VERSION, MODERN_MCP_PROTOCOL_VERSION, checkServerConfig, redactServerText, redactedData, serverTextRedactor, } from './protocol-family.js';
18
18
  import { McplMethod } from './types.js';
19
19
  /** Timeout for the initialize handshake in milliseconds.
20
20
  * Spring Boot + JDA servers can take 5-10s to boot, so 30s is safe. */
21
21
  const INITIALIZE_TIMEOUT_MS = 30_000;
22
+ /** How many errors down a `cause` chain stderrTailOf looks. */
23
+ const STDERR_TAIL_CAUSE_LINKS = 8;
22
24
  /** A failed connect's `stderrTail`, the last of the server's stderr that its
23
- * handshake's error keeps, when there is one. */
25
+ * handshake's error keeps, when there is one: the error's own, or the
26
+ * nearest one in its `cause` chain, since a launch that couldn't be reaped
27
+ * (McplUnreapedLaunchError) and the framework's refusals wrap the
28
+ * handshake's error. It looks at most STDERR_TAIL_CAUSE_LINKS causes down,
29
+ * so a chain that loops ends. */
24
30
  export function stderrTailOf(error) {
25
- const tail = error?.stderrTail;
26
- return typeof tail === 'string' && tail !== '' ? tail : undefined;
31
+ let at = error;
32
+ for (let link = 0; link <= STDERR_TAIL_CAUSE_LINKS && typeof at === 'object' && at !== null; link++) {
33
+ const { stderrTail, cause } = at;
34
+ if (typeof stderrTail === 'string' && stderrTail !== '')
35
+ return stderrTail;
36
+ at = cause;
37
+ }
38
+ return undefined;
27
39
  }
28
40
  /** For the host's own log line about a failed connect: the server's stderr
29
- * that the error keeps as `stderrTail`, with the server's credentials
30
- * taken out by `redact` (its redactServerText), one marked line per line of
31
- * it, each through log-value, since it's the server's text. '' when there's
32
- * none. */
41
+ * that the error, or the nearest error it wraps, keeps as `stderrTail`
42
+ * (stderrTailOf), with the server's credentials taken out by `redact` (its
43
+ * redactServerText), one marked line per line of it, each through
44
+ * log-value, since it's the server's text. '' when there's none. */
33
45
  export function withStderr(error, redact) {
34
46
  const tail = stderrTailOf(error);
35
47
  if (tail === undefined)
@@ -90,11 +102,13 @@ export class McplProtocolVersionError extends Error {
90
102
  data;
91
103
  offered;
92
104
  constructor(message, kind,
93
- /** Revision the server answered with (`mismatch`; null when it gave none). */
105
+ /** Revision the server answered with (`mismatch`; null when it gave
106
+ * none), redacted as the server's words are. */
94
107
  returned,
95
108
  /** Revisions the server says it supports (`rejected`, when stated). */
96
109
  supported,
97
- /** The JSON-RPC error's code and data, verbatim (`rejected`). */
110
+ /** The JSON-RPC error's code, and its data with each string in it
111
+ * redacted (`rejected`). */
98
112
  code, data,
99
113
  /** The revision this client offered: the legacy engine's, unless a
100
114
  * modern connection's. */
@@ -109,8 +123,13 @@ export class McplProtocolVersionError extends Error {
109
123
  this.name = 'McplProtocolVersionError';
110
124
  }
111
125
  }
112
- function protocolVersionRejection(id, error) {
113
- const data = error.data;
126
+ function protocolVersionRejection(config, error) {
127
+ const id = config.id;
128
+ // The server's words and data, redacted before they're bounded or kept:
129
+ // the error goes to the host. One build for all of them, so a
130
+ // configuration that can't be read is read once.
131
+ const redact = serverTextRedactor(config).now();
132
+ const data = redactedData(error.data, redact);
114
133
  const supported = Array.isArray(data?.supported) && data.supported.every((v) => typeof v === 'string')
115
134
  ? data.supported
116
135
  : null;
@@ -119,9 +138,10 @@ function protocolVersionRejection(id, error) {
119
138
  : '';
120
139
  return new McplProtocolVersionError(`MCPL server "${id}" does not support MCP ${MCP_PROTOCOL_VERSION}` +
121
140
  // The server's message can be any JSON value, so it's read without
122
- // throwing (describeCause) and bounded, as the initialize error is.
123
- (supported ? ` (it supports: ${supported.join(', ') || 'none listed'}).` : ` (${boundedForLog(describeCause(error.message))}).`) +
124
- modernHint, 'rejected', null, supported, error.code, error.data);
141
+ // throwing (describeCause), and redacted, then bounded, as the
142
+ // initialize error is.
143
+ (supported ? ` (it supports: ${boundedForLog(supported.join(', ')) || 'none listed'}).` : ` (${boundedForLog(redact(describeCause(error.message)))}).`) +
144
+ modernHint, 'rejected', null, supported, error.code, data);
125
145
  }
126
146
  const errorOf = (value) => (value instanceof Error ? value : new Error(String(value)));
127
147
  /**
@@ -147,17 +167,18 @@ class HandshakeCleanupError extends Error {
147
167
  * is confirmed, so the caller can still clean up, and should start nothing
148
168
  * else for this server until then. connect() and connectWithReconnect()
149
169
  * throw this, and the modern engine's ModernMcpConnection.connect() too.
150
- * `cause` is the connect's own failure.
170
+ * `cause` is the connect's own failure. `connection` isn't enumerable, so
171
+ * printing the error doesn't print the connection's configuration, its
172
+ * credentials included.
151
173
  */
152
174
  export class McplUnreapedLaunchError extends Error {
153
- connection;
154
175
  cleanup;
155
176
  constructor(connection, failure,
156
177
  /** The cleanup's own failure: the child it couldn't confirm exited. */
157
178
  cleanup) {
158
179
  super(`${failure.message}; its cleanup also failed: ${cleanup.message}`, { cause: failure });
159
- this.connection = connection;
160
180
  this.cleanup = cleanup;
181
+ Object.defineProperty(this, 'connection', { value: connection, enumerable: false });
161
182
  this.name = 'McplUnreapedLaunchError';
162
183
  }
163
184
  }
@@ -179,8 +200,9 @@ export class McplRequestError extends Error {
179
200
  outcome;
180
201
  data;
181
202
  constructor(message, outcome,
182
- /** The JSON-RPC error's `data`, verbatim, when the server supplied one
183
- * (e.g. which parts of a multi-part send were posted). */
203
+ /** The JSON-RPC error's `data`, when the server supplied one (e.g. which
204
+ * parts of a multi-part send were posted), with each string in it
205
+ * redacted (redactedData): a host hands it on. */
184
206
  data) {
185
207
  super(message);
186
208
  this.outcome = outcome;
@@ -405,8 +427,8 @@ export class McplServerConnection extends EventEmitter {
405
427
  publishDeadlineMs = DEFAULT_REQUEST_TIMEOUT_MS;
406
428
  // Event buffering: control-plane traffic can be released independently from
407
429
  // inference-bearing data-plane traffic. This lets a server finish its own
408
- // registration (and answer host tools/call requests) while startup/reconnect
409
- // reconciliation keeps agent wakes behind a durable barrier.
430
+ // registration (and answer host tools/call requests) while its data plane
431
+ // stays held, as through a quiesce.
410
432
  controlPlaneReady = false;
411
433
  dataPlaneReady = false;
412
434
  bufferedEvents = [];
@@ -443,6 +465,15 @@ export class McplServerConnection extends EventEmitter {
443
465
  refusedHeldRequests = 0;
444
466
  // Reconnect state (adapted from Anarchid/agent-framework@mcpl-module-proto)
445
467
  config = null;
468
+ /** The redactor of the server's text for `config`, made at its first error
469
+ * answer, by when `config` is set, and kept: a framework-launched child's
470
+ * `env` is a getter that reads the awareness ledger, so a redactor built
471
+ * per answer would read it per answer (#540's review, R1-2). An answer
472
+ * takes one build of it for its words, data and log line (`now()`), so
473
+ * it reads the ledger at most once. It builds again only after a build
474
+ * that failed, which withholds that answer's text, or once a dial notes
475
+ * something new (serverTextRedactor). */
476
+ redactor = null;
446
477
  hostCapabilities = null;
447
478
  reconnectEnabled = false;
448
479
  reconnectIntervalMs = 5000;
@@ -528,8 +559,8 @@ export class McplServerConnection extends EventEmitter {
528
559
  console.error(`[mcpl] ${this.id}: flushing ${pending.length} buffered event(s) synchronously ` +
529
560
  `(long pause backlog${dropped > 0 ? `; ${dropped} dropped at cap` : ''})`);
530
561
  }
531
- // Re-enter the gate for every buffered item. A control handler (notably
532
- // tools/list_changed) may install a newer data-plane barrier while this
562
+ // Re-enter the gate for every buffered item. A control handler (a
563
+ // host/command quiesce, say) may pause the data plane while this
533
564
  // snapshot is being flushed; later data items must observe that pause.
534
565
  this.flushHeld(pending);
535
566
  }
@@ -695,17 +726,16 @@ export class McplServerConnection extends EventEmitter {
695
726
  }
696
727
  /**
697
728
  * Close the data plane synchronously while leaving an already-released
698
- * control plane live. Used before list-change reconciliation so no new
699
- * inference event can beat barrier installation. A reconnect closes both
700
- * planes instead.
729
+ * control plane live. Used by quiesce, and by reconnectAfterFailure before
730
+ * its teardown. A reconnect closes both planes instead.
701
731
  */
702
732
  pauseDataPlane() {
703
733
  this.dataPlaneReady = false;
704
734
  }
705
735
  /**
706
736
  * Override emit to buffer server→host events until the corresponding plane
707
- * is ready. Lifecycle events always pass through so reconnect can install a
708
- * new data-plane gate before the fresh transport is exposed.
737
+ * is ready. Lifecycle events always pass through so the reconnect listener
738
+ * runs before the fresh transport's buffered traffic is released.
709
739
  */
710
740
  emit(event, ...args) {
711
741
  const name = typeof event === 'string' ? event : '';
@@ -999,18 +1029,21 @@ export class McplServerConnection extends EventEmitter {
999
1029
  clientInfo: { name: 'agent-framework', version: '1.0.0' },
1000
1030
  },
1001
1031
  };
1032
+ // When the transport fails, the end of the server's stderr often says
1033
+ // why, such as a missing token or a crash at startup. It goes on the
1034
+ // error as `stderrTail`, never into the message: an error's message
1035
+ // travels to traces and tool results, and a server's stderr is its own
1036
+ // text, which can hold a credential.
1037
+ const failed = (failure) => {
1038
+ // It goes to the host too, so it's redacted, from a window of the
1039
+ // stream longer than the tail, so a credential the tail's cut
1040
+ // would split is whole when it's matched (stderrTailRedacted).
1041
+ const tail = transport.stderrTailRedacted(serverTextRedactor(config)).trimEnd();
1042
+ return Object.assign(new Error(failure), tail ? { stderrTail: tail } : {});
1043
+ };
1002
1044
  // Await the initialize response, racing an early transport close/error,
1003
1045
  // a timeout and the owner's close. Every path cleans up its listeners.
1004
1046
  const { mcpl: rawCapabilities, mcpToolsAdvertised, protocolVersion } = await new Promise((resolve, reject) => {
1005
- // When the transport fails, the end of the server's stderr often says
1006
- // why, such as a missing token or a crash at startup. It goes on the
1007
- // error as `stderrTail`, never into the message: an error's message
1008
- // travels to traces and tool results, and a server's stderr is its
1009
- // own text, which can hold a credential.
1010
- const failed = (failure) => {
1011
- const tail = transport.stderrTail.trimEnd();
1012
- return Object.assign(new Error(failure), tail ? { stderrTail: tail } : {});
1013
- };
1014
1047
  const cleanup = () => {
1015
1048
  transport.off('line', onLine);
1016
1049
  transport.off('close', onClose);
@@ -1055,20 +1088,24 @@ export class McplServerConnection extends EventEmitter {
1055
1088
  // listener after cleanup() has cleared the timeout: an uncaught
1056
1089
  // exception, which ends a host that doesn't catch them, and a
1057
1090
  // handshake left to wait forever. It's the server's text in an
1058
- // error's message, so it's bounded as errors.ts says.
1091
+ // error the host gets, so it's redacted, then bounded as
1092
+ // errors.ts says: a cut or a replaced character first would
1093
+ // leave part of a credential the redactor can't match.
1059
1094
  reject(msg.error.code === UNSUPPORTED_PROTOCOL_VERSION_CODE
1060
- ? protocolVersionRejection(config.id, msg.error)
1061
- : new Error(`MCPL server "${config.id}" initialize error: ${boundedForLog(describeCause(msg.error.message))}`));
1095
+ ? protocolVersionRejection(config, msg.error)
1096
+ : new Error(`MCPL server "${config.id}" initialize error: ${boundedForLog(redactServerText(describeCause(msg.error.message), config))}`));
1062
1097
  return;
1063
1098
  }
1064
1099
  const result = msg.result;
1065
1100
  // The server's answer is the established revision. This engine
1066
1101
  // implements exactly one, so any other answer (or none) means the
1067
1102
  // two sides never agreed on what they're speaking.
1068
- const returned = typeof result?.protocolVersion === 'string' ? result.protocolVersion : null;
1069
- if (returned !== MCP_PROTOCOL_VERSION) {
1103
+ const answered = typeof result?.protocolVersion === 'string' ? result.protocolVersion : null;
1104
+ if (answered !== MCP_PROTOCOL_VERSION) {
1105
+ // The server's words go to the host, so they're redacted.
1106
+ const returned = answered === null ? null : redactServerText(answered, config);
1070
1107
  reject(new McplProtocolVersionError(`MCPL server "${config.id}" answered initialize with protocolVersion ` +
1071
- `${returned === null ? '(none)' : JSON.stringify(returned)}; this client's legacy engine speaks only ${MCP_PROTOCOL_VERSION}`, 'mismatch', returned, null));
1108
+ `${returned === null ? '(none)' : boundedForLog(JSON.stringify(returned))}; this client's legacy engine speaks only ${MCP_PROTOCOL_VERSION}`, 'mismatch', returned, null));
1072
1109
  return;
1073
1110
  }
1074
1111
  const caps = result?.capabilities;
@@ -1079,7 +1116,7 @@ export class McplServerConnection extends EventEmitter {
1079
1116
  resolve({
1080
1117
  mcpl: experimental?.mcpl ?? null,
1081
1118
  mcpToolsAdvertised: caps?.tools !== undefined,
1082
- protocolVersion: returned,
1119
+ protocolVersion: answered,
1083
1120
  });
1084
1121
  };
1085
1122
  const onClose = (info) => {
@@ -1107,6 +1144,22 @@ export class McplServerConnection extends EventEmitter {
1107
1144
  transport.on('error', onError);
1108
1145
  transport.writeLine(JSON.stringify(initRequest));
1109
1146
  });
1147
+ // The transport has found the child's stdin or stdout failed before the
1148
+ // handshake could hand it on, such as when this host's answer to a ping
1149
+ // the server sent met EPIPE. Nothing more is written to the child then,
1150
+ // so the connection couldn't serve. It's read here, once the answer has
1151
+ // passed its own checks, rather than as the answer arrives: a write's
1152
+ // EPIPE is reported only once the callback that wrote it has returned,
1153
+ // so a ping and the answer read in one callback would pass a check made
1154
+ // there. A child that outlived SIGKILL may already have said so with
1155
+ // nothing listening (the transport's 'unreaped' is wired only once the
1156
+ // handshake hands it on). So the handshake fails, and its cleanup holds
1157
+ // the launch if it can't reap the child. A failure of the write below
1158
+ // is reported only once the caller has wired the transport, so it
1159
+ // reaches the connection as a loss, like any later one.
1160
+ const pipeFailure = transport.pipeFailure;
1161
+ if (pipeFailure)
1162
+ throw failed(`MCPL server "${config.id}" stdio pipe failed with ${pipeFailure.message} during the handshake`);
1110
1163
  // Send `initialized` notification (no id)
1111
1164
  transport.writeLine(JSON.stringify({ jsonrpc: '2.0', method: 'notifications/initialized' }));
1112
1165
  // §5.1 boolean shorthand expands to explicit leaves BEFORE the config
@@ -1282,9 +1335,13 @@ export class McplServerConnection extends EventEmitter {
1282
1335
  const timeoutMs = this.requestTimeoutMs > 0 ? this.requestTimeoutMs : this.publishDeadlineMs;
1283
1336
  return this.sendRequest(McplMethod.ChannelsOpen, params, { timeoutMs });
1284
1337
  }
1285
- /** Send `channels/close` request and await result. */
1338
+ /** Send `channels/close` request and await result. It keeps a deadline as
1339
+ * channels/open does: a delivery waits for a channel's queued lifecycle
1340
+ * work, closes included, so a close that is never answered would hold the
1341
+ * delivery, and the turn that waits for it, for good. */
1286
1342
  sendChannelsClose(params) {
1287
- return this.sendRequest(McplMethod.ChannelsClose, params);
1343
+ const timeoutMs = this.requestTimeoutMs > 0 ? this.requestTimeoutMs : this.publishDeadlineMs;
1344
+ return this.sendRequest(McplMethod.ChannelsClose, params, { timeoutMs });
1288
1345
  }
1289
1346
  /** Send `channels/acknowledge` request and await result. */
1290
1347
  sendChannelsAcknowledge(params) {
@@ -1367,10 +1424,11 @@ export class McplServerConnection extends EventEmitter {
1367
1424
  return { ...rest, tools };
1368
1425
  }
1369
1426
  if (typeof result.nextCursor !== 'string') {
1370
- throw malformed(`nextCursor must be a string, got ${JSON.stringify(result.nextCursor)}`);
1427
+ // The cursor is the server's, so it's redacted, then bounded.
1428
+ throw malformed(`nextCursor must be a string, got ${boundedForLog(redactServerText(JSON.stringify(result.nextCursor), this.config ?? {}))}`);
1371
1429
  }
1372
1430
  if (seen.has(result.nextCursor)) {
1373
- throw new Error(`MCPL server "${this.id}" repeated tools/list cursor ${JSON.stringify(result.nextCursor)}`);
1431
+ throw new Error(`MCPL server "${this.id}" repeated tools/list cursor ${boundedForLog(redactServerText(JSON.stringify(result.nextCursor), this.config ?? {}))}`);
1374
1432
  }
1375
1433
  seen.add(result.nextCursor);
1376
1434
  cursor = result.nextCursor;
@@ -1662,9 +1720,8 @@ export class McplServerConnection extends EventEmitter {
1662
1720
  // boundary resets, so control traffic too (a server's channels/register
1663
1721
  // right after initialize) must wait for the new grant rather than be
1664
1722
  // refused against the empty one. The reconnect lifecycle event bypasses
1665
- // buffering; its framework listener installs the awareness barrier,
1666
- // re-establishes the grant (§5.3 policy responses are never buffered),
1667
- // and then opens the planes.
1723
+ // buffering; its framework listener re-establishes the grant (§5.3
1724
+ // policy responses are never buffered), and then opens the planes.
1668
1725
  this.controlPlaneReady = false;
1669
1726
  this.dataPlaneReady = false;
1670
1727
  this.resetPolicyForTransportBoundary();
@@ -1685,6 +1742,17 @@ export class McplServerConnection extends EventEmitter {
1685
1742
  // ==========================================================================
1686
1743
  // Private: message sending
1687
1744
  // ==========================================================================
1745
+ /**
1746
+ * A request refused before anything is kept for it, as `error`, with its
1747
+ * operator's line logged after the refusal: a host logger that throws then
1748
+ * loses that line, and can't turn the refusal into a throw from the call.
1749
+ */
1750
+ static refused(error, line) {
1751
+ return new Promise((_, reject) => {
1752
+ reject(error);
1753
+ console.error(line);
1754
+ });
1755
+ }
1688
1756
  /**
1689
1757
  * Send a JSON-RPC request and return a promise that resolves with the result
1690
1758
  * or rejects with a JSON-RPC error.
@@ -1716,11 +1784,10 @@ export class McplServerConnection extends EventEmitter {
1716
1784
  // pipe's error are the operator's, so they go to the log.
1717
1785
  const pipeFailure = this.transport?.pipeFailure;
1718
1786
  if (pipeFailure) {
1719
- console.error(`MCPL server "${this.id}": ${method} not sent, since its stdio pipe failed: ${logDetail(pipeFailure.message)}`);
1720
- return Promise.reject(new McplRequestError(`The request wasn't sent: this host can no longer write to the "${this.id}" server, so nothing ran. ` +
1787
+ return McplServerConnection.refused(new McplRequestError(`The request wasn't sent: this host can no longer write to the "${this.id}" server, so nothing ran. ` +
1721
1788
  (this.willReconnect
1722
1789
  ? 'This host is reconnecting to it; try again later.'
1723
- : "This host won't reconnect to it on its own. If you need it, ask whoever runs this host."), 'not-sent'));
1790
+ : "This host won't reconnect to it on its own. If you need it, ask whoever runs this host."), 'not-sent'), `MCPL server "${this.id}": ${method} not sent, since its stdio pipe failed: ${logDetail(pipeFailure.message)}`);
1724
1791
  }
1725
1792
  const id = this.nextRequestId++;
1726
1793
  const request = {
@@ -1729,6 +1796,18 @@ export class McplServerConnection extends EventEmitter {
1729
1796
  id,
1730
1797
  params,
1731
1798
  };
1799
+ // A request JSON can't write (a BigInt, a cycle) never leaves this host,
1800
+ // and calling again fails the same way, so it's refused before anything
1801
+ // is kept for it, in the modern engine's words (#556). The method, id and
1802
+ // the serializer's words are the operator's.
1803
+ let line;
1804
+ try {
1805
+ line = JSON.stringify(request);
1806
+ }
1807
+ catch (err) {
1808
+ return McplServerConnection.refused(new McplRequestError(`The request wasn't sent: this host couldn't send it to the "${this.id}" server, so nothing ran. ` +
1809
+ 'If calling it again fails, ask whoever runs this host.', 'not-sent'), `MCPL server "${this.id}": ${method} (id=${id}) not sent, since it can't be written as JSON: ${logDetail(err instanceof Error ? err.message : err)}`);
1810
+ }
1732
1811
  return new Promise((resolve, reject) => {
1733
1812
  const pending = { resolve, reject, method };
1734
1813
  const timeoutMs = options.timeoutMs ?? this.requestTimeoutMs;
@@ -1766,17 +1845,18 @@ export class McplServerConnection extends EventEmitter {
1766
1845
  }
1767
1846
  this.pendingRequests.set(id, pending);
1768
1847
  try {
1769
- this.transport.writeLine(JSON.stringify(request));
1848
+ this.transport.writeLine(line);
1770
1849
  }
1771
1850
  catch (err) {
1772
1851
  // A synchronous write rejection sent no request. Remove its pending
1773
1852
  // state and watchdog before reporting that it is safe to retry. The
1774
- // method, id and the transport's words are the operator's.
1853
+ // method, id and the transport's words are the operator's, logged
1854
+ // after the refusal, as refused() logs.
1775
1855
  this.pendingRequests.delete(id);
1776
1856
  if (pending.timer)
1777
1857
  clearTimeout(pending.timer);
1778
- console.error(`MCPL server "${this.id}": writing ${method} (id=${id}) failed: ${logDetail(err instanceof Error ? err.message : err)}`);
1779
1858
  reject(new McplRequestError(`The request wasn't sent: this host couldn't write it to the "${this.id}" server, so nothing ran. Try again later.`, 'not-sent'));
1859
+ console.error(`MCPL server "${this.id}": writing ${method} (id=${id}) failed: ${logDetail(err instanceof Error ? err.message : err)}`);
1780
1860
  }
1781
1861
  });
1782
1862
  }
@@ -2117,16 +2197,18 @@ export class McplServerConnection extends EventEmitter {
2117
2197
  if (pending.timer)
2118
2198
  clearTimeout(pending.timer);
2119
2199
  if (response.error) {
2120
- // The server's own words, after a word on whose they are, bounded as
2121
- // errors.ts says, since they're the server's text. Only a string is
2122
- // words: a message of any other JSON value reads as none. The method,
2123
- // id and JSON-RPC code are the operator's, so they go to the log, which
2124
- // prints any value a server can send without throwing (logValue). The
2125
- // caller's text keeps the server's words unredacted, as a JSON-RPC
2126
- // answer passes (redactServerText's scope); the log is a record of the
2127
- // server's text, so the message is redacted there, whatever JSON value
2128
- // it is, as every other line this connection writes is.
2129
- const said = typeof response.error.message === 'string' ? boundedForLog(response.error.message.trim()) : '';
2200
+ // The server's own words, after a word on whose they are, redacted and
2201
+ // then bounded as errors.ts says, since they're the server's text in
2202
+ // an error the caller gets (redactServerText's scope), and its data's
2203
+ // strings redacted too. It's trimmed after it's redacted, so a
2204
+ // credential that ends in a space is whole when it's matched. Only a
2205
+ // string is words: a message of any other JSON value reads as none.
2206
+ // The method and id are the operator's, so they go to the log, and the
2207
+ // code (loggedCode) and the message, whatever JSON values they are, go
2208
+ // there redacted (logValueRedacted), as every other line this
2209
+ // connection writes is.
2210
+ const redact = (this.redactor ??= serverTextRedactor(this.config ?? {})).now();
2211
+ const said = typeof response.error.message === 'string' ? boundedForLog(redact(response.error.message).trim()) : '';
2130
2212
  // The call is settled before its log line: its entry is gone and its
2131
2213
  // timer cleared, so nothing else would settle it, and a host's logger
2132
2214
  // can throw. The dispatch's containment reports such a throw. (A
@@ -2135,9 +2217,9 @@ export class McplServerConnection extends EventEmitter {
2135
2217
  pending.reject(new McplRequestError(said
2136
2218
  ? `The "${this.id}" server answered with an error: ${said}`
2137
2219
  : `The "${this.id}" server answered with an error without saying what went wrong, so whether the request took effect is unknown. ` +
2138
- 'Check its effect before trying again.', 'error-response', response.error.data));
2139
- console.error(`MCPL server "${this.id}" answered ${pending.method} (id=${response.id}) with error ${logValue(response.error.code)}: ` +
2140
- logValueRedacted(response.error.message, (text) => redactServerText(text, this.config ?? {})));
2220
+ 'Check its effect before trying again.', 'error-response', redactedData(response.error.data, redact)));
2221
+ console.error(`MCPL server "${this.id}" answered ${pending.method} (id=${response.id}) with error ${loggedCode(response.error.code, redact)}: ` +
2222
+ logValueRedacted(response.error.message, redact));
2141
2223
  }
2142
2224
  else {
2143
2225
  pending.resolve(response.result);
@@ -2246,8 +2328,10 @@ export class McplServerConnection extends EventEmitter {
2246
2328
  // reconnecting, and is lost as on a close, with the permanent failure
2247
2329
  // that raises the alert and takes its tools off the list. Its id stays
2248
2330
  // held until close() confirms the exit. A close the host has begun
2249
- // reports the failure itself. During a handshake nothing listens yet:
2250
- // the handshake's own cleanup holds the launch, once the handshake fails.
2331
+ // reports the failure itself. During a handshake nothing listens yet: a
2332
+ // handshake whose pipe has failed fails, when its answer comes (it's
2333
+ // refused then), when the child's exit closes the transport, or at its
2334
+ // timeout, and its own cleanup holds the launch.
2251
2335
  transport.on('unreaped', (failure) => {
2252
2336
  if (this.closed || this.transport !== transport)
2253
2337
  return;