@ashx-j/lunr 0.2.17 → 0.2.18

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 (339) hide show
  1. package/CHANGELOG.md +19 -1
  2. package/README.md +2 -1
  3. package/dist/builtin-extensions/ashxj-thinking.d.ts +1 -0
  4. package/dist/builtin-extensions/ashxj-thinking.d.ts.map +1 -1
  5. package/dist/builtin-extensions/ashxj-thinking.js +44 -19
  6. package/dist/builtin-extensions/ashxj-thinking.js.map +1 -1
  7. package/dist/builtin-extensions/ashxj-tui.d.ts +2 -2
  8. package/dist/builtin-extensions/ashxj-tui.d.ts.map +1 -1
  9. package/dist/builtin-extensions/ashxj-tui.js +8 -11
  10. package/dist/builtin-extensions/ashxj-tui.js.map +1 -1
  11. package/dist/builtin-extensions/index.d.ts.map +1 -1
  12. package/dist/builtin-extensions/index.js +2 -1
  13. package/dist/builtin-extensions/index.js.map +1 -1
  14. package/dist/builtin-extensions/pi-lsp-extension/src/index.d.ts +4 -0
  15. package/dist/builtin-extensions/pi-lsp-extension/src/index.d.ts.map +1 -1
  16. package/dist/builtin-extensions/pi-lsp-extension/src/index.js +172 -171
  17. package/dist/builtin-extensions/pi-lsp-extension/src/index.js.map +1 -1
  18. package/dist/builtin-extensions/pi-lsp-extension/src/runtime.d.ts +50 -0
  19. package/dist/builtin-extensions/pi-lsp-extension/src/runtime.d.ts.map +1 -0
  20. package/dist/builtin-extensions/pi-lsp-extension/src/runtime.js +131 -0
  21. package/dist/builtin-extensions/pi-lsp-extension/src/runtime.js.map +1 -0
  22. package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.d.ts +7 -0
  23. package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.d.ts.map +1 -0
  24. package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.js +211 -0
  25. package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.js.map +1 -0
  26. package/dist/builtin-extensions/pi-mcp-adapter/direct-tools.d.ts +0 -5
  27. package/dist/builtin-extensions/pi-mcp-adapter/direct-tools.d.ts.map +1 -1
  28. package/dist/builtin-extensions/pi-mcp-adapter/direct-tools.js +0 -202
  29. package/dist/builtin-extensions/pi-mcp-adapter/direct-tools.js.map +1 -1
  30. package/dist/builtin-extensions/pi-mcp-adapter/index.d.ts.map +1 -1
  31. package/dist/builtin-extensions/pi-mcp-adapter/index.js +276 -109
  32. package/dist/builtin-extensions/pi-mcp-adapter/index.js.map +1 -1
  33. package/dist/builtin-extensions/pi-mcp-adapter/init.d.ts +4 -1
  34. package/dist/builtin-extensions/pi-mcp-adapter/init.d.ts.map +1 -1
  35. package/dist/builtin-extensions/pi-mcp-adapter/init.js +10 -3
  36. package/dist/builtin-extensions/pi-mcp-adapter/init.js.map +1 -1
  37. package/dist/builtin-extensions/pi-mcp-adapter/metadata-cache.d.ts.map +1 -1
  38. package/dist/builtin-extensions/pi-mcp-adapter/metadata-cache.js +6 -1
  39. package/dist/builtin-extensions/pi-mcp-adapter/metadata-cache.js.map +1 -1
  40. package/dist/builtin-extensions/pi-mcp-adapter/server-manager.d.ts +6 -1
  41. package/dist/builtin-extensions/pi-mcp-adapter/server-manager.d.ts.map +1 -1
  42. package/dist/builtin-extensions/pi-mcp-adapter/server-manager.js +33 -8
  43. package/dist/builtin-extensions/pi-mcp-adapter/server-manager.js.map +1 -1
  44. package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.d.ts.map +1 -1
  45. package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.js +2 -1
  46. package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.js.map +1 -1
  47. package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.d.ts +1 -1
  48. package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.d.ts.map +1 -1
  49. package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.js +1 -1
  50. package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.js.map +1 -1
  51. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts +1 -1
  52. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  53. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +68 -15
  54. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  55. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.d.ts +1 -1
  56. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.d.ts.map +1 -1
  57. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js +5 -2
  58. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js.map +1 -1
  59. package/dist/builtin-extensions/pi-subagents/src/shared/fork-context.d.ts.map +1 -1
  60. package/dist/builtin-extensions/pi-subagents/src/shared/fork-context.js +1 -1
  61. package/dist/builtin-extensions/pi-subagents/src/shared/fork-context.js.map +1 -1
  62. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts +1 -1
  63. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts.map +1 -1
  64. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js +1 -1
  65. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js.map +1 -1
  66. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +2 -1
  67. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
  68. package/dist/builtin-extensions/pi-subagents/src/tui/render.js +72 -31
  69. package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
  70. package/dist/builtin-extensions/pi-subagents/src/watchdog/review.d.ts +1 -1
  71. package/dist/builtin-extensions/pi-subagents/src/watchdog/review.d.ts.map +1 -1
  72. package/dist/builtin-extensions/pi-subagents/src/watchdog/review.js +2 -1
  73. package/dist/builtin-extensions/pi-subagents/src/watchdog/review.js.map +1 -1
  74. package/dist/builtin-extensions/pi-web-access/extract.d.ts.map +1 -1
  75. package/dist/builtin-extensions/pi-web-access/extract.js +105 -54
  76. package/dist/builtin-extensions/pi-web-access/extract.js.map +1 -1
  77. package/dist/builtin-extensions/pi-web-access/gemini-search.d.ts +1 -1
  78. package/dist/builtin-extensions/pi-web-access/gemini-search.d.ts.map +1 -1
  79. package/dist/builtin-extensions/pi-web-access/gemini-search.js +82 -65
  80. package/dist/builtin-extensions/pi-web-access/gemini-search.js.map +1 -1
  81. package/dist/builtin-extensions/pi-web-access/github-extract.d.ts.map +1 -1
  82. package/dist/builtin-extensions/pi-web-access/github-extract.js +2 -0
  83. package/dist/builtin-extensions/pi-web-access/github-extract.js.map +1 -1
  84. package/dist/builtin-extensions/pi-web-access/index.d.ts.map +1 -1
  85. package/dist/builtin-extensions/pi-web-access/index.js +259 -168
  86. package/dist/builtin-extensions/pi-web-access/index.js.map +1 -1
  87. package/dist/builtin-extensions/pi-web-access/lazy.d.ts +18 -0
  88. package/dist/builtin-extensions/pi-web-access/lazy.d.ts.map +1 -0
  89. package/dist/builtin-extensions/pi-web-access/lazy.js +19 -0
  90. package/dist/builtin-extensions/pi-web-access/lazy.js.map +1 -0
  91. package/dist/builtin-extensions/pi-web-access/session-cleanup.d.ts +6 -0
  92. package/dist/builtin-extensions/pi-web-access/session-cleanup.d.ts.map +1 -0
  93. package/dist/builtin-extensions/pi-web-access/session-cleanup.js +17 -0
  94. package/dist/builtin-extensions/pi-web-access/session-cleanup.js.map +1 -0
  95. package/dist/cli-runtime.d.ts +3 -0
  96. package/dist/cli-runtime.d.ts.map +1 -0
  97. package/dist/cli-runtime.js +72 -0
  98. package/dist/cli-runtime.js.map +1 -0
  99. package/dist/cli.d.ts.map +1 -1
  100. package/dist/cli.js +11 -60
  101. package/dist/cli.js.map +1 -1
  102. package/dist/config.d.ts +1 -0
  103. package/dist/config.d.ts.map +1 -1
  104. package/dist/config.js +1 -0
  105. package/dist/config.js.map +1 -1
  106. package/dist/core/agent-session.d.ts.map +1 -1
  107. package/dist/core/agent-session.js +6 -3
  108. package/dist/core/agent-session.js.map +1 -1
  109. package/dist/core/extensions/host-static.d.ts.map +1 -1
  110. package/dist/core/extensions/host-static.js +34 -12
  111. package/dist/core/extensions/host-static.js.map +1 -1
  112. package/dist/core/extensions/loader.d.ts +1 -2
  113. package/dist/core/extensions/loader.d.ts.map +1 -1
  114. package/dist/core/extensions/loader.js +10 -64
  115. package/dist/core/extensions/loader.js.map +1 -1
  116. package/dist/core/keybindings.d.ts +2 -2
  117. package/dist/core/keybindings.d.ts.map +1 -1
  118. package/dist/core/keybindings.js +2 -2
  119. package/dist/core/keybindings.js.map +1 -1
  120. package/dist/core/package-manager.d.ts.map +1 -1
  121. package/dist/core/package-manager.js +1 -1
  122. package/dist/core/package-manager.js.map +1 -1
  123. package/dist/core/sdk.d.ts +1 -1
  124. package/dist/core/sdk.d.ts.map +1 -1
  125. package/dist/core/sdk.js +1 -1
  126. package/dist/core/sdk.js.map +1 -1
  127. package/dist/core/timings.d.ts +2 -1
  128. package/dist/core/timings.d.ts.map +1 -1
  129. package/dist/core/timings.js +17 -2
  130. package/dist/core/timings.js.map +1 -1
  131. package/dist/gateway/agent-bridge.d.ts +6 -1
  132. package/dist/gateway/agent-bridge.d.ts.map +1 -1
  133. package/dist/gateway/agent-bridge.js +23 -6
  134. package/dist/gateway/agent-bridge.js.map +1 -1
  135. package/dist/gateway/cron.d.ts +1 -1
  136. package/dist/gateway/cron.d.ts.map +1 -1
  137. package/dist/gateway/cron.js +3 -1
  138. package/dist/gateway/cron.js.map +1 -1
  139. package/dist/main.d.ts.map +1 -1
  140. package/dist/main.js +20 -14
  141. package/dist/main.js.map +1 -1
  142. package/dist/modes/interactive/injected-context.d.ts +2 -0
  143. package/dist/modes/interactive/injected-context.d.ts.map +1 -0
  144. package/dist/modes/interactive/injected-context.js +7 -0
  145. package/dist/modes/interactive/injected-context.js.map +1 -0
  146. package/dist/modes/interactive/interactive-mode.d.ts +2 -0
  147. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  148. package/dist/modes/interactive/interactive-mode.js +32 -8
  149. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  150. package/dist/modes/interactive/thinking-level-slash.d.ts +4 -0
  151. package/dist/modes/interactive/thinking-level-slash.d.ts.map +1 -0
  152. package/dist/modes/interactive/thinking-level-slash.js +23 -0
  153. package/dist/modes/interactive/thinking-level-slash.js.map +1 -0
  154. package/dist/node-runtime/agent-session-services-35WNVGMR.js +36 -0
  155. package/dist/node-runtime/benchmark-request-UC7PD3V3.js +57 -0
  156. package/dist/node-runtime/brave-UWDA3I22.js +143 -0
  157. package/dist/node-runtime/builtin-extensions-QATGXENO.js +28 -0
  158. package/dist/node-runtime/chunk-2SJB2AWP.js +47 -0
  159. package/dist/node-runtime/chunk-3NMWLTPV.js +64 -0
  160. package/dist/node-runtime/chunk-3WFAEVKS.js +115 -0
  161. package/dist/node-runtime/chunk-3X3KZKMI.js +49 -0
  162. package/dist/node-runtime/chunk-4CSFRBCN.js +7558 -0
  163. package/dist/node-runtime/chunk-4DJ6HEGH.js +296 -0
  164. package/dist/node-runtime/chunk-4HXHDDCF.js +16 -0
  165. package/dist/node-runtime/chunk-4I23VTC4.js +429 -0
  166. package/dist/node-runtime/chunk-4TLO4PO2.js +3427 -0
  167. package/dist/node-runtime/chunk-4ZWGEEAS.js +69 -0
  168. package/dist/node-runtime/chunk-53YJI7JU.js +137 -0
  169. package/dist/node-runtime/chunk-5EFIU3OM.js +295 -0
  170. package/dist/node-runtime/chunk-6BEIBLQ3.js +53 -0
  171. package/dist/node-runtime/chunk-6KDIOJL3.js +72 -0
  172. package/dist/node-runtime/chunk-7N3YHTYF.js +26 -0
  173. package/dist/node-runtime/chunk-7NBZ5P7I.js +24 -0
  174. package/dist/node-runtime/chunk-AD6VXAO7.js +342 -0
  175. package/dist/node-runtime/chunk-ARC4KOTI.js +11178 -0
  176. package/dist/node-runtime/chunk-AROOY4BB.js +173 -0
  177. package/dist/node-runtime/chunk-ATGA2WLC.js +5646 -0
  178. package/dist/node-runtime/chunk-AUXVGBO4.js +19 -0
  179. package/dist/node-runtime/chunk-AY6CAJSL.js +30 -0
  180. package/dist/node-runtime/chunk-BHO7O6E5.js +296 -0
  181. package/dist/node-runtime/chunk-BI3DHYCN.js +8845 -0
  182. package/dist/node-runtime/chunk-BOHIDQT4.js +21 -0
  183. package/dist/node-runtime/chunk-BRJX2PRC.js +53 -0
  184. package/dist/node-runtime/chunk-CBGB57XT.js +20211 -0
  185. package/dist/node-runtime/chunk-CCZJ3PYY.js +17 -0
  186. package/dist/node-runtime/chunk-CGBXPL3E.js +1171 -0
  187. package/dist/node-runtime/chunk-CJECDQKP.js +19 -0
  188. package/dist/node-runtime/chunk-CSFI6YXL.js +130 -0
  189. package/dist/node-runtime/chunk-DAPBPCBP.js +53 -0
  190. package/dist/node-runtime/chunk-DDWHZ633.js +37 -0
  191. package/dist/node-runtime/chunk-DMMTJQMQ.js +43 -0
  192. package/dist/node-runtime/chunk-DVGWF6A2.js +1180 -0
  193. package/dist/node-runtime/chunk-EBF6COVM.js +1734 -0
  194. package/dist/node-runtime/chunk-FQMM2EZ2.js +248 -0
  195. package/dist/node-runtime/chunk-FVDOXRUD.js +96 -0
  196. package/dist/node-runtime/chunk-G4P75AIS.js +9471 -0
  197. package/dist/node-runtime/chunk-G6LRAP36.js +105 -0
  198. package/dist/node-runtime/chunk-GKLEQ3I4.js +860 -0
  199. package/dist/node-runtime/chunk-H2EOZYMP.js +57 -0
  200. package/dist/node-runtime/chunk-HQCKFM2O.js +56 -0
  201. package/dist/node-runtime/chunk-HYHJIRDW.js +19 -0
  202. package/dist/node-runtime/chunk-I6R76AG7.js +22 -0
  203. package/dist/node-runtime/chunk-IRPJXI6U.js +1269 -0
  204. package/dist/node-runtime/chunk-J26TSGDL.js +633 -0
  205. package/dist/node-runtime/chunk-JZQ7F36T.js +610 -0
  206. package/dist/node-runtime/chunk-KBKMCJDU.js +126 -0
  207. package/dist/node-runtime/chunk-KWA4OC2J.js +100 -0
  208. package/dist/node-runtime/chunk-M3LZLQW2.js +98 -0
  209. package/dist/node-runtime/chunk-MCUNIRD5.js +8388 -0
  210. package/dist/node-runtime/chunk-NI6OTSBH.js +966 -0
  211. package/dist/node-runtime/chunk-NUIFPZWX.js +209 -0
  212. package/dist/node-runtime/chunk-OBMWP3I5.js +68 -0
  213. package/dist/node-runtime/chunk-OCVIXVTZ.js +88 -0
  214. package/dist/node-runtime/chunk-OPEK5RRY.js +466 -0
  215. package/dist/node-runtime/chunk-OR4L3IB2.js +42 -0
  216. package/dist/node-runtime/chunk-PL6JKXWI.js +3622 -0
  217. package/dist/node-runtime/chunk-PNJSG3IZ.js +807 -0
  218. package/dist/node-runtime/chunk-PVCDKGR6.js +55 -0
  219. package/dist/node-runtime/chunk-Q4Q6D4IY.js +364 -0
  220. package/dist/node-runtime/chunk-Q5ZU2VRT.js +83 -0
  221. package/dist/node-runtime/chunk-QFWG2RVL.js +5477 -0
  222. package/dist/node-runtime/chunk-QZMODZQ2.js +305 -0
  223. package/dist/node-runtime/chunk-R5EDISSV.js +375 -0
  224. package/dist/node-runtime/chunk-RNBHABBA.js +986 -0
  225. package/dist/node-runtime/chunk-RQ2Q5IYR.js +72 -0
  226. package/dist/node-runtime/chunk-RRIZE6QQ.js +17 -0
  227. package/dist/node-runtime/chunk-SN6G4OU6.js +4753 -0
  228. package/dist/node-runtime/chunk-STERBGUB.js +949 -0
  229. package/dist/node-runtime/chunk-UWQYRSYQ.js +8973 -0
  230. package/dist/node-runtime/chunk-VRB2IYGG.js +53 -0
  231. package/dist/node-runtime/chunk-VSELYKWU.js +772 -0
  232. package/dist/node-runtime/chunk-W3CVH5RX.js +62 -0
  233. package/dist/node-runtime/chunk-WJVFOIB5.js +24921 -0
  234. package/dist/node-runtime/chunk-WKDK4C5P.js +2834 -0
  235. package/dist/node-runtime/chunk-XATUM2HK.js +46 -0
  236. package/dist/node-runtime/chunk-XBWPBZBN.js +125 -0
  237. package/dist/node-runtime/chunk-XTHQ7XR7.js +509 -0
  238. package/dist/node-runtime/chunk-ZBV7FAHG.js +1345 -0
  239. package/dist/node-runtime/cli-runtime.js +80 -0
  240. package/dist/node-runtime/clipboard-OZ63BBC6.js +12 -0
  241. package/dist/node-runtime/clipboard-image-7QR6GXVA.js +13 -0
  242. package/dist/node-runtime/command-AAV3YRR5.js +13 -0
  243. package/dist/node-runtime/commands-MV5KOZ64.js +291 -0
  244. package/dist/node-runtime/config-QDD5PUE2.js +73 -0
  245. package/dist/node-runtime/curator-server-XCM43VEF.js +3816 -0
  246. package/dist/node-runtime/customize-XEXL2DGQ.js +12 -0
  247. package/dist/node-runtime/direct-tool-executor-BK7CLEBX.js +188 -0
  248. package/dist/node-runtime/exa-LL64QZR2.js +329 -0
  249. package/dist/node-runtime/export-html-TEXVV5RP.js +150 -0
  250. package/dist/node-runtime/extension-input-O4HSAEM4.js +14 -0
  251. package/dist/node-runtime/extension-selector-X5FCX43D.js +14 -0
  252. package/dist/node-runtime/extract-XLQSJN4V.js +17 -0
  253. package/dist/node-runtime/file-sync-HCOP2QVF.js +117 -0
  254. package/dist/node-runtime/gateway-OAC4OBBL.js +2137 -0
  255. package/dist/node-runtime/gemini-api-QE7ANVDZ.js +29 -0
  256. package/dist/node-runtime/gemini-search-U7SUMPQA.js +330 -0
  257. package/dist/node-runtime/gemini-url-context-PXWCBQHK.js +103 -0
  258. package/dist/node-runtime/gemini-web-MM446SEH.js +14 -0
  259. package/dist/node-runtime/github-extract-F64RZOEA.js +619 -0
  260. package/dist/node-runtime/goal-NJEE5CTU.js +1831 -0
  261. package/dist/node-runtime/index.js +859 -0
  262. package/dist/node-runtime/init-3C7Z24OI.js +28 -0
  263. package/dist/node-runtime/install-cli-EXMJQESX.js +308 -0
  264. package/dist/node-runtime/interactive-mode-2SZUO53H.js +56 -0
  265. package/dist/node-runtime/interactive-view-S6J3QHEF.js +247 -0
  266. package/dist/node-runtime/lsp-manager-3ASUSO4T.js +1104 -0
  267. package/dist/node-runtime/lunr-cron-AUUYP4N4.js +272 -0
  268. package/dist/node-runtime/main.js +54 -0
  269. package/dist/node-runtime/mcp-auth-flow-QIXHW6QN.js +32 -0
  270. package/dist/node-runtime/mcp-panel-IIGMXQGP.js +501 -0
  271. package/dist/node-runtime/mcp-setup-panel-FEK7663I.js +355 -0
  272. package/dist/node-runtime/memory-cap-3S4XRLNP.js +20 -0
  273. package/dist/node-runtime/model-tiers-NJLHUEGK.js +20 -0
  274. package/dist/node-runtime/openai-search-B3MSNCQA.js +288 -0
  275. package/dist/node-runtime/package-manager-cli-7RKSZGEN.js +749 -0
  276. package/dist/node-runtime/parallel-AI2MNSCU.js +265 -0
  277. package/dist/node-runtime/parser-manager-TQHWYDH7.js +152 -0
  278. package/dist/node-runtime/pdf-extract-IPE6H4HP.js +57 -0
  279. package/dist/node-runtime/perplexity-QVJW3I35.js +12 -0
  280. package/dist/node-runtime/pi-intercom-EEMBGQID.js +2215 -0
  281. package/dist/node-runtime/pi-mcp-adapter-GUFZWW54.js +428 -0
  282. package/dist/node-runtime/pi-ollama-cloud-2F3Y2QNM.js +1440 -0
  283. package/dist/node-runtime/pi-prompt-template-model-QWTCGLJU.js +3946 -0
  284. package/dist/node-runtime/pi-subagents-7YJ3I4VE.js +6048 -0
  285. package/dist/node-runtime/pi-web-access-2CQGFLT2.js +1867 -0
  286. package/dist/node-runtime/print-mode-XSFM26EL.js +12 -0
  287. package/dist/node-runtime/proxy-modes-V6YVFH3C.js +685 -0
  288. package/dist/node-runtime/rpc-entry.js +62 -0
  289. package/dist/node-runtime/rpc-mode-W5ZTLTMZ.js +13 -0
  290. package/dist/node-runtime/runtime-bridges-3RKBDLNA.js +14 -0
  291. package/dist/node-runtime/session-manager-E7AREDTV.js +33 -0
  292. package/dist/node-runtime/session-selector-FJ7M2AIX.js +14 -0
  293. package/dist/node-runtime/settings-manager-GHPTUN7R.js +21 -0
  294. package/dist/node-runtime/src-BPQFJR76.js +2427 -0
  295. package/dist/node-runtime/subagent-executor-5Q5A4HJ2.js +8499 -0
  296. package/dist/node-runtime/summary-review-YSMXKITO.js +228 -0
  297. package/dist/node-runtime/tavily-WEZFVFP7.js +154 -0
  298. package/dist/node-runtime/timings-UAD5BEAS.js +16 -0
  299. package/dist/node-runtime/tool-renderer-MV5O452K.js +204 -0
  300. package/dist/node-runtime/update-cli-L3JIBH2U.js +70 -0
  301. package/dist/node-runtime/v4-5MNC3H7G.js +424 -0
  302. package/dist/node-runtime/video-extract-OYT5WKS5.js +304 -0
  303. package/dist/node-runtime/workspace-index-6DBXSTJ6.js +163 -0
  304. package/dist/node-runtime/youtube-extract-TQYKGFGS.js +264 -0
  305. package/dist/rpc.d.ts +3 -0
  306. package/dist/rpc.d.ts.map +1 -0
  307. package/dist/rpc.js +18 -0
  308. package/dist/rpc.js.map +1 -0
  309. package/dist/startup/benchmark-request.d.ts +3 -0
  310. package/dist/startup/benchmark-request.d.ts.map +1 -0
  311. package/dist/startup/benchmark-request.js +65 -0
  312. package/dist/startup/benchmark-request.js.map +1 -0
  313. package/dist/startup/interactive-view.d.ts.map +1 -1
  314. package/dist/startup/interactive-view.js +1 -2
  315. package/dist/startup/interactive-view.js.map +1 -1
  316. package/dist/startup/startup-milestones.d.ts +1 -1
  317. package/dist/startup/startup-milestones.d.ts.map +1 -1
  318. package/dist/startup/startup-milestones.js.map +1 -1
  319. package/dist/utils/await-with-abort.d.ts +2 -0
  320. package/dist/utils/await-with-abort.d.ts.map +1 -0
  321. package/dist/utils/await-with-abort.js +19 -0
  322. package/dist/utils/await-with-abort.js.map +1 -0
  323. package/docs/development.md +5 -1
  324. package/docs/features.md +2 -2
  325. package/docs/interactive-startup.md +95 -48
  326. package/docs/keybindings.md +2 -2
  327. package/docs/terminal-setup.md +1 -1
  328. package/docs/usage.md +1 -1
  329. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  330. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  331. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  332. package/examples/extensions/gondolin/package-lock.json +2 -2
  333. package/examples/extensions/gondolin/package.json +1 -1
  334. package/examples/extensions/hidden-thinking-label.ts +1 -1
  335. package/examples/extensions/sandbox/package-lock.json +2 -2
  336. package/examples/extensions/sandbox/package.json +1 -1
  337. package/examples/extensions/with-deps/package-lock.json +2 -2
  338. package/examples/extensions/with-deps/package.json +1 -1
  339. package/package.json +8 -8
@@ -1 +1 @@
1
- {"version":3,"file":"server-manager.d.ts","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/server-manager.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { UnauthorizedError } from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport type { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport {\n ElicitationCompleteNotificationSchema,\n type ReadResourceResult,\n type UrlElicitationRequiredError,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type {\n McpTool,\n McpResource,\n ServerDefinition,\n ServerStreamResultPatchNotification,\n Transport,\n} from \"./types.ts\";\nimport { serverStreamResultPatchNotificationSchema } from \"./types.ts\";\nimport { resolveNpxBinary } from \"./npx-resolver.ts\";\nimport { logger } from \"./logger.ts\";\nimport { McpOAuthProvider } from \"./mcp-oauth-provider.ts\";\nimport { extractOAuthConfig, supportsOAuth } from \"./mcp-auth-flow.ts\";\nimport { registerSamplingHandler, type ServerSamplingConfig } from \"./sampling-handler.ts\";\nimport {\n handleUrlElicitation,\n registerElicitationHandler,\n type ServerElicitationConfig,\n} from \"./elicitation-handler.ts\";\nimport { interpolateEnvRecord, resolveBearerToken, resolveConfigPath } from \"./utils.ts\";\nimport { abortable, throwIfAborted } from \"./abort.ts\";\n\ninterface ServerConnection {\n client: Client;\n transport: Transport;\n definition: ServerDefinition;\n tools: McpTool[];\n resources: McpResource[];\n lastUsedAt: number;\n inFlight: number;\n status: \"connected\" | \"closed\" | \"needs-auth\";\n}\n\ntype UiStreamListener = (serverName: string, notification: ServerStreamResultPatchNotification[\"params\"]) => void;\n\nexport class McpServerManager {\n private connections = new Map<string, ServerConnection>();\n private connectPromises = new Map<string, Promise<ServerConnection>>();\n private uiStreamListeners = new Map<string, UiStreamListener>();\n private samplingConfig: ServerSamplingConfig | undefined;\n private elicitationConfig: ServerElicitationConfig | undefined;\n private acceptedUrlElicitations = new Map<string, Set<string>>();\n private defaultRequestTimeoutMs: number | undefined;\n\n /** Default cwd for stdio servers without an explicit config `cwd`. */\n constructor(private readonly defaultCwd?: string) {}\n\n setSamplingConfig(config: ServerSamplingConfig | undefined): void {\n this.samplingConfig = config;\n }\n\n setElicitationConfig(config: ServerElicitationConfig | undefined): void {\n this.elicitationConfig = config;\n }\n\n setDefaultRequestTimeoutMs(timeoutMs: number | undefined): void {\n this.defaultRequestTimeoutMs = normalizeRequestTimeoutMs(timeoutMs);\n }\n\n getRequestOptions(name: string, signal?: AbortSignal): RequestOptions | undefined {\n const connection = this.connections.get(name);\n return this.buildRequestOptions(connection?.definition, signal);\n }\n\n private getResolvedRequestTimeoutMs(definition?: ServerDefinition): number | undefined {\n if (definition?.requestTimeoutMs !== undefined) {\n return normalizeRequestTimeoutMs(definition.requestTimeoutMs);\n }\n return this.defaultRequestTimeoutMs;\n }\n\n private buildRequestOptions(\n definition?: ServerDefinition,\n signal?: AbortSignal,\n ): RequestOptions | undefined {\n const timeout = this.getResolvedRequestTimeoutMs(definition);\n\n if (!signal && timeout === undefined) {\n return undefined;\n }\n\n return {\n ...(signal ? { signal } : {}),\n ...(timeout !== undefined ? { timeout } : {}),\n };\n }\n\n async connect(name: string, definition: ServerDefinition, signal?: AbortSignal): Promise<ServerConnection> {\n throwIfAborted(signal);\n // Dedupe concurrent connection attempts\n if (this.connectPromises.has(name)) {\n return abortable(this.connectPromises.get(name)!, signal);\n }\n\n // Reuse existing connection if healthy\n const existing = this.connections.get(name);\n if (existing?.status === \"connected\") {\n existing.lastUsedAt = Date.now();\n return existing;\n }\n\n const promise = this.createConnection(name, definition, signal);\n this.connectPromises.set(name, promise);\n\n try {\n const connection = await promise;\n this.connections.set(name, connection);\n return connection;\n } finally {\n this.connectPromises.delete(name);\n }\n }\n\n private async createConnection(\n name: string,\n definition: ServerDefinition,\n signal?: AbortSignal,\n ): Promise<ServerConnection> {\n throwIfAborted(signal);\n const client = this.createClient(name);\n\n let transport: Transport;\n\n if (definition.command) {\n let command = definition.command;\n let args = definition.args ?? [];\n\n if (command === \"npx\" || command === \"npm\") {\n const resolved = await resolveNpxBinary(command, args);\n if (resolved) {\n command = resolved.isJs ? \"node\" : resolved.binPath;\n args = resolved.isJs ? [resolved.binPath, ...resolved.extraArgs] : resolved.extraArgs;\n logger.debug(`${name} resolved to ${resolved.binPath} (skipping npm parent)`);\n }\n }\n\n transport = new StdioClientTransport({\n command,\n args,\n env: resolveEnv(definition.env),\n cwd: resolveConfigPath(definition.cwd) ?? this.defaultCwd,\n stderr: definition.debug ? \"inherit\" : \"ignore\",\n });\n } else if (definition.url) {\n // HTTP transport with fallback\n transport = await this.createHttpTransport(definition, name, signal);\n } else {\n throw new Error(`Server ${name} has no command or url`);\n }\n\n const requestOptions = this.buildRequestOptions(definition, signal);\n\n try {\n await client.connect(transport, requestOptions);\n this.attachAdapterNotificationHandlers(name, client);\n\n // Discover tools and resources\n const [tools, resources] = await Promise.all([\n this.fetchAllTools(client, requestOptions),\n this.fetchAllResources(client, requestOptions),\n ]);\n\n return {\n client,\n transport,\n definition,\n tools,\n resources,\n lastUsedAt: Date.now(),\n inFlight: 0,\n status: \"connected\",\n };\n } catch (error) {\n // Check for UnauthorizedError - server requires OAuth\n if (error instanceof UnauthorizedError && supportsOAuth(definition)) {\n // Clean up both client and transport before reporting needs-auth.\n await client.close().catch(() => {});\n await transport.close().catch(() => {});\n\n return {\n client,\n transport,\n definition,\n tools: [],\n resources: [],\n lastUsedAt: Date.now(),\n inFlight: 0,\n status: \"needs-auth\",\n };\n }\n\n // Clean up both client and transport on any error\n await client.close().catch(() => {});\n await transport.close().catch(() => {});\n throw error;\n }\n }\n\n private buildClientCapabilities() {\n return {\n ...(this.samplingConfig ? { sampling: {} } : {}),\n ...(this.elicitationConfig\n ? {\n elicitation: {\n form: {},\n ...(this.elicitationConfig.allowUrl ? { url: {} } : {}),\n },\n }\n : {}),\n };\n }\n\n private createClient(serverName: string): Client {\n const capabilities = this.buildClientCapabilities();\n const client = new Client(\n { name: `pi-mcp-${serverName}`, version: \"1.0.0\" },\n Object.keys(capabilities).length > 0 ? { capabilities } : undefined,\n );\n if (this.samplingConfig) {\n registerSamplingHandler(client, { ...this.samplingConfig, serverName });\n }\n if (this.elicitationConfig) {\n registerElicitationHandler(client, {\n ...this.elicitationConfig,\n serverName,\n onUrlAccepted: elicitationId => this.rememberUrlElicitation(serverName, elicitationId),\n });\n if (this.elicitationConfig.allowUrl) {\n client.setNotificationHandler(ElicitationCompleteNotificationSchema, notification => {\n const accepted = this.acceptedUrlElicitations.get(serverName);\n if (!accepted?.delete(notification.params.elicitationId)) return;\n this.elicitationConfig?.ui.notify(\n `MCP browser interaction for ${serverName} completed. You can retry the tool now.`,\n \"info\",\n );\n });\n }\n }\n return client;\n }\n\n async handleUrlElicitationRequired(\n serverName: string,\n error: UrlElicitationRequiredError,\n ): Promise<\"accept\" | \"decline\" | \"cancel\"> {\n if (!this.elicitationConfig?.allowUrl) return \"cancel\";\n for (const params of error.elicitations) {\n const result = await handleUrlElicitation({\n ...this.elicitationConfig,\n serverName,\n onUrlAccepted: elicitationId => this.rememberUrlElicitation(serverName, elicitationId),\n }, params);\n if (result.action !== \"accept\") return result.action;\n }\n return \"accept\";\n }\n\n private rememberUrlElicitation(serverName: string, elicitationId: string): void {\n let accepted = this.acceptedUrlElicitations.get(serverName);\n if (!accepted) {\n accepted = new Set();\n this.acceptedUrlElicitations.set(serverName, accepted);\n }\n accepted.add(elicitationId);\n }\n\n private async createHttpTransport(\n definition: ServerDefinition,\n serverName: string,\n signal?: AbortSignal,\n ): Promise<Transport> {\n throwIfAborted(signal);\n const url = new URL(definition.url!);\n\n // Build headers first (including any bearer token)\n const headers = resolveHeaders(definition.headers) ?? {};\n\n // For bearer auth, add the token to headers BEFORE creating requestInit\n if (definition.auth === \"bearer\") {\n const token = resolveBearerToken(definition);\n if (token) {\n headers[\"Authorization\"] = `Bearer ${token}`;\n }\n }\n\n // Create request init with headers (Authorization now included for bearer auth)\n const requestInit = Object.keys(headers).length > 0 ? { headers } : undefined;\n\n // For OAuth servers, create an auth provider\n let authProvider: McpOAuthProvider | undefined;\n if (supportsOAuth(definition)) {\n const oauthConfig = extractOAuthConfig(definition);\n authProvider = new McpOAuthProvider(\n serverName,\n definition.url!,\n oauthConfig,\n {\n onRedirect: async (_authUrl) => {\n // URL is captured by startAuth, no need to log\n },\n }\n );\n }\n\n // Try StreamableHTTP first (modern MCP servers)\n const streamableTransport = new StreamableHTTPClientTransport(url, {\n requestInit,\n authProvider,\n });\n\n try {\n // Create a test client to verify the transport works\n const testClient = new Client({ name: \"pi-mcp-probe\", version: \"2.1.2\" });\n await testClient.connect(streamableTransport, this.buildRequestOptions(definition, signal));\n await testClient.close().catch(() => {});\n // Close probe transport before creating fresh one\n await streamableTransport.close().catch(() => {});\n\n // StreamableHTTP works - create fresh transport for actual use\n return new StreamableHTTPClientTransport(url, { requestInit, authProvider });\n } catch (error) {\n // StreamableHTTP failed, close and try SSE fallback\n await streamableTransport.close().catch(() => {});\n\n // Host cancellation is not transport capability evidence; do not fall\n // through to SSE when the caller is trying to cancel the connect.\n if (signal?.aborted) {\n throwIfAborted(signal);\n }\n\n // If this was an UnauthorizedError, don't try SSE - the server needs auth\n if (error instanceof UnauthorizedError) {\n throw error;\n }\n\n // SSE is the legacy transport\n return new SSEClientTransport(url, { requestInit, authProvider });\n }\n }\n\n private async fetchAllTools(client: Client, requestOptions?: RequestOptions): Promise<McpTool[]> {\n const allTools: McpTool[] = [];\n let cursor: string | undefined;\n\n do {\n const result = await client.listTools(cursor ? { cursor } : undefined, requestOptions);\n allTools.push(...(result.tools ?? []));\n cursor = result.nextCursor;\n } while (cursor);\n\n return allTools;\n }\n\n private async fetchAllResources(client: Client, requestOptions?: RequestOptions): Promise<McpResource[]> {\n try {\n const allResources: McpResource[] = [];\n let cursor: string | undefined;\n\n do {\n const result = await client.listResources(cursor ? { cursor } : undefined, requestOptions);\n allResources.push(...(result.resources ?? []));\n cursor = result.nextCursor;\n } while (cursor);\n\n return allResources;\n } catch {\n if (requestOptions?.signal?.aborted) {\n throwIfAborted(requestOptions.signal);\n }\n // Server may not support resources\n return [];\n }\n }\n\n private attachAdapterNotificationHandlers(serverName: string, client: Client): void {\n client.setNotificationHandler(serverStreamResultPatchNotificationSchema, (notification) => {\n const listener = this.uiStreamListeners.get(notification.params.streamToken);\n if (!listener) return;\n listener(serverName, notification.params);\n });\n }\n\n registerUiStreamListener(streamToken: string, listener: UiStreamListener): void {\n this.uiStreamListeners.set(streamToken, listener);\n }\n\n removeUiStreamListener(streamToken: string): void {\n this.uiStreamListeners.delete(streamToken);\n }\n\n async readResource(name: string, uri: string, signal?: AbortSignal): Promise<ReadResourceResult> {\n const connection = this.connections.get(name);\n if (!connection || connection.status !== \"connected\") {\n throw new Error(`Server \"${name}\" is not connected`);\n }\n\n try {\n this.touch(name);\n this.incrementInFlight(name);\n return await connection.client.readResource({ uri }, this.getRequestOptions(name, signal));\n } finally {\n this.decrementInFlight(name);\n this.touch(name);\n }\n }\n\n async close(name: string): Promise<void> {\n const connection = this.connections.get(name);\n if (!connection) return;\n\n // Delete from map BEFORE async cleanup to prevent a race where a\n // concurrent connect() creates a new connection that our deferred\n // delete() would then remove, orphaning the new server process.\n connection.status = \"closed\";\n this.connections.delete(name);\n this.acceptedUrlElicitations.delete(name);\n await connection.client.close().catch(() => {});\n await connection.transport.close().catch(() => {});\n }\n\n async closeAll(): Promise<void> {\n const names = [...this.connections.keys()];\n await Promise.all(names.map(name => this.close(name)));\n }\n\n getConnection(name: string): ServerConnection | undefined {\n return this.connections.get(name);\n }\n\n getAllConnections(): Map<string, ServerConnection> {\n return new Map(this.connections);\n }\n\n touch(name: string): void {\n const connection = this.connections.get(name);\n if (connection) {\n connection.lastUsedAt = Date.now();\n }\n }\n\n incrementInFlight(name: string): void {\n const connection = this.connections.get(name);\n if (connection) {\n connection.inFlight = (connection.inFlight ?? 0) + 1;\n }\n }\n\n decrementInFlight(name: string): void {\n const connection = this.connections.get(name);\n if (connection && connection.inFlight) {\n connection.inFlight--;\n }\n }\n\n isIdle(name: string, timeoutMs: number): boolean {\n const connection = this.connections.get(name);\n if (!connection || connection.status !== \"connected\") return false;\n if (connection.inFlight > 0) return false;\n return (Date.now() - connection.lastUsedAt) > timeoutMs;\n }\n}\n\n/**\n * Resolve environment variables with interpolation.\n */\nfunction resolveEnv(env?: Record<string, string>): Record<string, string> {\n // Copy process.env, filtering out undefined values\n const resolved: Record<string, string> = {};\n for (const [key, value] of Object.entries(process.env)) {\n if (value !== undefined) {\n resolved[key] = value;\n }\n }\n\n if (!env) return resolved;\n\n const overrides = interpolateEnvRecord(env);\n return overrides ? { ...resolved, ...overrides } : resolved;\n}\n\n/**\n * Resolve headers with environment variable interpolation.\n */\nfunction resolveHeaders(headers?: Record<string, string>): Record<string, string> | undefined {\n return interpolateEnvRecord(headers);\n}\n\nfunction normalizeRequestTimeoutMs(timeoutMs: number | undefined): number | undefined {\n return typeof timeoutMs === \"number\" && Number.isFinite(timeoutMs) && timeoutMs > 0\n ? timeoutMs\n : undefined;\n}\n"]}
1
+ {"version":3,"file":"server-manager.d.ts","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/server-manager.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { UnauthorizedError } from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport type { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport {\n ElicitationCompleteNotificationSchema,\n type ReadResourceResult,\n type UrlElicitationRequiredError,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type {\n McpTool,\n McpResource,\n ServerDefinition,\n ServerStreamResultPatchNotification,\n Transport,\n} from \"./types.ts\";\nimport { serverStreamResultPatchNotificationSchema } from \"./types.ts\";\nimport { resolveNpxBinary } from \"./npx-resolver.ts\";\nimport { logger } from \"./logger.ts\";\nimport { McpOAuthProvider } from \"./mcp-oauth-provider.ts\";\nimport { extractOAuthConfig, supportsOAuth } from \"./mcp-auth-flow.ts\";\nimport { registerSamplingHandler, type ServerSamplingConfig } from \"./sampling-handler.ts\";\nimport {\n handleUrlElicitation,\n registerElicitationHandler,\n type ServerElicitationConfig,\n} from \"./elicitation-handler.ts\";\nimport { interpolateEnvRecord, resolveBearerToken, resolveConfigPath } from \"./utils.ts\";\nimport { abortable, throwIfAborted } from \"./abort.ts\";\n\ninterface PendingConnection {\n client: Client;\n transport: Transport;\n}\n\ninterface ServerConnection extends PendingConnection {\n definition: ServerDefinition;\n tools: McpTool[];\n resources: McpResource[];\n lastUsedAt: number;\n inFlight: number;\n status: \"connected\" | \"closed\" | \"needs-auth\";\n}\n\ntype UiStreamListener = (serverName: string, notification: ServerStreamResultPatchNotification[\"params\"]) => void;\n\nexport class McpServerManager {\n private connections = new Map<string, ServerConnection>();\n private connectPromises = new Map<string, Promise<ServerConnection>>();\n private pendingConnections = new Map<string, PendingConnection>();\n private closing = false;\n private uiStreamListeners = new Map<string, UiStreamListener>();\n private samplingConfig: ServerSamplingConfig | undefined;\n private elicitationConfig: ServerElicitationConfig | undefined;\n private acceptedUrlElicitations = new Map<string, Set<string>>();\n private defaultRequestTimeoutMs: number | undefined;\n\n /** Default cwd for stdio servers without an explicit config `cwd`. */\n constructor(private readonly defaultCwd?: string) {}\n\n setSamplingConfig(config: ServerSamplingConfig | undefined): void {\n this.samplingConfig = config;\n }\n\n setElicitationConfig(config: ServerElicitationConfig | undefined): void {\n this.elicitationConfig = config;\n }\n\n setDefaultRequestTimeoutMs(timeoutMs: number | undefined): void {\n this.defaultRequestTimeoutMs = normalizeRequestTimeoutMs(timeoutMs);\n }\n\n getRequestOptions(name: string, signal?: AbortSignal): RequestOptions | undefined {\n const connection = this.connections.get(name);\n return this.buildRequestOptions(connection?.definition, signal);\n }\n\n private getResolvedRequestTimeoutMs(definition?: ServerDefinition): number | undefined {\n if (definition?.requestTimeoutMs !== undefined) {\n return normalizeRequestTimeoutMs(definition.requestTimeoutMs);\n }\n return this.defaultRequestTimeoutMs;\n }\n\n private buildRequestOptions(\n definition?: ServerDefinition,\n signal?: AbortSignal,\n ): RequestOptions | undefined {\n const timeout = this.getResolvedRequestTimeoutMs(definition);\n\n if (!signal && timeout === undefined) {\n return undefined;\n }\n\n return {\n ...(signal ? { signal } : {}),\n ...(timeout !== undefined ? { timeout } : {}),\n };\n }\n\n async connect(name: string, definition: ServerDefinition, signal?: AbortSignal): Promise<ServerConnection> {\n throwIfAborted(signal);\n if (this.closing) throw new Error(\"MCP server manager is closed\");\n // Dedupe concurrent connection attempts\n if (this.connectPromises.has(name)) {\n return abortable(this.connectPromises.get(name)!, signal);\n }\n\n // Reuse existing connection if healthy\n const existing = this.connections.get(name);\n if (existing?.status === \"connected\") {\n existing.lastUsedAt = Date.now();\n return existing;\n }\n\n const promise = this.createConnection(name, definition, signal).then(async connection => {\n if (this.closing || signal?.aborted) {\n await this.disposeConnection(connection);\n throwIfAborted(signal);\n throw new Error(\"MCP server manager closed during connection\");\n }\n this.connections.set(name, connection);\n return connection;\n });\n this.connectPromises.set(name, promise);\n\n try {\n return await promise;\n } finally {\n if (this.connectPromises.get(name) === promise) this.connectPromises.delete(name);\n }\n }\n\n private async createConnection(\n name: string,\n definition: ServerDefinition,\n signal?: AbortSignal,\n ): Promise<ServerConnection> {\n throwIfAborted(signal);\n const client = this.createClient(name);\n\n let transport: Transport;\n\n if (definition.command) {\n let command = definition.command;\n let args = definition.args ?? [];\n\n if (command === \"npx\" || command === \"npm\") {\n const resolved = await resolveNpxBinary(command, args);\n if (resolved) {\n command = resolved.isJs ? \"node\" : resolved.binPath;\n args = resolved.isJs ? [resolved.binPath, ...resolved.extraArgs] : resolved.extraArgs;\n logger.debug(`${name} resolved to ${resolved.binPath} (skipping npm parent)`);\n }\n }\n\n transport = new StdioClientTransport({\n command,\n args,\n env: resolveEnv(definition.env),\n cwd: resolveConfigPath(definition.cwd) ?? this.defaultCwd,\n stderr: definition.debug ? \"inherit\" : \"ignore\",\n });\n } else if (definition.url) {\n // HTTP transport with fallback\n transport = await this.createHttpTransport(definition, name, signal);\n } else {\n throw new Error(`Server ${name} has no command or url`);\n }\n\n const requestOptions = this.buildRequestOptions(definition, signal);\n const pending = { client, transport };\n this.pendingConnections.set(name, pending);\n\n try {\n await client.connect(transport, requestOptions);\n this.attachAdapterNotificationHandlers(name, client);\n\n // Discover tools and resources\n const [tools, resources] = await Promise.all([\n this.fetchAllTools(client, requestOptions),\n this.fetchAllResources(client, requestOptions),\n ]);\n\n return {\n client,\n transport,\n definition,\n tools,\n resources,\n lastUsedAt: Date.now(),\n inFlight: 0,\n status: \"connected\",\n };\n } catch (error) {\n // Check for UnauthorizedError - server requires OAuth\n if (error instanceof UnauthorizedError && supportsOAuth(definition)) {\n // Clean up both client and transport before reporting needs-auth.\n await client.close().catch(() => {});\n await transport.close().catch(() => {});\n\n return {\n client,\n transport,\n definition,\n tools: [],\n resources: [],\n lastUsedAt: Date.now(),\n inFlight: 0,\n status: \"needs-auth\",\n };\n }\n\n // Clean up both client and transport on any error\n await client.close().catch(() => {});\n await transport.close().catch(() => {});\n throw error;\n } finally {\n if (this.pendingConnections.get(name) === pending) this.pendingConnections.delete(name);\n }\n }\n\n private buildClientCapabilities() {\n return {\n ...(this.samplingConfig ? { sampling: {} } : {}),\n ...(this.elicitationConfig\n ? {\n elicitation: {\n form: {},\n ...(this.elicitationConfig.allowUrl ? { url: {} } : {}),\n },\n }\n : {}),\n };\n }\n\n private createClient(serverName: string): Client {\n const capabilities = this.buildClientCapabilities();\n const client = new Client(\n { name: `pi-mcp-${serverName}`, version: \"1.0.0\" },\n Object.keys(capabilities).length > 0 ? { capabilities } : undefined,\n );\n if (this.samplingConfig) {\n registerSamplingHandler(client, { ...this.samplingConfig, serverName });\n }\n if (this.elicitationConfig) {\n registerElicitationHandler(client, {\n ...this.elicitationConfig,\n serverName,\n onUrlAccepted: elicitationId => this.rememberUrlElicitation(serverName, elicitationId),\n });\n if (this.elicitationConfig.allowUrl) {\n client.setNotificationHandler(ElicitationCompleteNotificationSchema, notification => {\n const accepted = this.acceptedUrlElicitations.get(serverName);\n if (!accepted?.delete(notification.params.elicitationId)) return;\n this.elicitationConfig?.ui.notify(\n `MCP browser interaction for ${serverName} completed. You can retry the tool now.`,\n \"info\",\n );\n });\n }\n }\n return client;\n }\n\n async handleUrlElicitationRequired(\n serverName: string,\n error: UrlElicitationRequiredError,\n ): Promise<\"accept\" | \"decline\" | \"cancel\"> {\n if (!this.elicitationConfig?.allowUrl) return \"cancel\";\n for (const params of error.elicitations) {\n const result = await handleUrlElicitation({\n ...this.elicitationConfig,\n serverName,\n onUrlAccepted: elicitationId => this.rememberUrlElicitation(serverName, elicitationId),\n }, params);\n if (result.action !== \"accept\") return result.action;\n }\n return \"accept\";\n }\n\n private rememberUrlElicitation(serverName: string, elicitationId: string): void {\n let accepted = this.acceptedUrlElicitations.get(serverName);\n if (!accepted) {\n accepted = new Set();\n this.acceptedUrlElicitations.set(serverName, accepted);\n }\n accepted.add(elicitationId);\n }\n\n private async createHttpTransport(\n definition: ServerDefinition,\n serverName: string,\n signal?: AbortSignal,\n ): Promise<Transport> {\n throwIfAborted(signal);\n const url = new URL(definition.url!);\n\n // Build headers first (including any bearer token)\n const headers = resolveHeaders(definition.headers) ?? {};\n\n // For bearer auth, add the token to headers BEFORE creating requestInit\n if (definition.auth === \"bearer\") {\n const token = resolveBearerToken(definition);\n if (token) {\n headers[\"Authorization\"] = `Bearer ${token}`;\n }\n }\n\n // Create request init with headers (Authorization now included for bearer auth)\n const requestInit = Object.keys(headers).length > 0 ? { headers } : undefined;\n\n // For OAuth servers, create an auth provider\n let authProvider: McpOAuthProvider | undefined;\n if (supportsOAuth(definition)) {\n const oauthConfig = extractOAuthConfig(definition);\n authProvider = new McpOAuthProvider(\n serverName,\n definition.url!,\n oauthConfig,\n {\n onRedirect: async (_authUrl) => {\n // URL is captured by startAuth, no need to log\n },\n }\n );\n }\n\n // Try StreamableHTTP first (modern MCP servers)\n const streamableTransport = new StreamableHTTPClientTransport(url, {\n requestInit,\n authProvider,\n });\n\n try {\n // Create a test client to verify the transport works\n const testClient = new Client({ name: \"pi-mcp-probe\", version: \"2.1.2\" });\n await testClient.connect(streamableTransport, this.buildRequestOptions(definition, signal));\n await testClient.close().catch(() => {});\n // Close probe transport before creating fresh one\n await streamableTransport.close().catch(() => {});\n\n // StreamableHTTP works - create fresh transport for actual use\n return new StreamableHTTPClientTransport(url, { requestInit, authProvider });\n } catch (error) {\n // StreamableHTTP failed, close and try SSE fallback\n await streamableTransport.close().catch(() => {});\n\n // Host cancellation is not transport capability evidence; do not fall\n // through to SSE when the caller is trying to cancel the connect.\n if (signal?.aborted) {\n throwIfAborted(signal);\n }\n\n // If this was an UnauthorizedError, don't try SSE - the server needs auth\n if (error instanceof UnauthorizedError) {\n throw error;\n }\n\n // SSE is the legacy transport\n return new SSEClientTransport(url, { requestInit, authProvider });\n }\n }\n\n private async fetchAllTools(client: Client, requestOptions?: RequestOptions): Promise<McpTool[]> {\n const allTools: McpTool[] = [];\n let cursor: string | undefined;\n\n do {\n const result = await client.listTools(cursor ? { cursor } : undefined, requestOptions);\n allTools.push(...(result.tools ?? []));\n cursor = result.nextCursor;\n } while (cursor);\n\n return allTools;\n }\n\n private async fetchAllResources(client: Client, requestOptions?: RequestOptions): Promise<McpResource[]> {\n try {\n const allResources: McpResource[] = [];\n let cursor: string | undefined;\n\n do {\n const result = await client.listResources(cursor ? { cursor } : undefined, requestOptions);\n allResources.push(...(result.resources ?? []));\n cursor = result.nextCursor;\n } while (cursor);\n\n return allResources;\n } catch {\n if (requestOptions?.signal?.aborted) {\n throwIfAborted(requestOptions.signal);\n }\n // Server may not support resources\n return [];\n }\n }\n\n private attachAdapterNotificationHandlers(serverName: string, client: Client): void {\n client.setNotificationHandler(serverStreamResultPatchNotificationSchema, (notification) => {\n const listener = this.uiStreamListeners.get(notification.params.streamToken);\n if (!listener) return;\n listener(serverName, notification.params);\n });\n }\n\n registerUiStreamListener(streamToken: string, listener: UiStreamListener): void {\n this.uiStreamListeners.set(streamToken, listener);\n }\n\n removeUiStreamListener(streamToken: string): void {\n this.uiStreamListeners.delete(streamToken);\n }\n\n async readResource(name: string, uri: string, signal?: AbortSignal): Promise<ReadResourceResult> {\n const connection = this.connections.get(name);\n if (!connection || connection.status !== \"connected\") {\n throw new Error(`Server \"${name}\" is not connected`);\n }\n\n try {\n this.touch(name);\n this.incrementInFlight(name);\n return await connection.client.readResource({ uri }, this.getRequestOptions(name, signal));\n } finally {\n this.decrementInFlight(name);\n this.touch(name);\n }\n }\n\n private async disposeConnection(connection: PendingConnection): Promise<void> {\n await connection.client.close().catch(() => {});\n await connection.transport.close().catch(() => {});\n }\n\n async close(name: string): Promise<void> {\n const connection = this.connections.get(name);\n if (!connection) return;\n\n // Delete from map BEFORE async cleanup to prevent a race where a\n // concurrent connect() creates a new connection that our deferred\n // delete() would then remove, orphaning the new server process.\n connection.status = \"closed\";\n this.connections.delete(name);\n this.acceptedUrlElicitations.delete(name);\n await this.disposeConnection(connection);\n }\n\n async closeAll(): Promise<void> {\n this.closing = true;\n const names = [...this.connections.keys()];\n const pending = [...this.pendingConnections.values()];\n await Promise.all([\n ...names.map(name => this.close(name)),\n ...pending.map(connection => this.disposeConnection(connection)),\n ]);\n }\n\n getConnection(name: string): ServerConnection | undefined {\n return this.connections.get(name);\n }\n\n getAllConnections(): Map<string, ServerConnection> {\n return new Map(this.connections);\n }\n\n touch(name: string): void {\n const connection = this.connections.get(name);\n if (connection) {\n connection.lastUsedAt = Date.now();\n }\n }\n\n incrementInFlight(name: string): void {\n const connection = this.connections.get(name);\n if (connection) {\n connection.inFlight = (connection.inFlight ?? 0) + 1;\n }\n }\n\n decrementInFlight(name: string): void {\n const connection = this.connections.get(name);\n if (connection && connection.inFlight) {\n connection.inFlight--;\n }\n }\n\n isIdle(name: string, timeoutMs: number): boolean {\n const connection = this.connections.get(name);\n if (!connection || connection.status !== \"connected\") return false;\n if (connection.inFlight > 0) return false;\n return (Date.now() - connection.lastUsedAt) > timeoutMs;\n }\n}\n\n/**\n * Resolve environment variables with interpolation.\n */\nfunction resolveEnv(env?: Record<string, string>): Record<string, string> {\n // Copy process.env, filtering out undefined values\n const resolved: Record<string, string> = {};\n for (const [key, value] of Object.entries(process.env)) {\n if (value !== undefined) {\n resolved[key] = value;\n }\n }\n\n if (!env) return resolved;\n\n const overrides = interpolateEnvRecord(env);\n return overrides ? { ...resolved, ...overrides } : resolved;\n}\n\n/**\n * Resolve headers with environment variable interpolation.\n */\nfunction resolveHeaders(headers?: Record<string, string>): Record<string, string> | undefined {\n return interpolateEnvRecord(headers);\n}\n\nfunction normalizeRequestTimeoutMs(timeoutMs: number | undefined): number | undefined {\n return typeof timeoutMs === \"number\" && Number.isFinite(timeoutMs) && timeoutMs > 0\n ? timeoutMs\n : undefined;\n}\n"]}
@@ -18,6 +18,8 @@ export class McpServerManager {
18
18
  defaultCwd;
19
19
  connections = new Map();
20
20
  connectPromises = new Map();
21
+ pendingConnections = new Map();
22
+ closing = false;
21
23
  uiStreamListeners = new Map();
22
24
  samplingConfig;
23
25
  elicitationConfig;
@@ -58,6 +60,8 @@ export class McpServerManager {
58
60
  }
59
61
  async connect(name, definition, signal) {
60
62
  throwIfAborted(signal);
63
+ if (this.closing)
64
+ throw new Error("MCP server manager is closed");
61
65
  // Dedupe concurrent connection attempts
62
66
  if (this.connectPromises.has(name)) {
63
67
  return abortable(this.connectPromises.get(name), signal);
@@ -68,15 +72,22 @@ export class McpServerManager {
68
72
  existing.lastUsedAt = Date.now();
69
73
  return existing;
70
74
  }
71
- const promise = this.createConnection(name, definition, signal);
72
- this.connectPromises.set(name, promise);
73
- try {
74
- const connection = await promise;
75
+ const promise = this.createConnection(name, definition, signal).then(async connection => {
76
+ if (this.closing || signal?.aborted) {
77
+ await this.disposeConnection(connection);
78
+ throwIfAborted(signal);
79
+ throw new Error("MCP server manager closed during connection");
80
+ }
75
81
  this.connections.set(name, connection);
76
82
  return connection;
83
+ });
84
+ this.connectPromises.set(name, promise);
85
+ try {
86
+ return await promise;
77
87
  }
78
88
  finally {
79
- this.connectPromises.delete(name);
89
+ if (this.connectPromises.get(name) === promise)
90
+ this.connectPromises.delete(name);
80
91
  }
81
92
  }
82
93
  async createConnection(name, definition, signal) {
@@ -110,6 +121,8 @@ export class McpServerManager {
110
121
  throw new Error(`Server ${name} has no command or url`);
111
122
  }
112
123
  const requestOptions = this.buildRequestOptions(definition, signal);
124
+ const pending = { client, transport };
125
+ this.pendingConnections.set(name, pending);
113
126
  try {
114
127
  await client.connect(transport, requestOptions);
115
128
  this.attachAdapterNotificationHandlers(name, client);
@@ -151,6 +164,10 @@ export class McpServerManager {
151
164
  await transport.close().catch(() => { });
152
165
  throw error;
153
166
  }
167
+ finally {
168
+ if (this.pendingConnections.get(name) === pending)
169
+ this.pendingConnections.delete(name);
170
+ }
154
171
  }
155
172
  buildClientCapabilities() {
156
173
  return {
@@ -323,6 +340,10 @@ export class McpServerManager {
323
340
  this.touch(name);
324
341
  }
325
342
  }
343
+ async disposeConnection(connection) {
344
+ await connection.client.close().catch(() => { });
345
+ await connection.transport.close().catch(() => { });
346
+ }
326
347
  async close(name) {
327
348
  const connection = this.connections.get(name);
328
349
  if (!connection)
@@ -333,12 +354,16 @@ export class McpServerManager {
333
354
  connection.status = "closed";
334
355
  this.connections.delete(name);
335
356
  this.acceptedUrlElicitations.delete(name);
336
- await connection.client.close().catch(() => { });
337
- await connection.transport.close().catch(() => { });
357
+ await this.disposeConnection(connection);
338
358
  }
339
359
  async closeAll() {
360
+ this.closing = true;
340
361
  const names = [...this.connections.keys()];
341
- await Promise.all(names.map(name => this.close(name)));
362
+ const pending = [...this.pendingConnections.values()];
363
+ await Promise.all([
364
+ ...names.map(name => this.close(name)),
365
+ ...pending.map(connection => this.disposeConnection(connection)),
366
+ ]);
342
367
  }
343
368
  getConnection(name) {
344
369
  return this.connections.get(name);
@@ -1 +1 @@
1
- {"version":3,"file":"server-manager.js","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/server-manager.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { UnauthorizedError } from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport type { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport {\n ElicitationCompleteNotificationSchema,\n type ReadResourceResult,\n type UrlElicitationRequiredError,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type {\n McpTool,\n McpResource,\n ServerDefinition,\n ServerStreamResultPatchNotification,\n Transport,\n} from \"./types.ts\";\nimport { serverStreamResultPatchNotificationSchema } from \"./types.ts\";\nimport { resolveNpxBinary } from \"./npx-resolver.ts\";\nimport { logger } from \"./logger.ts\";\nimport { McpOAuthProvider } from \"./mcp-oauth-provider.ts\";\nimport { extractOAuthConfig, supportsOAuth } from \"./mcp-auth-flow.ts\";\nimport { registerSamplingHandler, type ServerSamplingConfig } from \"./sampling-handler.ts\";\nimport {\n handleUrlElicitation,\n registerElicitationHandler,\n type ServerElicitationConfig,\n} from \"./elicitation-handler.ts\";\nimport { interpolateEnvRecord, resolveBearerToken, resolveConfigPath } from \"./utils.ts\";\nimport { abortable, throwIfAborted } from \"./abort.ts\";\n\ninterface ServerConnection {\n client: Client;\n transport: Transport;\n definition: ServerDefinition;\n tools: McpTool[];\n resources: McpResource[];\n lastUsedAt: number;\n inFlight: number;\n status: \"connected\" | \"closed\" | \"needs-auth\";\n}\n\ntype UiStreamListener = (serverName: string, notification: ServerStreamResultPatchNotification[\"params\"]) => void;\n\nexport class McpServerManager {\n private connections = new Map<string, ServerConnection>();\n private connectPromises = new Map<string, Promise<ServerConnection>>();\n private uiStreamListeners = new Map<string, UiStreamListener>();\n private samplingConfig: ServerSamplingConfig | undefined;\n private elicitationConfig: ServerElicitationConfig | undefined;\n private acceptedUrlElicitations = new Map<string, Set<string>>();\n private defaultRequestTimeoutMs: number | undefined;\n\n /** Default cwd for stdio servers without an explicit config `cwd`. */\n constructor(private readonly defaultCwd?: string) {}\n\n setSamplingConfig(config: ServerSamplingConfig | undefined): void {\n this.samplingConfig = config;\n }\n\n setElicitationConfig(config: ServerElicitationConfig | undefined): void {\n this.elicitationConfig = config;\n }\n\n setDefaultRequestTimeoutMs(timeoutMs: number | undefined): void {\n this.defaultRequestTimeoutMs = normalizeRequestTimeoutMs(timeoutMs);\n }\n\n getRequestOptions(name: string, signal?: AbortSignal): RequestOptions | undefined {\n const connection = this.connections.get(name);\n return this.buildRequestOptions(connection?.definition, signal);\n }\n\n private getResolvedRequestTimeoutMs(definition?: ServerDefinition): number | undefined {\n if (definition?.requestTimeoutMs !== undefined) {\n return normalizeRequestTimeoutMs(definition.requestTimeoutMs);\n }\n return this.defaultRequestTimeoutMs;\n }\n\n private buildRequestOptions(\n definition?: ServerDefinition,\n signal?: AbortSignal,\n ): RequestOptions | undefined {\n const timeout = this.getResolvedRequestTimeoutMs(definition);\n\n if (!signal && timeout === undefined) {\n return undefined;\n }\n\n return {\n ...(signal ? { signal } : {}),\n ...(timeout !== undefined ? { timeout } : {}),\n };\n }\n\n async connect(name: string, definition: ServerDefinition, signal?: AbortSignal): Promise<ServerConnection> {\n throwIfAborted(signal);\n // Dedupe concurrent connection attempts\n if (this.connectPromises.has(name)) {\n return abortable(this.connectPromises.get(name)!, signal);\n }\n\n // Reuse existing connection if healthy\n const existing = this.connections.get(name);\n if (existing?.status === \"connected\") {\n existing.lastUsedAt = Date.now();\n return existing;\n }\n\n const promise = this.createConnection(name, definition, signal);\n this.connectPromises.set(name, promise);\n\n try {\n const connection = await promise;\n this.connections.set(name, connection);\n return connection;\n } finally {\n this.connectPromises.delete(name);\n }\n }\n\n private async createConnection(\n name: string,\n definition: ServerDefinition,\n signal?: AbortSignal,\n ): Promise<ServerConnection> {\n throwIfAborted(signal);\n const client = this.createClient(name);\n\n let transport: Transport;\n\n if (definition.command) {\n let command = definition.command;\n let args = definition.args ?? [];\n\n if (command === \"npx\" || command === \"npm\") {\n const resolved = await resolveNpxBinary(command, args);\n if (resolved) {\n command = resolved.isJs ? \"node\" : resolved.binPath;\n args = resolved.isJs ? [resolved.binPath, ...resolved.extraArgs] : resolved.extraArgs;\n logger.debug(`${name} resolved to ${resolved.binPath} (skipping npm parent)`);\n }\n }\n\n transport = new StdioClientTransport({\n command,\n args,\n env: resolveEnv(definition.env),\n cwd: resolveConfigPath(definition.cwd) ?? this.defaultCwd,\n stderr: definition.debug ? \"inherit\" : \"ignore\",\n });\n } else if (definition.url) {\n // HTTP transport with fallback\n transport = await this.createHttpTransport(definition, name, signal);\n } else {\n throw new Error(`Server ${name} has no command or url`);\n }\n\n const requestOptions = this.buildRequestOptions(definition, signal);\n\n try {\n await client.connect(transport, requestOptions);\n this.attachAdapterNotificationHandlers(name, client);\n\n // Discover tools and resources\n const [tools, resources] = await Promise.all([\n this.fetchAllTools(client, requestOptions),\n this.fetchAllResources(client, requestOptions),\n ]);\n\n return {\n client,\n transport,\n definition,\n tools,\n resources,\n lastUsedAt: Date.now(),\n inFlight: 0,\n status: \"connected\",\n };\n } catch (error) {\n // Check for UnauthorizedError - server requires OAuth\n if (error instanceof UnauthorizedError && supportsOAuth(definition)) {\n // Clean up both client and transport before reporting needs-auth.\n await client.close().catch(() => {});\n await transport.close().catch(() => {});\n\n return {\n client,\n transport,\n definition,\n tools: [],\n resources: [],\n lastUsedAt: Date.now(),\n inFlight: 0,\n status: \"needs-auth\",\n };\n }\n\n // Clean up both client and transport on any error\n await client.close().catch(() => {});\n await transport.close().catch(() => {});\n throw error;\n }\n }\n\n private buildClientCapabilities() {\n return {\n ...(this.samplingConfig ? { sampling: {} } : {}),\n ...(this.elicitationConfig\n ? {\n elicitation: {\n form: {},\n ...(this.elicitationConfig.allowUrl ? { url: {} } : {}),\n },\n }\n : {}),\n };\n }\n\n private createClient(serverName: string): Client {\n const capabilities = this.buildClientCapabilities();\n const client = new Client(\n { name: `pi-mcp-${serverName}`, version: \"1.0.0\" },\n Object.keys(capabilities).length > 0 ? { capabilities } : undefined,\n );\n if (this.samplingConfig) {\n registerSamplingHandler(client, { ...this.samplingConfig, serverName });\n }\n if (this.elicitationConfig) {\n registerElicitationHandler(client, {\n ...this.elicitationConfig,\n serverName,\n onUrlAccepted: elicitationId => this.rememberUrlElicitation(serverName, elicitationId),\n });\n if (this.elicitationConfig.allowUrl) {\n client.setNotificationHandler(ElicitationCompleteNotificationSchema, notification => {\n const accepted = this.acceptedUrlElicitations.get(serverName);\n if (!accepted?.delete(notification.params.elicitationId)) return;\n this.elicitationConfig?.ui.notify(\n `MCP browser interaction for ${serverName} completed. You can retry the tool now.`,\n \"info\",\n );\n });\n }\n }\n return client;\n }\n\n async handleUrlElicitationRequired(\n serverName: string,\n error: UrlElicitationRequiredError,\n ): Promise<\"accept\" | \"decline\" | \"cancel\"> {\n if (!this.elicitationConfig?.allowUrl) return \"cancel\";\n for (const params of error.elicitations) {\n const result = await handleUrlElicitation({\n ...this.elicitationConfig,\n serverName,\n onUrlAccepted: elicitationId => this.rememberUrlElicitation(serverName, elicitationId),\n }, params);\n if (result.action !== \"accept\") return result.action;\n }\n return \"accept\";\n }\n\n private rememberUrlElicitation(serverName: string, elicitationId: string): void {\n let accepted = this.acceptedUrlElicitations.get(serverName);\n if (!accepted) {\n accepted = new Set();\n this.acceptedUrlElicitations.set(serverName, accepted);\n }\n accepted.add(elicitationId);\n }\n\n private async createHttpTransport(\n definition: ServerDefinition,\n serverName: string,\n signal?: AbortSignal,\n ): Promise<Transport> {\n throwIfAborted(signal);\n const url = new URL(definition.url!);\n\n // Build headers first (including any bearer token)\n const headers = resolveHeaders(definition.headers) ?? {};\n\n // For bearer auth, add the token to headers BEFORE creating requestInit\n if (definition.auth === \"bearer\") {\n const token = resolveBearerToken(definition);\n if (token) {\n headers[\"Authorization\"] = `Bearer ${token}`;\n }\n }\n\n // Create request init with headers (Authorization now included for bearer auth)\n const requestInit = Object.keys(headers).length > 0 ? { headers } : undefined;\n\n // For OAuth servers, create an auth provider\n let authProvider: McpOAuthProvider | undefined;\n if (supportsOAuth(definition)) {\n const oauthConfig = extractOAuthConfig(definition);\n authProvider = new McpOAuthProvider(\n serverName,\n definition.url!,\n oauthConfig,\n {\n onRedirect: async (_authUrl) => {\n // URL is captured by startAuth, no need to log\n },\n }\n );\n }\n\n // Try StreamableHTTP first (modern MCP servers)\n const streamableTransport = new StreamableHTTPClientTransport(url, {\n requestInit,\n authProvider,\n });\n\n try {\n // Create a test client to verify the transport works\n const testClient = new Client({ name: \"pi-mcp-probe\", version: \"2.1.2\" });\n await testClient.connect(streamableTransport, this.buildRequestOptions(definition, signal));\n await testClient.close().catch(() => {});\n // Close probe transport before creating fresh one\n await streamableTransport.close().catch(() => {});\n\n // StreamableHTTP works - create fresh transport for actual use\n return new StreamableHTTPClientTransport(url, { requestInit, authProvider });\n } catch (error) {\n // StreamableHTTP failed, close and try SSE fallback\n await streamableTransport.close().catch(() => {});\n\n // Host cancellation is not transport capability evidence; do not fall\n // through to SSE when the caller is trying to cancel the connect.\n if (signal?.aborted) {\n throwIfAborted(signal);\n }\n\n // If this was an UnauthorizedError, don't try SSE - the server needs auth\n if (error instanceof UnauthorizedError) {\n throw error;\n }\n\n // SSE is the legacy transport\n return new SSEClientTransport(url, { requestInit, authProvider });\n }\n }\n\n private async fetchAllTools(client: Client, requestOptions?: RequestOptions): Promise<McpTool[]> {\n const allTools: McpTool[] = [];\n let cursor: string | undefined;\n\n do {\n const result = await client.listTools(cursor ? { cursor } : undefined, requestOptions);\n allTools.push(...(result.tools ?? []));\n cursor = result.nextCursor;\n } while (cursor);\n\n return allTools;\n }\n\n private async fetchAllResources(client: Client, requestOptions?: RequestOptions): Promise<McpResource[]> {\n try {\n const allResources: McpResource[] = [];\n let cursor: string | undefined;\n\n do {\n const result = await client.listResources(cursor ? { cursor } : undefined, requestOptions);\n allResources.push(...(result.resources ?? []));\n cursor = result.nextCursor;\n } while (cursor);\n\n return allResources;\n } catch {\n if (requestOptions?.signal?.aborted) {\n throwIfAborted(requestOptions.signal);\n }\n // Server may not support resources\n return [];\n }\n }\n\n private attachAdapterNotificationHandlers(serverName: string, client: Client): void {\n client.setNotificationHandler(serverStreamResultPatchNotificationSchema, (notification) => {\n const listener = this.uiStreamListeners.get(notification.params.streamToken);\n if (!listener) return;\n listener(serverName, notification.params);\n });\n }\n\n registerUiStreamListener(streamToken: string, listener: UiStreamListener): void {\n this.uiStreamListeners.set(streamToken, listener);\n }\n\n removeUiStreamListener(streamToken: string): void {\n this.uiStreamListeners.delete(streamToken);\n }\n\n async readResource(name: string, uri: string, signal?: AbortSignal): Promise<ReadResourceResult> {\n const connection = this.connections.get(name);\n if (!connection || connection.status !== \"connected\") {\n throw new Error(`Server \"${name}\" is not connected`);\n }\n\n try {\n this.touch(name);\n this.incrementInFlight(name);\n return await connection.client.readResource({ uri }, this.getRequestOptions(name, signal));\n } finally {\n this.decrementInFlight(name);\n this.touch(name);\n }\n }\n\n async close(name: string): Promise<void> {\n const connection = this.connections.get(name);\n if (!connection) return;\n\n // Delete from map BEFORE async cleanup to prevent a race where a\n // concurrent connect() creates a new connection that our deferred\n // delete() would then remove, orphaning the new server process.\n connection.status = \"closed\";\n this.connections.delete(name);\n this.acceptedUrlElicitations.delete(name);\n await connection.client.close().catch(() => {});\n await connection.transport.close().catch(() => {});\n }\n\n async closeAll(): Promise<void> {\n const names = [...this.connections.keys()];\n await Promise.all(names.map(name => this.close(name)));\n }\n\n getConnection(name: string): ServerConnection | undefined {\n return this.connections.get(name);\n }\n\n getAllConnections(): Map<string, ServerConnection> {\n return new Map(this.connections);\n }\n\n touch(name: string): void {\n const connection = this.connections.get(name);\n if (connection) {\n connection.lastUsedAt = Date.now();\n }\n }\n\n incrementInFlight(name: string): void {\n const connection = this.connections.get(name);\n if (connection) {\n connection.inFlight = (connection.inFlight ?? 0) + 1;\n }\n }\n\n decrementInFlight(name: string): void {\n const connection = this.connections.get(name);\n if (connection && connection.inFlight) {\n connection.inFlight--;\n }\n }\n\n isIdle(name: string, timeoutMs: number): boolean {\n const connection = this.connections.get(name);\n if (!connection || connection.status !== \"connected\") return false;\n if (connection.inFlight > 0) return false;\n return (Date.now() - connection.lastUsedAt) > timeoutMs;\n }\n}\n\n/**\n * Resolve environment variables with interpolation.\n */\nfunction resolveEnv(env?: Record<string, string>): Record<string, string> {\n // Copy process.env, filtering out undefined values\n const resolved: Record<string, string> = {};\n for (const [key, value] of Object.entries(process.env)) {\n if (value !== undefined) {\n resolved[key] = value;\n }\n }\n\n if (!env) return resolved;\n\n const overrides = interpolateEnvRecord(env);\n return overrides ? { ...resolved, ...overrides } : resolved;\n}\n\n/**\n * Resolve headers with environment variable interpolation.\n */\nfunction resolveHeaders(headers?: Record<string, string>): Record<string, string> | undefined {\n return interpolateEnvRecord(headers);\n}\n\nfunction normalizeRequestTimeoutMs(timeoutMs: number | undefined): number | undefined {\n return typeof timeoutMs === \"number\" && Number.isFinite(timeoutMs) && timeoutMs > 0\n ? timeoutMs\n : undefined;\n}\n"]}
1
+ {"version":3,"file":"server-manager.js","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-mcp-adapter/server-manager.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { UnauthorizedError } from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport type { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport {\n ElicitationCompleteNotificationSchema,\n type ReadResourceResult,\n type UrlElicitationRequiredError,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type {\n McpTool,\n McpResource,\n ServerDefinition,\n ServerStreamResultPatchNotification,\n Transport,\n} from \"./types.ts\";\nimport { serverStreamResultPatchNotificationSchema } from \"./types.ts\";\nimport { resolveNpxBinary } from \"./npx-resolver.ts\";\nimport { logger } from \"./logger.ts\";\nimport { McpOAuthProvider } from \"./mcp-oauth-provider.ts\";\nimport { extractOAuthConfig, supportsOAuth } from \"./mcp-auth-flow.ts\";\nimport { registerSamplingHandler, type ServerSamplingConfig } from \"./sampling-handler.ts\";\nimport {\n handleUrlElicitation,\n registerElicitationHandler,\n type ServerElicitationConfig,\n} from \"./elicitation-handler.ts\";\nimport { interpolateEnvRecord, resolveBearerToken, resolveConfigPath } from \"./utils.ts\";\nimport { abortable, throwIfAborted } from \"./abort.ts\";\n\ninterface PendingConnection {\n client: Client;\n transport: Transport;\n}\n\ninterface ServerConnection extends PendingConnection {\n definition: ServerDefinition;\n tools: McpTool[];\n resources: McpResource[];\n lastUsedAt: number;\n inFlight: number;\n status: \"connected\" | \"closed\" | \"needs-auth\";\n}\n\ntype UiStreamListener = (serverName: string, notification: ServerStreamResultPatchNotification[\"params\"]) => void;\n\nexport class McpServerManager {\n private connections = new Map<string, ServerConnection>();\n private connectPromises = new Map<string, Promise<ServerConnection>>();\n private pendingConnections = new Map<string, PendingConnection>();\n private closing = false;\n private uiStreamListeners = new Map<string, UiStreamListener>();\n private samplingConfig: ServerSamplingConfig | undefined;\n private elicitationConfig: ServerElicitationConfig | undefined;\n private acceptedUrlElicitations = new Map<string, Set<string>>();\n private defaultRequestTimeoutMs: number | undefined;\n\n /** Default cwd for stdio servers without an explicit config `cwd`. */\n constructor(private readonly defaultCwd?: string) {}\n\n setSamplingConfig(config: ServerSamplingConfig | undefined): void {\n this.samplingConfig = config;\n }\n\n setElicitationConfig(config: ServerElicitationConfig | undefined): void {\n this.elicitationConfig = config;\n }\n\n setDefaultRequestTimeoutMs(timeoutMs: number | undefined): void {\n this.defaultRequestTimeoutMs = normalizeRequestTimeoutMs(timeoutMs);\n }\n\n getRequestOptions(name: string, signal?: AbortSignal): RequestOptions | undefined {\n const connection = this.connections.get(name);\n return this.buildRequestOptions(connection?.definition, signal);\n }\n\n private getResolvedRequestTimeoutMs(definition?: ServerDefinition): number | undefined {\n if (definition?.requestTimeoutMs !== undefined) {\n return normalizeRequestTimeoutMs(definition.requestTimeoutMs);\n }\n return this.defaultRequestTimeoutMs;\n }\n\n private buildRequestOptions(\n definition?: ServerDefinition,\n signal?: AbortSignal,\n ): RequestOptions | undefined {\n const timeout = this.getResolvedRequestTimeoutMs(definition);\n\n if (!signal && timeout === undefined) {\n return undefined;\n }\n\n return {\n ...(signal ? { signal } : {}),\n ...(timeout !== undefined ? { timeout } : {}),\n };\n }\n\n async connect(name: string, definition: ServerDefinition, signal?: AbortSignal): Promise<ServerConnection> {\n throwIfAborted(signal);\n if (this.closing) throw new Error(\"MCP server manager is closed\");\n // Dedupe concurrent connection attempts\n if (this.connectPromises.has(name)) {\n return abortable(this.connectPromises.get(name)!, signal);\n }\n\n // Reuse existing connection if healthy\n const existing = this.connections.get(name);\n if (existing?.status === \"connected\") {\n existing.lastUsedAt = Date.now();\n return existing;\n }\n\n const promise = this.createConnection(name, definition, signal).then(async connection => {\n if (this.closing || signal?.aborted) {\n await this.disposeConnection(connection);\n throwIfAborted(signal);\n throw new Error(\"MCP server manager closed during connection\");\n }\n this.connections.set(name, connection);\n return connection;\n });\n this.connectPromises.set(name, promise);\n\n try {\n return await promise;\n } finally {\n if (this.connectPromises.get(name) === promise) this.connectPromises.delete(name);\n }\n }\n\n private async createConnection(\n name: string,\n definition: ServerDefinition,\n signal?: AbortSignal,\n ): Promise<ServerConnection> {\n throwIfAborted(signal);\n const client = this.createClient(name);\n\n let transport: Transport;\n\n if (definition.command) {\n let command = definition.command;\n let args = definition.args ?? [];\n\n if (command === \"npx\" || command === \"npm\") {\n const resolved = await resolveNpxBinary(command, args);\n if (resolved) {\n command = resolved.isJs ? \"node\" : resolved.binPath;\n args = resolved.isJs ? [resolved.binPath, ...resolved.extraArgs] : resolved.extraArgs;\n logger.debug(`${name} resolved to ${resolved.binPath} (skipping npm parent)`);\n }\n }\n\n transport = new StdioClientTransport({\n command,\n args,\n env: resolveEnv(definition.env),\n cwd: resolveConfigPath(definition.cwd) ?? this.defaultCwd,\n stderr: definition.debug ? \"inherit\" : \"ignore\",\n });\n } else if (definition.url) {\n // HTTP transport with fallback\n transport = await this.createHttpTransport(definition, name, signal);\n } else {\n throw new Error(`Server ${name} has no command or url`);\n }\n\n const requestOptions = this.buildRequestOptions(definition, signal);\n const pending = { client, transport };\n this.pendingConnections.set(name, pending);\n\n try {\n await client.connect(transport, requestOptions);\n this.attachAdapterNotificationHandlers(name, client);\n\n // Discover tools and resources\n const [tools, resources] = await Promise.all([\n this.fetchAllTools(client, requestOptions),\n this.fetchAllResources(client, requestOptions),\n ]);\n\n return {\n client,\n transport,\n definition,\n tools,\n resources,\n lastUsedAt: Date.now(),\n inFlight: 0,\n status: \"connected\",\n };\n } catch (error) {\n // Check for UnauthorizedError - server requires OAuth\n if (error instanceof UnauthorizedError && supportsOAuth(definition)) {\n // Clean up both client and transport before reporting needs-auth.\n await client.close().catch(() => {});\n await transport.close().catch(() => {});\n\n return {\n client,\n transport,\n definition,\n tools: [],\n resources: [],\n lastUsedAt: Date.now(),\n inFlight: 0,\n status: \"needs-auth\",\n };\n }\n\n // Clean up both client and transport on any error\n await client.close().catch(() => {});\n await transport.close().catch(() => {});\n throw error;\n } finally {\n if (this.pendingConnections.get(name) === pending) this.pendingConnections.delete(name);\n }\n }\n\n private buildClientCapabilities() {\n return {\n ...(this.samplingConfig ? { sampling: {} } : {}),\n ...(this.elicitationConfig\n ? {\n elicitation: {\n form: {},\n ...(this.elicitationConfig.allowUrl ? { url: {} } : {}),\n },\n }\n : {}),\n };\n }\n\n private createClient(serverName: string): Client {\n const capabilities = this.buildClientCapabilities();\n const client = new Client(\n { name: `pi-mcp-${serverName}`, version: \"1.0.0\" },\n Object.keys(capabilities).length > 0 ? { capabilities } : undefined,\n );\n if (this.samplingConfig) {\n registerSamplingHandler(client, { ...this.samplingConfig, serverName });\n }\n if (this.elicitationConfig) {\n registerElicitationHandler(client, {\n ...this.elicitationConfig,\n serverName,\n onUrlAccepted: elicitationId => this.rememberUrlElicitation(serverName, elicitationId),\n });\n if (this.elicitationConfig.allowUrl) {\n client.setNotificationHandler(ElicitationCompleteNotificationSchema, notification => {\n const accepted = this.acceptedUrlElicitations.get(serverName);\n if (!accepted?.delete(notification.params.elicitationId)) return;\n this.elicitationConfig?.ui.notify(\n `MCP browser interaction for ${serverName} completed. You can retry the tool now.`,\n \"info\",\n );\n });\n }\n }\n return client;\n }\n\n async handleUrlElicitationRequired(\n serverName: string,\n error: UrlElicitationRequiredError,\n ): Promise<\"accept\" | \"decline\" | \"cancel\"> {\n if (!this.elicitationConfig?.allowUrl) return \"cancel\";\n for (const params of error.elicitations) {\n const result = await handleUrlElicitation({\n ...this.elicitationConfig,\n serverName,\n onUrlAccepted: elicitationId => this.rememberUrlElicitation(serverName, elicitationId),\n }, params);\n if (result.action !== \"accept\") return result.action;\n }\n return \"accept\";\n }\n\n private rememberUrlElicitation(serverName: string, elicitationId: string): void {\n let accepted = this.acceptedUrlElicitations.get(serverName);\n if (!accepted) {\n accepted = new Set();\n this.acceptedUrlElicitations.set(serverName, accepted);\n }\n accepted.add(elicitationId);\n }\n\n private async createHttpTransport(\n definition: ServerDefinition,\n serverName: string,\n signal?: AbortSignal,\n ): Promise<Transport> {\n throwIfAborted(signal);\n const url = new URL(definition.url!);\n\n // Build headers first (including any bearer token)\n const headers = resolveHeaders(definition.headers) ?? {};\n\n // For bearer auth, add the token to headers BEFORE creating requestInit\n if (definition.auth === \"bearer\") {\n const token = resolveBearerToken(definition);\n if (token) {\n headers[\"Authorization\"] = `Bearer ${token}`;\n }\n }\n\n // Create request init with headers (Authorization now included for bearer auth)\n const requestInit = Object.keys(headers).length > 0 ? { headers } : undefined;\n\n // For OAuth servers, create an auth provider\n let authProvider: McpOAuthProvider | undefined;\n if (supportsOAuth(definition)) {\n const oauthConfig = extractOAuthConfig(definition);\n authProvider = new McpOAuthProvider(\n serverName,\n definition.url!,\n oauthConfig,\n {\n onRedirect: async (_authUrl) => {\n // URL is captured by startAuth, no need to log\n },\n }\n );\n }\n\n // Try StreamableHTTP first (modern MCP servers)\n const streamableTransport = new StreamableHTTPClientTransport(url, {\n requestInit,\n authProvider,\n });\n\n try {\n // Create a test client to verify the transport works\n const testClient = new Client({ name: \"pi-mcp-probe\", version: \"2.1.2\" });\n await testClient.connect(streamableTransport, this.buildRequestOptions(definition, signal));\n await testClient.close().catch(() => {});\n // Close probe transport before creating fresh one\n await streamableTransport.close().catch(() => {});\n\n // StreamableHTTP works - create fresh transport for actual use\n return new StreamableHTTPClientTransport(url, { requestInit, authProvider });\n } catch (error) {\n // StreamableHTTP failed, close and try SSE fallback\n await streamableTransport.close().catch(() => {});\n\n // Host cancellation is not transport capability evidence; do not fall\n // through to SSE when the caller is trying to cancel the connect.\n if (signal?.aborted) {\n throwIfAborted(signal);\n }\n\n // If this was an UnauthorizedError, don't try SSE - the server needs auth\n if (error instanceof UnauthorizedError) {\n throw error;\n }\n\n // SSE is the legacy transport\n return new SSEClientTransport(url, { requestInit, authProvider });\n }\n }\n\n private async fetchAllTools(client: Client, requestOptions?: RequestOptions): Promise<McpTool[]> {\n const allTools: McpTool[] = [];\n let cursor: string | undefined;\n\n do {\n const result = await client.listTools(cursor ? { cursor } : undefined, requestOptions);\n allTools.push(...(result.tools ?? []));\n cursor = result.nextCursor;\n } while (cursor);\n\n return allTools;\n }\n\n private async fetchAllResources(client: Client, requestOptions?: RequestOptions): Promise<McpResource[]> {\n try {\n const allResources: McpResource[] = [];\n let cursor: string | undefined;\n\n do {\n const result = await client.listResources(cursor ? { cursor } : undefined, requestOptions);\n allResources.push(...(result.resources ?? []));\n cursor = result.nextCursor;\n } while (cursor);\n\n return allResources;\n } catch {\n if (requestOptions?.signal?.aborted) {\n throwIfAborted(requestOptions.signal);\n }\n // Server may not support resources\n return [];\n }\n }\n\n private attachAdapterNotificationHandlers(serverName: string, client: Client): void {\n client.setNotificationHandler(serverStreamResultPatchNotificationSchema, (notification) => {\n const listener = this.uiStreamListeners.get(notification.params.streamToken);\n if (!listener) return;\n listener(serverName, notification.params);\n });\n }\n\n registerUiStreamListener(streamToken: string, listener: UiStreamListener): void {\n this.uiStreamListeners.set(streamToken, listener);\n }\n\n removeUiStreamListener(streamToken: string): void {\n this.uiStreamListeners.delete(streamToken);\n }\n\n async readResource(name: string, uri: string, signal?: AbortSignal): Promise<ReadResourceResult> {\n const connection = this.connections.get(name);\n if (!connection || connection.status !== \"connected\") {\n throw new Error(`Server \"${name}\" is not connected`);\n }\n\n try {\n this.touch(name);\n this.incrementInFlight(name);\n return await connection.client.readResource({ uri }, this.getRequestOptions(name, signal));\n } finally {\n this.decrementInFlight(name);\n this.touch(name);\n }\n }\n\n private async disposeConnection(connection: PendingConnection): Promise<void> {\n await connection.client.close().catch(() => {});\n await connection.transport.close().catch(() => {});\n }\n\n async close(name: string): Promise<void> {\n const connection = this.connections.get(name);\n if (!connection) return;\n\n // Delete from map BEFORE async cleanup to prevent a race where a\n // concurrent connect() creates a new connection that our deferred\n // delete() would then remove, orphaning the new server process.\n connection.status = \"closed\";\n this.connections.delete(name);\n this.acceptedUrlElicitations.delete(name);\n await this.disposeConnection(connection);\n }\n\n async closeAll(): Promise<void> {\n this.closing = true;\n const names = [...this.connections.keys()];\n const pending = [...this.pendingConnections.values()];\n await Promise.all([\n ...names.map(name => this.close(name)),\n ...pending.map(connection => this.disposeConnection(connection)),\n ]);\n }\n\n getConnection(name: string): ServerConnection | undefined {\n return this.connections.get(name);\n }\n\n getAllConnections(): Map<string, ServerConnection> {\n return new Map(this.connections);\n }\n\n touch(name: string): void {\n const connection = this.connections.get(name);\n if (connection) {\n connection.lastUsedAt = Date.now();\n }\n }\n\n incrementInFlight(name: string): void {\n const connection = this.connections.get(name);\n if (connection) {\n connection.inFlight = (connection.inFlight ?? 0) + 1;\n }\n }\n\n decrementInFlight(name: string): void {\n const connection = this.connections.get(name);\n if (connection && connection.inFlight) {\n connection.inFlight--;\n }\n }\n\n isIdle(name: string, timeoutMs: number): boolean {\n const connection = this.connections.get(name);\n if (!connection || connection.status !== \"connected\") return false;\n if (connection.inFlight > 0) return false;\n return (Date.now() - connection.lastUsedAt) > timeoutMs;\n }\n}\n\n/**\n * Resolve environment variables with interpolation.\n */\nfunction resolveEnv(env?: Record<string, string>): Record<string, string> {\n // Copy process.env, filtering out undefined values\n const resolved: Record<string, string> = {};\n for (const [key, value] of Object.entries(process.env)) {\n if (value !== undefined) {\n resolved[key] = value;\n }\n }\n\n if (!env) return resolved;\n\n const overrides = interpolateEnvRecord(env);\n return overrides ? { ...resolved, ...overrides } : resolved;\n}\n\n/**\n * Resolve headers with environment variable interpolation.\n */\nfunction resolveHeaders(headers?: Record<string, string>): Record<string, string> | undefined {\n return interpolateEnvRecord(headers);\n}\n\nfunction normalizeRequestTimeoutMs(timeoutMs: number | undefined): number | undefined {\n return typeof timeoutMs === \"number\" && Number.isFinite(timeoutMs) && timeoutMs > 0\n ? timeoutMs\n : undefined;\n}\n"]}