@humain/terminal 0.0.3-beta.3 → 0.0.4-beta.2

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 (737) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +1 -0
  3. package/dist/bun/cli.d.ts.map +1 -1
  4. package/dist/bun/cli.js.map +1 -1
  5. package/dist/bun/restore-sandbox-env.d.ts.map +1 -1
  6. package/dist/bun/restore-sandbox-env.js.map +1 -1
  7. package/dist/cli/args.d.ts +1 -0
  8. package/dist/cli/args.d.ts.map +1 -1
  9. package/dist/cli/args.js +11 -0
  10. package/dist/cli/args.js.map +1 -1
  11. package/dist/cli/auth-check.d.ts.map +1 -1
  12. package/dist/cli/auth-check.js.map +1 -1
  13. package/dist/cli/auth-command.d.ts.map +1 -1
  14. package/dist/cli/auth-command.js.map +1 -1
  15. package/dist/cli/config-selector.d.ts.map +1 -1
  16. package/dist/cli/config-selector.js.map +1 -1
  17. package/dist/cli/credential-print.d.ts.map +1 -1
  18. package/dist/cli/credential-print.js.map +1 -1
  19. package/dist/cli/experimental/auth.d.ts.map +1 -1
  20. package/dist/cli/experimental/auth.js.map +1 -1
  21. package/dist/cli/experimental/cli.d.ts.map +1 -1
  22. package/dist/cli/experimental/command-options.d.ts.map +1 -1
  23. package/dist/cli/experimental/command-options.js.map +1 -1
  24. package/dist/cli/experimental/command.d.ts.map +1 -1
  25. package/dist/cli/experimental/command.js +2 -5
  26. package/dist/cli/experimental/command.js.map +1 -1
  27. package/dist/cli/experimental/commands/client.d.ts.map +1 -1
  28. package/dist/cli/experimental/commands/client.js.map +1 -1
  29. package/dist/cli/experimental/commands/pi.d.ts.map +1 -1
  30. package/dist/cli/experimental/commands/pi.js.map +1 -1
  31. package/dist/cli/experimental/commands/server.d.ts.map +1 -1
  32. package/dist/cli/experimental/commands/server.js.map +1 -1
  33. package/dist/cli/experimental/transport-address.d.ts.map +1 -1
  34. package/dist/cli/experimental/transport-address.js.map +1 -1
  35. package/dist/cli/file-processor.d.ts.map +1 -1
  36. package/dist/cli/file-processor.js.map +1 -1
  37. package/dist/cli/initial-message.d.ts +1 -1
  38. package/dist/cli/initial-message.d.ts.map +1 -1
  39. package/dist/cli/initial-message.js.map +1 -1
  40. package/dist/cli/list-models.d.ts.map +1 -1
  41. package/dist/cli/list-models.js.map +1 -1
  42. package/dist/cli/project-trust.d.ts.map +1 -1
  43. package/dist/cli/project-trust.js.map +1 -1
  44. package/dist/cli/session-picker.d.ts.map +1 -1
  45. package/dist/cli/session-picker.js.map +1 -1
  46. package/dist/cli/startup-ui.d.ts.map +1 -1
  47. package/dist/cli/startup-ui.js.map +1 -1
  48. package/dist/cli.d.ts.map +1 -1
  49. package/dist/cli.js.map +1 -1
  50. package/dist/client/index.d.ts.map +1 -1
  51. package/dist/client/remote-session.d.ts.map +1 -1
  52. package/dist/client/remote-session.js.map +1 -1
  53. package/dist/client/transcript.d.ts.map +1 -1
  54. package/dist/client/transcript.js +1 -1
  55. package/dist/client/transcript.js.map +1 -1
  56. package/dist/config.d.ts.map +1 -1
  57. package/dist/config.js.map +1 -1
  58. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  59. package/dist/core/agent-session-runtime.js +0 -8
  60. package/dist/core/agent-session-runtime.js.map +1 -1
  61. package/dist/core/agent-session-services.d.ts.map +1 -1
  62. package/dist/core/agent-session-services.js.map +1 -1
  63. package/dist/core/agent-session.d.ts +36 -2
  64. package/dist/core/agent-session.d.ts.map +1 -1
  65. package/dist/core/agent-session.js +107 -129
  66. package/dist/core/agent-session.js.map +1 -1
  67. package/dist/core/auth-guidance.d.ts.map +1 -1
  68. package/dist/core/auth-guidance.js.map +1 -1
  69. package/dist/core/auth-storage.d.ts.map +1 -1
  70. package/dist/core/auth-storage.js +3 -8
  71. package/dist/core/auth-storage.js.map +1 -1
  72. package/dist/core/bash-executor.d.ts.map +1 -1
  73. package/dist/core/bash-executor.js.map +1 -1
  74. package/dist/core/cache-stats.d.ts.map +1 -1
  75. package/dist/core/cache-stats.js.map +1 -1
  76. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  77. package/dist/core/compaction/branch-summarization.js.map +1 -1
  78. package/dist/core/compaction/compaction.d.ts.map +1 -1
  79. package/dist/core/compaction/compaction.js.map +1 -1
  80. package/dist/core/compaction/index.d.ts.map +1 -1
  81. package/dist/core/compaction/utils.d.ts.map +1 -1
  82. package/dist/core/compaction/utils.js.map +1 -1
  83. package/dist/core/defaults.d.ts.map +1 -1
  84. package/dist/core/diagnostics.d.ts.map +1 -1
  85. package/dist/core/event-bus.d.ts.map +1 -1
  86. package/dist/core/event-bus.js.map +1 -1
  87. package/dist/core/exec.d.ts.map +1 -1
  88. package/dist/core/exec.js.map +1 -1
  89. package/dist/core/experimental.d.ts +4 -0
  90. package/dist/core/experimental.d.ts.map +1 -1
  91. package/dist/core/experimental.js +4 -0
  92. package/dist/core/experimental.js.map +1 -1
  93. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  94. package/dist/core/export-html/ansi-to-html.js.map +1 -1
  95. package/dist/core/export-html/index.d.ts.map +1 -1
  96. package/dist/core/export-html/index.js.map +1 -1
  97. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  98. package/dist/core/export-html/tool-renderer.js.map +1 -1
  99. package/dist/core/extensions/index.d.ts.map +1 -1
  100. package/dist/core/extensions/loader.d.ts.map +1 -1
  101. package/dist/core/extensions/loader.js.map +1 -1
  102. package/dist/core/extensions/runner.d.ts.map +1 -1
  103. package/dist/core/extensions/runner.js +22 -30
  104. package/dist/core/extensions/runner.js.map +1 -1
  105. package/dist/core/extensions/types.d.ts +4 -0
  106. package/dist/core/extensions/types.d.ts.map +1 -1
  107. package/dist/core/extensions/types.js.map +1 -1
  108. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  109. package/dist/core/extensions/wrapper.js.map +1 -1
  110. package/dist/core/footer-data-provider.d.ts.map +1 -1
  111. package/dist/core/footer-data-provider.js +17 -18
  112. package/dist/core/footer-data-provider.js.map +1 -1
  113. package/dist/core/http-dispatcher.d.ts.map +1 -1
  114. package/dist/core/http-dispatcher.js.map +1 -1
  115. package/dist/core/index.d.ts.map +1 -1
  116. package/dist/core/keybindings.d.ts +24 -0
  117. package/dist/core/keybindings.d.ts.map +1 -1
  118. package/dist/core/keybindings.js +0 -1
  119. package/dist/core/keybindings.js.map +1 -1
  120. package/dist/core/messages.d.ts.map +1 -1
  121. package/dist/core/messages.js.map +1 -1
  122. package/dist/core/model-config.d.ts +5 -0
  123. package/dist/core/model-config.d.ts.map +1 -1
  124. package/dist/core/model-config.js +1 -2
  125. package/dist/core/model-config.js.map +1 -1
  126. package/dist/core/model-registry.d.ts.map +1 -1
  127. package/dist/core/model-registry.js +0 -1
  128. package/dist/core/model-registry.js.map +1 -1
  129. package/dist/core/model-resolver.d.ts.map +1 -1
  130. package/dist/core/model-resolver.js.map +1 -1
  131. package/dist/core/model-runtime.d.ts.map +1 -1
  132. package/dist/core/model-runtime.js +15 -25
  133. package/dist/core/model-runtime.js.map +1 -1
  134. package/dist/core/models-store.d.ts.map +1 -1
  135. package/dist/core/models-store.js +3 -4
  136. package/dist/core/models-store.js.map +1 -1
  137. package/dist/core/output-guard.d.ts.map +1 -1
  138. package/dist/core/output-guard.js.map +1 -1
  139. package/dist/core/package-manager.d.ts.map +1 -1
  140. package/dist/core/package-manager.js +0 -7
  141. package/dist/core/package-manager.js.map +1 -1
  142. package/dist/core/pi-manifest.d.ts.map +1 -1
  143. package/dist/core/pi-manifest.js.map +1 -1
  144. package/dist/core/project-trust.d.ts.map +1 -1
  145. package/dist/core/project-trust.js.map +1 -1
  146. package/dist/core/prompt-templates.d.ts.map +1 -1
  147. package/dist/core/prompt-templates.js.map +1 -1
  148. package/dist/core/provider-attribution.d.ts.map +1 -1
  149. package/dist/core/provider-attribution.js.map +1 -1
  150. package/dist/core/provider-composer.d.ts.map +1 -1
  151. package/dist/core/provider-composer.js.map +1 -1
  152. package/dist/core/radius.d.ts.map +1 -1
  153. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  154. package/dist/core/remote-catalog-provider.js.map +1 -1
  155. package/dist/core/resolve-config-value.d.ts.map +1 -1
  156. package/dist/core/resolve-config-value.js.map +1 -1
  157. package/dist/core/resource-loader.d.ts.map +1 -1
  158. package/dist/core/resource-loader.js +0 -44
  159. package/dist/core/resource-loader.js.map +1 -1
  160. package/dist/core/runtime-credentials.d.ts.map +1 -1
  161. package/dist/core/runtime-credentials.js +1 -2
  162. package/dist/core/runtime-credentials.js.map +1 -1
  163. package/dist/core/sdk.d.ts +5 -3
  164. package/dist/core/sdk.d.ts.map +1 -1
  165. package/dist/core/sdk.js +3 -2
  166. package/dist/core/sdk.js.map +1 -1
  167. package/dist/core/session-cwd.d.ts.map +1 -1
  168. package/dist/core/session-cwd.js +0 -1
  169. package/dist/core/session-cwd.js.map +1 -1
  170. package/dist/core/session-manager.d.ts +4 -0
  171. package/dist/core/session-manager.d.ts.map +1 -1
  172. package/dist/core/session-manager.js +55 -35
  173. package/dist/core/session-manager.js.map +1 -1
  174. package/dist/core/settings-manager.d.ts +6 -0
  175. package/dist/core/settings-manager.d.ts.map +1 -1
  176. package/dist/core/settings-manager.js +19 -17
  177. package/dist/core/settings-manager.js.map +1 -1
  178. package/dist/core/skills.d.ts.map +1 -1
  179. package/dist/core/skills.js.map +1 -1
  180. package/dist/core/slash-commands.d.ts.map +1 -1
  181. package/dist/core/source-info.d.ts.map +1 -1
  182. package/dist/core/source-info.js.map +1 -1
  183. package/dist/core/system-prompt.d.ts.map +1 -1
  184. package/dist/core/system-prompt.js +1 -1
  185. package/dist/core/system-prompt.js.map +1 -1
  186. package/dist/core/telemetry.d.ts.map +1 -1
  187. package/dist/core/telemetry.js.map +1 -1
  188. package/dist/core/timings.d.ts.map +1 -1
  189. package/dist/core/timings.js.map +1 -1
  190. package/dist/core/tools/bash.d.ts.map +1 -1
  191. package/dist/core/tools/bash.js +10 -5
  192. package/dist/core/tools/bash.js.map +1 -1
  193. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  194. package/dist/core/tools/edit-diff.js.map +1 -1
  195. package/dist/core/tools/edit.d.ts.map +1 -1
  196. package/dist/core/tools/edit.js +2 -0
  197. package/dist/core/tools/edit.js.map +1 -1
  198. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  199. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  200. package/dist/core/tools/find.d.ts +1 -1
  201. package/dist/core/tools/find.d.ts.map +1 -1
  202. package/dist/core/tools/find.js +1 -1
  203. package/dist/core/tools/find.js.map +1 -1
  204. package/dist/core/tools/grep.d.ts.map +1 -1
  205. package/dist/core/tools/grep.js +1 -1
  206. package/dist/core/tools/grep.js.map +1 -1
  207. package/dist/core/tools/index.d.ts +2 -1
  208. package/dist/core/tools/index.d.ts.map +1 -1
  209. package/dist/core/tools/index.js +9 -1
  210. package/dist/core/tools/index.js.map +1 -1
  211. package/dist/core/tools/ls.d.ts.map +1 -1
  212. package/dist/core/tools/ls.js.map +1 -1
  213. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  214. package/dist/core/tools/output-accumulator.js +12 -18
  215. package/dist/core/tools/output-accumulator.js.map +1 -1
  216. package/dist/core/tools/path-utils.d.ts.map +1 -1
  217. package/dist/core/tools/path-utils.js.map +1 -1
  218. package/dist/core/tools/read.d.ts.map +1 -1
  219. package/dist/core/tools/read.js +2 -0
  220. package/dist/core/tools/read.js.map +1 -1
  221. package/dist/core/tools/render-utils.d.ts.map +1 -1
  222. package/dist/core/tools/render-utils.js.map +1 -1
  223. package/dist/core/tools/subagent.d.ts +82 -0
  224. package/dist/core/tools/subagent.d.ts.map +1 -0
  225. package/dist/core/tools/subagent.js +980 -0
  226. package/dist/core/tools/subagent.js.map +1 -0
  227. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  228. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  229. package/dist/core/tools/truncate.d.ts.map +1 -1
  230. package/dist/core/tools/truncate.js.map +1 -1
  231. package/dist/core/tools/write.d.ts.map +1 -1
  232. package/dist/core/tools/write.js +2 -1
  233. package/dist/core/tools/write.js.map +1 -1
  234. package/dist/core/trust-manager.d.ts.map +1 -1
  235. package/dist/core/trust-manager.js +0 -1
  236. package/dist/core/trust-manager.js.map +1 -1
  237. package/dist/core/usage-totals.d.ts.map +1 -1
  238. package/dist/core/usage-totals.js.map +1 -1
  239. package/dist/extensions/index.d.ts.map +1 -1
  240. package/dist/extensions/llama/client.d.ts.map +1 -1
  241. package/dist/extensions/llama/client.js +0 -2
  242. package/dist/extensions/llama/client.js.map +1 -1
  243. package/dist/extensions/llama/huggingface.d.ts.map +1 -1
  244. package/dist/extensions/llama/huggingface.js +0 -2
  245. package/dist/extensions/llama/huggingface.js.map +1 -1
  246. package/dist/extensions/llama/index.d.ts.map +1 -1
  247. package/dist/extensions/llama/index.js.map +1 -1
  248. package/dist/extensions/llama/provider.d.ts.map +1 -1
  249. package/dist/extensions/llama/provider.js.map +1 -1
  250. package/dist/extensions/llama/ui.d.ts.map +1 -1
  251. package/dist/extensions/llama/ui.js +12 -28
  252. package/dist/extensions/llama/ui.js.map +1 -1
  253. package/dist/humain/agent-execution-protocol.d.ts.map +1 -1
  254. package/dist/humain/agent-execution-protocol.js.map +1 -1
  255. package/dist/humain/agent-execution-runtime.d.ts.map +1 -1
  256. package/dist/humain/agent-execution-runtime.js.map +1 -1
  257. package/dist/humain/bedrock-provider/vendor/index.bundle.mjs +127 -7
  258. package/dist/humain/brand-logo.d.ts.map +1 -1
  259. package/dist/humain/index.d.ts.map +1 -1
  260. package/dist/humain/index.js.map +1 -1
  261. package/dist/humain/legacy-workflow-tiers.d.ts.map +1 -1
  262. package/dist/humain/legacy-workflow-tiers.js.map +1 -1
  263. package/dist/humain/mcp-adapter/vendor/CHANGELOG.md +36 -0
  264. package/dist/humain/mcp-adapter/vendor/README.md +47 -5
  265. package/dist/humain/mcp-adapter/vendor/cli.js +163 -1
  266. package/dist/humain/mcp-adapter/vendor/commands.ts +128 -22
  267. package/dist/humain/mcp-adapter/vendor/config.ts +25 -7
  268. package/dist/humain/mcp-adapter/vendor/direct-tools.ts +5 -4
  269. package/dist/humain/mcp-adapter/vendor/index.bundle.mjs +1663 -458
  270. package/dist/humain/mcp-adapter/vendor/index.ts +219 -32
  271. package/dist/humain/mcp-adapter/vendor/init.ts +36 -4
  272. package/dist/humain/mcp-adapter/vendor/lifecycle.ts +315 -24
  273. package/dist/humain/mcp-adapter/vendor/mcp-auth-flow.ts +39 -6
  274. package/dist/humain/mcp-adapter/vendor/mcp-bearer-store.ts +387 -0
  275. package/dist/humain/mcp-adapter/vendor/mcp-callback-server.ts +27 -3
  276. package/dist/humain/mcp-adapter/vendor/mcp-code.ts +4 -0
  277. package/dist/humain/mcp-adapter/vendor/mcp-panel.ts +42 -13
  278. package/dist/humain/mcp-adapter/vendor/metadata-cache.ts +32 -21
  279. package/dist/humain/mcp-adapter/vendor/package-mcp-loader.ts +168 -0
  280. package/dist/humain/mcp-adapter/vendor/package.json +179 -177
  281. package/dist/humain/mcp-adapter/vendor/proxy-modes.ts +5 -4
  282. package/dist/humain/mcp-adapter/vendor/request-headers-command.ts +31 -37
  283. package/dist/humain/mcp-adapter/vendor/search-ranking.ts +92 -22
  284. package/dist/humain/mcp-adapter/vendor/server-manager.ts +140 -2
  285. package/dist/humain/mcp-adapter/vendor/session-recovery.ts +7 -0
  286. package/dist/humain/mcp-adapter/vendor/tool-approval.ts +15 -2
  287. package/dist/humain/mcp-adapter/vendor/tool-result-renderer.ts +44 -4
  288. package/dist/humain/mcp-adapter/vendor/types.ts +2 -0
  289. package/dist/humain/mcp-adapter/vendor/ui-server.ts +18 -16
  290. package/dist/humain/mcp-adapter/vendor/utils.ts +70 -0
  291. package/dist/humain/mcp-adapter.d.ts.map +1 -1
  292. package/dist/humain/mcp-adapter.js.map +1 -1
  293. package/dist/humain/pi-agent-execution-host.d.ts.map +1 -1
  294. package/dist/humain/pi-agent-execution-host.js.map +1 -1
  295. package/dist/humain/web-access/host.d.ts.map +1 -1
  296. package/dist/humain/web-access/index.d.ts.map +1 -1
  297. package/dist/humain/web-access/index.js.map +1 -1
  298. package/dist/humain/web-access/vendor/activity.d.ts.map +1 -1
  299. package/dist/humain/web-access/vendor/activity.js +7 -5
  300. package/dist/humain/web-access/vendor/activity.js.map +1 -1
  301. package/dist/humain/web-access/vendor/anysearch.d.ts.map +1 -1
  302. package/dist/humain/web-access/vendor/anysearch.js +3 -2
  303. package/dist/humain/web-access/vendor/anysearch.js.map +1 -1
  304. package/dist/humain/web-access/vendor/auth-fetch.d.ts.map +1 -1
  305. package/dist/humain/web-access/vendor/auth-fetch.js.map +1 -1
  306. package/dist/humain/web-access/vendor/bocha.d.ts.map +1 -1
  307. package/dist/humain/web-access/vendor/bocha.js.map +1 -1
  308. package/dist/humain/web-access/vendor/brave.d.ts.map +1 -1
  309. package/dist/humain/web-access/vendor/brave.js +14 -4
  310. package/dist/humain/web-access/vendor/brave.js.map +1 -1
  311. package/dist/humain/web-access/vendor/brightdata-unlocker.d.ts.map +1 -1
  312. package/dist/humain/web-access/vendor/brightdata-unlocker.js.map +1 -1
  313. package/dist/humain/web-access/vendor/brightdata.d.ts.map +1 -1
  314. package/dist/humain/web-access/vendor/brightdata.js.map +1 -1
  315. package/dist/humain/web-access/vendor/chrome-cookies.d.ts.map +1 -1
  316. package/dist/humain/web-access/vendor/chrome-cookies.js +92 -14
  317. package/dist/humain/web-access/vendor/chrome-cookies.js.map +1 -1
  318. package/dist/humain/web-access/vendor/content-find.d.ts.map +1 -1
  319. package/dist/humain/web-access/vendor/content-find.js.map +1 -1
  320. package/dist/humain/web-access/vendor/credential-source.d.ts.map +1 -1
  321. package/dist/humain/web-access/vendor/credential-source.js +0 -2
  322. package/dist/humain/web-access/vendor/credential-source.js.map +1 -1
  323. package/dist/humain/web-access/vendor/curator-page.d.ts +3 -0
  324. package/dist/humain/web-access/vendor/curator-page.d.ts.map +1 -1
  325. package/dist/humain/web-access/vendor/curator-page.js +4 -1
  326. package/dist/humain/web-access/vendor/curator-page.js.map +1 -1
  327. package/dist/humain/web-access/vendor/curator-server.d.ts +3 -0
  328. package/dist/humain/web-access/vendor/curator-server.d.ts.map +1 -1
  329. package/dist/humain/web-access/vendor/curator-server.js +6 -0
  330. package/dist/humain/web-access/vendor/curator-server.js.map +1 -1
  331. package/dist/humain/web-access/vendor/data-uri-sanitize.d.ts +21 -0
  332. package/dist/humain/web-access/vendor/data-uri-sanitize.d.ts.map +1 -0
  333. package/dist/humain/web-access/vendor/data-uri-sanitize.js +373 -0
  334. package/dist/humain/web-access/vendor/data-uri-sanitize.js.map +1 -0
  335. package/dist/humain/web-access/vendor/datalab-pdf-extract.d.ts.map +1 -1
  336. package/dist/humain/web-access/vendor/datalab-pdf-extract.js.map +1 -1
  337. package/dist/humain/web-access/vendor/declared-web-links.d.ts.map +1 -1
  338. package/dist/humain/web-access/vendor/declared-web-links.js.map +1 -1
  339. package/dist/humain/web-access/vendor/duckduckgo.d.ts.map +1 -1
  340. package/dist/humain/web-access/vendor/duckduckgo.js.map +1 -1
  341. package/dist/humain/web-access/vendor/exa.d.ts.map +1 -1
  342. package/dist/humain/web-access/vendor/exa.js +16 -7
  343. package/dist/humain/web-access/vendor/exa.js.map +1 -1
  344. package/dist/humain/web-access/vendor/extract.d.ts.map +1 -1
  345. package/dist/humain/web-access/vendor/extract.js +45 -5
  346. package/dist/humain/web-access/vendor/extract.js.map +1 -1
  347. package/dist/humain/web-access/vendor/feature-config.d.ts.map +1 -1
  348. package/dist/humain/web-access/vendor/feature-config.js.map +1 -1
  349. package/dist/humain/web-access/vendor/fetch-params.d.ts.map +1 -1
  350. package/dist/humain/web-access/vendor/fetch-params.js.map +1 -1
  351. package/dist/humain/web-access/vendor/firecrawl.d.ts.map +1 -1
  352. package/dist/humain/web-access/vendor/firecrawl.js +15 -2
  353. package/dist/humain/web-access/vendor/firecrawl.js.map +1 -1
  354. package/dist/humain/web-access/vendor/gemini-api.d.ts.map +1 -1
  355. package/dist/humain/web-access/vendor/gemini-api.js.map +1 -1
  356. package/dist/humain/web-access/vendor/gemini-pdf-extract.d.ts.map +1 -1
  357. package/dist/humain/web-access/vendor/gemini-pdf-extract.js.map +1 -1
  358. package/dist/humain/web-access/vendor/gemini-search.d.ts +2 -2
  359. package/dist/humain/web-access/vendor/gemini-search.d.ts.map +1 -1
  360. package/dist/humain/web-access/vendor/gemini-search.js +25 -8
  361. package/dist/humain/web-access/vendor/gemini-search.js.map +1 -1
  362. package/dist/humain/web-access/vendor/gemini-url-context.d.ts.map +1 -1
  363. package/dist/humain/web-access/vendor/gemini-url-context.js.map +1 -1
  364. package/dist/humain/web-access/vendor/gemini-web-config.d.ts.map +1 -1
  365. package/dist/humain/web-access/vendor/gemini-web-config.js.map +1 -1
  366. package/dist/humain/web-access/vendor/gemini-web.d.ts.map +1 -1
  367. package/dist/humain/web-access/vendor/gemini-web.js.map +1 -1
  368. package/dist/humain/web-access/vendor/github-api.d.ts.map +1 -1
  369. package/dist/humain/web-access/vendor/github-api.js.map +1 -1
  370. package/dist/humain/web-access/vendor/github-extract.d.ts.map +1 -1
  371. package/dist/humain/web-access/vendor/github-extract.js +69 -35
  372. package/dist/humain/web-access/vendor/github-extract.js.map +1 -1
  373. package/dist/humain/web-access/vendor/index.d.ts.map +1 -1
  374. package/dist/humain/web-access/vendor/index.js +58 -54
  375. package/dist/humain/web-access/vendor/index.js.map +1 -1
  376. package/dist/humain/web-access/vendor/jina-search.d.ts.map +1 -1
  377. package/dist/humain/web-access/vendor/jina-search.js.map +1 -1
  378. package/dist/humain/web-access/vendor/kagi.d.ts.map +1 -1
  379. package/dist/humain/web-access/vendor/kagi.js.map +1 -1
  380. package/dist/humain/web-access/vendor/ollama.d.ts.map +1 -1
  381. package/dist/humain/web-access/vendor/ollama.js.map +1 -1
  382. package/dist/humain/web-access/vendor/openai-search.d.ts +1 -1
  383. package/dist/humain/web-access/vendor/openai-search.d.ts.map +1 -1
  384. package/dist/humain/web-access/vendor/openai-search.js +15 -5
  385. package/dist/humain/web-access/vendor/openai-search.js.map +1 -1
  386. package/dist/humain/web-access/vendor/page-query.d.ts +1 -2
  387. package/dist/humain/web-access/vendor/page-query.d.ts.map +1 -1
  388. package/dist/humain/web-access/vendor/page-query.js +5 -2
  389. package/dist/humain/web-access/vendor/page-query.js.map +1 -1
  390. package/dist/humain/web-access/vendor/parallel-mcp.d.ts +10 -0
  391. package/dist/humain/web-access/vendor/parallel-mcp.d.ts.map +1 -0
  392. package/dist/humain/web-access/vendor/parallel-mcp.js +224 -0
  393. package/dist/humain/web-access/vendor/parallel-mcp.js.map +1 -0
  394. package/dist/humain/web-access/vendor/parallel.d.ts +1 -0
  395. package/dist/humain/web-access/vendor/parallel.d.ts.map +1 -1
  396. package/dist/humain/web-access/vendor/parallel.js +2 -2
  397. package/dist/humain/web-access/vendor/parallel.js.map +1 -1
  398. package/dist/humain/web-access/vendor/pdf-extract.d.ts +1 -0
  399. package/dist/humain/web-access/vendor/pdf-extract.d.ts.map +1 -1
  400. package/dist/humain/web-access/vendor/pdf-extract.js +15 -5
  401. package/dist/humain/web-access/vendor/pdf-extract.js.map +1 -1
  402. package/dist/humain/web-access/vendor/perplexity.d.ts.map +1 -1
  403. package/dist/humain/web-access/vendor/perplexity.js.map +1 -1
  404. package/dist/humain/web-access/vendor/querit.d.ts.map +1 -1
  405. package/dist/humain/web-access/vendor/querit.js.map +1 -1
  406. package/dist/humain/web-access/vendor/query-rewrite.d.ts +3 -0
  407. package/dist/humain/web-access/vendor/query-rewrite.d.ts.map +1 -0
  408. package/dist/humain/web-access/vendor/query-rewrite.js +42 -0
  409. package/dist/humain/web-access/vendor/query-rewrite.js.map +1 -0
  410. package/dist/humain/web-access/vendor/render-search-error.d.ts.map +1 -1
  411. package/dist/humain/web-access/vendor/render-search-error.js.map +1 -1
  412. package/dist/humain/web-access/vendor/rsc-extract.d.ts.map +1 -1
  413. package/dist/humain/web-access/vendor/rsc-extract.js.map +1 -1
  414. package/dist/humain/web-access/vendor/search1api.d.ts.map +1 -1
  415. package/dist/humain/web-access/vendor/search1api.js.map +1 -1
  416. package/dist/humain/web-access/vendor/searchinfinity.d.ts.map +1 -1
  417. package/dist/humain/web-access/vendor/searchinfinity.js.map +1 -1
  418. package/dist/humain/web-access/vendor/searxng.d.ts.map +1 -1
  419. package/dist/humain/web-access/vendor/searxng.js.map +1 -1
  420. package/dist/humain/web-access/vendor/serpbase.d.ts.map +1 -1
  421. package/dist/humain/web-access/vendor/serpbase.js.map +1 -1
  422. package/dist/humain/web-access/vendor/serpdive.d.ts.map +1 -1
  423. package/dist/humain/web-access/vendor/serpdive.js.map +1 -1
  424. package/dist/humain/web-access/vendor/serper.d.ts +4 -0
  425. package/dist/humain/web-access/vendor/serper.d.ts.map +1 -0
  426. package/dist/humain/web-access/vendor/serper.js +206 -0
  427. package/dist/humain/web-access/vendor/serper.js.map +1 -0
  428. package/dist/humain/web-access/vendor/source-check.d.ts.map +1 -1
  429. package/dist/humain/web-access/vendor/source-check.js.map +1 -1
  430. package/dist/humain/web-access/vendor/ssrf-protection.d.ts +2 -0
  431. package/dist/humain/web-access/vendor/ssrf-protection.d.ts.map +1 -1
  432. package/dist/humain/web-access/vendor/ssrf-protection.js +11 -2
  433. package/dist/humain/web-access/vendor/ssrf-protection.js.map +1 -1
  434. package/dist/humain/web-access/vendor/storage.d.ts.map +1 -1
  435. package/dist/humain/web-access/vendor/storage.js.map +1 -1
  436. package/dist/humain/web-access/vendor/summary-model-scope.d.ts +5 -0
  437. package/dist/humain/web-access/vendor/summary-model-scope.d.ts.map +1 -1
  438. package/dist/humain/web-access/vendor/summary-model-scope.js +10 -5
  439. package/dist/humain/web-access/vendor/summary-model-scope.js.map +1 -1
  440. package/dist/humain/web-access/vendor/summary-review.d.ts.map +1 -1
  441. package/dist/humain/web-access/vendor/summary-review.js +40 -14
  442. package/dist/humain/web-access/vendor/summary-review.js.map +1 -1
  443. package/dist/humain/web-access/vendor/tavily.d.ts.map +1 -1
  444. package/dist/humain/web-access/vendor/tavily.js +14 -4
  445. package/dist/humain/web-access/vendor/tavily.js.map +1 -1
  446. package/dist/humain/web-access/vendor/tinyfish.d.ts.map +1 -1
  447. package/dist/humain/web-access/vendor/tinyfish.js.map +1 -1
  448. package/dist/humain/web-access/vendor/utils.d.ts +10 -0
  449. package/dist/humain/web-access/vendor/utils.d.ts.map +1 -1
  450. package/dist/humain/web-access/vendor/utils.js +70 -0
  451. package/dist/humain/web-access/vendor/utils.js.map +1 -1
  452. package/dist/humain/web-access/vendor/valyu.d.ts +6 -0
  453. package/dist/humain/web-access/vendor/valyu.d.ts.map +1 -0
  454. package/dist/humain/web-access/vendor/valyu.js +194 -0
  455. package/dist/humain/web-access/vendor/valyu.js.map +1 -0
  456. package/dist/humain/web-access/vendor/video-extract.d.ts.map +1 -1
  457. package/dist/humain/web-access/vendor/video-extract.js.map +1 -1
  458. package/dist/humain/web-access/vendor/xai-search.d.ts.map +1 -1
  459. package/dist/humain/web-access/vendor/xai-search.js.map +1 -1
  460. package/dist/humain/web-access/vendor/youtube-extract.d.ts.map +1 -1
  461. package/dist/humain/web-access/vendor/youtube-extract.js.map +1 -1
  462. package/dist/index.d.ts +1 -1
  463. package/dist/index.d.ts.map +1 -1
  464. package/dist/index.js.map +1 -1
  465. package/dist/main.d.ts.map +1 -1
  466. package/dist/main.js +4 -0
  467. package/dist/main.js.map +1 -1
  468. package/dist/migrations.d.ts.map +1 -1
  469. package/dist/migrations.js.map +1 -1
  470. package/dist/modes/agent-exec-mode.d.ts.map +1 -1
  471. package/dist/modes/agent-exec-mode.js.map +1 -1
  472. package/dist/modes/index.d.ts.map +1 -1
  473. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  474. package/dist/modes/interactive/components/armin.js +6 -10
  475. package/dist/modes/interactive/components/armin.js.map +1 -1
  476. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  477. package/dist/modes/interactive/components/assistant-message.js +2 -9
  478. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  479. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  480. package/dist/modes/interactive/components/bash-execution.js +4 -9
  481. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  482. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  483. package/dist/modes/interactive/components/bordered-loader.js +0 -3
  484. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  485. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  486. package/dist/modes/interactive/components/branch-summary-message.js +1 -3
  487. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  488. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  489. package/dist/modes/interactive/components/compaction-summary-message.js +1 -3
  490. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  491. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  492. package/dist/modes/interactive/components/config-selector.js +5 -22
  493. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  494. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  495. package/dist/modes/interactive/components/countdown-timer.js +0 -5
  496. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  497. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  498. package/dist/modes/interactive/components/custom-editor.js +1 -8
  499. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  500. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
  501. package/dist/modes/interactive/components/custom-entry.js +1 -4
  502. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  503. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  504. package/dist/modes/interactive/components/custom-message.js +1 -7
  505. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  506. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
  507. package/dist/modes/interactive/components/daxnuts.js +6 -8
  508. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  509. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  510. package/dist/modes/interactive/components/diff.js +2 -2
  511. package/dist/modes/interactive/components/diff.js.map +1 -1
  512. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  513. package/dist/modes/interactive/components/dynamic-border.js +0 -1
  514. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  515. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -1
  516. package/dist/modes/interactive/components/earendil-announcement.js.map +1 -1
  517. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  518. package/dist/modes/interactive/components/extension-editor.js +1 -7
  519. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  520. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  521. package/dist/modes/interactive/components/extension-input.js +2 -8
  522. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  523. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  524. package/dist/modes/interactive/components/extension-selector.js +1 -9
  525. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  526. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  527. package/dist/modes/interactive/components/first-time-setup.js +2 -4
  528. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  529. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  530. package/dist/modes/interactive/components/footer.js +1 -3
  531. package/dist/modes/interactive/components/footer.js.map +1 -1
  532. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  533. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  534. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  535. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  536. package/dist/modes/interactive/components/login-dialog.js +3 -9
  537. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  538. package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -1
  539. package/dist/modes/interactive/components/markdown-transform.js.map +1 -1
  540. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
  541. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  542. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  543. package/dist/modes/interactive/components/model-selector.js +14 -26
  544. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  545. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  546. package/dist/modes/interactive/components/oauth-selector.js +3 -11
  547. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  548. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  549. package/dist/modes/interactive/components/scoped-models-selector.js +9 -14
  550. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  551. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  552. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  553. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  554. package/dist/modes/interactive/components/session-selector.js +33 -57
  555. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  556. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  557. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  558. package/dist/modes/interactive/components/settings-selector.js +10 -14
  559. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  560. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  561. package/dist/modes/interactive/components/show-images-selector.js +0 -1
  562. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  563. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  564. package/dist/modes/interactive/components/skill-invocation-message.js +1 -3
  565. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  566. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  567. package/dist/modes/interactive/components/status-indicator.js +0 -2
  568. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  569. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  570. package/dist/modes/interactive/components/theme-selector.js +0 -2
  571. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  572. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  573. package/dist/modes/interactive/components/thinking-selector.js +0 -1
  574. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  575. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  576. package/dist/modes/interactive/components/tool-execution.js +19 -25
  577. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  578. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  579. package/dist/modes/interactive/components/tree-selector.js +18 -34
  580. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  581. package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
  582. package/dist/modes/interactive/components/trust-selector.js +0 -6
  583. package/dist/modes/interactive/components/trust-selector.js.map +1 -1
  584. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  585. package/dist/modes/interactive/components/user-message-selector.js +3 -6
  586. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  587. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  588. package/dist/modes/interactive/components/user-message.js +0 -4
  589. package/dist/modes/interactive/components/user-message.js.map +1 -1
  590. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  591. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  592. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  593. package/dist/modes/interactive/external-editor.js.map +1 -1
  594. package/dist/modes/interactive/interactive-mode.d.ts +18 -2
  595. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  596. package/dist/modes/interactive/interactive-mode.js +147 -137
  597. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  598. package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
  599. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
  600. package/dist/modes/interactive/model-catalog-refresh.js +36 -0
  601. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
  602. package/dist/modes/interactive/model-search.d.ts.map +1 -1
  603. package/dist/modes/interactive/model-search.js.map +1 -1
  604. package/dist/modes/interactive/theme/dark.json +2 -0
  605. package/dist/modes/interactive/theme/light.json +2 -0
  606. package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
  607. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  608. package/dist/modes/interactive/theme/theme-controller.js +25 -18
  609. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  610. package/dist/modes/interactive/theme/theme-schema.json +9 -1
  611. package/dist/modes/interactive/theme/theme.d.ts +7 -5
  612. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  613. package/dist/modes/interactive/theme/theme.js +12 -8
  614. package/dist/modes/interactive/theme/theme.js.map +1 -1
  615. package/dist/modes/json-event.d.ts +4 -1
  616. package/dist/modes/json-event.d.ts.map +1 -1
  617. package/dist/modes/json-event.js +5 -2
  618. package/dist/modes/json-event.js.map +1 -1
  619. package/dist/modes/print-mode.d.ts.map +1 -1
  620. package/dist/modes/print-mode.js.map +1 -1
  621. package/dist/modes/rpc/jsonl.d.ts.map +1 -1
  622. package/dist/modes/rpc/jsonl.js.map +1 -1
  623. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  624. package/dist/modes/rpc/rpc-client.js +9 -10
  625. package/dist/modes/rpc/rpc-client.js.map +1 -1
  626. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  627. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  628. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  629. package/dist/package-manager-cli.d.ts.map +1 -1
  630. package/dist/package-manager-cli.js.map +1 -1
  631. package/dist/rpc-entry.d.ts.map +1 -1
  632. package/dist/rpc-entry.js.map +1 -1
  633. package/dist/server/create-harness.d.ts.map +1 -1
  634. package/dist/server/create-harness.js +2 -0
  635. package/dist/server/create-harness.js.map +1 -1
  636. package/dist/utils/abort.d.ts.map +1 -1
  637. package/dist/utils/abort.js.map +1 -1
  638. package/dist/utils/ansi.d.ts.map +1 -1
  639. package/dist/utils/ansi.js.map +1 -1
  640. package/dist/utils/changelog.d.ts.map +1 -1
  641. package/dist/utils/changelog.js.map +1 -1
  642. package/dist/utils/child-process.d.ts.map +1 -1
  643. package/dist/utils/child-process.js.map +1 -1
  644. package/dist/utils/clipboard-image.d.ts.map +1 -1
  645. package/dist/utils/clipboard-image.js +1 -1
  646. package/dist/utils/clipboard-image.js.map +1 -1
  647. package/dist/utils/clipboard-native.d.ts.map +1 -1
  648. package/dist/utils/clipboard-native.js.map +1 -1
  649. package/dist/utils/clipboard.d.ts.map +1 -1
  650. package/dist/utils/clipboard.js.map +1 -1
  651. package/dist/utils/deprecation.d.ts.map +1 -1
  652. package/dist/utils/deprecation.js.map +1 -1
  653. package/dist/utils/exif-orientation.d.ts.map +1 -1
  654. package/dist/utils/exif-orientation.js.map +1 -1
  655. package/dist/utils/frontmatter.d.ts.map +1 -1
  656. package/dist/utils/frontmatter.js.map +1 -1
  657. package/dist/utils/fs-watch.d.ts.map +1 -1
  658. package/dist/utils/fs-watch.js.map +1 -1
  659. package/dist/utils/git.d.ts.map +1 -1
  660. package/dist/utils/git.js.map +1 -1
  661. package/dist/utils/html.d.ts.map +1 -1
  662. package/dist/utils/html.js.map +1 -1
  663. package/dist/utils/image-convert.d.ts.map +1 -1
  664. package/dist/utils/image-convert.js.map +1 -1
  665. package/dist/utils/image-process.d.ts.map +1 -1
  666. package/dist/utils/image-process.js.map +1 -1
  667. package/dist/utils/image-resize-core.d.ts.map +1 -1
  668. package/dist/utils/image-resize-core.js.map +1 -1
  669. package/dist/utils/image-resize-worker.d.ts.map +1 -1
  670. package/dist/utils/image-resize-worker.js.map +1 -1
  671. package/dist/utils/image-resize.d.ts.map +1 -1
  672. package/dist/utils/image-resize.js.map +1 -1
  673. package/dist/utils/json.d.ts.map +1 -1
  674. package/dist/utils/json.js.map +1 -1
  675. package/dist/utils/management-http.d.ts.map +1 -1
  676. package/dist/utils/management-http.js.map +1 -1
  677. package/dist/utils/mime.d.ts.map +1 -1
  678. package/dist/utils/mime.js.map +1 -1
  679. package/dist/utils/open-browser.d.ts.map +1 -1
  680. package/dist/utils/open-browser.js.map +1 -1
  681. package/dist/utils/paths.d.ts.map +1 -1
  682. package/dist/utils/paths.js.map +1 -1
  683. package/dist/utils/photon.d.ts.map +1 -1
  684. package/dist/utils/photon.js.map +1 -1
  685. package/dist/utils/pi-user-agent.d.ts.map +1 -1
  686. package/dist/utils/pi-user-agent.js.map +1 -1
  687. package/dist/utils/shell.d.ts.map +1 -1
  688. package/dist/utils/shell.js.map +1 -1
  689. package/dist/utils/sleep.d.ts.map +1 -1
  690. package/dist/utils/sleep.js.map +1 -1
  691. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  692. package/dist/utils/syntax-highlight.js +1 -1
  693. package/dist/utils/syntax-highlight.js.map +1 -1
  694. package/dist/utils/tool-result-images.d.ts.map +1 -1
  695. package/dist/utils/tool-result-images.js.map +1 -1
  696. package/dist/utils/tools-manager.d.ts +10 -1
  697. package/dist/utils/tools-manager.d.ts.map +1 -1
  698. package/dist/utils/tools-manager.js +14 -19
  699. package/dist/utils/tools-manager.js.map +1 -1
  700. package/dist/utils/version-check.d.ts.map +1 -1
  701. package/dist/utils/version-check.js.map +1 -1
  702. package/dist/utils/windows-self-update.d.ts.map +1 -1
  703. package/dist/utils/windows-self-update.js.map +1 -1
  704. package/docs/compaction.md +3 -3
  705. package/docs/custom-provider.md +1 -1
  706. package/docs/environment-variables.md +1 -0
  707. package/docs/extensions.md +5 -1
  708. package/docs/json.md +6 -4
  709. package/docs/keybindings.md +8 -2
  710. package/docs/rpc.md +15 -4
  711. package/docs/sdk.md +9 -0
  712. package/docs/settings.md +31 -0
  713. package/docs/terminal-setup.md +23 -2
  714. package/docs/themes.md +23 -3
  715. package/docs/tui.md +2 -2
  716. package/docs/usage.md +3 -2
  717. package/examples/extensions/README.md +1 -1
  718. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  719. package/examples/extensions/custom-provider-anthropic/package.json +2 -2
  720. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  721. package/examples/extensions/gondolin/package-lock.json +2 -2
  722. package/examples/extensions/gondolin/package.json +1 -1
  723. package/examples/extensions/minimal-mode.ts +6 -6
  724. package/examples/extensions/sandbox/package-lock.json +2 -2
  725. package/examples/extensions/sandbox/package.json +2 -2
  726. package/examples/extensions/subagent/README.md +24 -147
  727. package/examples/extensions/with-deps/package-lock.json +2 -2
  728. package/examples/extensions/with-deps/package.json +1 -1
  729. package/npm-shrinkwrap.json +853 -661
  730. package/package.json +33 -33
  731. package/src/humain/mcp-adapter/UPSTREAM.md +1 -1
  732. package/src/humain/mcp-adapter/upstream.json +3 -3
  733. package/src/humain/mcp-adapter/vendor/CHANGELOG.md +36 -0
  734. package/src/humain/web-access/UPSTREAM.md +1 -1
  735. package/src/humain/web-access/upstream.json +4 -4
  736. package/examples/extensions/subagent/agents.ts +0 -126
  737. package/examples/extensions/subagent/index.ts +0 -1015
@@ -662,15 +662,155 @@ var init_agent_plugin_loader = __esm({
662
662
  }
663
663
  });
664
664
 
665
+ // packages/coding-agent/src/humain/mcp-adapter/vendor/package-mcp-loader.ts
666
+ import { existsSync as existsSync2, readFileSync as readFileSync3, realpathSync, statSync as statSync2 } from "node:fs";
667
+ import { isAbsolute as isAbsolute2, join as join2, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
668
+ import stripJsonComments from "strip-json-comments";
669
+ function loadPackageMcpConfigs(cwd = process.cwd()) {
670
+ const mcpServers = {};
671
+ const seen = /* @__PURE__ */ new Set();
672
+ for (const packageRoot of getConfiguredPackageRoots(cwd)) {
673
+ const manifest = readPackageManifest(packageRoot);
674
+ if (!manifest || typeof manifest.name !== "string" || !manifest.name) continue;
675
+ const paths = getManifestMcpPaths(manifest.pi?.mcp, manifest.name);
676
+ if (!paths) continue;
677
+ const packagePrefix = formatPackageName(manifest.name);
678
+ const packageServers = /* @__PURE__ */ new Set();
679
+ for (const path2 of paths) {
680
+ const configPath = resolvePackageConfigPath(packageRoot, path2);
681
+ if (!configPath) {
682
+ console.warn(`Pi package ${manifest.name} skips MCP config ${path2}: file must stay inside the package`);
683
+ continue;
684
+ }
685
+ const config = readMcpConfig(configPath, manifest.name);
686
+ if (!config) continue;
687
+ for (const [serverName, server2] of Object.entries(config.mcpServers)) {
688
+ const normalizedName = `${packagePrefix}__${formatServerName(serverName)}`;
689
+ if (packageServers.has(normalizedName) || seen.has(normalizedName)) {
690
+ console.warn(`Pi package ${manifest.name} skips duplicate normalized MCP server ${normalizedName}`);
691
+ continue;
692
+ }
693
+ packageServers.add(normalizedName);
694
+ seen.add(normalizedName);
695
+ mcpServers[normalizedName] = server2;
696
+ }
697
+ }
698
+ }
699
+ return { mcpServers };
700
+ }
701
+ function getConfiguredPackageRoots(cwd) {
702
+ const roots = [];
703
+ for (const [settingsPath, scope] of [
704
+ [join2(cwd, getConfigDirName(), "settings.json"), "project"],
705
+ [join2(getAgentDir(), "settings.json"), "user"]
706
+ ]) {
707
+ const settings = readOptionalJson(settingsPath, `${scope} Pi settings`);
708
+ if (settings === void 0) continue;
709
+ if (typeof settings !== "object" || settings === null || Array.isArray(settings)) {
710
+ throw new Error(`${scope} Pi settings ${settingsPath} must be a JSON object`);
711
+ }
712
+ const packages = settings.packages;
713
+ if (packages === void 0) continue;
714
+ if (!Array.isArray(packages)) throw new Error(`${scope} Pi settings ${settingsPath} packages must be an array`);
715
+ for (const entry of packages) {
716
+ const source = typeof entry === "string" ? entry : entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.source === "string" ? entry.source : void 0;
717
+ if (!source) throw new Error(`${scope} Pi settings ${settingsPath} package entries must be strings or objects with a string source`);
718
+ const root = resolvePackageRoot(source, scope, cwd);
719
+ if (root && !roots.includes(root)) roots.push(root);
720
+ }
721
+ }
722
+ return roots;
723
+ }
724
+ function resolvePackageRoot(source, scope, cwd) {
725
+ const baseDir = scope === "user" ? getAgentDir() : join2(cwd, getConfigDirName());
726
+ if (source.startsWith("npm:")) {
727
+ const name = source.slice(4).trim().match(/^(@?[^@]+(?:\/[^@]+)?)/)?.[1];
728
+ return name ? resolveContainedPath2(join2(baseDir, "npm", "node_modules"), name) : null;
729
+ }
730
+ const gitSource = source.startsWith("git:") ? source.slice(4).trim() : /^(?:(?:https?|ssh):\/\/|git@[^:]+:)/.test(source) ? source : null;
731
+ if (gitSource) {
732
+ const value = gitSource.replace(/^ssh:\/\/git@/, "").replace(/^git@([^:]+):/, "$1/").replace(/^[a-z]+:\/\//i, "");
733
+ const path2 = value.replace(/@[^/]+$/, "").replace(/\.git$/, "");
734
+ return path2 && !path2.startsWith("/") ? resolveContainedPath2(join2(baseDir, "git"), path2) : null;
735
+ }
736
+ return isAbsolute2(source) ? resolve3(source) : resolve3(baseDir, source);
737
+ }
738
+ function readPackageManifest(packageRoot) {
739
+ const manifest = readOptionalJson(join2(packageRoot, "package.json"), `Pi package manifest ${packageRoot}`);
740
+ return manifest && typeof manifest === "object" && !Array.isArray(manifest) ? manifest : null;
741
+ }
742
+ function getManifestMcpPaths(value, packageName) {
743
+ const paths = typeof value === "string" ? [value] : Array.isArray(value) && value.every((path2) => typeof path2 === "string") ? value : null;
744
+ if (value !== void 0 && !paths) console.warn(`Pi package ${packageName} ignores invalid pi.mcp manifest entry`);
745
+ return paths;
746
+ }
747
+ function readMcpConfig(path2, packageName) {
748
+ const config = readRequiredJson(path2, `Pi package ${packageName} MCP config`);
749
+ if (!config || typeof config !== "object" || Array.isArray(config)) {
750
+ throw new Error(`Pi package ${packageName} MCP config ${path2} must be a JSON object`);
751
+ }
752
+ const servers = config.mcpServers;
753
+ if (!servers || typeof servers !== "object" || Array.isArray(servers)) {
754
+ throw new Error(`Pi package ${packageName} MCP config ${path2} must contain a JSON object mcpServers field`);
755
+ }
756
+ const mcpServers = {};
757
+ for (const [name, server2] of Object.entries(servers)) {
758
+ if (!server2 || typeof server2 !== "object" || Array.isArray(server2)) {
759
+ throw new Error(`Pi package ${packageName} MCP config ${path2} server ${name} must be a JSON object`);
760
+ }
761
+ mcpServers[name] = server2;
762
+ }
763
+ return { mcpServers };
764
+ }
765
+ function readRequiredJson(path2, description) {
766
+ try {
767
+ return JSON.parse(stripJsonComments(readFileSync3(path2, "utf8"), { trailingCommas: true }));
768
+ } catch (error) {
769
+ throw new Error(`${description} ${path2} contains invalid JSON: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
770
+ }
771
+ }
772
+ function readOptionalJson(path2, description) {
773
+ if (!existsSync2(path2)) return void 0;
774
+ return readRequiredJson(path2, description);
775
+ }
776
+ function resolveContainedPath2(root, path2) {
777
+ const resolved = resolve3(root, path2);
778
+ const rel = relative2(root, resolved);
779
+ return rel === "" || !rel.startsWith("..") && !rel.startsWith(sep2) && !isAbsolute2(rel) ? resolved : null;
780
+ }
781
+ function resolvePackageConfigPath(packageRoot, path2) {
782
+ const lexicalPath = resolveContainedPath2(packageRoot, path2);
783
+ if (!lexicalPath || !existsSync2(lexicalPath) || !statSync2(lexicalPath).isFile()) return null;
784
+ try {
785
+ const realPackageRoot = realpathSync(packageRoot);
786
+ const realConfigPath = realpathSync(lexicalPath);
787
+ return resolveContainedPath2(realPackageRoot, realConfigPath);
788
+ } catch {
789
+ return null;
790
+ }
791
+ }
792
+ function formatPackageName(name) {
793
+ return name.replace(/[^A-Za-z0-9_-]+/g, "_").replace(/^[_-]+|[_-]+$/g, "") || "package";
794
+ }
795
+ function formatServerName(name) {
796
+ return name.replace(/[^A-Za-z0-9_-]+/g, "_").replace(/^[_-]+|[_-]+$/g, "") || "server";
797
+ }
798
+ var init_package_mcp_loader = __esm({
799
+ "packages/coding-agent/src/humain/mcp-adapter/vendor/package-mcp-loader.ts"() {
800
+ "use strict";
801
+ init_agent_dir();
802
+ }
803
+ });
804
+
665
805
  // packages/coding-agent/src/humain/mcp-adapter/vendor/utils.ts
666
806
  import { spawnSync } from "node:child_process";
667
807
  import { homedir as homedir2, platform } from "node:os";
668
- import { extname, isAbsolute as isAbsolute2, join as join2 } from "node:path";
808
+ import { extname, isAbsolute as isAbsolute3, join as join3 } from "node:path";
669
809
  async function execOpen(pi, target, browser, signal) {
670
810
  const os = platform();
671
811
  if (os === "darwin") {
672
812
  if (browser) {
673
- return isAbsolute2(browser) && extname(browser).toLowerCase() !== ".app" ? pi.exec(browser, [target], signal ? { signal } : {}) : pi.exec("open", ["-a", browser, target], signal ? { signal } : {});
813
+ return isAbsolute3(browser) && extname(browser).toLowerCase() !== ".app" ? pi.exec(browser, [target], signal ? { signal } : {}) : pi.exec("open", ["-a", browser, target], signal ? { signal } : {});
674
814
  }
675
815
  return pi.exec("open", [target], signal ? { signal } : {});
676
816
  }
@@ -798,7 +938,7 @@ function resolveConfigPath(value) {
798
938
  const resolved = interpolateEnvVars(value);
799
939
  if (resolved === "~") return homedir2();
800
940
  if (resolved.startsWith("~/") || resolved.startsWith("~\\")) {
801
- return join2(homedir2(), resolved.slice(2));
941
+ return join3(homedir2(), resolved.slice(2));
802
942
  }
803
943
  return resolved;
804
944
  }
@@ -870,6 +1010,67 @@ function normalizeDirectToolInputSchema(schema) {
870
1010
  const { $schema, additionalProperties, ...normalized } = inputSchema;
871
1011
  return normalized;
872
1012
  }
1013
+ function normalizeToolArguments(value, context = "tool arguments") {
1014
+ if (value === void 0 || value === null || value === "") return {};
1015
+ if (typeof value === "string") {
1016
+ const trimmed = value.trim();
1017
+ if (trimmed === "") return {};
1018
+ let parsed;
1019
+ try {
1020
+ parsed = JSON.parse(trimmed);
1021
+ } catch (error) {
1022
+ throw new Error(
1023
+ `${context}: invalid args JSON (${error instanceof SyntaxError ? error.message : String(error)}); pass args as a JSON object, or as a valid JSON string encoding one`,
1024
+ { cause: error }
1025
+ );
1026
+ }
1027
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
1028
+ throw new Error(
1029
+ `${context}: expected a JSON object, got ${Array.isArray(parsed) ? "array" : typeof parsed}`
1030
+ );
1031
+ }
1032
+ return parsed;
1033
+ }
1034
+ if (typeof value !== "object" || Array.isArray(value)) {
1035
+ throw new Error(
1036
+ `${context}: expected a JSON object, got ${Array.isArray(value) ? "array" : typeof value}`
1037
+ );
1038
+ }
1039
+ assertJsonSerializable(value, context);
1040
+ try {
1041
+ return JSON.parse(JSON.stringify(value));
1042
+ } catch (error) {
1043
+ throw new Error(
1044
+ `${context}: value is not JSON-serializable: ${error instanceof Error ? error.message : String(error)}`,
1045
+ { cause: error }
1046
+ );
1047
+ }
1048
+ }
1049
+ function assertJsonSerializable(value, context, path2 = "") {
1050
+ if (value === null) return;
1051
+ if (typeof value === "string" || typeof value === "boolean") return;
1052
+ if (typeof value === "number") {
1053
+ if (!Number.isFinite(value)) throw new Error(`${context}: value at ${path2 || "root"} is not a finite number`);
1054
+ return;
1055
+ }
1056
+ if (Array.isArray(value)) {
1057
+ for (const [index, item] of value.entries()) assertJsonSerializable(item, context, `${path2}[${index}]`);
1058
+ return;
1059
+ }
1060
+ if (typeof value === "object") {
1061
+ if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {
1062
+ throw new Error(`${context}: value at ${path2 || "root"} is not a plain JSON object`);
1063
+ }
1064
+ if (Object.getOwnPropertySymbols(value).length > 0) {
1065
+ throw new Error(`${context}: value at ${path2 || "root"} has symbol keys`);
1066
+ }
1067
+ for (const [key, item] of Object.entries(value)) {
1068
+ assertJsonSerializable(item, context, path2 ? `${path2}.${key}` : key);
1069
+ }
1070
+ return;
1071
+ }
1072
+ throw new Error(`${context}: value at ${path2 || "root"} is not JSON-serializable`);
1073
+ }
873
1074
  function formatAuthRequiredMessage(config, serverName, defaultMessage) {
874
1075
  const template = config.settings?.authRequiredMessage;
875
1076
  return template ? template.replaceAll("${server}", serverName) : defaultMessage;
@@ -897,19 +1098,19 @@ var init_utils = __esm({
897
1098
  });
898
1099
 
899
1100
  // packages/coding-agent/src/humain/mcp-adapter/vendor/config.ts
900
- import { existsSync as existsSync2, readFileSync as readFileSync3, writeFileSync, mkdirSync, renameSync } from "node:fs";
1101
+ import { existsSync as existsSync3, readFileSync as readFileSync4, writeFileSync, mkdirSync, renameSync } from "node:fs";
901
1102
  import { homedir as homedir3 } from "node:os";
902
- import { dirname, join as join3, resolve as resolve3 } from "node:path";
1103
+ import { dirname, join as join4, resolve as resolve4 } from "node:path";
903
1104
  import { parse as parseToml } from "smol-toml";
904
- import stripJsonComments from "strip-json-comments";
1105
+ import stripJsonComments2 from "strip-json-comments";
905
1106
  function getPiGlobalConfigPath(overridePath) {
906
- return overridePath ? resolve3(overridePath) : getAgentPath("mcp.json");
1107
+ return overridePath ? resolve4(overridePath) : getAgentPath("mcp.json");
907
1108
  }
908
1109
  function getProjectConfigPath(cwd = process.cwd()) {
909
- return resolve3(cwd, PROJECT_CONFIG_NAME);
1110
+ return resolve4(cwd, PROJECT_CONFIG_NAME);
910
1111
  }
911
1112
  function getProjectPiConfigPath(cwd = process.cwd()) {
912
- return resolve3(cwd, getConfigDirName(), PROJECT_PI_CONFIG_NAME);
1113
+ return resolve4(cwd, getConfigDirName(), PROJECT_PI_CONFIG_NAME);
913
1114
  }
914
1115
  function getConfigSourceSummaries(sourceSpecs) {
915
1116
  return sourceSpecs.map((source) => {
@@ -918,7 +1119,7 @@ function getConfigSourceSummaries(sourceSpecs) {
918
1119
  id: source.id,
919
1120
  label: source.label,
920
1121
  path: source.readPath,
921
- exists: existsSync2(source.readPath),
1122
+ exists: existsSync3(source.readPath),
922
1123
  scope: source.scope,
923
1124
  kind: source.shared ? "shared" : "pi",
924
1125
  serverCount: loaded ? Object.keys(loaded.mcpServers).length : 0
@@ -993,8 +1194,12 @@ function loadMcpConfig(overridePath, cwd = process.cwd()) {
993
1194
  if (!loaded) continue;
994
1195
  config = mergeConfigs(config, expandImports(loaded, cwd));
995
1196
  }
1197
+ const packageConfig = loadPackageMcpConfigs(cwd);
996
1198
  const pluginConfig = loadAgentPluginConfigs(config.settings?.agentPluginPaths, cwd);
997
- return mergeConfigs(pluginConfig, config);
1199
+ const packageServers = Object.fromEntries(
1200
+ Object.entries(packageConfig.mcpServers).filter(([name]) => !Object.hasOwn(pluginConfig.mcpServers, name))
1201
+ );
1202
+ return mergeConfigs({ mcpServers: packageServers }, mergeConfigs(pluginConfig, config));
998
1203
  }
999
1204
  function getMergedSettings(overridePath, cwd = process.cwd()) {
1000
1205
  let settings;
@@ -1134,25 +1339,54 @@ function mergeServerMaps(base, next) {
1134
1339
  for (const [name, definition] of Object.entries(next)) {
1135
1340
  const existing = merged[name];
1136
1341
  let baseEntry = existing ?? {};
1137
- if (existing && typeof definition.socket === "string") {
1342
+ if (existing && typeof definition.command === "string") {
1343
+ baseEntry = { ...existing };
1344
+ for (const field of [
1345
+ "url",
1346
+ "headers",
1347
+ "requestHeadersCommand",
1348
+ "auth",
1349
+ "bearerToken",
1350
+ "bearerTokenEnv",
1351
+ "oauth",
1352
+ "httpTransport",
1353
+ "socket"
1354
+ ]) {
1355
+ delete baseEntry[field];
1356
+ }
1357
+ } else if (existing && typeof definition.url === "string") {
1138
1358
  baseEntry = { ...existing };
1139
1359
  for (const field of [
1140
1360
  "command",
1141
1361
  "args",
1142
1362
  "env",
1143
1363
  "cwd",
1364
+ "pluginDataDir",
1365
+ "literalEnv",
1366
+ "socket"
1367
+ ]) {
1368
+ delete baseEntry[field];
1369
+ }
1370
+ } else if (existing && typeof definition.socket === "string") {
1371
+ baseEntry = { ...existing };
1372
+ for (const field of [
1373
+ "command",
1374
+ "args",
1375
+ "env",
1376
+ "cwd",
1377
+ "pluginDataDir",
1378
+ "literalEnv",
1144
1379
  "url",
1145
1380
  "headers",
1381
+ "requestHeadersCommand",
1146
1382
  "auth",
1147
1383
  "bearerToken",
1148
1384
  "bearerTokenEnv",
1149
- "oauth"
1385
+ "oauth",
1386
+ "httpTransport"
1150
1387
  ]) {
1151
1388
  delete baseEntry[field];
1152
1389
  }
1153
- } else if (existing?.socket && (typeof definition.command === "string" || typeof definition.url === "string")) {
1154
- baseEntry = { ...existing };
1155
- delete baseEntry.socket;
1156
1390
  }
1157
1391
  if (existing && typeof definition.url === "string" && definition.url !== existing.url) {
1158
1392
  if (baseEntry === existing) baseEntry = { ...existing };
@@ -1194,11 +1428,11 @@ function expandImports(config, cwd = process.cwd()) {
1194
1428
  function resolveImportCandidates(importKind, cwd) {
1195
1429
  return (IMPORT_PATHS[importKind] ?? []).map((candidate) => {
1196
1430
  if (importKind === "opencode" && candidate === "./opencode.json") {
1197
- const start = resolve3(cwd);
1431
+ const start = resolve4(cwd);
1198
1432
  let gitRoot;
1199
1433
  let current = start;
1200
1434
  while (true) {
1201
- if (existsSync2(join3(current, ".git"))) {
1435
+ if (existsSync3(join4(current, ".git"))) {
1202
1436
  gitRoot = current;
1203
1437
  break;
1204
1438
  }
@@ -1206,22 +1440,22 @@ function resolveImportCandidates(importKind, cwd) {
1206
1440
  if (parent === current) break;
1207
1441
  current = parent;
1208
1442
  }
1209
- if (!gitRoot) return join3(start, "opencode.json");
1443
+ if (!gitRoot) return join4(start, "opencode.json");
1210
1444
  current = start;
1211
1445
  while (true) {
1212
- const projectConfig = join3(current, "opencode.json");
1213
- if (existsSync2(projectConfig) || current === gitRoot) return projectConfig;
1446
+ const projectConfig = join4(current, "opencode.json");
1447
+ if (existsSync3(projectConfig) || current === gitRoot) return projectConfig;
1214
1448
  current = dirname(current);
1215
1449
  }
1216
1450
  }
1217
- return candidate.startsWith(".") ? resolve3(cwd, candidate) : candidate;
1451
+ return candidate.startsWith(".") ? resolve4(cwd, candidate) : candidate;
1218
1452
  });
1219
1453
  }
1220
1454
  function parseJsonConfig(raw) {
1221
- return JSON.parse(stripJsonComments(raw, { trailingCommas: true }));
1455
+ return JSON.parse(stripJsonComments2(raw, { trailingCommas: true }));
1222
1456
  }
1223
1457
  function readImportedConfig(path2) {
1224
- const raw = readFileSync3(path2, "utf-8");
1458
+ const raw = readFileSync4(path2, "utf-8");
1225
1459
  return path2.endsWith(".toml") ? parseToml(raw) : parseJsonConfig(raw);
1226
1460
  }
1227
1461
  function loadImportedConfig(importKind, cwd, warningPrefix) {
@@ -1229,7 +1463,7 @@ function loadImportedConfig(importKind, cwd, warningPrefix) {
1229
1463
  let merged = {};
1230
1464
  let highestPrecedencePath;
1231
1465
  for (const path2 of resolveImportCandidates(importKind, cwd)) {
1232
- if (!existsSync2(path2)) continue;
1466
+ if (!existsSync3(path2)) continue;
1233
1467
  try {
1234
1468
  const value = readImportedConfig(path2);
1235
1469
  if (value && typeof value === "object" && !Array.isArray(value)) {
@@ -1243,7 +1477,7 @@ function loadImportedConfig(importKind, cwd, warningPrefix) {
1243
1477
  return highestPrecedencePath ? { path: highestPrecedencePath, value: merged } : null;
1244
1478
  }
1245
1479
  for (const path2 of resolveImportCandidates(importKind, cwd)) {
1246
- if (!existsSync2(path2)) continue;
1480
+ if (!existsSync3(path2)) continue;
1247
1481
  try {
1248
1482
  return { path: path2, value: readImportedConfig(path2) };
1249
1483
  } catch (error) {
@@ -1253,9 +1487,9 @@ function loadImportedConfig(importKind, cwd, warningPrefix) {
1253
1487
  return null;
1254
1488
  }
1255
1489
  function readValidatedConfig(path2, label) {
1256
- if (!existsSync2(path2)) return null;
1490
+ if (!existsSync3(path2)) return null;
1257
1491
  try {
1258
- return validateConfig(parseJsonConfig(readFileSync3(path2, "utf-8")));
1492
+ return validateConfig(parseJsonConfig(readFileSync4(path2, "utf-8")));
1259
1493
  } catch (error) {
1260
1494
  console.warn(`Failed to load ${label}:`, error);
1261
1495
  return null;
@@ -1467,7 +1701,7 @@ function buildUnifiedDiff(beforeText, afterText) {
1467
1701
  return lines.join("\n");
1468
1702
  }
1469
1703
  function buildConfigWritePreview(filePath, nextRaw) {
1470
- const existed = existsSync2(filePath);
1704
+ const existed = existsSync3(filePath);
1471
1705
  const beforeRaw = readRawConfigObject(filePath);
1472
1706
  const beforeText = existed ? serializeRawConfig(beforeRaw) : "";
1473
1707
  const afterText = serializeRawConfig(nextRaw);
@@ -1481,9 +1715,9 @@ function buildConfigWritePreview(filePath, nextRaw) {
1481
1715
  };
1482
1716
  }
1483
1717
  function readRawConfigObject(filePath) {
1484
- if (!existsSync2(filePath)) return {};
1718
+ if (!existsSync3(filePath)) return {};
1485
1719
  try {
1486
- const raw = parseJsonConfig(readFileSync3(filePath, "utf-8"));
1720
+ const raw = parseJsonConfig(readFileSync4(filePath, "utf-8"));
1487
1721
  return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
1488
1722
  } catch {
1489
1723
  return {};
@@ -1510,9 +1744,9 @@ function setServersObject(raw, servers) {
1510
1744
  function writeProjectServerDisabledOverride(overridePath, cwd, serverName, disabled) {
1511
1745
  const filePath = getProjectPiConfigPath(cwd);
1512
1746
  let raw = {};
1513
- if (existsSync2(filePath)) {
1747
+ if (existsSync3(filePath)) {
1514
1748
  try {
1515
- const parsed = parseJsonConfig(readFileSync3(filePath, "utf-8"));
1749
+ const parsed = parseJsonConfig(readFileSync4(filePath, "utf-8"));
1516
1750
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
1517
1751
  throw new Error("root value must be an object");
1518
1752
  }
@@ -1572,9 +1806,9 @@ function isRepoPromptServer(name, entry) {
1572
1806
  return (entry.args ?? []).some((arg) => typeof arg === "string" && arg.toLowerCase().includes("repoprompt"));
1573
1807
  }
1574
1808
  function findProjectRoot(cwd = process.cwd()) {
1575
- let current = resolve3(cwd);
1809
+ let current = resolve4(cwd);
1576
1810
  while (true) {
1577
- if (existsSync2(join3(current, ".git")) || existsSync2(join3(current, "package.json")) || existsSync2(join3(current, PROJECT_CONFIG_NAME)) || existsSync2(join3(current, ".pi"))) {
1811
+ if (existsSync3(join4(current, ".git")) || existsSync3(join4(current, "package.json")) || existsSync3(join4(current, PROJECT_CONFIG_NAME)) || existsSync3(join4(current, ".pi"))) {
1578
1812
  return current;
1579
1813
  }
1580
1814
  const parent = dirname(current);
@@ -1600,12 +1834,12 @@ function detectRepoPrompt(summary, cwd = process.cwd()) {
1600
1834
  }
1601
1835
  }
1602
1836
  }
1603
- const executablePath = REPOPROMPT_BINARY_CANDIDATES.find((candidate) => existsSync2(candidate));
1837
+ const executablePath = REPOPROMPT_BINARY_CANDIDATES.find((candidate) => existsSync3(candidate));
1604
1838
  if (!executablePath) {
1605
1839
  return { configured: false };
1606
1840
  }
1607
1841
  const projectRoot = findProjectRoot(cwd);
1608
- const targetPath = projectRoot ? join3(projectRoot, PROJECT_CONFIG_NAME) : GENERIC_GLOBAL_CONFIG_PATH;
1842
+ const targetPath = projectRoot ? join4(projectRoot, PROJECT_CONFIG_NAME) : GENERIC_GLOBAL_CONFIG_PATH;
1609
1843
  return {
1610
1844
  configured: false,
1611
1845
  executablePath,
@@ -1740,7 +1974,7 @@ function resolveConfiguredOAuthDir(raw, cwd = process.cwd()) {
1740
1974
  }
1741
1975
  const trimmed = raw.trim();
1742
1976
  if (!trimmed) return void 0;
1743
- return resolve3(cwd, trimmed);
1977
+ return resolve4(cwd, trimmed);
1744
1978
  }
1745
1979
  var GENERIC_GLOBAL_CONFIG_PATH, AGENTS_GLOBAL_CONFIG_PATHS, PROJECT_CONFIG_NAME, PROJECT_PI_CONFIG_NAME, REPOPROMPT_BINARY_CANDIDATES, KNOWN_SERVER_PRESETS, IMPORT_PATHS, URL_BOUND_AUTH_FIELDS;
1746
1980
  var init_config = __esm({
@@ -1748,17 +1982,18 @@ var init_config = __esm({
1748
1982
  "use strict";
1749
1983
  init_agent_dir();
1750
1984
  init_agent_plugin_loader();
1985
+ init_package_mcp_loader();
1751
1986
  init_types();
1752
1987
  init_utils();
1753
- GENERIC_GLOBAL_CONFIG_PATH = join3(homedir3(), ".config", "mcp", "mcp.json");
1988
+ GENERIC_GLOBAL_CONFIG_PATH = join4(homedir3(), ".config", "mcp", "mcp.json");
1754
1989
  AGENTS_GLOBAL_CONFIG_PATHS = [
1755
- join3(homedir3(), ".agents", "mcp.json"),
1756
- join3(homedir3(), ".agents", "mcp", "mcp.json")
1990
+ join4(homedir3(), ".agents", "mcp.json"),
1991
+ join4(homedir3(), ".agents", "mcp", "mcp.json")
1757
1992
  ];
1758
1993
  PROJECT_CONFIG_NAME = ".mcp.json";
1759
1994
  PROJECT_PI_CONFIG_NAME = "mcp.json";
1760
1995
  REPOPROMPT_BINARY_CANDIDATES = [
1761
- join3(homedir3(), "RepoPrompt", "repoprompt_cli"),
1996
+ join4(homedir3(), "RepoPrompt", "repoprompt_cli"),
1762
1997
  "/Applications/Repo Prompt.app/Contents/MacOS/repoprompt-mcp"
1763
1998
  ];
1764
1999
  KNOWN_SERVER_PRESETS = [
@@ -1794,25 +2029,25 @@ var init_config = __esm({
1794
2029
  }
1795
2030
  ];
1796
2031
  IMPORT_PATHS = {
1797
- cursor: [join3(homedir3(), ".cursor", "mcp.json")],
2032
+ cursor: [join4(homedir3(), ".cursor", "mcp.json")],
1798
2033
  "claude-code": [
1799
- join3(homedir3(), ".claude", "mcp.json"),
1800
- join3(homedir3(), ".claude.json"),
1801
- join3(homedir3(), ".claude", "claude_desktop_config.json")
2034
+ join4(homedir3(), ".claude", "mcp.json"),
2035
+ join4(homedir3(), ".claude.json"),
2036
+ join4(homedir3(), ".claude", "claude_desktop_config.json")
1802
2037
  ],
1803
- "claude-desktop": [join3(homedir3(), "Library", "Application Support", "Claude", "claude_desktop_config.json")],
2038
+ "claude-desktop": [join4(homedir3(), "Library", "Application Support", "Claude", "claude_desktop_config.json")],
1804
2039
  codex: [
1805
- join3(homedir3(), ".codex", "config.toml"),
1806
- join3(homedir3(), ".codex", "config.json")
2040
+ join4(homedir3(), ".codex", "config.toml"),
2041
+ join4(homedir3(), ".codex", "config.json")
1807
2042
  ],
1808
2043
  opencode: [
1809
- join3(homedir3(), ".config", "opencode", "opencode.json"),
2044
+ join4(homedir3(), ".config", "opencode", "opencode.json"),
1810
2045
  "./opencode.json"
1811
2046
  ],
1812
- windsurf: [join3(homedir3(), ".windsurf", "mcp.json")],
2047
+ windsurf: [join4(homedir3(), ".windsurf", "mcp.json")],
1813
2048
  vscode: [".vscode/mcp.json"]
1814
2049
  };
1815
- URL_BOUND_AUTH_FIELDS = ["headers", "bearerToken", "bearerTokenEnv", "requestHeadersCommand"];
2050
+ URL_BOUND_AUTH_FIELDS = ["headers", "bearerToken", "bearerTokenEnv", "bearerTokenStore", "requestHeadersCommand"];
1816
2051
  }
1817
2052
  });
1818
2053
 
@@ -1896,7 +2131,7 @@ var init_ui_tool_visibility = __esm({
1896
2131
  });
1897
2132
 
1898
2133
  // packages/coding-agent/src/humain/mcp-adapter/vendor/metadata-cache.ts
1899
- import { existsSync as existsSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync2, renameSync as renameSync2, mkdirSync as mkdirSync2 } from "node:fs";
2134
+ import { existsSync as existsSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync2, renameSync as renameSync2, mkdirSync as mkdirSync2 } from "node:fs";
1900
2135
  import { dirname as dirname3 } from "node:path";
1901
2136
  import { createHash as createHash2 } from "node:crypto";
1902
2137
  function getMetadataCachePath() {
@@ -1904,9 +2139,9 @@ function getMetadataCachePath() {
1904
2139
  }
1905
2140
  function loadMetadataCache() {
1906
2141
  const cachePath = getMetadataCachePath();
1907
- if (!existsSync4(cachePath)) return null;
2142
+ if (!existsSync5(cachePath)) return null;
1908
2143
  try {
1909
- const raw = JSON.parse(readFileSync5(cachePath, "utf-8"));
2144
+ const raw = JSON.parse(readFileSync6(cachePath, "utf-8"));
1910
2145
  if (!raw || typeof raw !== "object") return null;
1911
2146
  if (raw.version !== CACHE_VERSION) return null;
1912
2147
  if (!raw.servers || typeof raw.servers !== "object") return null;
@@ -1921,8 +2156,8 @@ function saveMetadataCache(cache) {
1921
2156
  mkdirSync2(dir, { recursive: true });
1922
2157
  let merged = { version: CACHE_VERSION, servers: {} };
1923
2158
  try {
1924
- if (existsSync4(cachePath)) {
1925
- const existing = JSON.parse(readFileSync5(cachePath, "utf-8"));
2159
+ if (existsSync5(cachePath)) {
2160
+ const existing = JSON.parse(readFileSync6(cachePath, "utf-8"));
1926
2161
  if (existing && existing.version === CACHE_VERSION && existing.servers) {
1927
2162
  merged.servers = { ...existing.servers };
1928
2163
  }
@@ -1932,7 +2167,7 @@ function saveMetadataCache(cache) {
1932
2167
  merged.version = CACHE_VERSION;
1933
2168
  merged.servers = { ...merged.servers, ...cache.servers };
1934
2169
  const tmpPath = `${cachePath}.${process.pid}.tmp`;
1935
- writeFileSync2(tmpPath, JSON.stringify(merged, null, 2), "utf-8");
2170
+ writeFileSync2(tmpPath, JSON.stringify(merged), "utf-8");
1936
2171
  renameSync2(tmpPath, cachePath);
1937
2172
  }
1938
2173
  function computeServerHash(definition) {
@@ -2008,30 +2243,12 @@ function getMissingConfiguredDirectToolServers(config, cache, envOverride) {
2008
2243
  }
2009
2244
  return missing;
2010
2245
  }
2011
- function reconstructToolMetadata(serverName, entry, prefix, definition, configuredServers, cache) {
2246
+ function reconstructToolMetadata(serverName, entry, prefix, definition, configuredServers, cache, sharedSelectorCandidateIndex) {
2012
2247
  const metadata = [];
2013
2248
  const seenNames = /* @__PURE__ */ new Set();
2014
2249
  const effectivePrefix = resolveToolPrefix(definition, prefix);
2015
2250
  const hasToolFilters = Array.isArray(definition.includeTools) && definition.includeTools.length > 0 || Array.isArray(definition.excludeTools) && definition.excludeTools.length > 0;
2016
- const selectorCandidateIndex = hasToolFilters && configuredServers && cache ? (() => {
2017
- const candidates = /* @__PURE__ */ new Set();
2018
- for (const [otherServerName, otherDefinition] of Object.entries(configuredServers)) {
2019
- const otherEntry = cache.servers[otherServerName];
2020
- if (!otherEntry || !isServerCacheValid(otherEntry, otherDefinition) || isServerDisabled(otherDefinition)) continue;
2021
- const otherPrefix = resolveToolPrefix(otherDefinition, prefix);
2022
- for (const otherTool of otherEntry.tools ?? []) {
2023
- if (!isUiToolVisibleToModel(otherTool.uiVisibility)) continue;
2024
- for (const candidate of getToolNameCandidates(otherTool.name, otherServerName, otherPrefix, false)) candidates.add(candidate);
2025
- }
2026
- if (otherDefinition.exposeResources !== false) {
2027
- for (const resource of otherEntry.resources ?? []) {
2028
- const baseName = `read_${resourceNameToToolName(resource.name)}`;
2029
- for (const candidate of getToolNameCandidates(baseName, otherServerName, otherPrefix, false)) candidates.add(candidate);
2030
- }
2031
- }
2032
- }
2033
- return createToolSelectorCandidateIndex(candidates);
2034
- })() : void 0;
2251
+ const selectorCandidateIndex = hasToolFilters ? sharedSelectorCandidateIndex ?? (configuredServers && cache ? createCachedToolSelectorCandidateIndex(configuredServers, cache, prefix) : void 0) : void 0;
2035
2252
  for (const tool of entry.tools ?? []) {
2036
2253
  if (!tool?.name) continue;
2037
2254
  if (!isUiToolVisibleToModel(tool.uiVisibility)) {
@@ -2077,6 +2294,25 @@ function reconstructToolMetadata(serverName, entry, prefix, definition, configur
2077
2294
  }
2078
2295
  return metadata;
2079
2296
  }
2297
+ function createCachedToolSelectorCandidateIndex(configuredServers, cache, prefix) {
2298
+ const candidates = /* @__PURE__ */ new Set();
2299
+ for (const [serverName, definition] of Object.entries(configuredServers)) {
2300
+ const entry = cache.servers[serverName];
2301
+ if (!entry || !isServerCacheValid(entry, definition) || isServerDisabled(definition)) continue;
2302
+ const effectivePrefix = resolveToolPrefix(definition, prefix);
2303
+ for (const tool of entry.tools ?? []) {
2304
+ if (!isUiToolVisibleToModel(tool.uiVisibility)) continue;
2305
+ for (const candidate of getToolNameCandidates(tool.name, serverName, effectivePrefix, false)) candidates.add(candidate);
2306
+ }
2307
+ if (definition.exposeResources !== false) {
2308
+ for (const resource of entry.resources ?? []) {
2309
+ const baseName = `read_${resourceNameToToolName(resource.name)}`;
2310
+ for (const candidate of getToolNameCandidates(baseName, serverName, effectivePrefix, false)) candidates.add(candidate);
2311
+ }
2312
+ }
2313
+ }
2314
+ return createToolSelectorCandidateIndex(candidates);
2315
+ }
2080
2316
  function serializeTools(tools) {
2081
2317
  return tools.filter((t) => t?.name).map((t) => {
2082
2318
  const uiResourceUri = tryGetToolUiResourceUri(t);
@@ -2759,8 +2995,8 @@ var init_mcp_setup_panel = __esm({
2759
2995
  });
2760
2996
 
2761
2997
  // packages/coding-agent/src/utils/clipboard-native.ts
2762
- import { createRequire as createRequire2 } from "module";
2763
- import { dirname as dirname7, join as join6 } from "path";
2998
+ import { createRequire as createRequire3 } from "module";
2999
+ import { dirname as dirname8, join as join8 } from "path";
2764
3000
  import { pathToFileURL } from "url";
2765
3001
  function loadClipboardNative(requires = [moduleRequire, executableDirRequire]) {
2766
3002
  for (const requireClipboard of requires) {
@@ -2775,21 +3011,21 @@ var moduleRequire, executableDirRequire, hasDisplay, clipboard;
2775
3011
  var init_clipboard_native = __esm({
2776
3012
  "packages/coding-agent/src/utils/clipboard-native.ts"() {
2777
3013
  "use strict";
2778
- moduleRequire = createRequire2(import.meta.url);
2779
- executableDirRequire = createRequire2(pathToFileURL(join6(dirname7(process.execPath), "package.json")).href);
3014
+ moduleRequire = createRequire3(import.meta.url);
3015
+ executableDirRequire = createRequire3(pathToFileURL(join8(dirname8(process.execPath), "package.json")).href);
2780
3016
  hasDisplay = process.platform !== "linux" || Boolean(process.env.DISPLAY || process.env.WAYLAND_DISPLAY);
2781
3017
  clipboard = !process.env.TERMUX_VERSION && hasDisplay ? loadClipboardNative() : null;
2782
3018
  }
2783
3019
  });
2784
3020
 
2785
3021
  // packages/coding-agent/src/utils/photon.ts
2786
- import { createRequire as createRequire3 } from "module";
2787
- var require3, fs;
3022
+ import { createRequire as createRequire4 } from "module";
3023
+ var require4, fs;
2788
3024
  var init_photon = __esm({
2789
3025
  "packages/coding-agent/src/utils/photon.ts"() {
2790
3026
  "use strict";
2791
- require3 = createRequire3(import.meta.url);
2792
- fs = require3("fs");
3027
+ require4 = createRequire4(import.meta.url);
3028
+ fs = require4("fs");
2793
3029
  }
2794
3030
  });
2795
3031
 
@@ -2866,10 +3102,10 @@ async function copyToClipboard(text) {
2866
3102
  if (isWayland && hasWaylandDisplay) {
2867
3103
  try {
2868
3104
  execSync("which wl-copy", { stdio: "ignore" });
2869
- const wlCopyExit = await new Promise((resolve6) => {
3105
+ const wlCopyExit = await new Promise((resolve7) => {
2870
3106
  const proc = spawn2("wl-copy", [], { stdio: ["pipe", "ignore", "ignore"] });
2871
- proc.on("error", () => resolve6(1));
2872
- proc.on("close", (code) => resolve6(code ?? 1));
3107
+ proc.on("error", () => resolve7(1));
3108
+ proc.on("close", (code) => resolve7(code ?? 1));
2873
3109
  proc.stdin.on("error", () => {
2874
3110
  });
2875
3111
  proc.stdin.write(text);
@@ -3100,6 +3336,13 @@ var init_mcp_panel = __esm({
3100
3336
  }
3101
3337
  const status = callbacks.getConnectionStatus(serverName);
3102
3338
  const failureMessage = callbacks.getFailureMessage?.(serverName) ?? null;
3339
+ let directCount = 0;
3340
+ let directTokens = 0;
3341
+ for (const tool of tools) {
3342
+ if (!tool.isDirect) continue;
3343
+ directCount++;
3344
+ directTokens += tool.estimatedTokens;
3345
+ }
3103
3346
  this.servers.push({
3104
3347
  name: serverName,
3105
3348
  expanded: false,
@@ -3111,6 +3354,8 @@ var init_mcp_panel = __esm({
3111
3354
  connectionStatus: status,
3112
3355
  failureMessage,
3113
3356
  tools,
3357
+ directCount,
3358
+ directTokens,
3114
3359
  hasCachedData: !!serverCache
3115
3360
  });
3116
3361
  }
@@ -3297,7 +3542,7 @@ var init_mcp_panel = __esm({
3297
3542
  } else if (item.toolIndex !== void 0) {
3298
3543
  const tool = server2.tools[item.toolIndex];
3299
3544
  if (!tool) return;
3300
- tool.isDirect = !tool.isDirect;
3545
+ this.toggleToolDirect(server2, tool);
3301
3546
  if (tool.isDirect && server2.source === "import") {
3302
3547
  this.importNotice = `Imported from ${sanitizeDisplayText(server2.importKind ?? "external")} \u2014 will copy to user config on save`;
3303
3548
  }
@@ -3430,17 +3675,28 @@ var init_mcp_panel = __esm({
3430
3675
  if (server2.source === "import" && newState) {
3431
3676
  this.importNotice = `Imported from ${sanitizeDisplayText(server2.importKind ?? "external")} \u2014 will copy to user config on save`;
3432
3677
  }
3433
- for (const t of server2.tools) t.isDirect = newState;
3678
+ let directTokens = 0;
3679
+ for (const tool of server2.tools) {
3680
+ tool.isDirect = newState;
3681
+ if (newState) directTokens += tool.estimatedTokens;
3682
+ }
3683
+ server2.directCount = newState ? server2.tools.length : 0;
3684
+ server2.directTokens = directTokens;
3434
3685
  } else if (item.toolIndex !== void 0) {
3435
3686
  const tool = server2.tools[item.toolIndex];
3436
3687
  if (!tool) return;
3437
- tool.isDirect = !tool.isDirect;
3688
+ this.toggleToolDirect(server2, tool);
3438
3689
  if (tool.isDirect && server2.source === "import") {
3439
3690
  this.importNotice = `Imported from ${sanitizeDisplayText(server2.importKind ?? "external")} \u2014 will copy to user config on save`;
3440
3691
  }
3441
3692
  }
3442
3693
  this.updateDirty();
3443
3694
  }
3695
+ toggleToolDirect(server2, tool) {
3696
+ tool.isDirect = !tool.isDirect;
3697
+ server2.directCount += tool.isDirect ? 1 : -1;
3698
+ server2.directTokens += tool.isDirect ? tool.estimatedTokens : -tool.estimatedTokens;
3699
+ }
3444
3700
  handleDiscardInput(data) {
3445
3701
  if (matchesKey3(data, "ctrl+c")) {
3446
3702
  this.cleanup();
@@ -3536,6 +3792,13 @@ var init_mcp_panel = __esm({
3536
3792
  }
3537
3793
  }
3538
3794
  server2.tools = newTools;
3795
+ server2.directCount = 0;
3796
+ server2.directTokens = 0;
3797
+ for (const tool of newTools) {
3798
+ if (!tool.isDirect) continue;
3799
+ server2.directCount++;
3800
+ server2.directTokens += tool.estimatedTokens;
3801
+ }
3539
3802
  this.rebuildVisibleItems();
3540
3803
  this.updateDirty();
3541
3804
  }
@@ -3625,12 +3888,13 @@ var init_mcp_panel = __esm({
3625
3888
  if (this.authOnly) {
3626
3889
  lines.push(row(fg2(t.description, "select a server to authenticate")));
3627
3890
  } else {
3628
- const directCount = this.servers.reduce((sum, s) => sum + s.tools.filter((t2) => t2.isDirect).length, 0);
3629
- const totalTokens = this.servers.reduce(
3630
- (sum, s) => sum + s.tools.filter((t2) => t2.isDirect).reduce((ts, t2) => ts + t2.estimatedTokens, 0),
3631
- 0
3632
- );
3633
- const stats = directCount > 0 ? `${directCount} direct ~${totalTokens.toLocaleString()} tokens` : "no direct tools";
3891
+ let directCount = 0;
3892
+ let directTokens = 0;
3893
+ for (const server2 of this.servers) {
3894
+ directCount += server2.directCount;
3895
+ directTokens += server2.directTokens;
3896
+ }
3897
+ const stats = directCount > 0 ? `${directCount} direct ~${directTokens.toLocaleString()} tokens` : "no direct tools";
3634
3898
  lines.push(row(fg2(t.description, stats + (this.dirty ? fg2(t.needsAuth, " (unsaved)") : ""))));
3635
3899
  }
3636
3900
  }
@@ -3688,7 +3952,7 @@ var init_mcp_panel = __esm({
3688
3952
  if (!server2.hasCachedData && !this.authOnly) {
3689
3953
  return `${prefix} ${nameStr}${importLabel} ${fg2(t.description, "(not cached)")}${statusLabel}`;
3690
3954
  }
3691
- const directCount = server2.tools.filter((t2) => t2.isDirect).length;
3955
+ const directCount = server2.directCount;
3692
3956
  const totalCount = server2.tools.length;
3693
3957
  let toggleIcon = fg2(t.description, "\u25CB");
3694
3958
  if (directCount === totalCount && totalCount > 0) {
@@ -3700,8 +3964,7 @@ var init_mcp_panel = __esm({
3700
3964
  if (totalCount > 0) {
3701
3965
  toolInfo = `${directCount}/${totalCount}`;
3702
3966
  if (directCount > 0) {
3703
- const tokens = server2.tools.filter((t2) => t2.isDirect).reduce((s, t2) => s + t2.estimatedTokens, 0);
3704
- toolInfo += ` ~${tokens.toLocaleString()}`;
3967
+ toolInfo += ` ~${server2.directTokens.toLocaleString()}`;
3705
3968
  }
3706
3969
  toolInfo = fg2(t.description, toolInfo);
3707
3970
  }
@@ -3788,7 +4051,7 @@ init_config();
3788
4051
  // packages/coding-agent/src/humain/mcp-adapter/vendor/init.ts
3789
4052
  init_types();
3790
4053
  init_config();
3791
- import { existsSync as existsSync6 } from "node:fs";
4054
+ import { existsSync as existsSync7 } from "node:fs";
3792
4055
 
3793
4056
  // packages/coding-agent/src/humain/mcp-adapter/vendor/errors.ts
3794
4057
  var McpUiError = class extends Error {
@@ -4053,6 +4316,7 @@ var ConsentManager = class {
4053
4316
 
4054
4317
  // packages/coding-agent/src/humain/mcp-adapter/vendor/lifecycle.ts
4055
4318
  init_types();
4319
+ import { SdkError, SdkErrorCode } from "@modelcontextprotocol/client";
4056
4320
 
4057
4321
  // packages/coding-agent/src/humain/mcp-adapter/vendor/mcp-auth-flow.ts
4058
4322
  import {
@@ -4074,8 +4338,8 @@ init_config();
4074
4338
  import { spawnSync as spawnSync2 } from "child_process";
4075
4339
  import { createHash } from "crypto";
4076
4340
  import { createRequire } from "module";
4077
- import { readFileSync as readFileSync4, existsSync as existsSync3, rmSync } from "fs";
4078
- import { dirname as dirname2, join as join4 } from "path";
4341
+ import { readFileSync as readFileSync5, existsSync as existsSync4, rmSync } from "fs";
4342
+ import { dirname as dirname2, join as join5 } from "path";
4079
4343
  import { fileURLToPath } from "url";
4080
4344
  var require2 = createRequire(import.meta.url);
4081
4345
  var AUTH_SECRET_SERVICE = "pi-mcp-adapter.oauth";
@@ -4230,7 +4494,7 @@ function loadKeyringNativeBindingFallback(keyringRequire, platform4, arch) {
4230
4494
  for (const target of targets) {
4231
4495
  try {
4232
4496
  const packageJsonPath = keyringRequire.resolve(`${target.packageName}/package.json`);
4233
- return keyringRequire(join4(dirname2(packageJsonPath), target.bindingFile));
4497
+ return keyringRequire(join5(dirname2(packageJsonPath), target.bindingFile));
4234
4498
  } catch (error) {
4235
4499
  lastError = error;
4236
4500
  }
@@ -4335,7 +4599,7 @@ function getServerDir(serverName, options) {
4335
4599
  throw new Error(`Invalid MCP server name: ${JSON.stringify(serverName)}`);
4336
4600
  }
4337
4601
  const storageKey = getAuthEntryAccount(serverName);
4338
- return join4(getAuthBaseDir(options), storageKey);
4602
+ return join5(getAuthBaseDir(options), storageKey);
4339
4603
  }
4340
4604
  function getAuthEntryAccount(serverName) {
4341
4605
  if (typeof serverName !== "string") {
@@ -4344,7 +4608,7 @@ function getAuthEntryAccount(serverName) {
4344
4608
  return `sha256-${createHash("sha256").update(serverName, "utf8").digest("hex")}`;
4345
4609
  }
4346
4610
  function getAuthEntryFilePath(serverName, options) {
4347
- return join4(getServerDir(serverName, options), "tokens.json");
4611
+ return join5(getServerDir(serverName, options), "tokens.json");
4348
4612
  }
4349
4613
  function parseJsonPayload(serverName, payload, source) {
4350
4614
  try {
@@ -4455,8 +4719,8 @@ function readExistingChunkManifest(store, serverName, account) {
4455
4719
  }
4456
4720
  }
4457
4721
  function removeChunkPayloads(store, account, manifest) {
4458
- for (const chunkAccount of getAuthEntryChunkAccounts(account, manifest)) {
4459
- store.remove(chunkAccount);
4722
+ for (const chunkAccount2 of getAuthEntryChunkAccounts(account, manifest)) {
4723
+ store.remove(chunkAccount2);
4460
4724
  }
4461
4725
  }
4462
4726
  function tryRemoveChunkPayloads(store, account, manifest) {
@@ -4474,11 +4738,11 @@ function createChunkManifest(payload) {
4474
4738
  };
4475
4739
  }
4476
4740
  function readChunkedAuthEntry(store, serverName, account, manifest) {
4477
- const chunks = getAuthEntryChunkAccounts(account, manifest).map((chunkAccount) => {
4741
+ const chunks = getAuthEntryChunkAccounts(account, manifest).map((chunkAccount2) => {
4478
4742
  try {
4479
- const chunk = store.read(chunkAccount);
4743
+ const chunk = store.read(chunkAccount2);
4480
4744
  if (chunk === void 0) {
4481
- throw new Error(`Missing OAuth credential chunk ${chunkAccount} for ${serverName}`);
4745
+ throw new Error(`Missing OAuth credential chunk ${chunkAccount2} for ${serverName}`);
4482
4746
  }
4483
4747
  return chunk;
4484
4748
  } catch (error) {
@@ -4493,13 +4757,13 @@ function readChunkedAuthEntry(store, serverName, account, manifest) {
4493
4757
  }
4494
4758
  function readLegacyAuthEntry(serverName, options) {
4495
4759
  const filePath = getAuthEntryFilePath(serverName, options);
4496
- if (!existsSync3(filePath)) return void 0;
4497
- const data = readFileSync4(filePath, "utf-8");
4760
+ if (!existsSync4(filePath)) return void 0;
4761
+ const data = readFileSync5(filePath, "utf-8");
4498
4762
  return parseAuthEntryPayload(serverName, data, filePath);
4499
4763
  }
4500
4764
  function removeLegacyAuthEntry(serverName, options) {
4501
4765
  const filePath = getAuthEntryFilePath(serverName, options);
4502
- if (!existsSync3(filePath)) return;
4766
+ if (!existsSync4(filePath)) return;
4503
4767
  try {
4504
4768
  rmSync(filePath, { force: true });
4505
4769
  } catch (error) {
@@ -5260,6 +5524,7 @@ function htmlError(error) {
5260
5524
  var server;
5261
5525
  var bindingPromise;
5262
5526
  var stoppingPromise;
5527
+ var restartableStoppingPromise;
5263
5528
  var callbackGeneration = 0;
5264
5529
  var pendingAuths = /* @__PURE__ */ new Map();
5265
5530
  var reservedAuthStates = /* @__PURE__ */ new Set();
@@ -5327,10 +5592,16 @@ function handleRequest(req, res) {
5327
5592
  res.end(htmlSuccess());
5328
5593
  }
5329
5594
  async function ensureCallbackServer(options = {}) {
5595
+ const generation = callbackGeneration;
5330
5596
  if (stoppingPromise) {
5331
- throw new Error("OAuth callback server stopped");
5597
+ if (!restartableStoppingPromise) {
5598
+ throw new Error("OAuth callback server stopped");
5599
+ }
5600
+ await restartableStoppingPromise;
5601
+ if (generation !== callbackGeneration) {
5602
+ throw new Error("OAuth callback server stopped");
5603
+ }
5332
5604
  }
5333
- const generation = callbackGeneration;
5334
5605
  while (bindingPromise) {
5335
5606
  await bindingPromise;
5336
5607
  if (generation !== callbackGeneration) {
@@ -5389,12 +5660,12 @@ async function ensureCallbackServerLocked(options = {}) {
5389
5660
  const candidateServer = createServer(handleRequest);
5390
5661
  const listenPort = strictPort ? requiredPort : 0;
5391
5662
  try {
5392
- await new Promise((resolve6, reject) => {
5663
+ await new Promise((resolve7, reject) => {
5393
5664
  candidateServer.once("error", (err) => {
5394
5665
  reject(err);
5395
5666
  });
5396
5667
  candidateServer.listen(listenPort, requestedHost, () => {
5397
- resolve6();
5668
+ resolve7();
5398
5669
  });
5399
5670
  });
5400
5671
  if (strictPort) {
@@ -5407,8 +5678,8 @@ async function ensureCallbackServerLocked(options = {}) {
5407
5678
  setOAuthCallbackPort(address.port);
5408
5679
  }
5409
5680
  if (previousServer && (needsStrictRebind || needsHostSwitch)) {
5410
- await new Promise((resolve6) => {
5411
- previousServer.close(() => resolve6());
5681
+ await new Promise((resolve7) => {
5682
+ previousServer.close(() => resolve7());
5412
5683
  });
5413
5684
  }
5414
5685
  callbackServerHost = requestedHost;
@@ -5424,8 +5695,8 @@ async function ensureCallbackServerLocked(options = {}) {
5424
5695
  reservedAuthStates.delete(reservedState);
5425
5696
  }
5426
5697
  const nodeError = error;
5427
- await new Promise((resolve6) => {
5428
- candidateServer.close(() => resolve6());
5698
+ await new Promise((resolve7) => {
5699
+ candidateServer.close(() => resolve7());
5429
5700
  });
5430
5701
  if (strictPort && nodeError.code === "EADDRINUSE") {
5431
5702
  throw new Error(
@@ -5441,14 +5712,14 @@ function releaseCallbackServer(oauthState) {
5441
5712
  }
5442
5713
  function waitForCallback(oauthState) {
5443
5714
  reservedAuthStates.delete(oauthState);
5444
- return new Promise((resolve6, reject) => {
5715
+ return new Promise((resolve7, reject) => {
5445
5716
  const timeout = setTimeout(() => {
5446
5717
  if (pendingAuths.has(oauthState)) {
5447
5718
  pendingAuths.delete(oauthState);
5448
5719
  reject(new Error("OAuth callback timeout - authorization took too long"));
5449
5720
  }
5450
5721
  }, CALLBACK_TIMEOUT_MS);
5451
- pendingAuths.set(oauthState, { resolve: resolve6, reject, timeout });
5722
+ pendingAuths.set(oauthState, { resolve: resolve7, reject, timeout });
5452
5723
  });
5453
5724
  }
5454
5725
  function cancelPendingCallback(oauthState) {
@@ -5461,7 +5732,11 @@ function cancelPendingCallback(oauthState) {
5461
5732
  }
5462
5733
  }
5463
5734
  function stopCallbackServer() {
5464
- if (stoppingPromise) return stoppingPromise;
5735
+ if (stoppingPromise) {
5736
+ restartableStoppingPromise = void 0;
5737
+ callbackGeneration += 1;
5738
+ return stoppingPromise;
5739
+ }
5465
5740
  callbackGeneration += 1;
5466
5741
  const cleanup = (async () => {
5467
5742
  while (bindingPromise) {
@@ -5469,9 +5744,9 @@ function stopCallbackServer() {
5469
5744
  });
5470
5745
  }
5471
5746
  if (server) {
5472
- await new Promise((resolve6) => {
5747
+ await new Promise((resolve7) => {
5473
5748
  server.close(() => {
5474
- resolve6();
5749
+ resolve7();
5475
5750
  });
5476
5751
  });
5477
5752
  server = void 0;
@@ -5495,6 +5770,17 @@ function stopCallbackServer() {
5495
5770
  stoppingPromise = operation;
5496
5771
  return operation;
5497
5772
  }
5773
+ function stopCallbackServerIfIdle() {
5774
+ if (stoppingPromise) return stoppingPromise;
5775
+ if (bindingPromise || !server || pendingAuths.size > 0 || reservedAuthStates.size > 0) {
5776
+ return Promise.resolve();
5777
+ }
5778
+ const operation = stopCallbackServer().finally(() => {
5779
+ if (restartableStoppingPromise === operation) restartableStoppingPromise = void 0;
5780
+ });
5781
+ restartableStoppingPromise = operation;
5782
+ return operation;
5783
+ }
5498
5784
 
5499
5785
  // packages/coding-agent/src/humain/mcp-adapter/vendor/mcp-auth-flow.ts
5500
5786
  init_types();
@@ -5508,7 +5794,7 @@ function throwIfAborted(signal) {
5508
5794
  async function abortable(promise, signal) {
5509
5795
  if (!signal) return promise;
5510
5796
  throwIfAborted(signal);
5511
- return await new Promise((resolve6, reject) => {
5797
+ return await new Promise((resolve7, reject) => {
5512
5798
  let settled = false;
5513
5799
  const cleanup = () => signal.removeEventListener("abort", onAbort);
5514
5800
  const onAbort = () => {
@@ -5523,7 +5809,7 @@ async function abortable(promise, signal) {
5523
5809
  if (settled) return;
5524
5810
  settled = true;
5525
5811
  cleanup();
5526
- resolve6(value);
5812
+ resolve7(value);
5527
5813
  },
5528
5814
  (error) => {
5529
5815
  if (settled) return;
@@ -5867,7 +6153,7 @@ async function startAuth(serverName, serverUrl, definition, options = {}) {
5867
6153
  } catch (error) {
5868
6154
  releaseCallbackServer(oauthState);
5869
6155
  try {
5870
- await clearOAuthState(serverName, authStorageOptions);
6156
+ await cleanupAndReleaseCallbackServerIfIdle(() => clearOAuthState(serverName, authStorageOptions));
5871
6157
  } catch (cleanupError) {
5872
6158
  throw new AggregateError([error, cleanupError], "OAuth startup cleanup failed");
5873
6159
  }
@@ -5905,6 +6191,7 @@ async function startAuth(serverName, serverUrl, definition, options = {}) {
5905
6191
  authProvider.deactivate();
5906
6192
  releaseCallbackServer(oauthState);
5907
6193
  await clearOAuthState(serverName, authStorageOptions);
6194
+ await stopCallbackServerIfIdle();
5908
6195
  return { authorizationUrl: "" };
5909
6196
  }
5910
6197
  if (!capturedUrl) {
@@ -5915,7 +6202,7 @@ async function startAuth(serverName, serverUrl, definition, options = {}) {
5915
6202
  } catch (error) {
5916
6203
  authProvider.deactivate();
5917
6204
  try {
5918
- await clearPendingAuth(runtime, serverName, oauthState, authStorageOptions);
6205
+ await clearPendingAuthAndReleaseIfIdle(runtime, serverName, oauthState, authStorageOptions);
5919
6206
  } catch (cleanupError) {
5920
6207
  throw new AggregateError([error, cleanupError], "OAuth startup cleanup failed");
5921
6208
  }
@@ -5931,7 +6218,7 @@ async function setPendingAuth(runtime, serverName, pendingAuth, oauthState, sign
5931
6218
  state.pendingAuths.set(key, pendingAuth);
5932
6219
  state.pendingAuthStates.set(key, oauthState);
5933
6220
  const cleanupTimer = setTimeout(() => {
5934
- void clearPendingAuth(runtime, serverName, oauthState, pendingAuth.authStorageOptions).catch((error) => {
6221
+ void clearPendingAuthAndReleaseIfIdle(runtime, serverName, oauthState, pendingAuth.authStorageOptions).catch((error) => {
5935
6222
  console.error(`MCP Auth: Timed-out flow cleanup failed: ${formatTerminalError(error)}`);
5936
6223
  });
5937
6224
  }, MANUAL_AUTH_TIMEOUT_MS);
@@ -5962,6 +6249,28 @@ async function clearPendingAuth(runtime, serverName, oauthState, fallbackStorage
5962
6249
  }
5963
6250
  }
5964
6251
  }
6252
+ async function clearPendingAuthAndReleaseIfIdle(runtime, serverName, oauthState, fallbackStorageOptions = {}) {
6253
+ await cleanupAndReleaseCallbackServerIfIdle(
6254
+ () => clearPendingAuth(runtime, serverName, oauthState, fallbackStorageOptions)
6255
+ );
6256
+ }
6257
+ async function cleanupAndReleaseCallbackServerIfIdle(cleanup) {
6258
+ let cleanupFailure;
6259
+ try {
6260
+ await cleanup();
6261
+ } catch (error) {
6262
+ cleanupFailure = { error };
6263
+ }
6264
+ try {
6265
+ await stopCallbackServerIfIdle();
6266
+ } catch (releaseError) {
6267
+ if (cleanupFailure) {
6268
+ throw new AggregateError([cleanupFailure.error, releaseError], "OAuth callback cleanup failed");
6269
+ }
6270
+ throw releaseError;
6271
+ }
6272
+ if (cleanupFailure) throw cleanupFailure.error;
6273
+ }
5965
6274
  function getSearchParamsFromInput(input) {
5966
6275
  try {
5967
6276
  const url = new URL(input);
@@ -6099,7 +6408,7 @@ async function completeAuth(serverName, authorizationCode, options = {}) {
6099
6408
  } finally {
6100
6409
  if (!keepPendingForRetry) {
6101
6410
  try {
6102
- await clearPendingAuth(runtime, serverName, oauthState, authStorageOptions);
6411
+ await clearPendingAuthAndReleaseIfIdle(runtime, serverName, oauthState, authStorageOptions);
6103
6412
  } catch (cleanupError) {
6104
6413
  if (caughtError !== void 0) {
6105
6414
  throw new AggregateError([caughtError, cleanupError], "OAuth completion cleanup failed");
@@ -6171,7 +6480,7 @@ ${authorizationUrl}`);
6171
6480
  } catch (error) {
6172
6481
  if (oauthState) cancelPendingCallback(oauthState);
6173
6482
  try {
6174
- await clearPendingAuth(runtime, serverName, oauthState, authStorageOptions);
6483
+ await clearPendingAuthAndReleaseIfIdle(runtime, serverName, oauthState, authStorageOptions);
6175
6484
  } catch (cleanupError) {
6176
6485
  throw new AggregateError([error, cleanupError], "OAuth cancellation cleanup failed");
6177
6486
  }
@@ -6197,7 +6506,7 @@ async function removeAuth(serverName, options = {}) {
6197
6506
  if (oauthState) {
6198
6507
  cancelPendingCallback(oauthState);
6199
6508
  }
6200
- await clearPendingAuth(runtime, serverName, oauthState, authStorageOptions);
6509
+ await clearPendingAuthAndReleaseIfIdle(runtime, serverName, oauthState, authStorageOptions);
6201
6510
  throwIfAborted(signal);
6202
6511
  clearAllCredentials(serverName, authStorageOptions);
6203
6512
  await clearOAuthState(serverName, authStorageOptions);
@@ -6230,6 +6539,87 @@ async function shutdownOAuth(runtime = legacyRuntime) {
6230
6539
 
6231
6540
  // packages/coding-agent/src/humain/mcp-adapter/vendor/lifecycle.ts
6232
6541
  init_utils();
6542
+
6543
+ // packages/coding-agent/src/humain/mcp-adapter/vendor/session-recovery.ts
6544
+ import { ProtocolError, SdkHttpError, UnauthorizedError as UnauthorizedError3 } from "@modelcontextprotocol/client";
6545
+ init_types();
6546
+ var CONNECTION_CLOSED_PROTOCOL_CODE = -32e3;
6547
+ var SERVER_NOT_INITIALIZED_MCP_MESSAGES = /* @__PURE__ */ new Set([
6548
+ "Server not initialized",
6549
+ "Bad Request: Server not initialized"
6550
+ ]);
6551
+ function isTerminatedSession(err, hadSessionId) {
6552
+ if (!hadSessionId) return false;
6553
+ if (err instanceof SdkHttpError) {
6554
+ return err.status === 404 || err.status === 400 && /"code"\s*:\s*-32000/.test(err.message) && /"message"\s*:\s*"Bad Request: Server not initialized"/.test(err.message);
6555
+ }
6556
+ return err instanceof ProtocolError && err.code === CONNECTION_CLOSED_PROTOCOL_CODE && SERVER_NOT_INITIALIZED_MCP_MESSAGES.has(err.message);
6557
+ }
6558
+ function hasSessionId(connection) {
6559
+ const transport = connection.transport;
6560
+ return transport?.sessionId != null;
6561
+ }
6562
+ var SessionRecoveryAuthRequiredError = class extends Error {
6563
+ constructor(serverName, authMessage) {
6564
+ super(authMessage ?? `MCP server "${serverName}" requires OAuth authentication after reconnect.`);
6565
+ this.serverName = serverName;
6566
+ this.authMessage = authMessage;
6567
+ this.name = "SessionRecoveryAuthRequiredError";
6568
+ }
6569
+ };
6570
+ async function withSessionRecovery(deps, serverName, fn) {
6571
+ if (isServerDisabled(deps.config.mcpServers[serverName])) {
6572
+ throw new Error(`MCP server "${serverName}" is disabled`);
6573
+ }
6574
+ const connection = deps.manager.getConnection(serverName);
6575
+ if (!connection) {
6576
+ throw new Error(`Server "${serverName}" is not connected`);
6577
+ }
6578
+ const hadSessionId = hasSessionId(connection);
6579
+ try {
6580
+ return await fn(connection);
6581
+ } catch (err) {
6582
+ const definition = deps.config.mcpServers[serverName];
6583
+ if (definition && supportsOAuth(definition) && (err instanceof UnauthorizedError3 || err instanceof SdkHttpError && err.status === 401)) {
6584
+ invalidateAuthEntryCache(serverName);
6585
+ }
6586
+ if (!isTerminatedSession(err, hadSessionId)) {
6587
+ throw err;
6588
+ }
6589
+ if (!definition) {
6590
+ throw err;
6591
+ }
6592
+ throwIfAborted(deps.signal);
6593
+ logger.debug(`MCP session for "${serverName}" expired; reconnecting`, {
6594
+ server: serverName
6595
+ });
6596
+ let freshConnection = deps.signal ? await deps.manager.reconnect(serverName, definition, connection, deps.signal) : await deps.manager.reconnect(serverName, definition, connection);
6597
+ throwIfAborted(deps.signal);
6598
+ if (freshConnection.status === "needs-auth") {
6599
+ freshConnection = await deps.onNeedsAuth?.(serverName) ?? freshConnection;
6600
+ throwIfAborted(deps.signal);
6601
+ }
6602
+ if (freshConnection.status === "needs-auth") {
6603
+ throw new SessionRecoveryAuthRequiredError(serverName);
6604
+ }
6605
+ if (freshConnection.status !== "connected") {
6606
+ throw err;
6607
+ }
6608
+ try {
6609
+ deps.manager.publishMetadataChanged(serverName, freshConnection, "session-reconnect");
6610
+ } catch (publicationError) {
6611
+ const message = publicationError instanceof Error ? publicationError.message : String(publicationError);
6612
+ logger.debug(`MCP metadata publication after reconnect failed for "${serverName}": ${message}`);
6613
+ }
6614
+ throwIfAborted(deps.signal);
6615
+ return fn(freshConnection);
6616
+ }
6617
+ }
6618
+
6619
+ // packages/coding-agent/src/humain/mcp-adapter/vendor/lifecycle.ts
6620
+ var KEEP_ALIVE_RETRY_BASE_MS = 3e4;
6621
+ var KEEP_ALIVE_RETRY_MAX_MS = 5 * 6e4;
6622
+ var KEEP_ALIVE_CHECK_CONCURRENCY = 10;
6233
6623
  var McpLifecycleManager = class {
6234
6624
  constructor(manager, hasPendingAuthForServer = hasPendingAuth) {
6235
6625
  this.manager = manager;
@@ -6238,6 +6628,8 @@ var McpLifecycleManager = class {
6238
6628
  this.allServers = /* @__PURE__ */ new Map();
6239
6629
  this.serverSettings = /* @__PURE__ */ new Map();
6240
6630
  this.globalIdleTimeout = 10 * 60 * 1e3;
6631
+ this.retryStates = /* @__PURE__ */ new Map();
6632
+ this.pendingMetadataPublications = /* @__PURE__ */ new Set();
6241
6633
  this.stopped = false;
6242
6634
  }
6243
6635
  setReconnectCallback(callback) {
@@ -6246,6 +6638,12 @@ var McpLifecycleManager = class {
6246
6638
  setReconnectFailureCallback(callback) {
6247
6639
  this.onReconnectFailure = callback;
6248
6640
  }
6641
+ setHealthRestoredCallback(callback) {
6642
+ this.onHealthRestored = callback;
6643
+ }
6644
+ setAuthRequiredCallback(callback) {
6645
+ this.onAuthRequired = callback;
6646
+ }
6249
6647
  markKeepAlive(name, definition) {
6250
6648
  if (isServerDisabled(definition)) return;
6251
6649
  this.keepAliveServers.set(name, definition);
@@ -6255,6 +6653,13 @@ var McpLifecycleManager = class {
6255
6653
  this.allServers.set(name, definition);
6256
6654
  if (settings?.idleTimeout !== void 0) this.serverSettings.set(name, settings);
6257
6655
  }
6656
+ unregisterServer(name) {
6657
+ this.allServers.delete(name);
6658
+ this.keepAliveServers.delete(name);
6659
+ this.serverSettings.delete(name);
6660
+ this.retryStates.delete(name);
6661
+ this.pendingMetadataPublications.delete(name);
6662
+ }
6258
6663
  setGlobalIdleTimeout(minutes) {
6259
6664
  this.globalIdleTimeout = minutes * 60 * 1e3;
6260
6665
  }
@@ -6287,29 +6692,21 @@ var McpLifecycleManager = class {
6287
6692
  }, intervalMs);
6288
6693
  this.healthCheckInterval.unref();
6289
6694
  }
6290
- async checkConnections(signal) {
6695
+ async ensureConverged(signal) {
6291
6696
  if (this.stopped || signal?.aborted) return;
6292
- for (const [name, definition] of this.keepAliveServers) {
6293
- if (isServerDisabled(definition)) continue;
6294
- const connection = this.manager.getConnection(name);
6295
- if (!connection || connection.status !== "connected") {
6296
- if (this.hasPendingAuthForServer(name)) {
6297
- logger.debug(`Skipping reconnect for ${name} while OAuth authorization is pending`);
6298
- continue;
6299
- }
6300
- try {
6301
- await this.manager.connect(name, definition, signal);
6302
- if (this.stopped || signal?.aborted) return;
6303
- logger.debug(`Reconnected to ${name}`);
6304
- this.onReconnect?.(name);
6305
- } catch (error) {
6306
- if (this.stopped || signal?.aborted) return;
6307
- this.onReconnectFailure?.(name, error);
6308
- const message = error instanceof Error ? error.message : String(error);
6309
- console.error(`MCP: Failed to reconnect to ${name}: ${sanitizeTerminalText(message)}`);
6310
- }
6311
- }
6697
+ if (this.activeConvergence) return this.activeConvergence;
6698
+ const check = this.checkKeepAliveConnections(signal);
6699
+ this.activeConvergence = check;
6700
+ try {
6701
+ await check;
6702
+ } finally {
6703
+ if (this.activeConvergence === check) this.activeConvergence = void 0;
6312
6704
  }
6705
+ }
6706
+ async checkConnections(signal) {
6707
+ if (this.stopped || signal?.aborted) return;
6708
+ await this.ensureConverged(signal);
6709
+ if (this.stopped || signal?.aborted) return;
6313
6710
  for (const [name] of this.allServers) {
6314
6711
  if (this.keepAliveServers.has(name)) continue;
6315
6712
  const timeout = this.getIdleTimeout(name);
@@ -6320,6 +6717,202 @@ var McpLifecycleManager = class {
6320
6717
  }
6321
6718
  }
6322
6719
  }
6720
+ async checkKeepAliveConnections(signal) {
6721
+ if (this.stopped || signal?.aborted) return;
6722
+ await parallelLimit(
6723
+ [...this.keepAliveServers],
6724
+ KEEP_ALIVE_CHECK_CONCURRENCY,
6725
+ ([name, definition]) => this.checkKeepAliveConnection(name, definition, signal)
6726
+ );
6727
+ }
6728
+ async checkKeepAliveConnection(name, definition, signal, retrySuperseded = true) {
6729
+ if (isServerDisabled(definition) || this.stopped || signal?.aborted) return;
6730
+ if (this.keepAliveServers.get(name) !== definition) return;
6731
+ const connection = this.manager.getConnection(name);
6732
+ if (connection?.status === "needs-auth") {
6733
+ this.pendingMetadataPublications.delete(name);
6734
+ return;
6735
+ }
6736
+ if (!this.shouldAttemptConnection(name, connection)) return;
6737
+ if (!connection || connection.status !== "connected") {
6738
+ if (this.hasPendingAuthForServer(name)) {
6739
+ logger.debug(`Skipping reconnect for ${name} while OAuth authorization is pending`);
6740
+ return;
6741
+ }
6742
+ let freshConnection;
6743
+ try {
6744
+ freshConnection = await this.manager.connect(name, definition, signal);
6745
+ } catch (error) {
6746
+ if (this.stopped || signal?.aborted) return;
6747
+ this.reportConnectionFailure(name, definition, error, "reconnect", this.manager.getConnection(name));
6748
+ return;
6749
+ }
6750
+ if (this.stopped || signal?.aborted) return;
6751
+ if (freshConnection.status === "needs-auth") {
6752
+ await this.notifyAuthRequired(name, definition, freshConnection);
6753
+ return;
6754
+ }
6755
+ if (freshConnection.status !== "connected") {
6756
+ this.reportConnectionFailure(
6757
+ name,
6758
+ definition,
6759
+ new Error(`MCP server ${name} did not return a connected session`),
6760
+ "reconnect",
6761
+ freshConnection
6762
+ );
6763
+ return;
6764
+ }
6765
+ logger.debug(`Reconnected to ${name}`);
6766
+ await this.publishConnectedMetadata(name, definition, freshConnection);
6767
+ return;
6768
+ }
6769
+ if (this.pendingMetadataPublications.has(name)) {
6770
+ await this.publishConnectedMetadata(name, definition, connection);
6771
+ return;
6772
+ }
6773
+ if (!definition.url) return;
6774
+ const hadSessionId = connection.transport?.sessionId != null;
6775
+ let refreshResult;
6776
+ try {
6777
+ refreshResult = await this.manager.refreshTools(name, connection, signal);
6778
+ } catch (error) {
6779
+ if (this.stopped || signal?.aborted) return;
6780
+ const current = this.manager.getConnection(name);
6781
+ if (current !== connection || connection.status !== "connected") {
6782
+ await this.handleSupersededConnection(name, definition, connection, signal, retrySuperseded);
6783
+ return;
6784
+ }
6785
+ if (!shouldReconnectAfterRefresh(error, hadSessionId)) {
6786
+ this.reportConnectionFailure(name, definition, error, "refresh", connection);
6787
+ return;
6788
+ }
6789
+ if (this.hasPendingAuthForServer(name)) {
6790
+ logger.debug(`Skipping reconnect for ${name} while OAuth authorization is pending`);
6791
+ return;
6792
+ }
6793
+ let freshConnection;
6794
+ try {
6795
+ freshConnection = await this.manager.reconnect(name, definition, connection, signal);
6796
+ } catch (reconnectError) {
6797
+ if (this.stopped || signal?.aborted) return;
6798
+ this.reportConnectionFailure(name, definition, reconnectError, "reconnect", this.manager.getConnection(name));
6799
+ return;
6800
+ }
6801
+ if (this.stopped || signal?.aborted) return;
6802
+ if (freshConnection.status === "needs-auth") {
6803
+ await this.notifyAuthRequired(name, definition, freshConnection);
6804
+ return;
6805
+ }
6806
+ if (freshConnection.status !== "connected") {
6807
+ this.reportConnectionFailure(
6808
+ name,
6809
+ definition,
6810
+ new Error(`MCP server ${name} did not return a connected session`),
6811
+ "reconnect",
6812
+ freshConnection
6813
+ );
6814
+ return;
6815
+ }
6816
+ logger.debug(`Reconnected stale MCP session for ${name}`);
6817
+ await this.publishConnectedMetadata(name, definition, freshConnection);
6818
+ return;
6819
+ }
6820
+ if (refreshResult === "superseded") {
6821
+ await this.handleSupersededConnection(name, definition, connection, signal, retrySuperseded);
6822
+ return;
6823
+ }
6824
+ if (refreshResult === "refresh-timeout") {
6825
+ this.deferRefreshTimeout(name, definition, connection);
6826
+ return;
6827
+ }
6828
+ if (this.keepAliveServers.get(name) !== definition) return;
6829
+ if (this.retryStates.delete(name)) {
6830
+ await this.onHealthRestored?.(name);
6831
+ }
6832
+ }
6833
+ async handleSupersededConnection(name, definition, staleConnection, signal, retrySuperseded) {
6834
+ const current = this.manager.getConnection(name);
6835
+ if (this.keepAliveServers.get(name) !== definition) return;
6836
+ if (current === staleConnection && current.status === "connected") {
6837
+ if (this.retryStates.delete(name)) await this.onHealthRestored?.(name);
6838
+ return;
6839
+ }
6840
+ if (current?.status === "connected") {
6841
+ await this.publishConnectedMetadata(name, definition, current);
6842
+ return;
6843
+ }
6844
+ if (current?.status === "needs-auth") {
6845
+ await this.notifyAuthRequired(name, definition, current);
6846
+ return;
6847
+ }
6848
+ if (retrySuperseded) {
6849
+ await this.checkKeepAliveConnection(name, definition, signal, false);
6850
+ }
6851
+ }
6852
+ async publishConnectedMetadata(name, definition, connection) {
6853
+ if (this.keepAliveServers.get(name) !== definition) {
6854
+ if (this.manager.getConnection(name) === connection) await this.manager.close(name);
6855
+ return;
6856
+ }
6857
+ this.pendingMetadataPublications.add(name);
6858
+ try {
6859
+ await this.onReconnect?.(name);
6860
+ this.pendingMetadataPublications.delete(name);
6861
+ this.retryStates.delete(name);
6862
+ } catch (error) {
6863
+ if (this.stopped) return;
6864
+ this.reportConnectionFailure(name, definition, error, "publish", connection);
6865
+ }
6866
+ }
6867
+ async notifyAuthRequired(name, definition, connection) {
6868
+ if (this.keepAliveServers.get(name) !== definition) {
6869
+ if (this.manager.getConnection(name) === connection) await this.manager.close(name);
6870
+ return;
6871
+ }
6872
+ this.pendingMetadataPublications.delete(name);
6873
+ this.retryStates.delete(name);
6874
+ try {
6875
+ await this.onAuthRequired?.(name);
6876
+ } catch (error) {
6877
+ const message = error instanceof Error ? error.message : String(error);
6878
+ logger.debug(`MCP: auth-required callback failed for ${name}: ${sanitizeTerminalText(message)}`);
6879
+ }
6880
+ }
6881
+ shouldAttemptConnection(name, connection) {
6882
+ const retry = this.retryStates.get(name);
6883
+ if (!retry) return true;
6884
+ if (retry.connection !== connection || retry.status !== connection?.status) {
6885
+ this.retryStates.delete(name);
6886
+ return true;
6887
+ }
6888
+ return Date.now() >= retry.nextAttemptAt;
6889
+ }
6890
+ reportConnectionFailure(name, definition, error, action, connection) {
6891
+ if (!this.recordRetry(name, definition, connection)) return;
6892
+ this.onReconnectFailure?.(name, error);
6893
+ const message = error instanceof Error ? error.message : String(error);
6894
+ const target = action === "reconnect" ? `reconnect to ${name}` : action === "publish" ? `publish metadata for ${name}` : `refresh ${name}`;
6895
+ console.error(`MCP: Failed to ${target}: ${sanitizeTerminalText(message)}`);
6896
+ }
6897
+ deferRefreshTimeout(name, definition, connection) {
6898
+ if (!this.recordRetry(name, definition, connection)) return;
6899
+ logger.debug(`MCP: keep-alive tools/list refresh timed out for ${name}; retrying after backoff`);
6900
+ }
6901
+ recordRetry(name, definition, connection) {
6902
+ if (this.keepAliveServers.get(name) !== definition) return false;
6903
+ const attempts = (this.retryStates.get(name)?.attempts ?? 0) + 1;
6904
+ const delay = Math.min(
6905
+ KEEP_ALIVE_RETRY_BASE_MS * 2 ** Math.min(attempts - 1, 10),
6906
+ KEEP_ALIVE_RETRY_MAX_MS
6907
+ );
6908
+ this.retryStates.set(name, {
6909
+ attempts,
6910
+ nextAttemptAt: Date.now() + delay,
6911
+ connection,
6912
+ status: connection?.status
6913
+ });
6914
+ return true;
6915
+ }
6323
6916
  getIdleTimeout(name) {
6324
6917
  const perServer = this.serverSettings.get(name)?.idleTimeout;
6325
6918
  if (perServer !== void 0) return perServer * 60 * 1e3;
@@ -6338,26 +6931,39 @@ var McpLifecycleManager = class {
6338
6931
  this.removeHealthAbortListener = void 0;
6339
6932
  await this.activeHealthCheck;
6340
6933
  this.activeHealthCheck = void 0;
6934
+ await this.activeConvergence;
6935
+ this.activeConvergence = void 0;
6341
6936
  this.onReconnect = void 0;
6342
6937
  this.onReconnectFailure = void 0;
6938
+ this.onHealthRestored = void 0;
6939
+ this.onAuthRequired = void 0;
6343
6940
  this.onIdleShutdown = void 0;
6941
+ this.retryStates.clear();
6942
+ this.pendingMetadataPublications.clear();
6344
6943
  if (typeof this.manager.closeAll === "function") {
6345
6944
  await this.manager.closeAll();
6346
6945
  }
6347
6946
  }
6348
6947
  };
6948
+ function shouldReconnectAfterRefresh(error, hadSessionId) {
6949
+ if (isTerminatedSession(error, hadSessionId)) return true;
6950
+ return error instanceof SdkError && (error.code === SdkErrorCode.NotConnected || error.code === SdkErrorCode.ConnectionClosed);
6951
+ }
6349
6952
 
6350
6953
  // packages/coding-agent/src/humain/mcp-adapter/vendor/init.ts
6351
6954
  init_metadata_cache();
6352
6955
 
6353
6956
  // packages/coding-agent/src/humain/mcp-adapter/vendor/server-manager.ts
6354
6957
  import { mkdirSync as mkdirSync4 } from "node:fs";
6958
+ import { isDeepStrictEqual } from "node:util";
6355
6959
  import {
6356
6960
  Client,
6357
- SdkHttpError,
6961
+ SdkError as SdkError2,
6962
+ SdkErrorCode as SdkErrorCode2,
6963
+ SdkHttpError as SdkHttpError2,
6358
6964
  SSEClientTransport,
6359
6965
  StreamableHTTPClientTransport,
6360
- UnauthorizedError as UnauthorizedError3
6966
+ UnauthorizedError as UnauthorizedError4
6361
6967
  } from "@modelcontextprotocol/client";
6362
6968
  import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";
6363
6969
 
@@ -6373,13 +6979,13 @@ var UnixSocketClientTransport = class {
6373
6979
  if (this.socket) {
6374
6980
  throw new Error("UnixSocketClientTransport already started");
6375
6981
  }
6376
- await new Promise((resolve6, reject) => {
6982
+ await new Promise((resolve7, reject) => {
6377
6983
  const socket = createConnection(this.socketPath);
6378
6984
  this.socket = socket;
6379
6985
  let connected = false;
6380
6986
  socket.once("connect", () => {
6381
6987
  connected = true;
6382
- resolve6();
6988
+ resolve7();
6383
6989
  });
6384
6990
  socket.on("data", (chunk) => {
6385
6991
  try {
@@ -6411,12 +7017,12 @@ var UnixSocketClientTransport = class {
6411
7017
  this.socket = void 0;
6412
7018
  this.readBuffer.clear();
6413
7019
  if (!socket || socket.destroyed) return;
6414
- await new Promise((resolve6) => {
7020
+ await new Promise((resolve7) => {
6415
7021
  const timeout = setTimeout(() => socket.destroy(), 2e3);
6416
7022
  timeout.unref();
6417
7023
  socket.once("close", () => {
6418
7024
  clearTimeout(timeout);
6419
- resolve6();
7025
+ resolve7();
6420
7026
  });
6421
7027
  socket.end();
6422
7028
  });
@@ -6424,10 +7030,10 @@ var UnixSocketClientTransport = class {
6424
7030
  async send(message) {
6425
7031
  const socket = this.socket;
6426
7032
  if (!socket || socket.destroyed) throw new Error("Unix socket is not connected");
6427
- await new Promise((resolve6, reject) => {
7033
+ await new Promise((resolve7, reject) => {
6428
7034
  socket.write(serializeMessage(message), (error) => {
6429
7035
  if (error) reject(error);
6430
- else resolve6();
7036
+ else resolve7();
6431
7037
  });
6432
7038
  });
6433
7039
  }
@@ -6578,8 +7184,8 @@ init_types();
6578
7184
 
6579
7185
  // packages/coding-agent/src/humain/mcp-adapter/vendor/npx-resolver.ts
6580
7186
  init_agent_dir();
6581
- import { existsSync as existsSync5, readFileSync as readFileSync6, realpathSync, readdirSync, statSync as statSync2, writeFileSync as writeFileSync3, renameSync as renameSync3, mkdirSync as mkdirSync3, openSync, readSync, closeSync, unlinkSync } from "node:fs";
6582
- import { join as join5, dirname as dirname4, extname as extname2, resolve as resolve4, sep as sep2 } from "node:path";
7187
+ import { existsSync as existsSync6, readFileSync as readFileSync7, realpathSync as realpathSync2, readdirSync, statSync as statSync3, writeFileSync as writeFileSync3, renameSync as renameSync3, mkdirSync as mkdirSync3, openSync, readSync, closeSync, unlinkSync } from "node:fs";
7188
+ import { join as join6, dirname as dirname4, extname as extname2, resolve as resolve5, sep as sep3 } from "node:path";
6583
7189
  import crossSpawn from "cross-spawn";
6584
7190
  var CACHE_VERSION2 = 2;
6585
7191
  var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
@@ -6592,7 +7198,7 @@ async function resolveNpxBinary(command, args, signal) {
6592
7198
  const cacheKey = JSON.stringify([command, parsed.packageSpec, parsed.binName ?? ""]);
6593
7199
  const cache = loadCache();
6594
7200
  const cached = cache?.entries?.[cacheKey];
6595
- if (cached && Date.now() - cached.resolvedAt < CACHE_TTL_MS && existsSync5(cached.resolvedBin) && (!packageSpec?.exactVersion || cached.packageVersion === packageSpec.exactVersion)) {
7201
+ if (cached && Date.now() - cached.resolvedAt < CACHE_TTL_MS && existsSync6(cached.resolvedBin) && (!packageSpec?.exactVersion || cached.packageVersion === packageSpec.exactVersion)) {
6596
7202
  return { binPath: cached.resolvedBin, extraArgs: parsed.extraArgs, isJs: cached.isJs };
6597
7203
  }
6598
7204
  const resolved = resolveFromNpmCache(parsed.packageSpec, parsed.binName);
@@ -6699,11 +7305,11 @@ function resolveFromNpmCache(packageSpec, binName) {
6699
7305
  const { packageName, exactVersion } = parsedSpec;
6700
7306
  const packageDir = findCachedPackageDir(cacheDir, packageName, exactVersion);
6701
7307
  if (!packageDir) return null;
6702
- const packageJsonPath = join5(packageDir, "package.json");
6703
- if (!existsSync5(packageJsonPath)) return null;
7308
+ const packageJsonPath = join6(packageDir, "package.json");
7309
+ if (!existsSync6(packageJsonPath)) return null;
6704
7310
  let pkg = null;
6705
7311
  try {
6706
- pkg = JSON.parse(readFileSync6(packageJsonPath, "utf-8"));
7312
+ pkg = JSON.parse(readFileSync7(packageJsonPath, "utf-8"));
6707
7313
  } catch {
6708
7314
  return null;
6709
7315
  }
@@ -6733,11 +7339,11 @@ function resolveFromNpmCache(packageSpec, binName) {
6733
7339
  }
6734
7340
  if (!binRel) return null;
6735
7341
  const nodeModulesDir = findNodeModulesDir(packageDir);
6736
- const binLink = chosenBinName ? join5(nodeModulesDir, ".bin", chosenBinName) : null;
6737
- let resolvedBin = binLink && existsSync5(binLink) ? safeRealpath(binLink) : "";
7342
+ const binLink = chosenBinName ? join6(nodeModulesDir, ".bin", chosenBinName) : null;
7343
+ let resolvedBin = binLink && existsSync6(binLink) ? safeRealpath(binLink) : "";
6738
7344
  if (!resolvedBin) {
6739
- resolvedBin = resolve4(packageDir, binRel);
6740
- if (!existsSync5(resolvedBin)) return null;
7345
+ resolvedBin = resolve5(packageDir, binRel);
7346
+ if (!existsSync6(resolvedBin)) return null;
6741
7347
  }
6742
7348
  const isJs = detectJsBinary(resolvedBin);
6743
7349
  return {
@@ -6751,7 +7357,7 @@ var FORCE_CACHE_TIMEOUT_MS = 3e4;
6751
7357
  async function forceNpxCache(packageSpec, signal) {
6752
7358
  throwIfAborted(signal);
6753
7359
  try {
6754
- await new Promise((resolve6, reject) => {
7360
+ await new Promise((resolve7, reject) => {
6755
7361
  const proc = crossSpawn(
6756
7362
  "npm",
6757
7363
  ["exec", "--yes", "--package", packageSpec, "--", "node", "-e", "1"],
@@ -6770,7 +7376,7 @@ async function forceNpxCache(packageSpec, signal) {
6770
7376
  proc.on("close", () => {
6771
7377
  clearTimeout(timer);
6772
7378
  signal?.removeEventListener("abort", abort);
6773
- resolve6();
7379
+ resolve7();
6774
7380
  });
6775
7381
  proc.on("error", (err) => {
6776
7382
  clearTimeout(timer);
@@ -6835,21 +7441,21 @@ function defaultBinName(packageName) {
6835
7441
  return packageName;
6836
7442
  }
6837
7443
  function findCachedPackageDir(cacheDir, packageName, exactVersion) {
6838
- const npxDir = join5(cacheDir, "_npx");
6839
- if (!existsSync5(npxDir)) return null;
7444
+ const npxDir = join6(cacheDir, "_npx");
7445
+ if (!existsSync6(npxDir)) return null;
6840
7446
  const packagePathParts = packageName.startsWith("@") ? packageName.split("/") : [packageName];
6841
7447
  const candidates = readdirSync(npxDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => {
6842
- const full = join5(npxDir, entry.name);
7448
+ const full = join6(npxDir, entry.name);
6843
7449
  const mtime = safeStatMtime(full);
6844
7450
  return { name: entry.name, mtime };
6845
7451
  }).sort((a, b) => b.mtime - a.mtime);
6846
7452
  for (const entry of candidates) {
6847
- const pkgDir = join5(npxDir, entry.name, "node_modules", ...packagePathParts);
6848
- const packageJsonPath = join5(pkgDir, "package.json");
6849
- if (!existsSync5(packageJsonPath)) continue;
7453
+ const pkgDir = join6(npxDir, entry.name, "node_modules", ...packagePathParts);
7454
+ const packageJsonPath = join6(pkgDir, "package.json");
7455
+ if (!existsSync6(packageJsonPath)) continue;
6850
7456
  if (exactVersion) {
6851
7457
  try {
6852
- const pkg = JSON.parse(readFileSync6(packageJsonPath, "utf-8"));
7458
+ const pkg = JSON.parse(readFileSync7(packageJsonPath, "utf-8"));
6853
7459
  if (pkg.version !== exactVersion) continue;
6854
7460
  } catch {
6855
7461
  continue;
@@ -6860,12 +7466,12 @@ function findCachedPackageDir(cacheDir, packageName, exactVersion) {
6860
7466
  return null;
6861
7467
  }
6862
7468
  function findNodeModulesDir(packageDir) {
6863
- const parts = packageDir.split(sep2);
7469
+ const parts = packageDir.split(sep3);
6864
7470
  const idx = parts.lastIndexOf("node_modules");
6865
7471
  if (idx >= 0) {
6866
- return parts.slice(0, idx + 1).join(sep2);
7472
+ return parts.slice(0, idx + 1).join(sep3);
6867
7473
  }
6868
- return join5(packageDir, "..");
7474
+ return join6(packageDir, "..");
6869
7475
  }
6870
7476
  function detectJsBinary(binPath) {
6871
7477
  const ext = extname2(binPath).toLowerCase();
@@ -6909,9 +7515,9 @@ function getNpxCachePath() {
6909
7515
  return getAgentPath("mcp-npx-cache.json");
6910
7516
  }
6911
7517
  function readNpxCachePayload(cachePath) {
6912
- if (!existsSync5(cachePath)) return null;
7518
+ if (!existsSync6(cachePath)) return null;
6913
7519
  try {
6914
- return JSON.parse(readFileSync6(cachePath, "utf-8"));
7520
+ return JSON.parse(readFileSync7(cachePath, "utf-8"));
6915
7521
  } catch {
6916
7522
  return null;
6917
7523
  }
@@ -6985,14 +7591,14 @@ function saveCacheEntry(key, entry) {
6985
7591
  }
6986
7592
  function safeRealpath(path2) {
6987
7593
  try {
6988
- return realpathSync(path2);
7594
+ return realpathSync2(path2);
6989
7595
  } catch {
6990
7596
  return "";
6991
7597
  }
6992
7598
  }
6993
7599
  function safeStatMtime(path2) {
6994
7600
  try {
6995
- return statSync2(path2).mtimeMs;
7601
+ return statSync3(path2).mtimeMs;
6996
7602
  } catch {
6997
7603
  return 0;
6998
7604
  }
@@ -7053,6 +7659,245 @@ function createJsonSchemaValidator() {
7053
7659
  };
7054
7660
  }
7055
7661
 
7662
+ // packages/coding-agent/src/humain/mcp-adapter/vendor/mcp-bearer-store.ts
7663
+ import { createHash as createHash3 } from "node:crypto";
7664
+ import { createRequire as createRequire2 } from "node:module";
7665
+ import { dirname as dirname5, join as join7 } from "node:path";
7666
+ var require3 = createRequire2(import.meta.url);
7667
+ var BEARER_SECRET_SERVICE = "pi-mcp-adapter.bearer";
7668
+ var TEST_AUTH_STORE_ENV2 = "PI_MCP_ADAPTER_TEST_AUTH_STORE";
7669
+ var BEARER_SECRET_VALUE_LIMIT = 1280;
7670
+ var KeyringEntryClass2;
7671
+ var memoryBearerEntries = /* @__PURE__ */ new Map();
7672
+ var testBearerSecretStoreReadCount = 0;
7673
+ var BearerCredentialStoreError = class extends Error {
7674
+ // No parameter properties: cli.js loads this module under plain Node
7675
+ // type stripping, which rejects non-erasable TypeScript syntax.
7676
+ constructor(message, operation, cause) {
7677
+ super(message, { cause });
7678
+ this.code = "BEARER_CREDENTIAL_STORE_UNAVAILABLE";
7679
+ this.name = "BearerCredentialStoreError";
7680
+ this.operation = operation;
7681
+ }
7682
+ };
7683
+ var memoryBearerSecretStore = {
7684
+ read(account) {
7685
+ testBearerSecretStoreReadCount++;
7686
+ return memoryBearerEntries.get(account);
7687
+ },
7688
+ write(account, payload) {
7689
+ memoryBearerEntries.set(account, payload);
7690
+ },
7691
+ remove(account) {
7692
+ memoryBearerEntries.delete(account);
7693
+ }
7694
+ };
7695
+ var sizeLimitedBearerSecretStore = {
7696
+ read(account) {
7697
+ testBearerSecretStoreReadCount++;
7698
+ return memoryBearerEntries.get(account);
7699
+ },
7700
+ write(account, payload) {
7701
+ if (payload.length > BEARER_SECRET_VALUE_LIMIT) {
7702
+ throw new Error(`Value of 'password encoded as UTF-16' is longer than the platform limit of ${BEARER_SECRET_VALUE_LIMIT * 2} chars`);
7703
+ }
7704
+ memoryBearerEntries.set(account, payload);
7705
+ },
7706
+ remove(account) {
7707
+ memoryBearerEntries.delete(account);
7708
+ }
7709
+ };
7710
+ var unavailableBearerSecretStore = {
7711
+ read() {
7712
+ testBearerSecretStoreReadCount++;
7713
+ throw new Error("simulated secure credential store unavailable");
7714
+ },
7715
+ write() {
7716
+ throw new Error("simulated secure credential store unavailable");
7717
+ },
7718
+ remove() {
7719
+ throw new Error("simulated secure credential store unavailable");
7720
+ }
7721
+ };
7722
+ var keyringBearerSecretStore = {
7723
+ read(account) {
7724
+ return getKeyringEntry2(account).getPassword() ?? void 0;
7725
+ },
7726
+ write(account, payload) {
7727
+ getKeyringEntry2(account).setPassword(payload);
7728
+ },
7729
+ remove(account) {
7730
+ getKeyringEntry2(account).deleteCredential();
7731
+ }
7732
+ };
7733
+ function getBearerSecretStore() {
7734
+ if (process.env[TEST_AUTH_STORE_ENV2] === "memory") return memoryBearerSecretStore;
7735
+ if (process.env[TEST_AUTH_STORE_ENV2] === "sizelimited") return sizeLimitedBearerSecretStore;
7736
+ if (process.env[TEST_AUTH_STORE_ENV2] === "unavailable") return unavailableBearerSecretStore;
7737
+ return keyringBearerSecretStore;
7738
+ }
7739
+ function getKeyringEntry2(account) {
7740
+ try {
7741
+ KeyringEntryClass2 ??= loadKeyringEntryClass2();
7742
+ return new KeyringEntryClass2(BEARER_SECRET_SERVICE, account);
7743
+ } catch (error) {
7744
+ throw new Error("Bearer token secure credential storage is unavailable. Configure the OS credential store and retry.", { cause: error });
7745
+ }
7746
+ }
7747
+ function loadKeyringEntryClass2(keyringRequire = require3, platform4 = process.platform, arch = process.arch) {
7748
+ try {
7749
+ return keyringRequire("@napi-rs/keyring").Entry;
7750
+ } catch (loaderError) {
7751
+ try {
7752
+ return loadKeyringNativeBindingFallback2(keyringRequire, platform4, arch).Entry;
7753
+ } catch (fallbackError) {
7754
+ const message = fallbackError instanceof Error ? fallbackError.message : String(fallbackError);
7755
+ throw new Error(`Failed to load @napi-rs/keyring; absolute-path native binding fallback also failed: ${message}`, { cause: loaderError });
7756
+ }
7757
+ }
7758
+ }
7759
+ function loadKeyringNativeBindingFallback2(keyringRequire, platform4, arch) {
7760
+ const targets = getKeyringNativeBindingSuffixes2(platform4, arch).map((suffix) => ({
7761
+ packageName: `@napi-rs/keyring-${suffix}`,
7762
+ bindingFile: `keyring.${suffix}.node`
7763
+ }));
7764
+ let lastError;
7765
+ for (const target of targets) {
7766
+ try {
7767
+ const packageJsonPath = keyringRequire.resolve(`${target.packageName}/package.json`);
7768
+ return keyringRequire(join7(dirname5(packageJsonPath), target.bindingFile));
7769
+ } catch (error) {
7770
+ lastError = error;
7771
+ }
7772
+ }
7773
+ throw lastError instanceof Error ? lastError : new Error(String(lastError));
7774
+ }
7775
+ function getKeyringNativeBindingSuffixes2(platform4, arch) {
7776
+ if (platform4 === "darwin") {
7777
+ if (arch === "arm64") return ["darwin-arm64"];
7778
+ if (arch === "x64") return ["darwin-x64"];
7779
+ }
7780
+ if (platform4 === "win32") {
7781
+ if (arch === "arm64") return ["win32-arm64-msvc"];
7782
+ if (arch === "x64") return ["win32-x64-msvc"];
7783
+ if (arch === "ia32") return ["win32-ia32-msvc"];
7784
+ }
7785
+ if (platform4 === "linux") {
7786
+ if (arch === "arm64") return ["linux-arm64-gnu", "linux-arm64-musl"];
7787
+ if (arch === "arm") return ["linux-arm-gnueabihf"];
7788
+ if (arch === "riscv64") return ["linux-riscv64-gnu"];
7789
+ if (arch === "x64") return ["linux-x64-gnu", "linux-x64-musl"];
7790
+ }
7791
+ if (platform4 === "freebsd" && arch === "x64") return ["freebsd-x64"];
7792
+ return [];
7793
+ }
7794
+ function getBearerAccount(serverName) {
7795
+ if (typeof serverName !== "string") {
7796
+ throw new Error(`Invalid MCP server name: ${JSON.stringify(serverName)}`);
7797
+ }
7798
+ return `sha256-${createHash3("sha256").update(serverName, "utf8").digest("hex")}`;
7799
+ }
7800
+ function parseBearerPayload(serverName, payload) {
7801
+ const parsed = parseStoredBearerJson(serverName, payload);
7802
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
7803
+ throw new Error(`Stored bearer token record for ${serverName} has invalid shape`);
7804
+ }
7805
+ const record = parsed;
7806
+ if (typeof record.token !== "string" || typeof record.serverUrl !== "string") {
7807
+ throw new Error(`Stored bearer token record for ${serverName} has invalid shape`);
7808
+ }
7809
+ return { token: record.token, serverUrl: record.serverUrl };
7810
+ }
7811
+ function parseStoredBearerJson(serverName, payload) {
7812
+ try {
7813
+ return JSON.parse(payload);
7814
+ } catch {
7815
+ throw new Error(`Failed to parse stored bearer token record for ${serverName}`);
7816
+ }
7817
+ }
7818
+ function isBearerChunkManifest(value) {
7819
+ if (typeof value !== "object" || value === null) return false;
7820
+ const manifest = value;
7821
+ return manifest.__piMcpAdapterBearerChunked === 1 && typeof manifest.chunkCount === "number" && Number.isInteger(manifest.chunkCount) && manifest.chunkCount > 0 && typeof manifest.chunkDigest === "string" && /^[a-f0-9]{16}$/.test(manifest.chunkDigest);
7822
+ }
7823
+ function readManifest(serverName, payload) {
7824
+ const parsed = parseStoredBearerJson(serverName, payload);
7825
+ return isBearerChunkManifest(parsed) ? parsed : void 0;
7826
+ }
7827
+ function chunkAccount(account, manifest, index) {
7828
+ return `${account}.chunk.${manifest.chunkDigest}.${index}`;
7829
+ }
7830
+ function chunkAccounts(account, manifest) {
7831
+ return Array.from({ length: manifest.chunkCount }, (_, index) => chunkAccount(account, manifest, index));
7832
+ }
7833
+ function removeChunks(store, account, manifest) {
7834
+ if (!manifest) return;
7835
+ for (const accountName of chunkAccounts(account, manifest)) store.remove(accountName);
7836
+ }
7837
+ function readBearerRecordFromStore(store, serverName) {
7838
+ const account = getBearerAccount(serverName);
7839
+ let payload;
7840
+ try {
7841
+ payload = store.read(account);
7842
+ } catch (error) {
7843
+ throw new BearerCredentialStoreError(
7844
+ `Failed to read bearer token for ${serverName} from the OS secure credential store`,
7845
+ "read",
7846
+ error
7847
+ );
7848
+ }
7849
+ if (payload === void 0) return void 0;
7850
+ try {
7851
+ const manifest = readManifest(serverName, payload);
7852
+ const recordPayload = manifest ? chunkAccounts(account, manifest).map((chunkName) => {
7853
+ const chunk = store.read(chunkName);
7854
+ if (chunk === void 0) throw new Error(`Missing bearer token chunk for ${serverName}`);
7855
+ return chunk;
7856
+ }).join("") : payload;
7857
+ return parseBearerPayload(serverName, recordPayload);
7858
+ } catch (error) {
7859
+ throw new BearerCredentialStoreError(
7860
+ `Failed to read bearer token for ${serverName} from the OS secure credential store`,
7861
+ "read",
7862
+ error
7863
+ );
7864
+ }
7865
+ }
7866
+ function removeBearerRecordFromStore(store, serverName) {
7867
+ const account = getBearerAccount(serverName);
7868
+ try {
7869
+ const payload = store.read(account);
7870
+ const manifest = payload === void 0 ? void 0 : readManifest(serverName, payload);
7871
+ removeChunks(store, account, manifest);
7872
+ store.remove(account);
7873
+ } catch (error) {
7874
+ throw new BearerCredentialStoreError(
7875
+ `Failed to remove bearer token for ${serverName} from the OS secure credential store`,
7876
+ "remove",
7877
+ error
7878
+ );
7879
+ }
7880
+ }
7881
+ function getBearerTokenForUrl(serverName, serverUrl) {
7882
+ const record = readBearerRecordFromStore(getBearerSecretStore(), serverName);
7883
+ if (!record) return void 0;
7884
+ return record.serverUrl === serverUrl ? record.token : void 0;
7885
+ }
7886
+ function removeBearerToken(serverName) {
7887
+ removeBearerRecordFromStore(getBearerSecretStore(), serverName);
7888
+ }
7889
+ function inspectBearerTokenForUrl(serverName, serverUrl) {
7890
+ try {
7891
+ const record = readBearerRecordFromStore(getBearerSecretStore(), serverName);
7892
+ if (!record) return { status: "missing" };
7893
+ if (record.serverUrl !== serverUrl) return { status: "url-mismatch" };
7894
+ return { status: "present" };
7895
+ } catch (error) {
7896
+ if (!(error instanceof BearerCredentialStoreError)) throw error;
7897
+ return { status: "unavailable", message: "Bearer token secure credential store unavailable. Configure or unlock the OS credential store and retry." };
7898
+ }
7899
+ }
7900
+
7056
7901
  // packages/coding-agent/src/humain/mcp-adapter/vendor/sampling-handler.ts
7057
7902
  init_utils();
7058
7903
  import { complete } from "@earendil-works/pi-ai/compat";
@@ -7272,7 +8117,7 @@ function zeroUsage() {
7272
8117
 
7273
8118
  // packages/coding-agent/src/humain/mcp-adapter/vendor/elicitation-handler.ts
7274
8119
  import {
7275
- ProtocolError,
8120
+ ProtocolError as ProtocolError2,
7276
8121
  ProtocolErrorCode
7277
8122
  } from "@modelcontextprotocol/client";
7278
8123
  import { AjvJsonSchemaValidator as AjvJsonSchemaValidator2 } from "@modelcontextprotocol/client/validators/ajv";
@@ -7501,15 +8346,15 @@ function formatReview(serverName, properties, content) {
7501
8346
  return [`Review input for ${serverName}`, "", ...rows].join("\n");
7502
8347
  }
7503
8348
  async function handleUrlElicitation(options, params) {
7504
- if (!options.allowUrl) throw new ProtocolError(ProtocolErrorCode.InvalidParams, "URL elicitation is not supported");
8349
+ if (!options.allowUrl) throw new ProtocolError2(ProtocolErrorCode.InvalidParams, "URL elicitation is not supported");
7505
8350
  let parsed;
7506
8351
  try {
7507
8352
  parsed = new URL(params.url);
7508
8353
  } catch {
7509
- throw new ProtocolError(ProtocolErrorCode.InvalidParams, "URL elicitation supplied an invalid URL");
8354
+ throw new ProtocolError2(ProtocolErrorCode.InvalidParams, "URL elicitation supplied an invalid URL");
7510
8355
  }
7511
8356
  if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
7512
- throw new ProtocolError(ProtocolErrorCode.InvalidParams, "URL elicitation only supports HTTP and HTTPS URLs");
8357
+ throw new ProtocolError2(ProtocolErrorCode.InvalidParams, "URL elicitation only supports HTTP and HTTPS URLs");
7513
8358
  }
7514
8359
  const decision = await options.ui.select([
7515
8360
  "MCP Browser Request",
@@ -7544,7 +8389,7 @@ init_utils();
7544
8389
  // packages/coding-agent/src/humain/mcp-adapter/vendor/mcp-trace.ts
7545
8390
  import { appendFile, mkdir, writeFile } from "node:fs/promises";
7546
8391
  import { Buffer as Buffer2 } from "node:buffer";
7547
- import { dirname as dirname5, isAbsolute as isAbsolute3, resolve as resolve5 } from "node:path";
8392
+ import { dirname as dirname6, isAbsolute as isAbsolute4, resolve as resolve6 } from "node:path";
7548
8393
  var MCP_TRACE_SCHEMA_VERSION = 1;
7549
8394
  var DEFAULT_MCP_TRACE_MAX_BYTES = 256 * 1024;
7550
8395
  var DEFAULT_MCP_TRACE_MAX_EVENTS = 1e4;
@@ -7622,7 +8467,7 @@ var McpTraceWriter = class {
7622
8467
  await mkdir(path2, { recursive: true });
7623
8468
  return void 0;
7624
8469
  });
7625
- this.fileReady = this.makeDirectory(dirname5(this.options.filePath), { recursive: true }).then(() => this.resetFile(this.options.filePath, "", { encoding: "utf8" })).catch(() => {
8470
+ this.fileReady = this.makeDirectory(dirname6(this.options.filePath), { recursive: true }).then(() => this.resetFile(this.options.filePath, "", { encoding: "utf8" })).catch(() => {
7626
8471
  this.initializationFailed = true;
7627
8472
  this.disabled = true;
7628
8473
  });
@@ -7669,7 +8514,7 @@ var McpTraceWriter = class {
7669
8514
  function createMcpTraceWriter(sessionCwd, settings = {}, randomSuffix = Math.random().toString(36).slice(2, 10)) {
7670
8515
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
7671
8516
  const configuredPath = settings.file;
7672
- const filePath = configuredPath ? isAbsolute3(configuredPath) ? configuredPath : resolve5(sessionCwd ?? process.cwd(), configuredPath) : resolve5(sessionCwd ?? process.cwd(), ".pi", "mcp-traces", `mcp-${timestamp}-${randomSuffix}.jsonl`);
8517
+ const filePath = configuredPath ? isAbsolute4(configuredPath) ? configuredPath : resolve6(sessionCwd ?? process.cwd(), configuredPath) : resolve6(sessionCwd ?? process.cwd(), ".pi", "mcp-traces", `mcp-${timestamp}-${randomSuffix}.jsonl`);
7673
8518
  return new McpTraceWriter({
7674
8519
  filePath,
7675
8520
  ...settings.maxBytes !== void 0 ? { maxBytes: settings.maxBytes } : {},
@@ -7745,56 +8590,50 @@ var DEFAULT_TIMEOUT_MS = 1e4;
7745
8590
  var MAX_OUTPUT_BYTES = 64 * 1024;
7746
8591
  var USE_PROCESS_GROUP = process.platform !== "win32";
7747
8592
  var CLEANUP_TOKEN_ENV = "PI_MCP_REQUEST_HEADERS_CLEANUP_TOKEN";
8593
+ var PS_MAX_BUFFER_BYTES = 8 * 1024 * 1024;
7748
8594
  function isNoSuchProcessError(error) {
7749
8595
  return typeof error === "object" && error !== null && "code" in error && error.code === "ESRCH";
7750
8596
  }
7751
8597
  function runPosixPs(args) {
7752
- if (process.env.PI_MCP_ADAPTER_TEST_FAIL_PS === "1") return { status: 1, stdout: "" };
7753
- return spawnSync3("ps", args, { encoding: "utf8" });
8598
+ if (process.env.PI_MCP_ADAPTER_TEST_FAIL_PS === "1") return { status: 1, signal: null, stdout: "" };
8599
+ const result = spawnSync3("ps", args, { encoding: "utf8", maxBuffer: PS_MAX_BUFFER_BYTES });
8600
+ return { status: result.status, signal: result.signal, stdout: result.stdout };
8601
+ }
8602
+ function psFailureReason(result) {
8603
+ return result.status === null ? `ps was killed by signal ${result.signal ?? "unknown"}` : `ps exited with code ${result.status}`;
7754
8604
  }
7755
- function collectPosixDescendantPids(rootPid) {
7756
- const result = runPosixPs(["-axo", "pid=,ppid="]);
8605
+ function collectPosixProcessPids(rootPid, cleanupToken) {
8606
+ const result = runPosixPs(["axeww", "-o", "pid=,ppid=,command="]);
7757
8607
  if (result.status !== 0) {
7758
- throw new Error(`HTTP request headers command cleanup failed: ps exited with code ${result.status ?? "unknown"}`);
8608
+ throw new Error(`HTTP request headers command cleanup failed: ${psFailureReason(result)}`);
7759
8609
  }
7760
8610
  const childrenByParent = /* @__PURE__ */ new Map();
8611
+ const processPids = /* @__PURE__ */ new Set();
8612
+ const needle = cleanupToken ? `${CLEANUP_TOKEN_ENV}=${cleanupToken}` : void 0;
7761
8613
  for (const line of result.stdout.split("\n")) {
7762
- const [pidText, ppidText] = line.trim().split(/\s+/, 2);
7763
- const pid = Number(pidText);
7764
- const ppid = Number(ppidText);
8614
+ const match = /^\s*(\d+)\s+(\d+)(?:\s+(.*))?$/.exec(line);
8615
+ if (!match) continue;
8616
+ const pid = Number(match[1]);
8617
+ const ppid = Number(match[2]);
7765
8618
  if (!Number.isInteger(pid) || !Number.isInteger(ppid)) continue;
7766
8619
  const children = childrenByParent.get(ppid);
7767
8620
  if (children) children.push(pid);
7768
8621
  else childrenByParent.set(ppid, [pid]);
8622
+ if (needle && pid !== process.pid && match[3]?.includes(needle)) processPids.add(pid);
7769
8623
  }
7770
- const descendants = [];
7771
8624
  const stack = [...childrenByParent.get(rootPid) ?? []];
7772
8625
  while (stack.length > 0) {
7773
8626
  const pid = stack.pop();
7774
- descendants.push(pid);
8627
+ processPids.add(pid);
7775
8628
  stack.push(...childrenByParent.get(pid) ?? []);
7776
8629
  }
7777
- return descendants;
8630
+ return [...processPids];
7778
8631
  }
7779
- function collectPosixCleanupTokenPids(cleanupToken) {
7780
- const result = runPosixPs(["axeww", "-o", "pid=,command="]);
8632
+ function assertPosixProcessDiscoveryAvailable() {
8633
+ const result = runPosixPs(["axeww", "-o", "pid=,ppid=,command="]);
7781
8634
  if (result.status !== 0) {
7782
- throw new Error(`HTTP request headers command cleanup failed: ps exited with code ${result.status ?? "unknown"}`);
7783
- }
7784
- const needle = `${CLEANUP_TOKEN_ENV}=${cleanupToken}`;
7785
- const pids = [];
7786
- for (const line of result.stdout.split("\n")) {
7787
- const trimmed = line.trim();
7788
- if (!trimmed.includes(needle)) continue;
7789
- const [pidText] = trimmed.split(/\s+/, 1);
7790
- const pid = Number(pidText);
7791
- if (Number.isInteger(pid) && pid !== process.pid) pids.push(pid);
8635
+ throw new Error(`HTTP request headers command cleanup failed: ${psFailureReason(result)}`);
7792
8636
  }
7793
- return pids;
7794
- }
7795
- function assertPosixProcessDiscoveryAvailable() {
7796
- collectPosixDescendantPids(process.pid);
7797
- collectPosixCleanupTokenPids(`${process.pid}-preflight`);
7798
8637
  }
7799
8638
  function isTaskkillNoSuchProcess(result) {
7800
8639
  return `${result.stdout ?? ""}
@@ -7834,10 +8673,7 @@ function killRequestHeadersCommand(child, trackedPosixDescendantPids = /* @__PUR
7834
8673
  }
7835
8674
  let stablePasses = 0;
7836
8675
  for (let pass = 0; pass < 16; pass++) {
7837
- const candidates = [
7838
- ...collectPosixDescendantPids(child.pid),
7839
- ...cleanupToken ? collectPosixCleanupTokenPids(cleanupToken) : []
7840
- ];
8676
+ const candidates = collectPosixProcessPids(child.pid, cleanupToken);
7841
8677
  const newPids = candidates.filter((pid) => !frozenPids.has(pid));
7842
8678
  if (newPids.length === 0) {
7843
8679
  stablePasses++;
@@ -7894,7 +8730,7 @@ function resolvedCommand(config) {
7894
8730
  async function invokeRequestHeadersCommand(config, envelope, signal) {
7895
8731
  const resolved = resolvedCommand(config);
7896
8732
  if (USE_PROCESS_GROUP) assertPosixProcessDiscoveryAvailable();
7897
- return new Promise((resolve6, reject) => {
8733
+ return new Promise((resolve7, reject) => {
7898
8734
  let stdout = Buffer.alloc(0);
7899
8735
  let settled = false;
7900
8736
  const cleanupToken = randomUUID();
@@ -7909,8 +8745,7 @@ async function invokeRequestHeadersCommand(config, envelope, signal) {
7909
8745
  const trackPosixDescendants = () => {
7910
8746
  if (!USE_PROCESS_GROUP || child.pid === void 0 || settled || trackingError) return;
7911
8747
  try {
7912
- for (const pid of collectPosixDescendantPids(child.pid)) trackedPosixDescendantPids.add(pid);
7913
- for (const pid of collectPosixCleanupTokenPids(cleanupToken)) trackedPosixDescendantPids.add(pid);
8748
+ for (const pid of collectPosixProcessPids(child.pid, cleanupToken)) trackedPosixDescendantPids.add(pid);
7914
8749
  } catch (error) {
7915
8750
  trackingError = error instanceof Error ? error : new Error(String(error));
7916
8751
  }
@@ -7924,7 +8759,7 @@ async function invokeRequestHeadersCommand(config, envelope, signal) {
7924
8759
  if (descendantTracker) clearInterval(descendantTracker);
7925
8760
  signal.removeEventListener("abort", abort);
7926
8761
  if (result.status === "error") reject(result.error);
7927
- else resolve6(result.headers);
8762
+ else resolve7(result.headers);
7928
8763
  };
7929
8764
  const finishAfterKill = (result) => {
7930
8765
  try {
@@ -8028,11 +8863,11 @@ var MAX_CAPTURED_STDERR_BYTES = 8 * 1024;
8028
8863
  var MAX_CAPTURED_STDERR_LINES = 3;
8029
8864
  var abortCleanupPromises = /* @__PURE__ */ new WeakMap();
8030
8865
  function isUnauthorizedHttpError(error) {
8031
- return error instanceof UnauthorizedError3 || error instanceof SdkHttpError && error.status === 401;
8866
+ return error instanceof UnauthorizedError4 || error instanceof SdkHttpError2 && error.status === 401;
8032
8867
  }
8033
8868
  function shouldFallbackToSse(error, definition) {
8034
8869
  if (definition.protocolVersion === "2026-07-28") return false;
8035
- return error instanceof SdkHttpError && [404, 405, 406, 415].includes(error.status);
8870
+ return error instanceof SdkHttpError2 && [404, 405, 406, 415].includes(error.status);
8036
8871
  }
8037
8872
  function resolveVersionNegotiation(definition) {
8038
8873
  switch (definition.protocolVersion) {
@@ -8063,6 +8898,7 @@ function appendStderrTail(tail, chunk) {
8063
8898
  const combined = Buffer.concat([tail, bytes]);
8064
8899
  return combined.length > MAX_CAPTURED_STDERR_BYTES ? Buffer.from(combined.subarray(combined.length - MAX_CAPTURED_STDERR_BYTES)) : combined;
8065
8900
  }
8901
+ var KEEP_ALIVE_REFRESH_TIMEOUT_MS = 5e3;
8066
8902
  var McpServerManager = class {
8067
8903
  /** Default cwd for stdio servers without an explicit config `cwd`. */
8068
8904
  constructor(defaultCwd) {
@@ -8071,6 +8907,7 @@ var McpServerManager = class {
8071
8907
  this.connectPromises = /* @__PURE__ */ new Map();
8072
8908
  this.reconnectPromises = /* @__PURE__ */ new Map();
8073
8909
  this.uiStreamListeners = /* @__PURE__ */ new Map();
8910
+ this.pendingMetadataPublications = /* @__PURE__ */ new Map();
8074
8911
  this.authStorageOptions = {};
8075
8912
  this.acceptedUrlElicitations = /* @__PURE__ */ new Map();
8076
8913
  this.closePromises = /* @__PURE__ */ new Map();
@@ -8084,6 +8921,20 @@ var McpServerManager = class {
8084
8921
  setMetadataListChangedListener(listener) {
8085
8922
  this.metadataListChangedListener = listener;
8086
8923
  }
8924
+ publishMetadataChanged(name, expectedConnection, reason) {
8925
+ const current = this.connections.get(name);
8926
+ if (current !== expectedConnection || current.status !== "connected") return false;
8927
+ try {
8928
+ this.metadataListChangedListener?.(name, reason);
8929
+ this.pendingMetadataPublications.delete(name);
8930
+ return true;
8931
+ } catch (error) {
8932
+ this.pendingMetadataPublications.set(name, { connection: expectedConnection, reason });
8933
+ const message = error instanceof Error ? error.message : String(error);
8934
+ logger.debug(`MCP: metadata publication failed for ${name}; queued for retry: ${message}`);
8935
+ return false;
8936
+ }
8937
+ }
8087
8938
  setElicitationConfig(config) {
8088
8939
  this.elicitationConfig = config;
8089
8940
  }
@@ -8189,6 +9040,88 @@ var McpServerManager = class {
8189
9040
  this.reconnectPromises.set(name, promise);
8190
9041
  return abortable(promise, ownedSignal);
8191
9042
  }
9043
+ /**
9044
+ * Fetch the authoritative tool catalog for a connection that still appears
9045
+ * connected. The SDK response cache is explicitly bypassed so this request
9046
+ * also proves the remote Streamable HTTP session is usable. Results are
9047
+ * identity-guarded: a late response from a replaced connection is ignored.
9048
+ */
9049
+ async refreshTools(name, expectedConnection, signal) {
9050
+ if (this.stopped) throw new Error("MCP server manager is closed");
9051
+ const ownedSignal = combineAbortSignals(this.runtimeSignal, signal);
9052
+ throwIfAborted(ownedSignal);
9053
+ const current = this.connections.get(name);
9054
+ if (current !== expectedConnection || current.status !== "connected") {
9055
+ return "superseded";
9056
+ }
9057
+ const requestOptions = this.buildRequestOptions(expectedConnection.definition, signal);
9058
+ const timeout = Math.min(requestOptions?.timeout ?? KEEP_ALIVE_REFRESH_TIMEOUT_MS, KEEP_ALIVE_REFRESH_TIMEOUT_MS);
9059
+ const healthOptions = {
9060
+ ...requestOptions,
9061
+ timeout
9062
+ };
9063
+ if (!expectedConnection.client.getServerCapabilities?.()?.tools) {
9064
+ await expectedConnection.client.ping(healthOptions);
9065
+ throwIfAborted(ownedSignal);
9066
+ if (this.connections.get(name) !== expectedConnection || expectedConnection.status !== "connected") {
9067
+ return "superseded";
9068
+ }
9069
+ this.retryPendingMetadataPublication(name, expectedConnection);
9070
+ return "unchanged";
9071
+ }
9072
+ const toolsRevision = expectedConnection.toolsRevision ?? 0;
9073
+ const refreshSignal = combineAbortSignals(healthOptions.signal, AbortSignal.timeout(timeout));
9074
+ let tools;
9075
+ try {
9076
+ tools = await this.fetchAllTools(expectedConnection.client, {
9077
+ ...healthOptions,
9078
+ ...refreshSignal ? { signal: refreshSignal } : {},
9079
+ cacheMode: "refresh"
9080
+ });
9081
+ } catch (error) {
9082
+ throwIfAborted(ownedSignal);
9083
+ if (this.connections.get(name) !== expectedConnection || expectedConnection.status !== "connected") {
9084
+ return "superseded";
9085
+ }
9086
+ if (error instanceof SdkError2 && error.code === SdkErrorCode2.RequestTimeout) {
9087
+ return "refresh-timeout";
9088
+ }
9089
+ throw error;
9090
+ }
9091
+ throwIfAborted(ownedSignal);
9092
+ if (this.connections.get(name) !== expectedConnection || expectedConnection.status !== "connected") {
9093
+ return "superseded";
9094
+ }
9095
+ if ((expectedConnection.toolsRevision ?? 0) !== toolsRevision) {
9096
+ return "superseded";
9097
+ }
9098
+ if (isDeepStrictEqual(expectedConnection.tools, tools)) {
9099
+ this.retryPendingMetadataPublication(name, expectedConnection);
9100
+ return "unchanged";
9101
+ }
9102
+ const previousTools = expectedConnection.tools;
9103
+ expectedConnection.tools = tools;
9104
+ expectedConnection.toolsRevision = toolsRevision + 1;
9105
+ try {
9106
+ await this.metadataListChangedListener?.(name, "keep-alive-refresh");
9107
+ this.pendingMetadataPublications.delete(name);
9108
+ } catch (error) {
9109
+ if (this.connections.get(name) === expectedConnection && expectedConnection.tools === tools) {
9110
+ expectedConnection.tools = previousTools;
9111
+ expectedConnection.toolsRevision = toolsRevision;
9112
+ }
9113
+ throw error;
9114
+ }
9115
+ return "updated";
9116
+ }
9117
+ retryPendingMetadataPublication(name, connection) {
9118
+ const pendingPublication = this.pendingMetadataPublications.get(name);
9119
+ if (pendingPublication?.connection !== connection) return;
9120
+ this.metadataListChangedListener?.(name, pendingPublication.reason);
9121
+ if (this.pendingMetadataPublications.get(name) === pendingPublication) {
9122
+ this.pendingMetadataPublications.delete(name);
9123
+ }
9124
+ }
8192
9125
  async doReconnect(name, definition, staleConnection, signal) {
8193
9126
  throwIfAborted(signal);
8194
9127
  const current = this.connections.get(name);
@@ -8293,6 +9226,7 @@ var McpServerManager = class {
8293
9226
  transport,
8294
9227
  definition,
8295
9228
  tools: [],
9229
+ toolsRevision: 0,
8296
9230
  resources: [],
8297
9231
  prompts: [],
8298
9232
  ...instructions !== void 0 ? { instructions } : {},
@@ -8461,7 +9395,9 @@ var McpServerManager = class {
8461
9395
  const connection = this.connections.get(serverName);
8462
9396
  if (!connection || connection.client !== client || connection.status !== "connected") return;
8463
9397
  connection.tools = tools;
9398
+ connection.toolsRevision = (connection.toolsRevision ?? 0) + 1;
8464
9399
  this.metadataListChangedListener?.(serverName, "tools-list-changed");
9400
+ this.pendingMetadataPublications.delete(serverName);
8465
9401
  }
8466
9402
  handlePromptsListChanged(serverName, client, error, prompts) {
8467
9403
  if (error) {
@@ -8474,6 +9410,7 @@ var McpServerManager = class {
8474
9410
  connection.prompts = prompts;
8475
9411
  connection.promptDiscoveryFailed = false;
8476
9412
  this.metadataListChangedListener?.(serverName, "prompts-list-changed");
9413
+ this.pendingMetadataPublications.delete(serverName);
8477
9414
  }
8478
9415
  handleResourcesListChanged(serverName, client, error, resources) {
8479
9416
  if (error) {
@@ -8485,6 +9422,7 @@ var McpServerManager = class {
8485
9422
  if (!connection || connection.client !== client || connection.status !== "connected") return;
8486
9423
  connection.resources = resources;
8487
9424
  this.metadataListChangedListener?.(serverName, "resources-list-changed");
9425
+ this.pendingMetadataPublications.delete(serverName);
8488
9426
  }
8489
9427
  async handleUrlElicitationRequired(serverName, error) {
8490
9428
  if (this.runtimeSignal?.aborted || !this.elicitationConfig?.allowUrl) return "cancel";
@@ -8518,7 +9456,7 @@ var McpServerManager = class {
8518
9456
  ) ?? {};
8519
9457
  const commandBearer = definition.bearerToken?.startsWith("!") && !definition.bearerToken.startsWith("!!") ? definition.bearerToken : void 0;
8520
9458
  if (definition.auth === "bearer") {
8521
- const token = commandBearer ? resolveCommandSecret(commandBearer, `MCP server "${serverName}" HTTP bearer token`) : resolveBearerToken(definition);
9459
+ const token = commandBearer ? resolveCommandSecret(commandBearer, `MCP server "${serverName}" HTTP bearer token`) : resolveBearerToken(definition) ?? (definition.bearerToken === void 0 && definition.bearerTokenEnv === void 0 && definition.bearerTokenStore === true ? getBearerTokenForUrl(serverName, serverUrl) : void 0);
8522
9460
  if (token) headers["Authorization"] = `Bearer ${token}`;
8523
9461
  }
8524
9462
  if (hasCommandHeader || commandBearer) {
@@ -8705,6 +9643,7 @@ var McpServerManager = class {
8705
9643
  async close(name) {
8706
9644
  this.closeGenerations.set(name, (this.closeGenerations.get(name) ?? 0) + 1);
8707
9645
  this.connectAttempts.get(name)?.abort(new Error(`MCP connection ${name} was closed`));
9646
+ this.pendingMetadataPublications.delete(name);
8708
9647
  const connection = this.connections.get(name);
8709
9648
  if (!connection) {
8710
9649
  const pendingClose = this.closePromises.get(name);
@@ -8756,6 +9695,7 @@ var McpServerManager = class {
8756
9695
  const failures = [...pendingResults, ...results, ...lateResults].flatMap((result) => result.status === "rejected" ? [result.reason] : []).filter((error) => this.containsCleanupFailure(error));
8757
9696
  this.uiStreamListeners.clear();
8758
9697
  this.acceptedUrlElicitations.clear();
9698
+ this.pendingMetadataPublications.clear();
8759
9699
  this.samplingConfig = void 0;
8760
9700
  this.elicitationConfig = void 0;
8761
9701
  await this.traceWriter?.flush();
@@ -9071,77 +10011,6 @@ init_resource_tools();
9071
10011
  // packages/coding-agent/src/humain/mcp-adapter/vendor/ui-resource-handler.ts
9072
10012
  init_ui_app_bridge_helpers();
9073
10013
  import { UrlElicitationRequiredError } from "@modelcontextprotocol/client";
9074
-
9075
- // packages/coding-agent/src/humain/mcp-adapter/vendor/session-recovery.ts
9076
- import { ProtocolError as ProtocolError2, SdkHttpError as SdkHttpError2, UnauthorizedError as UnauthorizedError4 } from "@modelcontextprotocol/client";
9077
- init_types();
9078
- var CONNECTION_CLOSED_PROTOCOL_CODE = -32e3;
9079
- var SERVER_NOT_INITIALIZED_MCP_MESSAGES = /* @__PURE__ */ new Set([
9080
- "Server not initialized",
9081
- "Bad Request: Server not initialized"
9082
- ]);
9083
- function isTerminatedSession(err, hadSessionId) {
9084
- if (!hadSessionId) return false;
9085
- if (err instanceof SdkHttpError2) {
9086
- return err.status === 404 || err.status === 400 && /"code"\s*:\s*-32000/.test(err.message) && /"message"\s*:\s*"Bad Request: Server not initialized"/.test(err.message);
9087
- }
9088
- return err instanceof ProtocolError2 && err.code === CONNECTION_CLOSED_PROTOCOL_CODE && SERVER_NOT_INITIALIZED_MCP_MESSAGES.has(err.message);
9089
- }
9090
- function hasSessionId(connection) {
9091
- const transport = connection.transport;
9092
- return transport?.sessionId != null;
9093
- }
9094
- var SessionRecoveryAuthRequiredError = class extends Error {
9095
- constructor(serverName, authMessage) {
9096
- super(authMessage ?? `MCP server "${serverName}" requires OAuth authentication after reconnect.`);
9097
- this.serverName = serverName;
9098
- this.authMessage = authMessage;
9099
- this.name = "SessionRecoveryAuthRequiredError";
9100
- }
9101
- };
9102
- async function withSessionRecovery(deps, serverName, fn) {
9103
- if (isServerDisabled(deps.config.mcpServers[serverName])) {
9104
- throw new Error(`MCP server "${serverName}" is disabled`);
9105
- }
9106
- const connection = deps.manager.getConnection(serverName);
9107
- if (!connection) {
9108
- throw new Error(`Server "${serverName}" is not connected`);
9109
- }
9110
- const hadSessionId = hasSessionId(connection);
9111
- try {
9112
- return await fn(connection);
9113
- } catch (err) {
9114
- const definition = deps.config.mcpServers[serverName];
9115
- if (definition && supportsOAuth(definition) && (err instanceof UnauthorizedError4 || err instanceof SdkHttpError2 && err.status === 401)) {
9116
- invalidateAuthEntryCache(serverName);
9117
- }
9118
- if (!isTerminatedSession(err, hadSessionId)) {
9119
- throw err;
9120
- }
9121
- if (!definition) {
9122
- throw err;
9123
- }
9124
- throwIfAborted(deps.signal);
9125
- logger.debug(`MCP session for "${serverName}" expired; reconnecting`, {
9126
- server: serverName
9127
- });
9128
- let freshConnection = deps.signal ? await deps.manager.reconnect(serverName, definition, connection, deps.signal) : await deps.manager.reconnect(serverName, definition, connection);
9129
- throwIfAborted(deps.signal);
9130
- if (freshConnection.status === "needs-auth") {
9131
- freshConnection = await deps.onNeedsAuth?.(serverName) ?? freshConnection;
9132
- throwIfAborted(deps.signal);
9133
- }
9134
- if (freshConnection.status === "needs-auth") {
9135
- throw new SessionRecoveryAuthRequiredError(serverName);
9136
- }
9137
- if (freshConnection.status !== "connected") {
9138
- throw err;
9139
- }
9140
- return fn(freshConnection);
9141
- }
9142
- }
9143
-
9144
- // packages/coding-agent/src/humain/mcp-adapter/vendor/ui-resource-handler.ts
9145
10014
  init_types();
9146
10015
  var UiResourceHandler = class {
9147
10016
  constructor(manager, config = void 0) {
@@ -9532,8 +10401,20 @@ async function initializeMcp(pi, ctx, owner = createMcpRuntimeOwner(), options =
9532
10401
  },
9533
10402
  ...ui !== void 0 ? { ui } : {},
9534
10403
  sendMessage: (message, options2) => {
9535
- if (!owner.isActive()) return;
9536
- pi.sendMessage(message, options2);
10404
+ const deliver = () => {
10405
+ if (!owner.isActive()) return;
10406
+ pi.sendMessage(message, options2);
10407
+ };
10408
+ if (!options2?.triggerTurn) {
10409
+ deliver();
10410
+ return;
10411
+ }
10412
+ void lifecycle.ensureConverged(owner.signal).then(deliver, (error) => {
10413
+ if (!owner.isActive() || isAbortError(error, owner.signal)) return;
10414
+ const detail = error instanceof Error ? error.message : String(error);
10415
+ logger.debug(`MCP: pre-turn keep-alive convergence failed: ${sanitizeTerminalText(detail)}`);
10416
+ deliver();
10417
+ });
9537
10418
  },
9538
10419
  ...options.statusEvents !== void 0 ? { statusEvents: options.statusEvents } : {}
9539
10420
  };
@@ -9564,7 +10445,7 @@ async function initializeMcp(pi, ctx, owner = createMcpRuntimeOwner(), options =
9564
10445
  const idleSetting = typeof config.settings?.idleTimeout === "number" ? config.settings.idleTimeout : 10;
9565
10446
  lifecycle.setGlobalIdleTimeout(idleSetting);
9566
10447
  const cachePath = getMetadataCachePath();
9567
- const cacheFileExists = existsSync6(cachePath);
10448
+ const cacheFileExists = existsSync7(cachePath);
9568
10449
  let cache = loadMetadataCache();
9569
10450
  let bootstrapAll = false;
9570
10451
  if (!cacheFileExists) {
@@ -9575,6 +10456,7 @@ async function initializeMcp(pi, ctx, owner = createMcpRuntimeOwner(), options =
9575
10456
  saveMetadataCache(cache);
9576
10457
  }
9577
10458
  const prefix = config.settings?.toolPrefix ?? "server";
10459
+ let cachedSelectorCandidateIndex;
9578
10460
  for (const [name, definition] of serverEntries) {
9579
10461
  const lifecycleMode = definition.lifecycle ?? "lazy";
9580
10462
  const persistsAfterFirstSpawn = lifecycleMode === "eager" || lifecycleMode === "lazy-keep-alive";
@@ -9589,7 +10471,11 @@ async function initializeMcp(pi, ctx, owner = createMcpRuntimeOwner(), options =
9589
10471
  }
9590
10472
  const cachedEntry = cache?.servers?.[name];
9591
10473
  if (cachedEntry && isServerCacheValid(cachedEntry, definition)) {
9592
- const metadata = reconstructToolMetadata(name, cachedEntry, prefix, definition, config.mcpServers, cache ?? void 0);
10474
+ const hasToolFilters = Array.isArray(definition.includeTools) && definition.includeTools.length > 0 || Array.isArray(definition.excludeTools) && definition.excludeTools.length > 0;
10475
+ if (hasToolFilters && !cachedSelectorCandidateIndex && cache) {
10476
+ cachedSelectorCandidateIndex = createCachedToolSelectorCandidateIndex(config.mcpServers, cache, prefix);
10477
+ }
10478
+ const metadata = reconstructToolMetadata(name, cachedEntry, prefix, definition, config.mcpServers, cache ?? void 0, cachedSelectorCandidateIndex);
9593
10479
  toolMetadata.set(name, metadata);
9594
10480
  if (Array.isArray(cachedEntry.resources)) {
9595
10481
  resourceCounts.set(name, cachedEntry.resources.length);
@@ -9747,6 +10633,16 @@ async function initializeMcp(pi, ctx, owner = createMcpRuntimeOwner(), options =
9747
10633
  recordFailure(state, serverName, message);
9748
10634
  updateStatusBar(state);
9749
10635
  });
10636
+ lifecycle.setHealthRestoredCallback((serverName) => {
10637
+ if (!owner.isActive()) return;
10638
+ clearFailure(state, serverName);
10639
+ updateStatusBar(state);
10640
+ });
10641
+ lifecycle.setAuthRequiredCallback((serverName) => {
10642
+ if (!owner.isActive()) return;
10643
+ clearFailure(state, serverName);
10644
+ updateStatusBar(state);
10645
+ });
9750
10646
  lifecycle.setIdleShutdownCallback((serverName) => {
9751
10647
  if (!owner.isActive()) return;
9752
10648
  const idleMinutes = getEffectiveIdleTimeoutMinutes(state, serverName);
@@ -9942,8 +10838,8 @@ init_metadata_cache();
9942
10838
 
9943
10839
  // packages/coding-agent/src/humain/mcp-adapter/vendor/onboarding-state.ts
9944
10840
  init_agent_dir();
9945
- import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync4, renameSync as renameSync4 } from "node:fs";
9946
- import { dirname as dirname6 } from "node:path";
10841
+ import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync4, renameSync as renameSync4 } from "node:fs";
10842
+ import { dirname as dirname7 } from "node:path";
9947
10843
  var DEFAULT_STATE = {
9948
10844
  version: 1,
9949
10845
  sharedConfigHintShown: false,
@@ -9954,9 +10850,9 @@ function getOnboardingStatePath() {
9954
10850
  }
9955
10851
  function loadOnboardingState() {
9956
10852
  const path2 = getOnboardingStatePath();
9957
- if (!existsSync7(path2)) return { ...DEFAULT_STATE };
10853
+ if (!existsSync8(path2)) return { ...DEFAULT_STATE };
9958
10854
  try {
9959
- const raw = JSON.parse(readFileSync7(path2, "utf-8"));
10855
+ const raw = JSON.parse(readFileSync8(path2, "utf-8"));
9960
10856
  if (!raw || typeof raw !== "object") return { ...DEFAULT_STATE };
9961
10857
  return {
9962
10858
  version: 1,
@@ -9970,7 +10866,7 @@ function loadOnboardingState() {
9970
10866
  }
9971
10867
  function saveOnboardingState(state) {
9972
10868
  const path2 = getOnboardingStatePath();
9973
- mkdirSync5(dirname6(path2), { recursive: true });
10869
+ mkdirSync5(dirname7(path2), { recursive: true });
9974
10870
  const tmpPath = `${path2}.${process.pid}.tmp`;
9975
10871
  writeFileSync4(tmpPath, `${JSON.stringify(state, null, 2)}
9976
10872
  `, "utf-8");
@@ -10007,6 +10903,9 @@ init_utils();
10007
10903
  function terminalHyperlink(label, url) {
10008
10904
  return `\x1B]8;;${sanitizeTerminalText(url)}\x1B\\${sanitizeTerminalText(label)}\x1B]8;;\x1B\\`;
10009
10905
  }
10906
+ function canRenderPanel(ctx) {
10907
+ return ctx.hasUI && ctx.mode === "tui";
10908
+ }
10010
10909
  async function showStatus(state, ctx) {
10011
10910
  if (!ctx.hasUI) return;
10012
10911
  const lines = ["MCP Server Status:", ""];
@@ -10206,29 +11105,18 @@ Set "auth": "oauth" or omit auth for auto-detection.`,
10206
11105
  const authStorageOptions = getAuthStorageOptions(config.settings?.oauthDir, cwd);
10207
11106
  const status = await authenticate(serverName, serverUrl, definition, {
10208
11107
  ...authStorageOptions.baseDir ? { authStorageOptions } : {},
10209
- onAuthorizationUrl: (authorizationUrl) => {
10210
- ui.notify(
10211
- `Open this URL to authenticate ${serverName}:
10212
-
10213
- ${terminalHyperlink(authorizationUrl, authorizationUrl)}
10214
-
10215
- After approving, Pi will complete automatically if the browser can reach its localhost callback. On a remote machine, copy the full localhost URL from the browser address bar and paste it into Pi.`,
10216
- "info"
10217
- );
11108
+ onAuthorizationUrl: () => {
10218
11109
  },
10219
11110
  onAuthorizationInput: async (authorizationUrl, inputSignal) => {
10220
- const readyToPaste = await ui.confirm(
10221
- `Authorize ${serverName}`,
10222
- `Open this link in your browser:
10223
- ${terminalHyperlink(authorizationUrl, authorizationUrl)}
10224
-
10225
- After approving access, select Yes to paste the callback URL.`,
10226
- { signal: inputSignal }
10227
- );
10228
- if (!readyToPaste || inputSignal.aborted) return void 0;
11111
+ if (inputSignal.aborted) return void 0;
10229
11112
  return ui.input(
10230
- `Complete ${serverName} OAuth`,
10231
- "Paste the full callback URL",
11113
+ `Complete ${serverName} OAuth
11114
+
11115
+ ${terminalHyperlink("Open authorization page", authorizationUrl)}
11116
+ ${authorizationUrl}
11117
+
11118
+ Approve access, then paste the full localhost callback URL below.`,
11119
+ void 0,
10232
11120
  { signal: inputSignal }
10233
11121
  );
10234
11122
  },
@@ -10292,6 +11180,53 @@ async function logoutServer(serverName, state, ctx) {
10292
11180
  if (ui) ui.notify(message, "info");
10293
11181
  return { ok: true, message };
10294
11182
  }
11183
+ function validateBearerTokenStoreServer(serverName, state) {
11184
+ const safeName = sanitizeTerminalText(serverName);
11185
+ const definition = state.config.mcpServers[serverName];
11186
+ if (!definition) return { ok: false, message: `Server "${safeName}" not found in config`, type: "error" };
11187
+ if (isServerDisabled(definition)) return { ok: false, message: `Server "${safeName}" is disabled. Run /mcp enable ${safeName}, then /reload.`, type: "warning" };
11188
+ if (definition.auth !== "bearer" || definition.bearerTokenStore !== true) {
11189
+ return { ok: false, message: `Server "${safeName}" is not configured for bearerTokenStore.`, type: "error" };
11190
+ }
11191
+ let serverUrl;
11192
+ try {
11193
+ serverUrl = resolveServerUrl(definition);
11194
+ } catch {
11195
+ return { ok: false, message: `Server "${safeName}" has an invalid or unresolvable URL.`, type: "error" };
11196
+ }
11197
+ if (!serverUrl) return { ok: false, message: `Server "${safeName}" has no URL configured.`, type: "error" };
11198
+ return { ok: true, serverUrl };
11199
+ }
11200
+ async function manageBearerToken(action, serverName, state, ctx) {
11201
+ const ui = ctx.hasUI ? ctx.ui : void 0;
11202
+ const safeName = sanitizeTerminalText(serverName);
11203
+ const validation = validateBearerTokenStoreServer(serverName, state);
11204
+ if (!validation.ok) {
11205
+ if (ui) ui.notify(validation.message, validation.type);
11206
+ return { ok: false, message: validation.message };
11207
+ }
11208
+ if (action === "set") {
11209
+ const message2 = `Cannot store bearer token here: Pi extension UI has no masked secret input primitive. Run \`pi-mcp-adapter token set ${safeName}\` in a terminal; it reads the token from stdin only.`;
11210
+ if (ui) ui.notify(message2, "error");
11211
+ return { ok: false, message: message2 };
11212
+ }
11213
+ if (action === "status") {
11214
+ const status = inspectBearerTokenForUrl(serverName, validation.serverUrl);
11215
+ const message2 = status.status === "present" ? `Bearer token is stored for "${safeName}".` : status.status === "url-mismatch" ? `Bearer token is stored for "${safeName}", but its URL does not match the current server URL.` : status.status === "unavailable" ? status.message : `No bearer token is stored for "${safeName}".`;
11216
+ if (ui) ui.notify(message2, status.status === "unavailable" ? "error" : "info");
11217
+ return { ok: status.status !== "unavailable", message: message2 };
11218
+ }
11219
+ try {
11220
+ removeBearerToken(serverName);
11221
+ } catch (error) {
11222
+ const message2 = error instanceof Error ? error.message : String(error);
11223
+ if (ui) ui.notify(`Failed to remove bearer token for "${safeName}": ${sanitizeTerminalText(message2)}`, "error");
11224
+ return { ok: false, message: message2 };
11225
+ }
11226
+ const message = `Bearer token removed for "${safeName}".`;
11227
+ if (ui) ui.notify(message, "info");
11228
+ return { ok: true, message };
11229
+ }
10295
11230
  function buildSharedConfigNoticeLines(configOverridePath, cwd) {
10296
11231
  const discovery = getMcpStandardConfigSummary(configOverridePath, cwd);
10297
11232
  const onboardingState = loadOnboardingState();
@@ -10310,6 +11245,10 @@ function buildSharedConfigNoticeLines(configOverridePath, cwd) {
10310
11245
  }
10311
11246
  async function openMcpSetup(state, pi, ctx, configOverridePath, mode = "setup", options = {}) {
10312
11247
  if (!ctx.hasUI) return { configChanged: false };
11248
+ if (!canRenderPanel(ctx)) {
11249
+ ctx.ui.notify(`The interactive MCP setup panel is only available in the terminal UI (current mode: ${ctx.mode}). Edit .mcp.json directly, or run /mcp status to review servers.`, "info");
11250
+ return { configChanged: false };
11251
+ }
10313
11252
  if (state.programmaticConfig) {
10314
11253
  ctx.ui.notify("MCP setup is unavailable when config is supplied by createMcpAdapter().", "info");
10315
11254
  return { configChanged: false };
@@ -10358,19 +11297,19 @@ async function openMcpSetup(state, pi, ctx, configOverridePath, mode = "setup",
10358
11297
  markSetupCompleted(discovery.fingerprint);
10359
11298
  }
10360
11299
  };
10361
- return new Promise((resolve6) => {
11300
+ return new Promise((resolve7) => {
10362
11301
  ctx.ui.custom(
10363
11302
  (tui, _theme, keybindings, done) => {
10364
11303
  return createMcpSetupPanel2(discovery, callbacks, { mode, onboardingState, keybindings }, tui, () => {
10365
11304
  done(void 0);
10366
- resolve6({ configChanged });
11305
+ resolve7({ configChanged });
10367
11306
  });
10368
11307
  },
10369
11308
  { overlay: true, overlayOptions: { anchor: "center", width: 92 } }
10370
11309
  );
10371
11310
  });
10372
11311
  }
10373
- function buildMcpPanelCallbacks(state, config, ctx) {
11312
+ function buildMcpPanelCallbacks(state, config, ctx, getOverlayHandle) {
10374
11313
  const authStatusFailures = /* @__PURE__ */ new Map();
10375
11314
  return {
10376
11315
  reconnect: (serverName) => reconnectServer(state, ctx, serverName),
@@ -10378,7 +11317,16 @@ function buildMcpPanelCallbacks(state, config, ctx) {
10378
11317
  const definition = config.mcpServers[serverName];
10379
11318
  return definition ? !isServerDisabled(definition) && supportsOAuth(definition) : false;
10380
11319
  },
10381
- authenticate: (serverName) => authenticateServer(serverName, config, ctx, state.owner?.signal, state.oauthRuntime),
11320
+ authenticate: async (serverName) => {
11321
+ const overlay = getOverlayHandle?.();
11322
+ overlay?.setHidden(true);
11323
+ try {
11324
+ return await authenticateServer(serverName, config, ctx, state.owner?.signal, state.oauthRuntime);
11325
+ } finally {
11326
+ overlay?.setHidden(false);
11327
+ overlay?.focus();
11328
+ }
11329
+ },
10382
11330
  getConnectionStatus: (serverName) => {
10383
11331
  authStatusFailures.delete(serverName);
10384
11332
  const definition = config.mcpServers[serverName];
@@ -10420,6 +11368,10 @@ async function openMcpPanel(state, pi, ctx, configOverridePath, onDirectToolsCon
10420
11368
  }
10421
11369
  return { configChanged: false };
10422
11370
  }
11371
+ if (!canRenderPanel(ctx)) {
11372
+ await showStatus(state, ctx);
11373
+ return { configChanged: false };
11374
+ }
10423
11375
  if (Object.keys(state.config.mcpServers).length === 0) {
10424
11376
  return openMcpSetup(state, pi, ctx, configOverridePath, "empty", { includeHostConfigs: false });
10425
11377
  }
@@ -10428,10 +11380,11 @@ async function openMcpPanel(state, pi, ctx, configOverridePath, onDirectToolsCon
10428
11380
  const configPath = pi.getFlag("mcp-config") ?? configOverridePath;
10429
11381
  const provenanceMap = getServerProvenance(configPath, ctx.cwd);
10430
11382
  const { lines: noticeLines, fingerprint } = buildSharedConfigNoticeLines(configPath, ctx.cwd);
10431
- const callbacks = buildMcpPanelCallbacks(state, config, ctx);
11383
+ let overlayHandle;
11384
+ const callbacks = buildMcpPanelCallbacks(state, config, ctx, () => overlayHandle);
10432
11385
  const { createMcpPanel: createMcpPanel2 } = await Promise.resolve().then(() => (init_mcp_panel(), mcp_panel_exports));
10433
11386
  let configChanged = false;
10434
- await new Promise((resolve6) => {
11387
+ await new Promise((resolve7) => {
10435
11388
  ctx.ui.custom(
10436
11389
  (tui, _theme, keybindings, done) => {
10437
11390
  return createMcpPanel2(config, cache, provenanceMap, callbacks, tui, (result) => {
@@ -10442,17 +11395,23 @@ async function openMcpPanel(state, pi, ctx, configOverridePath, onDirectToolsCon
10442
11395
  ctx.ui.notify("Direct tools updated for this session.", "info");
10443
11396
  }
10444
11397
  done(void 0);
10445
- resolve6();
11398
+ resolve7();
10446
11399
  })().catch((error) => {
10447
11400
  const message = error instanceof Error ? error.message : String(error);
10448
11401
  ctx.ui.notify(`Direct tools updated, but live refresh failed: ${message}`, "error");
10449
11402
  configChanged = true;
10450
11403
  done(void 0);
10451
- resolve6();
11404
+ resolve7();
10452
11405
  });
10453
11406
  }, { noticeLines, keybindings });
10454
11407
  },
10455
- { overlay: true, overlayOptions: { anchor: "center", width: 82 } }
11408
+ {
11409
+ overlay: true,
11410
+ overlayOptions: { anchor: "center", width: 82 },
11411
+ onHandle: (handle) => {
11412
+ overlayHandle = handle;
11413
+ }
11414
+ }
10456
11415
  );
10457
11416
  });
10458
11417
  if (noticeLines.length > 0 && fingerprint) {
@@ -10462,6 +11421,10 @@ async function openMcpPanel(state, pi, ctx, configOverridePath, onDirectToolsCon
10462
11421
  }
10463
11422
  async function openMcpAuthPanel(state, pi, ctx, configOverridePath) {
10464
11423
  if (!ctx.hasUI) return { configChanged: false };
11424
+ if (!canRenderPanel(ctx)) {
11425
+ ctx.ui.notify(`The interactive MCP auth panel is only available in the terminal UI (current mode: ${ctx.mode}). Use /mcp-auth <server> to authenticate a specific server.`, "info");
11426
+ return { configChanged: false };
11427
+ }
10465
11428
  if (state.programmaticConfig) {
10466
11429
  ctx.ui.notify("Use /mcp-auth <server> to authenticate a server from the in-memory SDK config.", "info");
10467
11430
  return { configChanged: false };
@@ -10477,21 +11440,28 @@ async function openMcpAuthPanel(state, pi, ctx, configOverridePath) {
10477
11440
  const cache = loadMetadataCache();
10478
11441
  const configPath = pi.getFlag("mcp-config") ?? configOverridePath;
10479
11442
  const provenanceMap = getServerProvenance(configPath, ctx.cwd);
10480
- const callbacks = buildMcpPanelCallbacks(state, config, ctx);
11443
+ let overlayHandle;
11444
+ const callbacks = buildMcpPanelCallbacks(state, config, ctx, () => overlayHandle);
10481
11445
  const { createMcpPanel: createMcpPanel2 } = await Promise.resolve().then(() => (init_mcp_panel(), mcp_panel_exports));
10482
- await new Promise((resolve6) => {
11446
+ await new Promise((resolve7) => {
10483
11447
  ctx.ui.custom(
10484
11448
  (tui, _theme, keybindings, done) => {
10485
11449
  return createMcpPanel2(config, cache, provenanceMap, callbacks, tui, () => {
10486
11450
  done(void 0);
10487
- resolve6();
11451
+ resolve7();
10488
11452
  }, {
10489
11453
  authOnly: true,
10490
11454
  keybindings,
10491
11455
  noticeLines: ["Select an OAuth MCP server and press Enter or ctrl+a to authenticate."]
10492
11456
  });
10493
11457
  },
10494
- { overlay: true, overlayOptions: { anchor: "center", width: 82 } }
11458
+ {
11459
+ overlay: true,
11460
+ overlayOptions: { anchor: "center", width: 82 },
11461
+ onHandle: (handle) => {
11462
+ overlayHandle = handle;
11463
+ }
11464
+ }
10495
11465
  );
10496
11466
  });
10497
11467
  return { configChanged: false };
@@ -10508,7 +11478,7 @@ init_metadata_cache();
10508
11478
  // packages/coding-agent/src/humain/mcp-adapter/vendor/tool-registrar.ts
10509
11479
  import { mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
10510
11480
  import { tmpdir } from "node:os";
10511
- import { join as join7 } from "node:path";
11481
+ import { join as join9 } from "node:path";
10512
11482
  var MAX_BINARY_RESOURCE_BYTES = 10 * 1024 * 1024;
10513
11483
  var MAX_SESSION_RESOURCE_BYTES = 100 * 1024 * 1024;
10514
11484
  var MAX_SESSION_RESOURCE_FILES = 1e4;
@@ -10615,11 +11585,11 @@ function materializeBinaryResource(resource, scope) {
10615
11585
  return omitBinaryResource(resource, "session resource limit reached");
10616
11586
  }
10617
11587
  try {
10618
- session.directory ??= mkdtempSync(join7(tmpdir(), "pi-mcp-resource-"));
11588
+ session.directory ??= mkdtempSync(join9(tmpdir(), "pi-mcp-resource-"));
10619
11589
  } catch {
10620
11590
  return omitBinaryResource(resource, "could not be saved");
10621
11591
  }
10622
- const filePath = join7(session.directory, `resource-${++session.sequence}.bin`);
11592
+ const filePath = join9(session.directory, `resource-${++session.sequence}.bin`);
10623
11593
  session.bytes += decodedBytes;
10624
11594
  session.files += 1;
10625
11595
  try {
@@ -10712,7 +11682,7 @@ function stringifyStructuredContent(value) {
10712
11682
  import { randomBytes } from "node:crypto";
10713
11683
  import { mkdtemp, writeFile as writeFile2 } from "node:fs/promises";
10714
11684
  import { tmpdir as tmpdir2 } from "node:os";
10715
- import { join as join8 } from "node:path";
11685
+ import { join as join10 } from "node:path";
10716
11686
  var DEFAULT_MCP_OUTPUT_MAX_BYTES = 50 * 1024;
10717
11687
  var DEFAULT_MCP_OUTPUT_MAX_LINES = 2e3;
10718
11688
  var DEFAULT_MCP_DETAILS_MAX_BYTES = 16 * 1024;
@@ -10952,8 +11922,8 @@ function truncateKey(key) {
10952
11922
  }
10953
11923
  async function saveArtifact(kind, text) {
10954
11924
  try {
10955
- const dir = await mkdtemp(join8(tmpdir2(), "pi-mcp-output-"));
10956
- const path2 = join8(dir, `${kind}-${randomBytes(4).toString("hex")}.txt`);
11925
+ const dir = await mkdtemp(join10(tmpdir2(), "pi-mcp-output-"));
11926
+ const path2 = join10(dir, `${kind}-${randomBytes(4).toString("hex")}.txt`);
10957
11927
  await writeFile2(path2, text, { encoding: "utf8", mode: 384 });
10958
11928
  return { path: path2 };
10959
11929
  } catch (error) {
@@ -11427,9 +12397,20 @@ function escapeHtml2(value) {
11427
12397
  }
11428
12398
 
11429
12399
  // packages/coding-agent/src/humain/mcp-adapter/vendor/tool-approval.ts
11430
- import { randomUUID as randomUUID2 } from "node:crypto";
12400
+ import { createHash as createHash4, randomUUID as randomUUID2 } from "node:crypto";
11431
12401
  init_types();
11432
12402
  init_utils();
12403
+ function stableStringify2(value) {
12404
+ if (value === null || value === void 0 || typeof value !== "object") {
12405
+ const serialized = JSON.stringify(value);
12406
+ return serialized === void 0 ? "undefined" : serialized;
12407
+ }
12408
+ if (Array.isArray(value)) {
12409
+ return `[${value.map((item) => stableStringify2(item)).join(",")}]`;
12410
+ }
12411
+ const object = value;
12412
+ return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableStringify2(object[key])}`).join(",")}}`;
12413
+ }
11433
12414
  function isToolCallApprovalRequired(config, serverName, toolMeta, toolMetadata) {
11434
12415
  const definition = config.mcpServers[serverName];
11435
12416
  const serverApproval = definition?.approveTools;
@@ -11509,7 +12490,8 @@ async function requestBrokerApproval(state, serverName, toolMeta, args, origin,
11509
12490
  }
11510
12491
  }
11511
12492
  async function ensureToolCallApproved(state, serverName, toolMeta, args, signal, origin = toolMeta.resourceUri ? "resource" : "proxy", approvalMetadata) {
11512
- const cacheKey = `${serverName}\0${toolMeta.originalName}`;
12493
+ const argsHash = createHash4("sha256").update(stableStringify2(args ?? {})).digest("hex");
12494
+ const cacheKey = `${serverName}\0${toolMeta.originalName}\0${argsHash}`;
11513
12495
  const approvedToolCalls = state.approvedToolCalls ??= /* @__PURE__ */ new Map();
11514
12496
  if (approvedToolCalls.has(cacheKey)) {
11515
12497
  return { ok: true };
@@ -11581,6 +12563,7 @@ async function startUiServer(options) {
11581
12563
  let currentDisplayMode = options.hostContext?.displayMode ?? "inline";
11582
12564
  let nextEventId = 1;
11583
12565
  const eventLog = [];
12566
+ let latestCheckpointEventId;
11584
12567
  let streamSummary;
11585
12568
  const sessionMessages = {
11586
12569
  prompts: [],
@@ -11641,9 +12624,12 @@ async function startUiServer(options) {
11641
12624
  const touchHeartbeat = () => {
11642
12625
  lastHeartbeatAt = Date.now();
11643
12626
  };
11644
- const updateStreamSummary = (payload) => {
12627
+ const updateStreamSummary = (eventId, payload) => {
11645
12628
  const envelope = getVisualizationStreamEnvelope(payload?.structuredContent);
11646
12629
  if (!envelope) return;
12630
+ if (envelope.frameType === "checkpoint" || envelope.frameType === "final") {
12631
+ latestCheckpointEventId = eventId;
12632
+ }
11647
12633
  if (!streamSummary) {
11648
12634
  streamSummary = {
11649
12635
  streamId: envelope.streamId,
@@ -11668,15 +12654,9 @@ data: ${JSON.stringify(payload)}
11668
12654
  `;
11669
12655
  };
11670
12656
  const getLatestCheckpointIndex = () => {
11671
- for (let index = eventLog.length - 1; index >= 0; index -= 1) {
11672
- const entry = eventLog[index];
11673
- if (!entry) continue;
11674
- const envelope = getVisualizationStreamEnvelope(entry.payload?.structuredContent);
11675
- if (envelope?.frameType === "checkpoint" || envelope?.frameType === "final") {
11676
- return index;
11677
- }
11678
- }
11679
- return -1;
12657
+ const firstEventId = eventLog[0]?.id;
12658
+ if (latestCheckpointEventId === void 0 || firstEventId === void 0 || latestCheckpointEventId < firstEventId) return -1;
12659
+ return latestCheckpointEventId - firstEventId;
11680
12660
  };
11681
12661
  const pruneEventLog = () => {
11682
12662
  if (eventLog.length <= MAX_EVENT_LOG) return;
@@ -11692,7 +12672,7 @@ data: ${JSON.stringify(payload)}
11692
12672
  if (completed) return;
11693
12673
  const eventId = nextEventId++;
11694
12674
  eventLog.push({ id: eventId, name, payload });
11695
- updateStreamSummary(payload);
12675
+ updateStreamSummary(eventId, payload);
11696
12676
  pruneEventLog();
11697
12677
  const chunk = serializeEvent(eventId, name, payload);
11698
12678
  for (const client of sseClients) {
@@ -11868,9 +12848,16 @@ data: ${JSON.stringify(payload)}
11868
12848
  sendJson(res, 403, { ok: false, error: `MCP tool "${callParams.name}" is not callable by apps` });
11869
12849
  return;
11870
12850
  }
12851
+ let normalizedArguments;
12852
+ try {
12853
+ normalizedArguments = normalizeToolArguments(callParams.arguments, `tool "${callParams.name}" arguments`);
12854
+ } catch (error) {
12855
+ sendJson(res, 400, { ok: false, error: error instanceof Error ? error.message : String(error) });
12856
+ return;
12857
+ }
11871
12858
  const callArgs = {
11872
12859
  name: callParams.name,
11873
- arguments: callParams.arguments && typeof callParams.arguments === "object" && !Array.isArray(callParams.arguments) ? callParams.arguments : {}
12860
+ arguments: normalizedArguments
11874
12861
  };
11875
12862
  const toolMeta = {
11876
12863
  name: callParams.name,
@@ -12077,7 +13064,7 @@ data: ${JSON.stringify(payload)}
12077
13064
  closeSse();
12078
13065
  }, WATCHDOG_INTERVAL_MS);
12079
13066
  watchdog.unref();
12080
- return new Promise((resolve6, reject) => {
13067
+ return new Promise((resolve7, reject) => {
12081
13068
  const candidates = resolvePortCandidates(options.port);
12082
13069
  let candidateIndex = 0;
12083
13070
  const listen = () => {
@@ -12142,7 +13129,7 @@ data: ${JSON.stringify(payload)}
12142
13129
  getSessionMessages: () => ({ ...sessionMessages }),
12143
13130
  getStreamSummary: () => streamSummary ? { ...streamSummary, phases: [...streamSummary.phases] } : void 0
12144
13131
  };
12145
- resolve6(handle);
13132
+ resolve7(handle);
12146
13133
  };
12147
13134
  listen();
12148
13135
  });
@@ -12161,7 +13148,7 @@ async function parseBody(req, res) {
12161
13148
  }
12162
13149
  }
12163
13150
  function readBody(req) {
12164
- return new Promise((resolve6, reject) => {
13151
+ return new Promise((resolve7, reject) => {
12165
13152
  let size = 0;
12166
13153
  const chunks = [];
12167
13154
  req.on("data", (chunk) => {
@@ -12175,7 +13162,7 @@ function readBody(req) {
12175
13162
  });
12176
13163
  req.on("end", () => {
12177
13164
  try {
12178
- resolve6(JSON.parse(Buffer.concat(chunks).toString("utf-8")));
13165
+ resolve7(JSON.parse(Buffer.concat(chunks).toString("utf-8")));
12179
13166
  } catch (error) {
12180
13167
  reject(error);
12181
13168
  }
@@ -12232,11 +13219,11 @@ function sendText(res, status, text) {
12232
13219
  }
12233
13220
 
12234
13221
  // packages/coding-agent/src/humain/mcp-adapter/vendor/glimpse-ui.ts
12235
- import { existsSync as existsSync8 } from "node:fs";
13222
+ import { existsSync as existsSync9 } from "node:fs";
12236
13223
  import { execFileSync as execFileSync2 } from "node:child_process";
12237
- import { join as join9, dirname as dirname8 } from "node:path";
13224
+ import { join as join11, dirname as dirname9 } from "node:path";
12238
13225
  import { platform as platform3 } from "node:os";
12239
- import { createRequire as createRequire4 } from "node:module";
13226
+ import { createRequire as createRequire5 } from "node:module";
12240
13227
  var glimpseAvailable = null;
12241
13228
  var resolvedBinaryPath = null;
12242
13229
  function isGlimpseAvailable() {
@@ -12250,26 +13237,26 @@ function isGlimpseAvailable() {
12250
13237
  return glimpseAvailable;
12251
13238
  }
12252
13239
  function getGlimpseBinaryPath() {
12253
- if (process.env.GLIMPSE_BINARY && existsSync8(process.env.GLIMPSE_BINARY)) {
13240
+ if (process.env.GLIMPSE_BINARY && existsSync9(process.env.GLIMPSE_BINARY)) {
12254
13241
  return process.env.GLIMPSE_BINARY;
12255
13242
  }
12256
13243
  try {
12257
- const require5 = createRequire4(import.meta.url);
12258
- const glimpseuiPath = require5.resolve("glimpseui");
12259
- const binaryPath = join9(dirname8(glimpseuiPath), "glimpse");
12260
- if (existsSync8(binaryPath)) return binaryPath;
13244
+ const require6 = createRequire5(import.meta.url);
13245
+ const glimpseuiPath = require6.resolve("glimpseui");
13246
+ const binaryPath = join11(dirname9(glimpseuiPath), "glimpse");
13247
+ if (existsSync9(binaryPath)) return binaryPath;
12261
13248
  } catch {
12262
13249
  }
12263
13250
  try {
12264
13251
  const globalRoot = execFileSync2("npm", ["root", "-g"], { encoding: "utf-8" }).trim();
12265
- const binaryPath = join9(globalRoot, "glimpseui", "src", "glimpse");
12266
- if (existsSync8(binaryPath)) return binaryPath;
13252
+ const binaryPath = join11(globalRoot, "glimpseui", "src", "glimpse");
13253
+ if (existsSync9(binaryPath)) return binaryPath;
12267
13254
  } catch {
12268
13255
  }
12269
13256
  return null;
12270
13257
  }
12271
13258
  async function openGlimpseWindow(html, options) {
12272
- const modulePath = resolvedBinaryPath ? join9(dirname8(resolvedBinaryPath), "glimpse.mjs") : "glimpseui";
13259
+ const modulePath = resolvedBinaryPath ? join11(dirname9(resolvedBinaryPath), "glimpse.mjs") : "glimpseui";
12273
13260
  const glimpse = await import(modulePath);
12274
13261
  let active = true;
12275
13262
  const win = glimpse.open(html, {
@@ -12356,22 +13343,22 @@ function isRemoteSession2() {
12356
13343
  return Boolean(process.env.SSH_CONNECTION || process.env.SSH_TTY);
12357
13344
  }
12358
13345
  function hasActiveRemoteLogin() {
12359
- return new Promise((resolve6) => {
13346
+ return new Promise((resolve7) => {
12360
13347
  execFile("who", { encoding: "utf8", timeout: 2e3 }, (error, out) => {
12361
13348
  if (error) {
12362
- resolve6(false);
13349
+ resolve7(false);
12363
13350
  return;
12364
13351
  }
12365
- resolve6(/\(.+\)\s*$/m.test(out));
13352
+ resolve7(/\(.+\)\s*$/m.test(out));
12366
13353
  });
12367
13354
  });
12368
13355
  }
12369
13356
  function probeMoshiGateway() {
12370
- return new Promise((resolve6) => {
13357
+ return new Promise((resolve7) => {
12371
13358
  const socket = net.connect({ host: "127.0.0.1", port: 24543 });
12372
13359
  const done = (ok) => {
12373
13360
  socket.destroy();
12374
- resolve6(ok);
13361
+ resolve7(ok);
12375
13362
  };
12376
13363
  socket.setTimeout(300);
12377
13364
  socket.once("connect", () => done(true));
@@ -13084,6 +14071,7 @@ function createDirectToolExecutor(getState, getInitPromise, spec) {
13084
14071
  details: { error: "not_connected", server: spec.serverName }
13085
14072
  };
13086
14073
  }
14074
+ const normalizedParams = spec.resourceUri ? params : normalizeToolArguments(params);
13087
14075
  const approval = await ensureToolCallApproved(state, spec.serverName, {
13088
14076
  name: spec.prefixedName,
13089
14077
  originalName: spec.originalName,
@@ -13092,7 +14080,7 @@ function createDirectToolExecutor(getState, getInitPromise, spec) {
13092
14080
  ...spec.resourceUri !== void 0 ? { resourceUri: spec.resourceUri } : {},
13093
14081
  ...spec.uiResourceUri !== void 0 ? { uiResourceUri: spec.uiResourceUri } : {},
13094
14082
  ...spec.uiStreamMode !== void 0 ? { uiStreamMode: spec.uiStreamMode } : {}
13095
- }, params, ownedSignal, spec.resourceUri ? "resource" : "direct");
14083
+ }, normalizedParams, ownedSignal, spec.resourceUri ? "resource" : "direct");
13096
14084
  if (approval.ok === false) {
13097
14085
  const denied = approval.reason === "denied";
13098
14086
  const message = denied ? `The user declined approval to run MCP tool "${spec.originalName}" on server "${spec.serverName}".` : `MCP tool "${spec.originalName}" on server "${spec.serverName}" is approval-gated and requires an interactive session.`;
@@ -13155,7 +14143,7 @@ function createDirectToolExecutor(getState, getInitPromise, spec) {
13155
14143
  uiSession = hasUi ? await maybeStartUiSession(state, {
13156
14144
  serverName: spec.serverName,
13157
14145
  toolName: spec.originalName,
13158
- toolArgs: params ?? {},
14146
+ toolArgs: normalizedParams,
13159
14147
  uiResourceUri: spec.uiResourceUri,
13160
14148
  ...spec.uiStreamMode !== void 0 ? { streamMode: spec.uiStreamMode } : {},
13161
14149
  ...signal ? { signal } : {},
@@ -13171,7 +14159,7 @@ function createDirectToolExecutor(getState, getInitPromise, spec) {
13171
14159
  spec.serverName,
13172
14160
  (conn) => abortable(conn.client.callTool({
13173
14161
  name: spec.originalName,
13174
- arguments: params ?? {},
14162
+ arguments: normalizedParams,
13175
14163
  _meta: uiSession?.requestMeta
13176
14164
  }, requestOptions), ownedSignal)
13177
14165
  );
@@ -13506,7 +14494,7 @@ function buildCommandDescription(metadata) {
13506
14494
  // packages/coding-agent/src/humain/mcp-adapter/vendor/proxy-modes.ts
13507
14495
  init_types();
13508
14496
  import { UrlElicitationRequiredError as UrlElicitationRequiredError4 } from "@modelcontextprotocol/client";
13509
- import { createRequire as createRequire5 } from "node:module";
14497
+ import { createRequire as createRequire6 } from "node:module";
13510
14498
 
13511
14499
  // packages/coding-agent/src/humain/mcp-adapter/vendor/ts-shape.ts
13512
14500
  var UNSUPPORTED_KEYWORDS = ["if", "then", "else", "allOf", "not", "patternProperties", "additionalProperties"];
@@ -13657,6 +14645,7 @@ var FIELD_WEIGHTS = {
13657
14645
  description: 5,
13658
14646
  keywords: 5
13659
14647
  };
14648
+ var searchCache = /* @__PURE__ */ new WeakMap();
13660
14649
  function resolveSearchKeywords(definition, toolOriginalName, serverName, globalPrefix) {
13661
14650
  const map = definition?.searchKeywords;
13662
14651
  if (!map || typeof map !== "object" || Array.isArray(map)) return [];
@@ -13682,23 +14671,30 @@ function normalizeSearchText(value) {
13682
14671
  function tokenize(value) {
13683
14672
  return normalizeSearchText(value).split(/[^a-z0-9]+/).filter(Boolean);
13684
14673
  }
13685
- function scoreToolMatch(tool, server2, query, keywords) {
13686
- const normalizedQuery = normalizeSearchText(query).trim();
13687
- const queryTokens = tokenize(query);
13688
- if (queryTokens.length === 0) return null;
14674
+ function prepareToolSearch(tool, server2, keywords) {
13689
14675
  const fields = {
13690
14676
  name: normalizeSearchText(tool.name),
13691
14677
  originalName: normalizeSearchText(tool.originalName),
13692
14678
  server: normalizeSearchText(server2),
13693
14679
  description: normalizeSearchText(tool.description)
13694
14680
  };
14681
+ const preparedFields = Object.entries(fields).map(([field, value]) => [field, value, tokenize(value)]);
14682
+ const keywordPhrases = keywords?.map((keyword) => normalizeSearchText(keyword).trim()).filter(Boolean) ?? [];
14683
+ return {
14684
+ tool,
14685
+ fields: preparedFields,
14686
+ nameTokens: preparedFields[0][2],
14687
+ keywordPhrases,
14688
+ keywordTokens: keywordPhrases.flatMap(tokenize)
14689
+ };
14690
+ }
14691
+ function scorePreparedToolMatch(prepared, normalizedQuery, queryTokens) {
13695
14692
  let score = 0;
13696
14693
  let phraseMatched = false;
13697
14694
  let wholeFieldExact = false;
13698
14695
  const matchedTokens = /* @__PURE__ */ new Set();
13699
- for (const [field, value] of Object.entries(fields)) {
14696
+ for (const [field, value, fieldTokens] of prepared.fields) {
13700
14697
  const weight = FIELD_WEIGHTS[field];
13701
- const fieldTokens = tokenize(value);
13702
14698
  if (value === normalizedQuery) {
13703
14699
  score += weight * 14;
13704
14700
  phraseMatched = true;
@@ -13723,11 +14719,10 @@ function scoreToolMatch(tool, server2, query, keywords) {
13723
14719
  }
13724
14720
  }
13725
14721
  }
13726
- if (keywords !== void 0 && keywords.length > 0) {
14722
+ if (prepared.keywordPhrases.length > 0) {
13727
14723
  const weight = FIELD_WEIGHTS.keywords;
13728
- const phrases = keywords.map((keyword) => normalizeSearchText(keyword).trim()).filter(Boolean);
13729
14724
  let phraseScore = 0;
13730
- for (const phrase of phrases) {
14725
+ for (const phrase of prepared.keywordPhrases) {
13731
14726
  if (phrase === normalizedQuery) {
13732
14727
  phraseScore = Math.max(phraseScore, weight * 14);
13733
14728
  phraseMatched = true;
@@ -13741,15 +14736,14 @@ function scoreToolMatch(tool, server2, query, keywords) {
13741
14736
  }
13742
14737
  }
13743
14738
  score += phraseScore;
13744
- const keywordTokens = phrases.flatMap(tokenize);
13745
14739
  for (const token of queryTokens) {
13746
- if (keywordTokens.includes(token)) {
14740
+ if (prepared.keywordTokens.includes(token)) {
13747
14741
  score += weight * 4;
13748
14742
  matchedTokens.add(token);
13749
- } else if (keywordTokens.some((keywordToken) => keywordToken.startsWith(token) || keywordToken.length >= MIN_STEM_LENGTH && token.startsWith(keywordToken))) {
14743
+ } else if (prepared.keywordTokens.some((keywordToken) => keywordToken.startsWith(token) || keywordToken.length >= MIN_STEM_LENGTH && token.startsWith(keywordToken))) {
13750
14744
  score += weight * 2;
13751
14745
  matchedTokens.add(token);
13752
- } else if (phrases.some((phrase) => phrase.includes(token))) {
14746
+ } else if (prepared.keywordPhrases.some((phrase) => phrase.includes(token))) {
13753
14747
  score += weight;
13754
14748
  matchedTokens.add(token);
13755
14749
  }
@@ -13759,22 +14753,47 @@ function scoreToolMatch(tool, server2, query, keywords) {
13759
14753
  if (!phraseMatched && (queryTokens.length <= 2 ? coverage !== 1 : coverage < 0.6)) return null;
13760
14754
  score += coverage === 1 ? 25 : Math.round(coverage * 10);
13761
14755
  const firstQueryToken = queryTokens[0];
13762
- if (firstQueryToken !== void 0 && tokenize(fields.name).includes(firstQueryToken)) score += 8;
14756
+ if (firstQueryToken !== void 0 && prepared.nameTokens.includes(firstQueryToken)) score += 8;
13763
14757
  if (wholeFieldExact) score += 20;
13764
14758
  return score;
13765
14759
  }
14760
+ function getPreparedTools(state, serverName, metadata, definition, globalPrefix, includeKeywords) {
14761
+ let stateCache = searchCache.get(state);
14762
+ if (!stateCache) {
14763
+ stateCache = /* @__PURE__ */ new Map();
14764
+ searchCache.set(state, stateCache);
14765
+ }
14766
+ const toolPrefix = resolveToolPrefix(definition, globalPrefix);
14767
+ let cached = stateCache.get(serverName);
14768
+ if (cached?.metadata !== metadata || cached.searchKeywords !== definition?.searchKeywords || cached.toolPrefix !== toolPrefix) {
14769
+ cached = { metadata, searchKeywords: definition?.searchKeywords, toolPrefix };
14770
+ stateCache.set(serverName, cached);
14771
+ }
14772
+ const cacheKey = includeKeywords ? "withKeywords" : "withoutKeywords";
14773
+ let prepared = cached[cacheKey];
14774
+ if (!prepared) {
14775
+ prepared = metadata.map((tool) => prepareToolSearch(
14776
+ tool,
14777
+ serverName,
14778
+ includeKeywords && definition?.searchKeywords !== void 0 ? resolveSearchKeywords(definition, tool.originalName, serverName, globalPrefix) : void 0
14779
+ ));
14780
+ cached[cacheKey] = prepared;
14781
+ }
14782
+ return prepared;
14783
+ }
13766
14784
  function rankToolMatches(state, query, server2, includeKeywords = true) {
13767
14785
  const matches = [];
14786
+ const normalizedQuery = normalizeSearchText(query).trim();
14787
+ const queryTokens = tokenize(query);
14788
+ if (queryTokens.length === 0) return matches;
13768
14789
  const globalPrefix = state.config.settings?.toolPrefix ?? "server";
13769
14790
  for (const [serverName, metadata] of state.toolMetadata.entries()) {
13770
14791
  if (server2 && serverName !== server2) continue;
13771
14792
  const definition = state.config.mcpServers[serverName];
13772
14793
  if (isServerDisabled(definition)) continue;
13773
- const hasKeywords = includeKeywords && definition?.searchKeywords !== void 0;
13774
- for (const tool of metadata) {
13775
- const keywords = hasKeywords ? resolveSearchKeywords(definition, tool.originalName, serverName, globalPrefix) : void 0;
13776
- const score = scoreToolMatch(tool, serverName, query, keywords);
13777
- if (score !== null) matches.push({ server: serverName, tool, score });
14794
+ for (const prepared of getPreparedTools(state, serverName, metadata, definition, globalPrefix, includeKeywords)) {
14795
+ const score = scorePreparedToolMatch(prepared, normalizedQuery, queryTokens);
14796
+ if (score !== null) matches.push({ server: serverName, tool: prepared.tool, score });
13778
14797
  }
13779
14798
  }
13780
14799
  return matches.sort((a, b) => b.score - a.score || a.tool.name.localeCompare(b.tool.name));
@@ -13799,7 +14818,7 @@ function rankSuggestions(state, name, limit) {
13799
14818
  }
13800
14819
 
13801
14820
  // packages/coding-agent/src/humain/mcp-adapter/vendor/proxy-modes.ts
13802
- var require4 = createRequire5(import.meta.url);
14821
+ var require5 = createRequire6(import.meta.url);
13803
14822
  var MAX_REGEX_SEARCH_QUERY_LENGTH = 256;
13804
14823
  var INSTRUCTIONS_PREVIEW_LENGTH = 300;
13805
14824
  var REGEX_SAFETY_CHECK_PARAMS = {
@@ -14222,7 +15241,7 @@ function executeSearch(state, query, regex, server2, includeSchemas, limit = 12,
14222
15241
  pattern = new RegExp(query, "i");
14223
15242
  let safety;
14224
15243
  try {
14225
- const { checkSync } = require4("recheck");
15244
+ const { checkSync } = require5("recheck");
14226
15245
  safety = checkSync(query, "i", REGEX_SAFETY_CHECK_PARAMS);
14227
15246
  } catch (error) {
14228
15247
  const reason = error instanceof Error ? error.message : String(error);
@@ -14782,11 +15801,12 @@ async function executeCall(state, toolName, args, serverOverride, getPiTools, si
14782
15801
  if (isServerDisabled(state.config.mcpServers[serverName])) {
14783
15802
  return disabledCallResult(serverName, toolMeta);
14784
15803
  }
15804
+ const normalizedArgs = toolMeta.resourceUri ? args ?? {} : normalizeToolArguments(args);
14785
15805
  const approval = await ensureToolCallApproved(
14786
15806
  state,
14787
15807
  serverName,
14788
15808
  toolMeta,
14789
- args,
15809
+ normalizedArgs,
14790
15810
  ownedSignal,
14791
15811
  origin ?? (toolMeta.resourceUri ? "resource" : "proxy")
14792
15812
  );
@@ -14854,7 +15874,7 @@ async function executeCall(state, toolName, args, serverOverride, getPiTools, si
14854
15874
  uiSession = toolMeta.uiResourceUri ? await maybeStartUiSession(state, {
14855
15875
  serverName,
14856
15876
  toolName: toolMeta.originalName,
14857
- toolArgs: args ?? {},
15877
+ toolArgs: normalizedArgs,
14858
15878
  uiResourceUri: toolMeta.uiResourceUri,
14859
15879
  ...toolMeta.uiStreamMode !== void 0 ? { streamMode: toolMeta.uiStreamMode } : {},
14860
15880
  ...signal ? { signal } : {},
@@ -14870,7 +15890,7 @@ async function executeCall(state, toolName, args, serverOverride, getPiTools, si
14870
15890
  serverName,
14871
15891
  (conn) => abortable(conn.client.callTool({
14872
15892
  name: toolMeta.originalName,
14873
- arguments: args ?? {},
15893
+ arguments: normalizedArgs,
14874
15894
  _meta: uiSession?.requestMeta
14875
15895
  }, requestOptions), ownedSignal)
14876
15896
  );
@@ -14974,6 +15994,7 @@ init_utils();
14974
15994
  import { Text, truncateToWidth as truncateToWidth3, visibleWidth as visibleWidth3 } from "@earendil-works/pi-tui";
14975
15995
  var plainTheme = { fg: (_name, text) => text };
14976
15996
  var DEFAULT_MAX_CALL_INPUT_CHARS = 1500;
15997
+ var DEFAULT_MAX_COMPACT_INPUT_CHARS = 240;
14977
15998
  var DEFAULT_BOXED_COLLAPSED_LINES = 3;
14978
15999
  var DEFAULT_COMPACT_COLLAPSED_LINES = 1;
14979
16000
  var DEFAULT_MAX_COLLAPSED_CHARS = 8e3;
@@ -14986,8 +16007,9 @@ var EmptyComponent = class {
14986
16007
  }
14987
16008
  };
14988
16009
  var CompactMcpToolResult = class {
14989
- constructor(title, display, theme) {
16010
+ constructor(title, inputPreview, display, theme) {
14990
16011
  this.title = title;
16012
+ this.inputPreview = inputPreview;
14991
16013
  this.display = display;
14992
16014
  this.theme = theme;
14993
16015
  this.rendered = null;
@@ -15000,7 +16022,7 @@ var CompactMcpToolResult = class {
15000
16022
  });
15001
16023
  const lines = resultLines.length > 0 ? resultLines : [""];
15002
16024
  const bodies = lines.map((line, index) => {
15003
- const prefix = index === 0 && this.title ? `${this.theme.fg("toolTitle", this.title)} \u2192 ` : "";
16025
+ const prefix = index === 0 ? this.renderPrefix(safeWidth) : "";
15004
16026
  return `${prefix}${this.theme.fg("toolOutput", line)}`;
15005
16027
  });
15006
16028
  const hiddenText = this.display.truncated || bodies.some((body) => visibleWidth3(body) > safeWidth);
@@ -15022,6 +16044,19 @@ var CompactMcpToolResult = class {
15022
16044
  invalidate() {
15023
16045
  this.rendered = null;
15024
16046
  }
16047
+ renderPrefix(width) {
16048
+ if (!this.title) return "";
16049
+ const arrow = " \u2192 ";
16050
+ if (!this.inputPreview) return `${this.theme.fg("toolTitle", this.title)}${arrow}`;
16051
+ const maxPrefixWidth = Math.max(12, Math.floor(width * 0.55));
16052
+ const titleWidth = visibleWidth3(this.title);
16053
+ const inputWidth = Math.max(0, maxPrefixWidth - titleWidth - 1);
16054
+ if (inputWidth <= 3) {
16055
+ return `${this.theme.fg("toolTitle", truncateToWidth3(this.title, maxPrefixWidth, "\u2026"))}${arrow}`;
16056
+ }
16057
+ const input = truncateToWidth3(this.inputPreview, inputWidth, "\u2026");
16058
+ return `${this.theme.fg("toolTitle", this.title)} ${this.theme.fg("muted", input)}${arrow}`;
16059
+ }
15025
16060
  };
15026
16061
  var CollapsibleText = class {
15027
16062
  constructor(text, expanded, maxCollapsedLines, ellipsis, expandHint, preTruncated = false) {
@@ -15122,6 +16157,9 @@ function renderToolCallLines(lines, theme) {
15122
16157
  const styledRest = rest.map((line) => activeTheme.fg("muted", line));
15123
16158
  return new Text([styledTitle, ...styledRest].join("\n"), 0, 0);
15124
16159
  }
16160
+ function formatCompactInputPreview(lines, maxChars = DEFAULT_MAX_COMPACT_INPUT_CHARS) {
16161
+ return truncateText(lines.slice(1).join(" ").replace(/\s+/g, " ").trim(), maxChars);
16162
+ }
15125
16163
  function resolveMcpToolRenderOptions(settings) {
15126
16164
  const resultRendering = settings?.toolResultRendering === "boxed" ? "boxed" : "compact";
15127
16165
  const collapsedLines = settings?.collapsedResultLines;
@@ -15135,7 +16173,10 @@ function shouldUseCompactFinalRender(options, context) {
15135
16173
  return options.resultRendering === "compact" && context !== void 0 && context.isPartial === false && context.expanded !== true && context.isError !== true;
15136
16174
  }
15137
16175
  function renderToolCall(lines, theme, context, options) {
15138
- if (context?.state) context.state.compactTitle = lines[0] ?? "mcp";
16176
+ if (context?.state) {
16177
+ context.state.compactTitle = lines[0] ?? "mcp";
16178
+ context.state.compactInputPreview = formatCompactInputPreview(lines);
16179
+ }
15139
16180
  if (shouldUseCompactFinalRender(options, context)) return new EmptyComponent();
15140
16181
  return renderToolCallLines(lines, theme);
15141
16182
  }
@@ -15161,6 +16202,18 @@ function collectCollapsedResultLines(content, maxLines, maxChars) {
15161
16202
  let remainingChars = maxChars;
15162
16203
  let truncated = false;
15163
16204
  const appendLine = (line) => {
16205
+ if (lines.length === 0) {
16206
+ const previewWidth = Math.min(line.length, remainingChars);
16207
+ if (line.slice(0, previewWidth).trim() === "") {
16208
+ if (line.length >= remainingChars) {
16209
+ truncated = true;
16210
+ remainingChars = 0;
16211
+ return false;
16212
+ }
16213
+ remainingChars -= line.length + 1;
16214
+ return true;
16215
+ }
16216
+ }
15164
16217
  if (lines.length >= maxLines || remainingChars <= 0) {
15165
16218
  truncated = true;
15166
16219
  return false;
@@ -15190,7 +16243,7 @@ function collectCollapsedResultLines(content, maxLines, maxChars) {
15190
16243
  }
15191
16244
  if (truncated) break;
15192
16245
  }
15193
- if (lines.length === 0) lines.push("");
16246
+ if (lines.length === 0) lines.push(truncated ? "(leading blank output omitted)" : "");
15194
16247
  if (truncated && lines.length >= maxLines) lines.push("\u2026");
15195
16248
  return { lines, truncated };
15196
16249
  }
@@ -15221,7 +16274,8 @@ function renderMcpToolResult(result, options, theme, context, renderOptions = re
15221
16274
  if (!expanded && renderOptions.resultRendering === "compact") {
15222
16275
  const display2 = formatMcpToolResultLines(result, false, renderOptions.collapsedResultLines);
15223
16276
  const title = context?.state?.compactTitle ?? formatMcpToolResultIdentity(result.details) ?? "";
15224
- return new CompactMcpToolResult(title, display2, activeTheme);
16277
+ const inputPreview = context?.state?.compactInputPreview ?? "";
16278
+ return new CompactMcpToolResult(title, inputPreview, display2, activeTheme);
15225
16279
  }
15226
16280
  const display = formatMcpToolResultLines(result, expanded, renderOptions.collapsedResultLines);
15227
16281
  const identity = formatMcpToolResultIdentity(result.details);
@@ -15431,10 +16485,14 @@ async function runMcpScript(state, code, timeoutMs = DEFAULT_MCP_SCRIPT_TIMEOUT_
15431
16485
  }
15432
16486
  worker = new Worker(new URL("./mcp-script-worker.mjs", import.meta.url), {
15433
16487
  workerData: { code },
15434
- env: {}
16488
+ env: {},
16489
+ // The sandbox cannot open files, and the host always terminates this worker.
16490
+ // Disable Node's unmanaged FD bookkeeping, which emits false warnings when
16491
+ // short-lived workers are terminated on Node 24.
16492
+ trackUnmanagedFds: false
15435
16493
  });
15436
16494
  const activeWorker = worker;
15437
- const execution = new Promise((resolve6, reject) => {
16495
+ const execution = new Promise((resolve7, reject) => {
15438
16496
  let completed = false;
15439
16497
  activeWorker.on("message", (value) => {
15440
16498
  const message = parseWorkerMessage(value);
@@ -15446,7 +16504,7 @@ async function runMcpScript(state, code, timeoutMs = DEFAULT_MCP_SCRIPT_TIMEOUT_
15446
16504
  if (message.type === "done") {
15447
16505
  completed = true;
15448
16506
  if ("returnBlock" in message) output.push(toContentBlock(message.returnBlock));
15449
- resolve6();
16507
+ resolve7();
15450
16508
  return;
15451
16509
  }
15452
16510
  if (message.type === "error") {
@@ -15531,13 +16589,14 @@ async function runMcpScript(state, code, timeoutMs = DEFAULT_MCP_SCRIPT_TIMEOUT_
15531
16589
  init_types();
15532
16590
  var INIT_WAIT_TIMEOUT_MS = 3e4;
15533
16591
  var INIT_WAIT_TIMED_OUT = /* @__PURE__ */ Symbol("init-wait-timed-out");
16592
+ var runtimeRegistrars = /* @__PURE__ */ new WeakMap();
15534
16593
  async function awaitWithTimeout(promise, timeoutMs) {
15535
16594
  let timer;
15536
16595
  try {
15537
16596
  return await Promise.race([
15538
16597
  promise,
15539
- new Promise((resolve6) => {
15540
- timer = setTimeout(() => resolve6(INIT_WAIT_TIMED_OUT), timeoutMs);
16598
+ new Promise((resolve7) => {
16599
+ timer = setTimeout(() => resolve7(INIT_WAIT_TIMED_OUT), timeoutMs);
15541
16600
  timer.unref?.();
15542
16601
  })
15543
16602
  ]);
@@ -15603,6 +16662,14 @@ function installMcpAdapter(pi, options) {
15603
16662
  let proxyToolRegistered = false;
15604
16663
  let proxyToolDescription = null;
15605
16664
  let directToolsFrozen = false;
16665
+ const runtimeServers = /* @__PURE__ */ new Map();
16666
+ function attachRuntimeServerLifecycle(targetState, name, definition) {
16667
+ const lifecycleMode = definition.lifecycle ?? "lazy";
16668
+ const persistsAfterFirstSpawn = lifecycleMode === "eager" || lifecycleMode === "lazy-keep-alive";
16669
+ const idleOverride = definition.idleTimeout ?? (persistsAfterFirstSpawn ? 0 : void 0);
16670
+ targetState.lifecycle.registerServer(name, definition, idleOverride !== void 0 ? { idleTimeout: idleOverride } : void 0);
16671
+ if (lifecycleMode === "keep-alive") targetState.lifecycle.markKeepAlive(name, definition);
16672
+ }
15606
16673
  const toToolParameters = (schema) => typeof Type.Unsafe === "function" ? Type.Unsafe(schema) : schema;
15607
16674
  function directToolFingerprint(spec) {
15608
16675
  return JSON.stringify({
@@ -15725,6 +16792,42 @@ function installMcpAdapter(pi, options) {
15725
16792
  registerPromptCommands([...state?.promptMetadata?.values() ?? []].flat());
15726
16793
  }
15727
16794
  registerPromptCommands(resolveCachedPrompts(earlyConfig));
16795
+ runtimeRegistrars.set(pi, (name, definition) => {
16796
+ if (typeof name !== "string" || name.trim() === "") {
16797
+ throw new Error("MCP server name must be a non-empty string");
16798
+ }
16799
+ if (typeof definition !== "object" || definition === null || Array.isArray(definition)) {
16800
+ throw new Error(`MCP server definition for "${name}" must be an object`);
16801
+ }
16802
+ const effective = state?.config ?? earlyConfig;
16803
+ if (runtimeServers.has(name) || Object.hasOwn(effective.mcpServers, name)) {
16804
+ throw new Error(`MCP server "${name}" is already registered`);
16805
+ }
16806
+ const entry = { ...structuredClone(definition), directTools: false };
16807
+ runtimeServers.set(name, entry);
16808
+ const registeredState = state;
16809
+ if (registeredState) {
16810
+ registeredState.config.mcpServers[name] = entry;
16811
+ attachRuntimeServerLifecycle(registeredState, name, entry);
16812
+ syncToolSurface();
16813
+ updateStatusBar(registeredState);
16814
+ }
16815
+ let disposed = false;
16816
+ return {
16817
+ dispose: async () => {
16818
+ if (disposed) return;
16819
+ disposed = true;
16820
+ runtimeServers.delete(name);
16821
+ const currentState = state;
16822
+ if (!currentState || currentState.config.mcpServers[name] !== entry) return;
16823
+ delete currentState.config.mcpServers[name];
16824
+ currentState.lifecycle.unregisterServer(name);
16825
+ await currentState.manager.close(name);
16826
+ syncToolSurface();
16827
+ updateStatusBar(currentState);
16828
+ }
16829
+ };
16830
+ });
15728
16831
  const getPiTools = () => pi.getAllTools();
15729
16832
  pi.registerFlag("mcp-config", {
15730
16833
  description: "Path to MCP config file",
@@ -15737,8 +16840,7 @@ function installMcpAdapter(pi, options) {
15737
16840
  ...earlyConfigPath !== void 0 ? { configPath: earlyConfigPath } : {},
15738
16841
  ...sessionConfig !== void 0 ? { config: sessionConfig } : {}
15739
16842
  } : {},
15740
- oauthRuntime,
15741
- statusEvents: pi.events
16843
+ oauthRuntime
15742
16844
  });
15743
16845
  initPromise = promise;
15744
16846
  return promise.then(async (nextState) => {
@@ -15751,6 +16853,14 @@ function installMcpAdapter(pi, options) {
15751
16853
  return;
15752
16854
  }
15753
16855
  state = nextState;
16856
+ for (const [name, definition] of runtimeServers) {
16857
+ if (Object.hasOwn(nextState.config.mcpServers, name)) {
16858
+ console.error(`MCP: runtime-registered server "${name}" now collides with a configured server; keeping the configured server`);
16859
+ continue;
16860
+ }
16861
+ nextState.config.mcpServers[name] = definition;
16862
+ attachRuntimeServerLifecycle(nextState, name, definition);
16863
+ }
15754
16864
  nextState.onToolMetadataUpdated = (_serverName, _reason) => {
15755
16865
  if (state !== nextState || !owner.isActive()) return;
15756
16866
  syncPromptCommands();
@@ -15762,6 +16872,7 @@ function installMcpAdapter(pi, options) {
15762
16872
  };
15763
16873
  syncPromptCommands();
15764
16874
  syncToolSurface(ctx);
16875
+ nextState.statusEvents = pi.events;
15765
16876
  updateStatusBar(nextState);
15766
16877
  initPromise = null;
15767
16878
  if (earlyConfig.settings?.freezeDirectTools === true) {
@@ -15845,6 +16956,26 @@ function installMcpAdapter(pi, options) {
15845
16956
  }
15846
16957
  }
15847
16958
  });
16959
+ pi.on("input", async () => {
16960
+ const inputOwner = currentOwner;
16961
+ if (!inputOwner?.isActive()) return;
16962
+ if (!state && initPromise) {
16963
+ try {
16964
+ await awaitWithTimeout(initPromise, INIT_WAIT_TIMEOUT_MS);
16965
+ } catch {
16966
+ return;
16967
+ }
16968
+ }
16969
+ const inputState = state;
16970
+ if (!inputState || !inputOwner.isActive()) return;
16971
+ try {
16972
+ await inputState.lifecycle.ensureConverged(inputOwner.signal);
16973
+ } catch (error) {
16974
+ if (!isAbortError(error, inputOwner.signal)) {
16975
+ logger.debug(`MCP: keep-alive convergence failed before input: ${formatTerminalError(error)}`);
16976
+ }
16977
+ }
16978
+ });
15848
16979
  pi.on("session_shutdown", async () => {
15849
16980
  ++lifecycleGeneration;
15850
16981
  const currentState = state;
@@ -15866,7 +16997,7 @@ function installMcpAdapter(pi, options) {
15866
16997
  }
15867
16998
  });
15868
16999
  pi.on("tool_result", (event) => toolErrorOverride(event.details));
15869
- pi.registerCommand("mcp", {
17000
+ const registerMcpCommand = (commandName) => pi.registerCommand(commandName, {
15870
17001
  description: "Show MCP server status",
15871
17002
  getArgumentCompletions: (prefix) => {
15872
17003
  const normalized = prefix.trimStart();
@@ -15878,6 +17009,7 @@ function installMcpAdapter(pi, options) {
15878
17009
  { value: "prompts", label: "prompts \u2014 List all MCP prompts" },
15879
17010
  { value: "setup", label: "setup \u2014 Configure MCP servers" },
15880
17011
  { value: "logout", label: "logout \u2014 Clear server credentials" },
17012
+ { value: "token", label: "token \u2014 Manage stored bearer tokens" },
15881
17013
  { value: "disable", label: "disable \u2014 Disable a server" },
15882
17014
  { value: "enable", label: "enable \u2014 Enable a server" },
15883
17015
  { value: "status", label: "status \u2014 Show server status" }
@@ -15885,7 +17017,18 @@ function installMcpAdapter(pi, options) {
15885
17017
  return subcommands.length > 0 ? subcommands : null;
15886
17018
  }
15887
17019
  const [, subcommand, argumentPrefix] = argumentMatch;
15888
- if (subcommand !== "reconnect" && subcommand !== "logout" && subcommand !== "disable" && subcommand !== "enable" || argumentPrefix === void 0 || !state) return null;
17020
+ if (subcommand !== "reconnect" && subcommand !== "logout" && subcommand !== "disable" && subcommand !== "enable" && subcommand !== "token" || argumentPrefix === void 0 || !state) return null;
17021
+ if (subcommand === "token") {
17022
+ const tokenMatch = argumentPrefix.trimStart().match(/^(set|remove|status)\s+(.*)$/);
17023
+ if (!tokenMatch) {
17024
+ const actions = ["set", "remove", "status"].filter((action2) => action2.startsWith(argumentPrefix.trimStart())).map((action2) => ({ value: `token ${action2} `, label: `${action2} \u2014 Bearer token ${action2}` }));
17025
+ return actions.length > 0 ? actions : null;
17026
+ }
17027
+ const action = tokenMatch[1] ?? "";
17028
+ const serverPrefix = tokenMatch[2] ?? "";
17029
+ const servers2 = Object.keys(state.config.mcpServers).filter((serverName) => serverName.startsWith(serverPrefix.trimStart())).map((serverName) => ({ value: `token ${action} ${serverName}`, label: serverName }));
17030
+ return servers2.length > 0 ? servers2 : null;
17031
+ }
15889
17032
  const servers = Object.keys(state.config.mcpServers).filter((serverName) => serverName.startsWith(argumentPrefix.trimStart())).map((serverName) => ({ value: `${subcommand} ${serverName}`, label: serverName }));
15890
17033
  return servers.length > 0 ? servers : null;
15891
17034
  },
@@ -15956,6 +17099,21 @@ function installMcpAdapter(pi, options) {
15956
17099
  await logoutServer(serverName, state, commandCtx);
15957
17100
  break;
15958
17101
  }
17102
+ case "token": {
17103
+ const action = parts[1];
17104
+ const serverName = parts.slice(2).join(" ");
17105
+ if (action !== "set" && action !== "remove" && action !== "status") {
17106
+ if (commandCtx.hasUI) commandCtx.ui?.notify("Usage: /mcp token set|remove|status <server>", "error");
17107
+ return;
17108
+ }
17109
+ if (!serverName) {
17110
+ if (commandCtx.hasUI) commandCtx.ui?.notify("Usage: /mcp token set|remove|status <server>", "error");
17111
+ return;
17112
+ }
17113
+ commandOwner?.throwIfInactive();
17114
+ await manageBearerToken(action, serverName, state, commandCtx);
17115
+ break;
17116
+ }
15959
17117
  case "disable":
15960
17118
  case "enable": {
15961
17119
  const serverName = rest;
@@ -16006,6 +17164,8 @@ function installMcpAdapter(pi, options) {
16006
17164
  }
16007
17165
  }
16008
17166
  });
17167
+ registerMcpCommand("mcp");
17168
+ registerMcpCommand("pi-mcp");
16009
17169
  pi.registerCommand("mcp-auth", {
16010
17170
  description: "Authenticate with an MCP server (OAuth)",
16011
17171
  handler: async (args, ctx) => {
@@ -16127,12 +17287,12 @@ function installMcpAdapter(pi, options) {
16127
17287
  renderResult: renderMcpToolResult2,
16128
17288
  async execute(_toolCallId, params, signal, _onUpdate, _ctx) {
16129
17289
  const executeOwner = currentOwner;
16130
- let parsedArgs;
16131
- if (params.args !== void 0 && params.args !== "") {
17290
+ const parseArgs = (value) => {
17291
+ if (value === void 0 || value === "") return void 0;
16132
17292
  let args;
16133
- if (typeof params.args === "string") {
17293
+ if (typeof value === "string") {
16134
17294
  try {
16135
- args = JSON.parse(params.args);
17295
+ args = JSON.parse(value);
16136
17296
  } catch (error) {
16137
17297
  if (error instanceof SyntaxError) {
16138
17298
  throw new Error(`Invalid args JSON: ${error.message}`, { cause: error });
@@ -16140,13 +17300,49 @@ function installMcpAdapter(pi, options) {
16140
17300
  throw error;
16141
17301
  }
16142
17302
  } else {
16143
- args = params.args;
17303
+ args = value;
16144
17304
  }
16145
17305
  if (typeof args !== "object" || args === null || Array.isArray(args)) {
16146
17306
  const gotType = Array.isArray(args) ? "array" : args === null ? "null" : typeof args;
16147
17307
  throw new Error(`Invalid args: expected a JSON object, got ${gotType}`);
16148
17308
  }
16149
- parsedArgs = args;
17309
+ return args;
17310
+ };
17311
+ const validateNestedGatewayParams = (value) => {
17312
+ for (const key of ["tool", "connect", "describe", "instructions", "search", "server", "action"]) {
17313
+ if (value[key] !== void 0 && typeof value[key] !== "string") {
17314
+ throw new Error(`Invalid nested gateway param \`${key}\`: expected string, got ${Array.isArray(value[key]) ? "array" : typeof value[key]}`);
17315
+ }
17316
+ }
17317
+ for (const key of ["regex", "includeSchemas"]) {
17318
+ if (value[key] !== void 0 && typeof value[key] !== "boolean") {
17319
+ throw new Error(`Invalid nested gateway param \`${key}\`: expected boolean, got ${Array.isArray(value[key]) ? "array" : typeof value[key]}`);
17320
+ }
17321
+ }
17322
+ for (const key of ["limit", "offset"]) {
17323
+ if (value[key] !== void 0 && typeof value[key] !== "number") {
17324
+ throw new Error(`Invalid nested gateway param \`${key}\`: expected number, got ${Array.isArray(value[key]) ? "array" : typeof value[key]}`);
17325
+ }
17326
+ }
17327
+ const args = value.args;
17328
+ if (args !== void 0 && typeof args !== "string" && (typeof args !== "object" || args === null || Array.isArray(args))) {
17329
+ throw new Error(`Invalid nested gateway param \`args\`: expected JSON object or JSON string, got ${Array.isArray(args) ? "array" : args === null ? "null" : typeof args}`);
17330
+ }
17331
+ return value;
17332
+ };
17333
+ let parsedArgs = parseArgs(params.args);
17334
+ let dispatchParams = params;
17335
+ const hasGatewayMode = (value) => value.tool !== void 0 || value.connect !== void 0 || value.describe !== void 0 || value.instructions !== void 0 || value.search !== void 0 || value.server !== void 0 || value.action !== void 0;
17336
+ if (!hasGatewayMode(params) && parsedArgs) {
17337
+ const nestedParams = validateNestedGatewayParams(parsedArgs);
17338
+ if (hasGatewayMode(nestedParams)) {
17339
+ dispatchParams = nestedParams;
17340
+ parsedArgs = parseArgs(nestedParams.args);
17341
+ } else {
17342
+ throw new Error('Gateway params were nested inside `args`; pass them top-level (for example, mcp({ search: "..." }) or mcp({ tool: "...", args: {} })).');
17343
+ }
17344
+ } else if (!hasGatewayMode(params) && params.args !== void 0) {
17345
+ throw new Error('Gateway params were nested inside `args`; pass them top-level (for example, mcp({ search: "..." }) or mcp({ tool: "...", args: {} })).');
16150
17346
  }
16151
17347
  if (!state && initPromise) {
16152
17348
  try {
@@ -16175,20 +17371,20 @@ function installMcpAdapter(pi, options) {
16175
17371
  };
16176
17372
  }
16177
17373
  executeOwner?.throwIfInactive();
16178
- if (params.action === "ui-messages") {
17374
+ if (dispatchParams.action === "ui-messages") {
16179
17375
  return executeUiMessages(state);
16180
17376
  }
16181
- if (params.action === "auth-start") {
16182
- if (!params.server) {
17377
+ if (dispatchParams.action === "auth-start") {
17378
+ if (!dispatchParams.server) {
16183
17379
  return {
16184
17380
  content: [{ type: "text", text: 'auth-start requires `server`. Example: mcp({ action: "auth-start", server: "linear-server" })' }],
16185
17381
  details: { mode: "auth-start", error: "missing_server" }
16186
17382
  };
16187
17383
  }
16188
- return signal ? executeAuthStart(state, params.server, signal) : executeAuthStart(state, params.server);
17384
+ return signal ? executeAuthStart(state, dispatchParams.server, signal) : executeAuthStart(state, dispatchParams.server);
16189
17385
  }
16190
- if (params.action === "auth-complete") {
16191
- if (!params.server) {
17386
+ if (dispatchParams.action === "auth-complete") {
17387
+ if (!dispatchParams.server) {
16192
17388
  return {
16193
17389
  content: [{ type: "text", text: "auth-complete requires `server`." }],
16194
17390
  details: { mode: "auth-complete", error: "missing_server" }
@@ -16201,27 +17397,27 @@ function installMcpAdapter(pi, options) {
16201
17397
  details: { mode: "auth-complete", error: "missing_input" }
16202
17398
  };
16203
17399
  }
16204
- return signal ? executeAuthComplete(state, params.server, input, signal) : executeAuthComplete(state, params.server, input);
17400
+ return signal ? executeAuthComplete(state, dispatchParams.server, input, signal) : executeAuthComplete(state, dispatchParams.server, input);
16205
17401
  }
16206
- if (params.tool) {
16207
- return executeCall(state, params.tool, parsedArgs, params.server, getPiTools, signal);
17402
+ if (dispatchParams.tool) {
17403
+ return executeCall(state, dispatchParams.tool, parsedArgs, dispatchParams.server, getPiTools, signal);
16208
17404
  }
16209
- if (params.connect) {
16210
- const result = await executeConnect(state, params.connect, signal);
17405
+ if (dispatchParams.connect) {
17406
+ const result = await executeConnect(state, dispatchParams.connect, signal);
16211
17407
  syncToolSurface(_ctx);
16212
17408
  return result;
16213
17409
  }
16214
- if (params.describe) {
16215
- return executeDescribe(state, params.describe);
17410
+ if (dispatchParams.describe) {
17411
+ return executeDescribe(state, dispatchParams.describe);
16216
17412
  }
16217
- if (params.instructions) {
16218
- return executeInstructions(state, params.instructions);
17413
+ if (dispatchParams.instructions) {
17414
+ return executeInstructions(state, dispatchParams.instructions);
16219
17415
  }
16220
- if (params.search !== void 0) {
16221
- return executeSearch(state, params.search, params.regex, params.server, params.includeSchemas, params.limit, params.offset);
17416
+ if (dispatchParams.search !== void 0) {
17417
+ return executeSearch(state, dispatchParams.search, dispatchParams.regex, dispatchParams.server, dispatchParams.includeSchemas, dispatchParams.limit, dispatchParams.offset);
16222
17418
  }
16223
- if (params.server) {
16224
- return executeList(state, params.server);
17419
+ if (dispatchParams.server) {
17420
+ return executeList(state, dispatchParams.server);
16225
17421
  }
16226
17422
  return executeStatus(state);
16227
17423
  }
@@ -16269,11 +17465,20 @@ function createMcpAdapter(options = {}) {
16269
17465
  });
16270
17466
  };
16271
17467
  }
17468
+ function registerMcpServer(options) {
17469
+ const { pi, name, definition } = options;
17470
+ const register = runtimeRegistrars.get(pi);
17471
+ if (!register) {
17472
+ throw new Error("pi-mcp-adapter is not installed for this Pi instance");
17473
+ }
17474
+ return register(name, definition);
17475
+ }
16272
17476
  var index_default = createMcpAdapter();
16273
17477
  export {
16274
17478
  MCP_STATUS_EVENT,
16275
17479
  MCP_STATUS_SNAPSHOT_VERSION,
16276
17480
  MCP_TOOL_APPROVAL_REQUEST_EVENT,
16277
17481
  createMcpAdapter,
16278
- index_default as default
17482
+ index_default as default,
17483
+ registerMcpServer
16279
17484
  };