@ashx-j/lunr-dev 0.2.13-dev.8.1 → 0.2.16-dev.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (339) hide show
  1. package/CHANGELOG.md +29 -1
  2. package/dist/builtin-extensions/ashxj-tui.d.ts +14 -0
  3. package/dist/builtin-extensions/ashxj-tui.d.ts.map +1 -1
  4. package/dist/builtin-extensions/ashxj-tui.js +37 -3
  5. package/dist/builtin-extensions/ashxj-tui.js.map +1 -1
  6. package/dist/builtin-extensions/index.d.ts +1 -15
  7. package/dist/builtin-extensions/index.d.ts.map +1 -1
  8. package/dist/builtin-extensions/index.js +7 -21
  9. package/dist/builtin-extensions/index.js.map +1 -1
  10. package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.d.ts.map +1 -1
  11. package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.js +6 -2
  12. package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.js.map +1 -1
  13. package/dist/builtin-extensions/pi-lsp-extension/src/index.d.ts +4 -0
  14. package/dist/builtin-extensions/pi-lsp-extension/src/index.d.ts.map +1 -1
  15. package/dist/builtin-extensions/pi-lsp-extension/src/index.js +163 -169
  16. package/dist/builtin-extensions/pi-lsp-extension/src/index.js.map +1 -1
  17. package/dist/builtin-extensions/pi-lsp-extension/src/runtime.d.ts +46 -0
  18. package/dist/builtin-extensions/pi-lsp-extension/src/runtime.d.ts.map +1 -0
  19. package/dist/builtin-extensions/pi-lsp-extension/src/runtime.js +109 -0
  20. package/dist/builtin-extensions/pi-lsp-extension/src/runtime.js.map +1 -0
  21. package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.d.ts +7 -0
  22. package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.d.ts.map +1 -0
  23. package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.js +211 -0
  24. package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.js.map +1 -0
  25. package/dist/builtin-extensions/pi-mcp-adapter/direct-tools.d.ts +0 -5
  26. package/dist/builtin-extensions/pi-mcp-adapter/direct-tools.d.ts.map +1 -1
  27. package/dist/builtin-extensions/pi-mcp-adapter/direct-tools.js +0 -202
  28. package/dist/builtin-extensions/pi-mcp-adapter/direct-tools.js.map +1 -1
  29. package/dist/builtin-extensions/pi-mcp-adapter/index.d.ts.map +1 -1
  30. package/dist/builtin-extensions/pi-mcp-adapter/index.js +251 -94
  31. package/dist/builtin-extensions/pi-mcp-adapter/index.js.map +1 -1
  32. package/dist/builtin-extensions/pi-mcp-adapter/init.d.ts +4 -1
  33. package/dist/builtin-extensions/pi-mcp-adapter/init.d.ts.map +1 -1
  34. package/dist/builtin-extensions/pi-mcp-adapter/init.js +10 -3
  35. package/dist/builtin-extensions/pi-mcp-adapter/init.js.map +1 -1
  36. package/dist/builtin-extensions/pi-mcp-adapter/metadata-cache.d.ts.map +1 -1
  37. package/dist/builtin-extensions/pi-mcp-adapter/metadata-cache.js +6 -1
  38. package/dist/builtin-extensions/pi-mcp-adapter/metadata-cache.js.map +1 -1
  39. package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.d.ts.map +1 -1
  40. package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.js +2 -1
  41. package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.js.map +1 -1
  42. package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.d.ts +1 -1
  43. package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.d.ts.map +1 -1
  44. package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.js +1 -1
  45. package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.js.map +1 -1
  46. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts +1 -1
  47. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  48. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +38 -14
  49. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  50. package/dist/builtin-extensions/pi-subagents/src/shared/fork-context.d.ts.map +1 -1
  51. package/dist/builtin-extensions/pi-subagents/src/shared/fork-context.js +1 -1
  52. package/dist/builtin-extensions/pi-subagents/src/shared/fork-context.js.map +1 -1
  53. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts +1 -1
  54. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts.map +1 -1
  55. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js +1 -1
  56. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js.map +1 -1
  57. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +1 -1
  58. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
  59. package/dist/builtin-extensions/pi-subagents/src/tui/render.js +2 -1
  60. package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
  61. package/dist/builtin-extensions/pi-subagents/src/watchdog/review.d.ts +1 -1
  62. package/dist/builtin-extensions/pi-subagents/src/watchdog/review.d.ts.map +1 -1
  63. package/dist/builtin-extensions/pi-subagents/src/watchdog/review.js +2 -1
  64. package/dist/builtin-extensions/pi-subagents/src/watchdog/review.js.map +1 -1
  65. package/dist/builtin-extensions/pi-web-access/extract.d.ts.map +1 -1
  66. package/dist/builtin-extensions/pi-web-access/extract.js +105 -54
  67. package/dist/builtin-extensions/pi-web-access/extract.js.map +1 -1
  68. package/dist/builtin-extensions/pi-web-access/gemini-search.d.ts +1 -1
  69. package/dist/builtin-extensions/pi-web-access/gemini-search.d.ts.map +1 -1
  70. package/dist/builtin-extensions/pi-web-access/gemini-search.js +82 -65
  71. package/dist/builtin-extensions/pi-web-access/gemini-search.js.map +1 -1
  72. package/dist/builtin-extensions/pi-web-access/github-extract.d.ts.map +1 -1
  73. package/dist/builtin-extensions/pi-web-access/github-extract.js +2 -0
  74. package/dist/builtin-extensions/pi-web-access/github-extract.js.map +1 -1
  75. package/dist/builtin-extensions/pi-web-access/index.d.ts.map +1 -1
  76. package/dist/builtin-extensions/pi-web-access/index.js +167 -77
  77. package/dist/builtin-extensions/pi-web-access/index.js.map +1 -1
  78. package/dist/builtin-extensions/pi-web-access/lazy.d.ts +18 -0
  79. package/dist/builtin-extensions/pi-web-access/lazy.d.ts.map +1 -0
  80. package/dist/builtin-extensions/pi-web-access/lazy.js +19 -0
  81. package/dist/builtin-extensions/pi-web-access/lazy.js.map +1 -0
  82. package/dist/builtin-extensions/pi-web-access/session-cleanup.d.ts +6 -0
  83. package/dist/builtin-extensions/pi-web-access/session-cleanup.d.ts.map +1 -0
  84. package/dist/builtin-extensions/pi-web-access/session-cleanup.js +17 -0
  85. package/dist/builtin-extensions/pi-web-access/session-cleanup.js.map +1 -0
  86. package/dist/catalog/publication.json +12 -12
  87. package/dist/cli-runtime.d.ts +3 -0
  88. package/dist/cli-runtime.d.ts.map +1 -0
  89. package/dist/cli-runtime.js +73 -0
  90. package/dist/cli-runtime.js.map +1 -0
  91. package/dist/cli.d.ts.map +1 -1
  92. package/dist/cli.js +14 -53
  93. package/dist/cli.js.map +1 -1
  94. package/dist/config.d.ts +1 -0
  95. package/dist/config.d.ts.map +1 -1
  96. package/dist/config.js +1 -0
  97. package/dist/config.js.map +1 -1
  98. package/dist/core/agent-session.d.ts +3 -0
  99. package/dist/core/agent-session.d.ts.map +1 -1
  100. package/dist/core/agent-session.js +56 -12
  101. package/dist/core/agent-session.js.map +1 -1
  102. package/dist/core/compaction/compaction.d.ts.map +1 -1
  103. package/dist/core/compaction/compaction.js +10 -5
  104. package/dist/core/compaction/compaction.js.map +1 -1
  105. package/dist/core/extensions/host-static.d.ts.map +1 -1
  106. package/dist/core/extensions/host-static.js +34 -12
  107. package/dist/core/extensions/host-static.js.map +1 -1
  108. package/dist/core/extensions/loader.d.ts +1 -2
  109. package/dist/core/extensions/loader.d.ts.map +1 -1
  110. package/dist/core/extensions/loader.js +10 -64
  111. package/dist/core/extensions/loader.js.map +1 -1
  112. package/dist/core/extensions/types.d.ts +2 -2
  113. package/dist/core/extensions/types.d.ts.map +1 -1
  114. package/dist/core/extensions/types.js.map +1 -1
  115. package/dist/core/footer-data-provider.d.ts.map +1 -1
  116. package/dist/core/footer-data-provider.js +2 -0
  117. package/dist/core/footer-data-provider.js.map +1 -1
  118. package/dist/core/permissions.d.ts +0 -2
  119. package/dist/core/permissions.d.ts.map +1 -1
  120. package/dist/core/permissions.js +10 -18
  121. package/dist/core/permissions.js.map +1 -1
  122. package/dist/core/sdk.d.ts +1 -1
  123. package/dist/core/sdk.d.ts.map +1 -1
  124. package/dist/core/sdk.js +1 -1
  125. package/dist/core/sdk.js.map +1 -1
  126. package/dist/core/slash-commands.d.ts.map +1 -1
  127. package/dist/core/slash-commands.js +0 -1
  128. package/dist/core/slash-commands.js.map +1 -1
  129. package/dist/core/timings.d.ts +2 -1
  130. package/dist/core/timings.d.ts.map +1 -1
  131. package/dist/core/timings.js +17 -2
  132. package/dist/core/timings.js.map +1 -1
  133. package/dist/gateway/commands.d.ts +1 -1
  134. package/dist/gateway/commands.d.ts.map +1 -1
  135. package/dist/gateway/commands.js +1 -18
  136. package/dist/gateway/commands.js.map +1 -1
  137. package/dist/main.d.ts +2 -2
  138. package/dist/main.d.ts.map +1 -1
  139. package/dist/main.js +57 -48
  140. package/dist/main.js.map +1 -1
  141. package/dist/modes/interactive/interactive-mode.d.ts +12 -21
  142. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  143. package/dist/modes/interactive/interactive-mode.js +120 -144
  144. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  145. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  146. package/dist/modes/interactive/theme/theme.js +95 -84
  147. package/dist/modes/interactive/theme/theme.js.map +1 -1
  148. package/dist/node-runtime/agent-session-services-IFJMSX7Z.js +36 -0
  149. package/dist/node-runtime/benchmark-request-UC7PD3V3.js +57 -0
  150. package/dist/node-runtime/brave-UWDA3I22.js +143 -0
  151. package/dist/node-runtime/builtin-extensions-LYZ3BFWQ.js +28 -0
  152. package/dist/node-runtime/chunk-2QKLKMKC.js +173 -0
  153. package/dist/node-runtime/chunk-3GHXVUAK.js +21 -0
  154. package/dist/node-runtime/chunk-3RCWXWAY.js +466 -0
  155. package/dist/node-runtime/chunk-3WFAEVKS.js +115 -0
  156. package/dist/node-runtime/chunk-3X3KZKMI.js +49 -0
  157. package/dist/node-runtime/chunk-4HXHDDCF.js +16 -0
  158. package/dist/node-runtime/chunk-4TLO4PO2.js +3427 -0
  159. package/dist/node-runtime/chunk-4ZWGEEAS.js +69 -0
  160. package/dist/node-runtime/chunk-53YJI7JU.js +137 -0
  161. package/dist/node-runtime/chunk-5P7PZMRU.js +610 -0
  162. package/dist/node-runtime/chunk-7N3YHTYF.js +26 -0
  163. package/dist/node-runtime/chunk-7NBZ5P7I.js +24 -0
  164. package/dist/node-runtime/chunk-A2KQXUJD.js +105 -0
  165. package/dist/node-runtime/chunk-AD6VXAO7.js +342 -0
  166. package/dist/node-runtime/chunk-AHSTJBIB.js +64 -0
  167. package/dist/node-runtime/chunk-AJX357CL.js +20211 -0
  168. package/dist/node-runtime/chunk-ARC4KOTI.js +11178 -0
  169. package/dist/node-runtime/chunk-AUXVGBO4.js +19 -0
  170. package/dist/node-runtime/chunk-AY6CAJSL.js +30 -0
  171. package/dist/node-runtime/chunk-BHO7O6E5.js +296 -0
  172. package/dist/node-runtime/chunk-BI3DHYCN.js +8845 -0
  173. package/dist/node-runtime/chunk-BR7YDUKA.js +109 -0
  174. package/dist/node-runtime/chunk-BRJX2PRC.js +53 -0
  175. package/dist/node-runtime/chunk-C4O2RSQQ.js +37 -0
  176. package/dist/node-runtime/chunk-CCZJ3PYY.js +17 -0
  177. package/dist/node-runtime/chunk-CDFZEWPU.js +8388 -0
  178. package/dist/node-runtime/chunk-CGBXPL3E.js +1171 -0
  179. package/dist/node-runtime/chunk-CJECDQKP.js +19 -0
  180. package/dist/node-runtime/chunk-DAPBPCBP.js +53 -0
  181. package/dist/node-runtime/chunk-DDGMHUOW.js +305 -0
  182. package/dist/node-runtime/chunk-DMMTJQMQ.js +43 -0
  183. package/dist/node-runtime/chunk-DVGWF6A2.js +1180 -0
  184. package/dist/node-runtime/chunk-ECD5L7YI.js +1369 -0
  185. package/dist/node-runtime/chunk-EDBJNRSM.js +46 -0
  186. package/dist/node-runtime/chunk-F4VQFJI2.js +1269 -0
  187. package/dist/node-runtime/chunk-FVDOXRUD.js +96 -0
  188. package/dist/node-runtime/chunk-GZQHMEWL.js +126 -0
  189. package/dist/node-runtime/chunk-H2EOZYMP.js +57 -0
  190. package/dist/node-runtime/chunk-HQCKFM2O.js +56 -0
  191. package/dist/node-runtime/chunk-HYHJIRDW.js +19 -0
  192. package/dist/node-runtime/chunk-I6R76AG7.js +22 -0
  193. package/dist/node-runtime/chunk-IPA627GP.js +296 -0
  194. package/dist/node-runtime/chunk-JHYKXIMM.js +378 -0
  195. package/dist/node-runtime/chunk-KKSIVROT.js +88 -0
  196. package/dist/node-runtime/chunk-LZAW4ZX3.js +633 -0
  197. package/dist/node-runtime/chunk-M3LZLQW2.js +98 -0
  198. package/dist/node-runtime/chunk-MGWCVY6Y.js +47 -0
  199. package/dist/node-runtime/chunk-MJQDX3BA.js +72 -0
  200. package/dist/node-runtime/chunk-MKKH27PH.js +8956 -0
  201. package/dist/node-runtime/chunk-MX3GJNXJ.js +986 -0
  202. package/dist/node-runtime/chunk-N77MY65L.js +966 -0
  203. package/dist/node-runtime/chunk-NUIFPZWX.js +209 -0
  204. package/dist/node-runtime/chunk-OBMWP3I5.js +68 -0
  205. package/dist/node-runtime/chunk-OR4L3IB2.js +42 -0
  206. package/dist/node-runtime/chunk-PBC2Y6GS.js +903 -0
  207. package/dist/node-runtime/chunk-PCGNAY2O.js +1324 -0
  208. package/dist/node-runtime/chunk-PCIGF2XK.js +250 -0
  209. package/dist/node-runtime/chunk-PGAJ5MO5.js +7558 -0
  210. package/dist/node-runtime/chunk-PL6JKXWI.js +3622 -0
  211. package/dist/node-runtime/chunk-PVCDKGR6.js +55 -0
  212. package/dist/node-runtime/chunk-Q4Q6D4IY.js +364 -0
  213. package/dist/node-runtime/chunk-Q5ZU2VRT.js +83 -0
  214. package/dist/node-runtime/chunk-QFWG2RVL.js +5477 -0
  215. package/dist/node-runtime/chunk-QH42CDX3.js +9451 -0
  216. package/dist/node-runtime/chunk-RQ2Q5IYR.js +72 -0
  217. package/dist/node-runtime/chunk-RQ5DNUNG.js +429 -0
  218. package/dist/node-runtime/chunk-RRIZE6QQ.js +17 -0
  219. package/dist/node-runtime/chunk-SN6G4OU6.js +4753 -0
  220. package/dist/node-runtime/chunk-SWSN6HAB.js +53 -0
  221. package/dist/node-runtime/chunk-TQNSPERU.js +949 -0
  222. package/dist/node-runtime/chunk-VRB2IYGG.js +53 -0
  223. package/dist/node-runtime/chunk-VSELYKWU.js +772 -0
  224. package/dist/node-runtime/chunk-W3CVH5RX.js +62 -0
  225. package/dist/node-runtime/chunk-WJVFOIB5.js +24921 -0
  226. package/dist/node-runtime/chunk-WOVTOV5P.js +5653 -0
  227. package/dist/node-runtime/chunk-XBWPBZBN.js +125 -0
  228. package/dist/node-runtime/chunk-XTHQ7XR7.js +509 -0
  229. package/dist/node-runtime/chunk-YF63P5ZT.js +864 -0
  230. package/dist/node-runtime/chunk-YSKSB3BJ.js +295 -0
  231. package/dist/node-runtime/chunk-ZCHMJ34K.js +130 -0
  232. package/dist/node-runtime/chunk-ZKMFUD3Q.js +2834 -0
  233. package/dist/node-runtime/cli-runtime.js +81 -0
  234. package/dist/node-runtime/clipboard-OZ63BBC6.js +12 -0
  235. package/dist/node-runtime/clipboard-image-7QR6GXVA.js +13 -0
  236. package/dist/node-runtime/command-L3LAHDIH.js +13 -0
  237. package/dist/node-runtime/commands-RL5YBW5I.js +291 -0
  238. package/dist/node-runtime/config-FMEOZSWE.js +77 -0
  239. package/dist/node-runtime/curator-server-XCM43VEF.js +3816 -0
  240. package/dist/node-runtime/customize-XEXL2DGQ.js +12 -0
  241. package/dist/node-runtime/direct-tool-executor-JVDXTO7A.js +188 -0
  242. package/dist/node-runtime/exa-LL64QZR2.js +329 -0
  243. package/dist/node-runtime/export-html-KR26FOUZ.js +150 -0
  244. package/dist/node-runtime/extension-input-RV5N6APL.js +14 -0
  245. package/dist/node-runtime/extension-selector-CPD5LWDD.js +14 -0
  246. package/dist/node-runtime/extract-XLQSJN4V.js +17 -0
  247. package/dist/node-runtime/file-sync-HCOP2QVF.js +117 -0
  248. package/dist/node-runtime/gateway-X2TI5X7F.js +2484 -0
  249. package/dist/node-runtime/gemini-api-QE7ANVDZ.js +29 -0
  250. package/dist/node-runtime/gemini-search-U7SUMPQA.js +330 -0
  251. package/dist/node-runtime/gemini-url-context-PXWCBQHK.js +103 -0
  252. package/dist/node-runtime/gemini-web-MM446SEH.js +14 -0
  253. package/dist/node-runtime/github-extract-F64RZOEA.js +619 -0
  254. package/dist/node-runtime/goal-CZQ7FFQJ.js +1831 -0
  255. package/dist/node-runtime/index.js +859 -0
  256. package/dist/node-runtime/init-NJV2T55N.js +28 -0
  257. package/dist/node-runtime/install-cli-TH7IJJQQ.js +308 -0
  258. package/dist/node-runtime/interactive-mode-KOM35YF2.js +56 -0
  259. package/dist/node-runtime/interactive-view-U6OILKF3.js +249 -0
  260. package/dist/node-runtime/lsp-manager-3ASUSO4T.js +1104 -0
  261. package/dist/node-runtime/lunr-cron-YJ5UHYRD.js +268 -0
  262. package/dist/node-runtime/main.js +54 -0
  263. package/dist/node-runtime/mcp-auth-flow-QIXHW6QN.js +32 -0
  264. package/dist/node-runtime/mcp-panel-IIGMXQGP.js +501 -0
  265. package/dist/node-runtime/mcp-setup-panel-FEK7663I.js +355 -0
  266. package/dist/node-runtime/memory-cap-3S4XRLNP.js +20 -0
  267. package/dist/node-runtime/model-tiers-NJLHUEGK.js +20 -0
  268. package/dist/node-runtime/openai-search-B3MSNCQA.js +288 -0
  269. package/dist/node-runtime/package-manager-cli-TZZHJCVI.js +749 -0
  270. package/dist/node-runtime/parallel-AI2MNSCU.js +265 -0
  271. package/dist/node-runtime/parser-manager-TQHWYDH7.js +152 -0
  272. package/dist/node-runtime/pdf-extract-IPE6H4HP.js +57 -0
  273. package/dist/node-runtime/perplexity-QVJW3I35.js +12 -0
  274. package/dist/node-runtime/pi-intercom-EEMBGQID.js +2215 -0
  275. package/dist/node-runtime/pi-mcp-adapter-QFB37AVN.js +422 -0
  276. package/dist/node-runtime/pi-ollama-cloud-4VZRMULP.js +1440 -0
  277. package/dist/node-runtime/pi-prompt-template-model-4QT4LLXF.js +3946 -0
  278. package/dist/node-runtime/pi-subagents-7XJ4H53P.js +6023 -0
  279. package/dist/node-runtime/pi-web-access-DPGAVKOA.js +1864 -0
  280. package/dist/node-runtime/print-mode-VWIRFDAC.js +12 -0
  281. package/dist/node-runtime/proxy-modes-HEEFK4KC.js +685 -0
  282. package/dist/node-runtime/rpc-entry.js +62 -0
  283. package/dist/node-runtime/rpc-mode-SJNSOA4G.js +13 -0
  284. package/dist/node-runtime/runtime-bridges-PPHNBFWL.js +14 -0
  285. package/dist/node-runtime/session-manager-MQNBYACL.js +35 -0
  286. package/dist/node-runtime/session-selector-5AZLJS6U.js +14 -0
  287. package/dist/node-runtime/settings-manager-5LF2VQWC.js +21 -0
  288. package/dist/node-runtime/src-Y7JSCK64.js +2407 -0
  289. package/dist/node-runtime/subagent-executor-5RNDEPIJ.js +8483 -0
  290. package/dist/node-runtime/summary-review-YSMXKITO.js +228 -0
  291. package/dist/node-runtime/tavily-WEZFVFP7.js +154 -0
  292. package/dist/node-runtime/timings-UAD5BEAS.js +16 -0
  293. package/dist/node-runtime/tool-renderer-MV5O452K.js +204 -0
  294. package/dist/node-runtime/update-cli-A253SZ7P.js +73 -0
  295. package/dist/node-runtime/v4-5MNC3H7G.js +424 -0
  296. package/dist/node-runtime/video-extract-OYT5WKS5.js +304 -0
  297. package/dist/node-runtime/workspace-index-6DBXSTJ6.js +163 -0
  298. package/dist/node-runtime/youtube-extract-TQYKGFGS.js +264 -0
  299. package/dist/startup/benchmark-request.d.ts +3 -0
  300. package/dist/startup/benchmark-request.d.ts.map +1 -0
  301. package/dist/startup/benchmark-request.js +65 -0
  302. package/dist/startup/benchmark-request.js.map +1 -0
  303. package/dist/startup/interactive-view.d.ts +55 -0
  304. package/dist/startup/interactive-view.d.ts.map +1 -0
  305. package/dist/startup/interactive-view.js +332 -0
  306. package/dist/startup/interactive-view.js.map +1 -0
  307. package/dist/startup/launch-routing.d.ts.map +1 -1
  308. package/dist/startup/launch-routing.js +9 -10
  309. package/dist/startup/launch-routing.js.map +1 -1
  310. package/dist/startup/startup-milestones.d.ts +1 -1
  311. package/dist/startup/startup-milestones.d.ts.map +1 -1
  312. package/dist/startup/startup-milestones.js +3 -2
  313. package/dist/startup/startup-milestones.js.map +1 -1
  314. package/dist/utils/await-with-abort.d.ts +2 -0
  315. package/dist/utils/await-with-abort.d.ts.map +1 -0
  316. package/dist/utils/await-with-abort.js +19 -0
  317. package/dist/utils/await-with-abort.js.map +1 -0
  318. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  319. package/dist/utils/syntax-highlight.js +10 -4
  320. package/dist/utils/syntax-highlight.js.map +1 -1
  321. package/docs/compaction.md +5 -3
  322. package/docs/development.md +5 -1
  323. package/docs/features.md +0 -1
  324. package/docs/interactive-startup.md +98 -0
  325. package/docs/usage.md +0 -1
  326. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  327. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  328. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  329. package/examples/extensions/gondolin/package-lock.json +2 -2
  330. package/examples/extensions/gondolin/package.json +1 -1
  331. package/examples/extensions/sandbox/package-lock.json +2 -2
  332. package/examples/extensions/sandbox/package.json +1 -1
  333. package/examples/extensions/with-deps/package-lock.json +2 -2
  334. package/examples/extensions/with-deps/package.json +1 -1
  335. package/package.json +20 -20
  336. package/dist/core/swarm.d.ts +0 -23
  337. package/dist/core/swarm.d.ts.map +0 -1
  338. package/dist/core/swarm.js +0 -45
  339. package/dist/core/swarm.js.map +0 -1
@@ -0,0 +1,1269 @@
1
+ import { createRequire as __lunrRequire } from "node:module"; const require = __lunrRequire(import.meta.url);
2
+ import {
3
+ AZ,
4
+ ServerError,
5
+ logger,
6
+ wrapError
7
+ } from "./chunk-MKKH27PH.js";
8
+ import {
9
+ UrlElicitationRequiredError
10
+ } from "./chunk-4TLO4PO2.js";
11
+ import {
12
+ UI_STREAM_HOST_CONTEXT_KEY,
13
+ UI_STREAM_REQUEST_META_KEY,
14
+ UI_STREAM_STRUCTURED_CONTENT_KEY,
15
+ extractUiPromptText,
16
+ getVisualizationStreamEnvelope
17
+ } from "./chunk-ARC4KOTI.js";
18
+
19
+ // packages/coding-agent/dist/builtin-extensions/pi-mcp-adapter/tool-registrar.js
20
+ function transformMcpContent(content) {
21
+ return content.map((c) => {
22
+ if (c.type === "text")
23
+ return { type: "text", text: c.text ?? "" };
24
+ if (c.type === "image")
25
+ return {
26
+ type: "image",
27
+ data: c.data ?? "",
28
+ mimeType: c.mimeType ?? "image/png"
29
+ };
30
+ if (c.type === "resource") {
31
+ let resourceUri = c.resource?.uri ?? "(no URI)", resourceContent = c.resource?.text ?? (c.resource ? JSON.stringify(c.resource) : "(no content)");
32
+ return {
33
+ type: "text",
34
+ text: `[Resource: ${resourceUri}]
35
+ ${resourceContent}`
36
+ };
37
+ }
38
+ if (c.type === "resource_link") {
39
+ let linkName = c.name ?? c.uri ?? "unknown", linkUri = c.uri ?? "(no URI)";
40
+ return {
41
+ type: "text",
42
+ text: `[Resource Link: ${linkName}]
43
+ URI: ${linkUri}`
44
+ };
45
+ }
46
+ return c.type === "audio" ? {
47
+ type: "text",
48
+ text: `[Audio content: ${c.mimeType ?? "audio/*"}]`
49
+ } : { type: "text", text: JSON.stringify(c) };
50
+ });
51
+ }
52
+ function resolveMcpResultContent(result) {
53
+ let blocks = transformMcpContent(Array.isArray(result.content) ? result.content : []);
54
+ return blocks.length > 0 ? blocks : result.structuredContent !== void 0 && result.structuredContent !== null ? [{ type: "text", text: stringifyStructuredContent(result.structuredContent) }] : [];
55
+ }
56
+ function stringifyStructuredContent(value) {
57
+ try {
58
+ return JSON.stringify(value, null, 2) ?? String(value);
59
+ } catch {
60
+ return String(value);
61
+ }
62
+ }
63
+
64
+ // packages/coding-agent/dist/builtin-extensions/pi-mcp-adapter/mcp-output-guard.js
65
+ import { randomBytes } from "node:crypto";
66
+ import { mkdtemp, writeFile } from "node:fs/promises";
67
+ import { tmpdir } from "node:os";
68
+ import { join } from "node:path";
69
+ var DEFAULT_MCP_OUTPUT_MAX_BYTES = 50 * 1024, DEFAULT_MCP_OUTPUT_MAX_LINES = 2e3, DEFAULT_MCP_DETAILS_MAX_BYTES = 16 * 1024, CONTENT_SUMMARY_LIMIT = 20, KEY_PREVIEW_LIMIT = 20, KEY_MAX_CHARS = 120;
70
+ function resolveMcpOutputGuardOptions(settings) {
71
+ let configured = settings?.outputGuard, tuning = typeof configured == "object" && configured !== null ? configured : void 0;
72
+ return {
73
+ enabled: envKillSwitch("MCP_OUTPUT_GUARD") ?? configured !== !1,
74
+ maxBytes: positiveInt(tuning?.maxBytes) ?? DEFAULT_MCP_OUTPUT_MAX_BYTES,
75
+ maxLines: positiveInt(tuning?.maxLines) ?? DEFAULT_MCP_OUTPUT_MAX_LINES,
76
+ detailsMaxBytes: positiveInt(tuning?.detailsMaxBytes) ?? DEFAULT_MCP_DETAILS_MAX_BYTES
77
+ };
78
+ }
79
+ function guardedMcpDetails(guarded) {
80
+ return {
81
+ ...guarded.mcpResult !== void 0 ? { mcpResult: guarded.mcpResult } : {},
82
+ ...guarded.outputGuard ? { outputGuard: guarded.outputGuard } : {}
83
+ };
84
+ }
85
+ async function guardMcpOutput(content, options = {}) {
86
+ let maxBytes = options.maxBytes ?? DEFAULT_MCP_OUTPUT_MAX_BYTES, maxLines = options.maxLines ?? DEFAULT_MCP_OUTPUT_MAX_LINES, detailsMaxBytes = options.detailsMaxBytes ?? DEFAULT_MCP_DETAILS_MAX_BYTES, prefix = options.prefix ?? "", suffix = options.suffix ?? "", normalizedContent = withEmptyTextFallback(content.length > 0 ? sanitizeContent(content) : [{ type: "text", text: options.emptyTextFallback ?? "(empty result)" }], options.emptyTextFallback);
87
+ if (options.enabled === !1)
88
+ return {
89
+ content: addAffixes(normalizedContent, prefix, suffix),
90
+ mcpResult: options.rawMcpResult
91
+ };
92
+ let imageBlocks = normalizedContent.filter((block) => block.type === "image"), textOutput = normalizedContent.filter((block) => block.type === "text").map((block) => block.text).join(`
93
+ `), composedOutput = `${prefix}${textOutput}${suffix}`, stats = textStats(composedOutput), guardedContent = addAffixes(normalizedContent, prefix, suffix), outputGuard;
94
+ if (stats.bytes > maxBytes || stats.lines > maxLines) {
95
+ let { path: fullOutputPath, error: writeError } = await saveArtifact("output", composedOutput), notice = formatTruncationNotice(stats, fullOutputPath, writeError), previewBudget = reserveBudget(maxBytes, maxLines, notice), finalText = `${truncateHead(composedOutput, previewBudget.maxBytes, previewBudget.maxLines).content}
96
+
97
+ ${notice}`, finalStats = textStats(finalText);
98
+ guardedContent = [{ type: "text", text: finalText }, ...imageBlocks], outputGuard = {
99
+ truncated: !0,
100
+ originalBytes: stats.bytes,
101
+ returnedBytes: finalStats.bytes,
102
+ originalLines: stats.lines,
103
+ returnedLines: finalStats.lines,
104
+ ...imageBlocks.length > 0 ? { imageBlocksPassedThrough: imageBlocks.length } : {},
105
+ fullOutputPath,
106
+ writeError
107
+ };
108
+ }
109
+ let mcpResult = options.rawMcpResult === void 0 ? void 0 : await boundMcpResult(options.rawMcpResult, detailsMaxBytes);
110
+ return { content: guardedContent, outputGuard, mcpResult };
111
+ }
112
+ function sanitizeContent(content) {
113
+ return content.map((block) => {
114
+ if (block.type !== "image")
115
+ return block;
116
+ let mimeType = typeof block.mimeType == "string" && block.mimeType.trim() ? block.mimeType.trim().slice(0, 100) : "image/png";
117
+ return { ...block, mimeType };
118
+ });
119
+ }
120
+ function withEmptyTextFallback(content, fallback) {
121
+ return !fallback || content.filter((block) => block.type === "text").map((block) => block.text).join(`
122
+ `) ? content : [{ type: "text", text: fallback }, ...content.filter((block) => block.type === "image")];
123
+ }
124
+ function addAffixes(content, prefix, suffix) {
125
+ if (!prefix && !suffix)
126
+ return content;
127
+ let next = [...content];
128
+ if (prefix) {
129
+ let index = next.findIndex((block2) => block2.type === "text"), block = next[index];
130
+ index >= 0 && block.type === "text" ? next[index] = { ...block, text: `${prefix}${block.text}` } : next.unshift({ type: "text", text: prefix });
131
+ }
132
+ if (suffix) {
133
+ let index = -1;
134
+ for (let i = next.length - 1; i >= 0; i--)
135
+ if (next[i].type === "text") {
136
+ index = i;
137
+ break;
138
+ }
139
+ let block = next[index];
140
+ index >= 0 && block.type === "text" ? next[index] = { ...block, text: `${block.text}${suffix}` } : next.push({ type: "text", text: suffix });
141
+ }
142
+ return next;
143
+ }
144
+ function reserveBudget(maxBytes, maxLines, notice) {
145
+ let noticeStats = textStats(`
146
+
147
+ ${notice}`);
148
+ return {
149
+ maxBytes: Math.max(0, maxBytes - noticeStats.bytes),
150
+ maxLines: Math.max(0, maxLines - noticeStats.lines)
151
+ };
152
+ }
153
+ function truncateHead(text, maxBytes, maxLines) {
154
+ let lines = text.split(`
155
+ `), output = [], bytes = 0;
156
+ for (let line of lines) {
157
+ if (output.length >= maxLines)
158
+ break;
159
+ let separatorBytes = output.length > 0 ? 1 : 0, lineBytes = byteLength(line);
160
+ if (bytes + separatorBytes + lineBytes > maxBytes) {
161
+ let remaining = maxBytes - bytes - separatorBytes;
162
+ remaining > 0 && output.push(truncateStringToBytes(line, remaining));
163
+ break;
164
+ }
165
+ output.push(line), bytes += separatorBytes + lineBytes;
166
+ }
167
+ let content = output.join(`
168
+ `), stats = textStats(content);
169
+ return { content, bytes: stats.bytes, lines: stats.lines };
170
+ }
171
+ function truncateStringToBytes(value, maxBytes) {
172
+ if (byteLength(value) <= maxBytes)
173
+ return value;
174
+ let buffer = Buffer.from(value, "utf8"), end = Math.max(0, maxBytes);
175
+ for (; end > 0 && (buffer[end] & 192) === 128; )
176
+ end--;
177
+ return buffer.subarray(0, end).toString("utf8");
178
+ }
179
+ function formatTruncationNotice(stats, fullOutputPath, writeError) {
180
+ let base = `[MCP text output truncated: original ${stats.lines.toLocaleString()} lines / ${formatSize(stats.bytes)}.`;
181
+ return fullOutputPath ? `${base} Full text saved to: ${fullOutputPath} \u2014 use read with offset/limit or grep to inspect.]` : `${base} Full output could not be saved: ${writeError ?? "unknown error"}]`;
182
+ }
183
+ async function boundMcpResult(result, detailsMaxBytes) {
184
+ let raw = safeStringify(result), rawBytes = byteLength(raw);
185
+ return rawBytes <= detailsMaxBytes ? result : summarizeMcpResult(result, raw, rawBytes);
186
+ }
187
+ async function summarizeMcpResult(result, raw, rawBytes) {
188
+ let { path: fullResultPath, error: resultWriteError } = await saveArtifact("mcp-result", raw), record = asRecord(result), content = Array.isArray(record?.content) ? record.content : [], summary = {
189
+ omitted: !0,
190
+ reason: "Raw MCP result exceeded the details size limit and was replaced with this summary to keep session context bounded.",
191
+ isError: record?.isError === !0,
192
+ contentBlocks: content.length,
193
+ contentSummary: summarizeContent(content),
194
+ rawResultBytes: rawBytes,
195
+ fullResultPath,
196
+ resultWriteError
197
+ };
198
+ if (record && "structuredContent" in record && (summary.structuredContent = summarizeValue(record.structuredContent)), record && "_meta" in record && (summary.meta = summarizeValue(record._meta)), record) {
199
+ let standard = /* @__PURE__ */ new Set(["content", "isError", "structuredContent", "_meta"]), extraFields = Object.keys(record).filter((key) => !standard.has(key)).slice(0, KEY_PREVIEW_LIMIT).map((key) => ({ key: truncateKey(key), type: typeof record[key], estimatedBytes: estimateValueBytes(record[key]), omitted: !0 }));
200
+ extraFields.length > 0 && (summary.extraFields = extraFields);
201
+ }
202
+ return summary;
203
+ }
204
+ function summarizeContent(content) {
205
+ let summaries = content.slice(0, CONTENT_SUMMARY_LIMIT).map((block) => {
206
+ let record = asRecord(block);
207
+ if (!record)
208
+ return { type: typeof block, omitted: !0 };
209
+ if (record.type === "text") {
210
+ let text = typeof record.text == "string" ? record.text : "";
211
+ return { type: "text", bytes: byteLength(text), lines: textStats(text).lines, textOmitted: !0 };
212
+ }
213
+ if (record.type === "image") {
214
+ let data = typeof record.data == "string" ? record.data : "";
215
+ return { type: "image", mimeType: typeof record.mimeType == "string" ? record.mimeType : void 0, dataBytes: byteLength(data), dataOmitted: !0 };
216
+ }
217
+ return { type: typeof record.type == "string" ? record.type : "unknown", estimatedBytes: estimateValueBytes(record), omitted: !0 };
218
+ });
219
+ return content.length > CONTENT_SUMMARY_LIMIT && summaries.push({ type: "omitted", count: content.length - CONTENT_SUMMARY_LIMIT }), summaries;
220
+ }
221
+ function summarizeValue(value) {
222
+ let record = asRecord(value);
223
+ if (!record)
224
+ return { type: value === null ? "null" : typeof value, estimatedBytes: estimateValueBytes(value), omitted: !0 };
225
+ let keys = Object.keys(record);
226
+ return {
227
+ type: Array.isArray(value) ? "array" : "object",
228
+ estimatedBytes: estimateValueBytes(value),
229
+ keyCount: keys.length,
230
+ keysPreview: keys.slice(0, KEY_PREVIEW_LIMIT).map(truncateKey),
231
+ omitted: !0
232
+ };
233
+ }
234
+ function estimateValueBytes(value, depth = 0) {
235
+ if (value == null)
236
+ return 0;
237
+ if (typeof value == "string")
238
+ return byteLength(value);
239
+ if (typeof value == "number" || typeof value == "boolean" || typeof value == "bigint")
240
+ return byteLength(String(value));
241
+ let record = asRecord(value);
242
+ return !record || depth >= 2 ? 0 : (Array.isArray(value) ? value.slice(0, KEY_PREVIEW_LIMIT) : Object.values(record).slice(0, KEY_PREVIEW_LIMIT)).reduce((total, item) => total + estimateValueBytes(item, depth + 1), 0);
243
+ }
244
+ function truncateKey(key) {
245
+ return key.length <= KEY_MAX_CHARS ? key : `${key.slice(0, KEY_MAX_CHARS - 1)}\u2026`;
246
+ }
247
+ async function saveArtifact(kind, text) {
248
+ try {
249
+ let dir = await mkdtemp(join(tmpdir(), "pi-mcp-output-")), path2 = join(dir, `${kind}-${randomBytes(4).toString("hex")}.txt`);
250
+ return await writeFile(path2, text, { encoding: "utf8", mode: 384 }), { path: path2 };
251
+ } catch (error) {
252
+ return { error: error instanceof Error ? error.message : String(error) };
253
+ }
254
+ }
255
+ function asRecord(value) {
256
+ return typeof value == "object" && value !== null ? value : void 0;
257
+ }
258
+ function safeStringify(value) {
259
+ try {
260
+ return JSON.stringify(value, null, 2);
261
+ } catch {
262
+ return String(value);
263
+ }
264
+ }
265
+ function textStats(text) {
266
+ return { bytes: byteLength(text), lines: text.length === 0 ? 0 : text.split(`
267
+ `).length };
268
+ }
269
+ function byteLength(text) {
270
+ return Buffer.byteLength(text, "utf8");
271
+ }
272
+ function positiveInt(value) {
273
+ if (typeof value != "number" || !Number.isFinite(value))
274
+ return;
275
+ let integer = Math.floor(value);
276
+ return integer > 0 ? integer : void 0;
277
+ }
278
+ function envKillSwitch(name) {
279
+ let value = process.env[name]?.trim().toLowerCase();
280
+ if (value) {
281
+ if (["0", "false", "no", "off"].includes(value))
282
+ return !1;
283
+ if (["1", "true", "yes", "on"].includes(value))
284
+ return !0;
285
+ }
286
+ }
287
+ function formatSize(bytes) {
288
+ return bytes < 1024 ? `${bytes} B` : bytes < 1024 * 1024 ? `${(bytes / 1024).toFixed(1)} KiB` : `${(bytes / (1024 * 1024)).toFixed(1)} MiB`;
289
+ }
290
+
291
+ // packages/coding-agent/dist/builtin-extensions/pi-mcp-adapter/ui-session.js
292
+ import { randomUUID as randomUUID2 } from "node:crypto";
293
+
294
+ // packages/coding-agent/dist/builtin-extensions/pi-mcp-adapter/ui-server.js
295
+ import http from "node:http";
296
+ import fs from "node:fs/promises";
297
+ import path from "node:path";
298
+ import { randomUUID } from "node:crypto";
299
+
300
+ // packages/coding-agent/dist/builtin-extensions/pi-mcp-adapter/host-html-template.js
301
+ var DEFAULT_APP_BRIDGE_MODULE_URL = "/app-bridge.bundle.js";
302
+ function buildHostHtmlTemplate(input) {
303
+ let cspContent = buildCspMetaContent(input.resource.meta.csp), resourceHtml = applyCspMeta(input.resource.html, cspContent), hostContext = input.hostContext ?? {}, sessionToken = safeInlineJSON(input.sessionToken), toolArgs = safeInlineJSON(input.toolArgs), uiHtml = safeInlineJSON(resourceHtml), serverName = safeInlineJSON(input.serverName), toolName = safeInlineJSON(input.toolName), hostContextJson = safeInlineJSON(hostContext), allowAttribute = safeInlineJSON(input.allowAttribute), requireToolConsent = safeInlineJSON(input.requireToolConsent), cacheToolConsent = safeInlineJSON(input.cacheToolConsent), moduleUrl = safeInlineJSON(input.appBridgeModuleUrl ?? DEFAULT_APP_BRIDGE_MODULE_URL);
304
+ return `<!doctype html>
305
+ <html lang="en">
306
+ <head>
307
+ <meta charset="utf-8" />
308
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
309
+ <title>MCP UI - ${escapeHtml(input.serverName)} / ${escapeHtml(input.toolName)}</title>
310
+ <style>
311
+ :root {
312
+ color-scheme: light dark;
313
+ --bg: #0f1115;
314
+ --surface: #181c22;
315
+ --text: #ecf0f5;
316
+ --muted: #a9b2bf;
317
+ --accent: #43c0ff;
318
+ --border: rgba(255, 255, 255, 0.12);
319
+ --good: #34d399;
320
+ --warn: #fbbf24;
321
+ --bad: #f87171;
322
+ }
323
+ @media (prefers-color-scheme: light) {
324
+ :root {
325
+ --bg: #f6f7fb;
326
+ --surface: #ffffff;
327
+ --text: #1d2939;
328
+ --muted: #667085;
329
+ --accent: #0ea5e9;
330
+ --border: rgba(15, 23, 42, 0.14);
331
+ --good: #059669;
332
+ --warn: #b45309;
333
+ --bad: #b91c1c;
334
+ }
335
+ }
336
+ * { box-sizing: border-box; }
337
+ html, body { margin: 0; padding: 0; height: 100%; font-family: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: var(--bg); color: var(--text); }
338
+ body { display: flex; flex-direction: column; min-height: 100vh; }
339
+ header { background: var(--surface); border-bottom: 1px solid var(--border); padding: 10px 14px; display: flex; align-items: center; justify-content: space-between; gap: 10px; }
340
+ .title { display: flex; gap: 8px; align-items: baseline; min-width: 0; }
341
+ .server { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; white-space: nowrap; }
342
+ .tool { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
343
+ .badge { border: 1px solid var(--border); border-radius: 999px; padding: 2px 8px; font-size: 11px; color: var(--muted); white-space: nowrap; }
344
+ .controls { display: flex; gap: 8px; align-items: center; }
345
+ .status { font-size: 12px; color: var(--muted); white-space: nowrap; }
346
+ button { border: 1px solid var(--border); background: transparent; color: var(--text); border-radius: 8px; padding: 6px 10px; cursor: pointer; font-size: 12px; }
347
+ button.primary { border-color: color-mix(in srgb, var(--good) 40%, var(--border) 60%); color: var(--good); }
348
+ button.danger { border-color: color-mix(in srgb, var(--bad) 40%, var(--border) 60%); color: var(--bad); }
349
+ button:hover { background: color-mix(in srgb, var(--surface) 75%, var(--accent) 25%); }
350
+ main { flex: 1; min-height: 0; padding: 10px; display: flex; }
351
+ iframe { width: 100%; height: 100%; border: 1px solid var(--border); border-radius: 10px; background: white; }
352
+ .overlay { position: fixed; inset: 0; background: color-mix(in srgb, var(--bg) 90%, black 10%); display: none; align-items: center; justify-content: center; z-index: 2; }
353
+ .overlay.visible { display: flex; }
354
+ .panel { width: min(680px, calc(100vw - 40px)); background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 18px; }
355
+ .panel h2 { margin: 0 0 8px; font-size: 16px; }
356
+ .panel p { margin: 0; color: var(--muted); line-height: 1.4; font-size: 14px; white-space: pre-wrap; }
357
+ </style>
358
+ </head>
359
+ <body>
360
+ <header>
361
+ <div class="title">
362
+ <span class="server">MCP \xB7 <span id="server-name"></span></span>
363
+ <span class="tool" id="tool-name"></span>
364
+ <span class="badge">Sandboxed</span>
365
+ </div>
366
+ <div class="controls">
367
+ <span class="status" id="status">Loading UI...</span>
368
+ <button class="primary" id="done-btn" title="Cmd/Ctrl+Enter">Done</button>
369
+ <button class="danger" id="cancel-btn" title="Escape">Cancel</button>
370
+ </div>
371
+ </header>
372
+ <main>
373
+ <iframe id="mcp-app" referrerpolicy="no-referrer"></iframe>
374
+ </main>
375
+ <div class="overlay" id="error-overlay">
376
+ <div class="panel">
377
+ <h2>UI Error</h2>
378
+ <p id="error-message"></p>
379
+ </div>
380
+ </div>
381
+ <script type="module">
382
+ import { AppBridge, PostMessageTransport } from ${moduleUrl};
383
+
384
+ const SESSION_TOKEN = ${sessionToken};
385
+ const SERVER_NAME = ${serverName};
386
+ const TOOL_NAME = ${toolName};
387
+ const TOOL_ARGS = ${toolArgs};
388
+ const HOST_CONTEXT = ${hostContextJson};
389
+ const ALLOW_ATTRIBUTE = ${allowAttribute};
390
+ const REQUIRE_TOOL_CONSENT = ${requireToolConsent};
391
+ const CACHE_TOOL_CONSENT = ${cacheToolConsent};
392
+ const STREAM_CONTEXT_KEY = "pi-mcp-adapter/stream";
393
+ const STREAM_PATCH_METHOD = "notifications/pi-mcp-adapter/ui-result-patch";
394
+
395
+ const iframe = document.getElementById("mcp-app");
396
+ const statusNode = document.getElementById("status");
397
+ const doneBtn = document.getElementById("done-btn");
398
+ const cancelBtn = document.getElementById("cancel-btn");
399
+ const errorOverlay = document.getElementById("error-overlay");
400
+ const errorMessage = document.getElementById("error-message");
401
+
402
+ document.getElementById("server-name").textContent = SERVER_NAME;
403
+ document.getElementById("tool-name").textContent = TOOL_NAME;
404
+
405
+ const setStatus = (text, isError = false) => {
406
+ statusNode.textContent = text;
407
+ statusNode.style.color = isError ? "var(--bad)" : "var(--muted)";
408
+ };
409
+
410
+ const showError = (message) => {
411
+ errorMessage.textContent = message;
412
+ errorOverlay.classList.add("visible");
413
+ setStatus("Error", true);
414
+ };
415
+
416
+ const post = async (endpoint, params) => {
417
+ const response = await fetch(endpoint, {
418
+ method: "POST",
419
+ headers: { "Content-Type": "application/json" },
420
+ body: JSON.stringify({ token: SESSION_TOKEN, params }),
421
+ });
422
+
423
+ const body = await response.json().catch(() => ({ ok: false, error: "Invalid JSON response" }));
424
+ if (!response.ok || !body.ok) {
425
+ const message = body.error || ("HTTP " + response.status);
426
+ throw new Error(message);
427
+ }
428
+ return body.result ?? {};
429
+ };
430
+
431
+ let consentGranted = !REQUIRE_TOOL_CONSENT;
432
+ const initialStreamContext = HOST_CONTEXT?.[STREAM_CONTEXT_KEY];
433
+ const streamMode = initialStreamContext?.mode === "stream-first" ? "stream-first" : "eager";
434
+
435
+ const bridge = new AppBridge(
436
+ null,
437
+ { name: "pi", version: "1.0.0" },
438
+ { serverTools: {}, openLinks: {}, logging: {}, updateModelContext: {}, message: {} },
439
+ { hostContext: HOST_CONTEXT }
440
+ );
441
+
442
+ bridge.oncalltool = async (params) => {
443
+ if (!consentGranted) {
444
+ const accepted = window.confirm("Allow this UI to call server tools for this session?");
445
+ if (!accepted) {
446
+ await post("/proxy/ui/consent", { approved: false }).catch(() => {});
447
+ return {
448
+ isError: true,
449
+ content: [{ type: "text", text: "Tool call denied by user." }],
450
+ };
451
+ }
452
+ await post("/proxy/ui/consent", { approved: true });
453
+ if (CACHE_TOOL_CONSENT) {
454
+ consentGranted = true;
455
+ }
456
+ }
457
+ const result = await post("/proxy/tools/call", params);
458
+ // Notify agent about the tool call
459
+ await post("/proxy/ui/message", {
460
+ type: "intent",
461
+ intent: "call_tool",
462
+ params: { tool: params.name, arguments: params.arguments, isError: result.isError }
463
+ }).catch(() => {});
464
+ return result;
465
+ };
466
+
467
+ bridge.onmessage = async (params) => post("/proxy/ui/message", params);
468
+ bridge.onupdatemodelcontext = async (params) => post("/proxy/ui/context", params);
469
+
470
+ // Also listen for raw postMessage events with custom types (notify, prompt, intent, etc.)
471
+ // These bypass the AppBridge protocol but are used by some MCP UI implementations
472
+ window.addEventListener("message", async (event) => {
473
+ const data = event.data;
474
+ if (!data || typeof data !== "object") return;
475
+
476
+ // Skip AppBridge protocol messages (handled by bridge)
477
+ if (data.jsonrpc || (typeof data.method === "string" && (data.method.startsWith("app/") || data.method.startsWith("host/")))) return;
478
+
479
+ // Handle raw UI action messages
480
+ const msgType = data.type;
481
+ if (typeof msgType !== "string") return;
482
+
483
+ if (msgType === "notify" || msgType === "prompt" || msgType === "intent" || msgType === "message") {
484
+ // Standard MCP-UI types - preserve their semantics
485
+ // Support both { type, payload: {...} } and { type, field: value } formats
486
+ const { type: _, payload, ...directFields } = data;
487
+ await post("/proxy/ui/message", { type: msgType, ...directFields, ...(payload || {}) }).catch(() => {});
488
+ } else if (!msgType.startsWith("ui-lifecycle-") && !msgType.startsWith("ui-message-")) {
489
+ // Any other custom type - forward as intent with type as intent name
490
+ // (Skip internal lifecycle/ack messages)
491
+ const payload = data.payload || {};
492
+ await post("/proxy/ui/message", {
493
+ type: "intent",
494
+ intent: msgType,
495
+ params: payload,
496
+ }).catch(() => {});
497
+ }
498
+ });
499
+ bridge.ondownloadfile = async (params) => post("/proxy/ui/download-file", params);
500
+ bridge.onrequestdisplaymode = async (params) => post("/proxy/ui/request-display-mode", params);
501
+ bridge.onopenlink = async (params) => {
502
+ const result = await post("/proxy/ui/open-link", params);
503
+ if (!result.isError) {
504
+ window.open(params.url, "_blank", "noopener,noreferrer");
505
+ // Notify agent about the link open
506
+ await post("/proxy/ui/message", {
507
+ type: "intent",
508
+ intent: "open_link",
509
+ params: { url: params.url }
510
+ }).catch(() => {});
511
+ }
512
+ return result;
513
+ };
514
+
515
+ bridge.oninitialized = () => {
516
+ if (streamMode !== "stream-first") {
517
+ bridge.sendToolInput({ arguments: TOOL_ARGS });
518
+ }
519
+ setStatus(streamMode === "stream-first" ? "Streaming\u2026" : "Connected");
520
+ };
521
+
522
+ bridge.onsizechange = ({ width, height }) => {
523
+ if (typeof width === "number" && width > 0) {
524
+ iframe.style.minWidth = Math.min(width, window.innerWidth - 24) + "px";
525
+ }
526
+ if (typeof height === "number" && height > 0) {
527
+ iframe.style.height = Math.max(height, 320) + "px";
528
+ }
529
+ };
530
+
531
+ if (ALLOW_ATTRIBUTE) {
532
+ iframe.setAttribute("allow", ALLOW_ATTRIBUTE);
533
+ }
534
+
535
+ // Connect bridge BEFORE loading iframe to ensure we're listening when the app sends ui/initialize
536
+ try {
537
+ const transport = new PostMessageTransport(iframe.contentWindow, null);
538
+ await bridge.connect(transport);
539
+ } catch (error) {
540
+ console.error("[host] Bridge connection failed:", error);
541
+ showError("Failed to initialize AppBridge: " + String(error));
542
+ }
543
+
544
+ const iframeLoaded = new Promise((resolve) => {
545
+ iframe.onload = resolve;
546
+ });
547
+ iframe.src = "/ui-app?session=" + encodeURIComponent(SESSION_TOKEN);
548
+ await iframeLoaded;
549
+
550
+ const eventSource = new EventSource("/events?session=" + encodeURIComponent(SESSION_TOKEN));
551
+ eventSource.addEventListener("tool-input", (event) => {
552
+ try {
553
+ bridge.sendToolInput(JSON.parse(event.data));
554
+ } catch (error) {
555
+ showError("Failed to forward tool input: " + String(error));
556
+ }
557
+ });
558
+ eventSource.addEventListener("tool-result", (event) => {
559
+ try {
560
+ bridge.sendToolResult(JSON.parse(event.data));
561
+ } catch (error) {
562
+ showError("Failed to forward tool result: " + String(error));
563
+ }
564
+ });
565
+ eventSource.addEventListener("tool-cancelled", (event) => {
566
+ try {
567
+ bridge.sendToolCancelled(JSON.parse(event.data));
568
+ } catch (error) {
569
+ showError("Failed to forward cancellation: " + String(error));
570
+ }
571
+ });
572
+ eventSource.addEventListener("result-patch", async (event) => {
573
+ try {
574
+ await bridge.notification({
575
+ method: STREAM_PATCH_METHOD,
576
+ params: JSON.parse(event.data),
577
+ });
578
+ } catch (error) {
579
+ showError("Failed to forward stream patch: " + String(error));
580
+ }
581
+ });
582
+ eventSource.addEventListener("host-context", (event) => {
583
+ try {
584
+ bridge.setHostContext(JSON.parse(event.data));
585
+ } catch {}
586
+ });
587
+ eventSource.addEventListener("session-complete", async () => {
588
+ await bridge.teardownResource({}).catch(() => {});
589
+ eventSource.close();
590
+ window.close();
591
+ });
592
+ eventSource.onerror = () => {
593
+ setStatus("Connection lost", true);
594
+ };
595
+
596
+ const heartbeat = setInterval(() => {
597
+ post("/proxy/ui/heartbeat", {}).catch(() => {});
598
+ }, 10000);
599
+
600
+ const complete = async (reason) => {
601
+ try {
602
+ await post("/proxy/ui/complete", { reason });
603
+ } catch {}
604
+ try {
605
+ await bridge.teardownResource({});
606
+ } catch {}
607
+ clearInterval(heartbeat);
608
+ eventSource.close();
609
+ window.close();
610
+ };
611
+
612
+ doneBtn.addEventListener("click", () => complete("done"));
613
+ cancelBtn.addEventListener("click", () => complete("cancel"));
614
+ window.addEventListener("keydown", (event) => {
615
+ if (event.key === "Escape") {
616
+ event.preventDefault();
617
+ complete("cancel");
618
+ } else if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
619
+ event.preventDefault();
620
+ complete("done");
621
+ }
622
+ });
623
+ </script>
624
+ </body>
625
+ </html>`;
626
+ }
627
+ function buildCspMetaContent(csp) {
628
+ if (!csp)
629
+ return;
630
+ let directives = [];
631
+ directives.push("default-src 'none'");
632
+ let scriptSrc = toDirective("script-src", csp.scriptDomains), styleSrc = toDirective("style-src", csp.styleDomains), fontSrc = toDirective("font-src", csp.fontDomains), imgSrc = toDirective("img-src", csp.imgDomains), mediaSrc = toDirective("media-src", csp.mediaDomains), connectSrc = toDirective("connect-src", csp.connectDomains), frameSrc = toDirective("frame-src", csp.frameDomains), workerSrc = toDirective("worker-src", csp.workerDomains), baseUri = toDirective("base-uri", csp.baseUriDomains);
633
+ return scriptSrc && directives.push(scriptSrc), styleSrc && directives.push(styleSrc), fontSrc && directives.push(fontSrc), imgSrc && directives.push(imgSrc), mediaSrc && directives.push(mediaSrc), connectSrc && directives.push(connectSrc), frameSrc && directives.push(frameSrc), workerSrc && directives.push(workerSrc), baseUri && directives.push(baseUri), directives.join("; ");
634
+ }
635
+ function toDirective(name, domains) {
636
+ return !domains || domains.length === 0 ? null : `${name} ${domains.join(" ")}`;
637
+ }
638
+ function applyCspMeta(html, cspContent) {
639
+ if (!cspContent || /http-equiv=["']Content-Security-Policy["']/i.test(html))
640
+ return html;
641
+ let metaTag = `<meta http-equiv="Content-Security-Policy" content="${escapeHtmlAttribute(cspContent)}">`;
642
+ return /<head[^>]*>/i.test(html) ? html.replace(/<head[^>]*>/i, (match) => `${match}
643
+ ${metaTag}`) : `${metaTag}
644
+ ${html}`;
645
+ }
646
+ function safeInlineJSON(value) {
647
+ return JSON.stringify(value).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
648
+ }
649
+ function escapeHtml(value) {
650
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
651
+ }
652
+ function escapeHtmlAttribute(value) {
653
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
654
+ }
655
+
656
+ // packages/coding-agent/dist/builtin-extensions/pi-mcp-adapter/ui-server.js
657
+ var MAX_BODY_SIZE = 2 * 1024 * 1024, ABANDONED_GRACE_MS = 6e4, WATCHDOG_INTERVAL_MS = 5e3, MAX_EVENT_LOG = 128;
658
+ async function startUiServer(options) {
659
+ let sessionToken = options.sessionToken ?? randomUUID(), log = logger.child({
660
+ component: "UiServer",
661
+ server: options.serverName,
662
+ tool: options.toolName,
663
+ session: sessionToken.slice(0, 8)
664
+ });
665
+ log.debug("Starting UI server");
666
+ let sseClients = /* @__PURE__ */ new Set(), completed = !1, lastHeartbeatAt = Date.now(), watchdog = null, currentDisplayMode = options.hostContext?.displayMode ?? "inline", nextEventId = 1, eventLog = [], streamSummary, sessionMessages = {
667
+ prompts: [],
668
+ notifications: [],
669
+ intents: []
670
+ }, hostContext = {
671
+ displayMode: currentDisplayMode,
672
+ availableDisplayModes: ["inline", "fullscreen", "pip"],
673
+ platform: "desktop",
674
+ ...options.hostContext
675
+ // Only include toolInfo if caller provides full tool definition with inputSchema
676
+ // The App validates toolInfo.tool.inputSchema as required object
677
+ }, initialStreamContext = hostContext["pi-mcp-adapter/stream"];
678
+ if (initialStreamContext && typeof initialStreamContext == "object") {
679
+ let streamId = initialStreamContext.streamId, mode = initialStreamContext.mode;
680
+ typeof streamId == "string" && (mode === "eager" || mode === "stream-first") && (streamSummary = {
681
+ streamId,
682
+ mode,
683
+ frames: 0,
684
+ phases: []
685
+ });
686
+ }
687
+ let touchHeartbeat = () => {
688
+ lastHeartbeatAt = Date.now();
689
+ }, updateStreamSummary = (payload) => {
690
+ let envelope = getVisualizationStreamEnvelope(payload?.structuredContent);
691
+ envelope && (streamSummary || (streamSummary = {
692
+ streamId: envelope.streamId,
693
+ mode: "eager",
694
+ frames: 0,
695
+ phases: []
696
+ }), streamSummary.frames += 1, streamSummary.phases.includes(envelope.phase) || streamSummary.phases.push(envelope.phase), streamSummary.finalStatus = envelope.status, streamSummary.lastMessage = envelope.message);
697
+ }, serializeEvent = (eventId, name, payload) => `id: ${eventId}
698
+ event: ${name}
699
+ data: ${JSON.stringify(payload)}
700
+
701
+ `, getLatestCheckpointIndex = () => {
702
+ for (let index = eventLog.length - 1; index >= 0; index -= 1) {
703
+ let entry = eventLog[index], envelope = getVisualizationStreamEnvelope(entry.payload?.structuredContent);
704
+ if (envelope?.frameType === "checkpoint" || envelope?.frameType === "final")
705
+ return index;
706
+ }
707
+ return -1;
708
+ }, pruneEventLog = () => {
709
+ if (eventLog.length <= MAX_EVENT_LOG)
710
+ return;
711
+ let latestCheckpointIndex = getLatestCheckpointIndex();
712
+ latestCheckpointIndex > 0 && eventLog.splice(0, latestCheckpointIndex), eventLog.length > MAX_EVENT_LOG && eventLog.splice(0, eventLog.length - MAX_EVENT_LOG);
713
+ }, pushEvent = (name, payload) => {
714
+ if (completed)
715
+ return;
716
+ let eventId = nextEventId++;
717
+ eventLog.push({ id: eventId, name, payload }), updateStreamSummary(payload), pruneEventLog();
718
+ let chunk = serializeEvent(eventId, name, payload);
719
+ for (let client of sseClients)
720
+ try {
721
+ client.write(chunk);
722
+ } catch {
723
+ sseClients.delete(client);
724
+ }
725
+ }, replayEvents = (res, lastEventIdHeader) => {
726
+ let parsedLastId = lastEventIdHeader ? Number(lastEventIdHeader) : Number.NaN, eventsToReplay = Number.isFinite(parsedLastId) ? eventLog.filter((entry) => entry.id > parsedLastId) : (() => {
727
+ let latestCheckpointIndex = getLatestCheckpointIndex();
728
+ return latestCheckpointIndex >= 0 ? eventLog.slice(latestCheckpointIndex) : eventLog;
729
+ })();
730
+ for (let entry of eventsToReplay)
731
+ try {
732
+ res.write(serializeEvent(entry.id, entry.name, entry.payload));
733
+ } catch {
734
+ sseClients.delete(res);
735
+ return;
736
+ }
737
+ }, closeSse = () => {
738
+ for (let client of sseClients)
739
+ try {
740
+ client.end();
741
+ } catch {
742
+ }
743
+ sseClients.clear();
744
+ }, stopWatchdog = () => {
745
+ watchdog && (clearInterval(watchdog), watchdog = null);
746
+ }, markCompleted = (reason) => {
747
+ completed || (log.debug("Session completed", { reason }), pushEvent("session-complete", { reason }), completed = !0, stopWatchdog(), options.onComplete?.(reason));
748
+ }, server = http.createServer(async (req, res) => {
749
+ try {
750
+ let method = req.method || "GET", url = new URL(req.url || "/", `http://${req.headers.host || "127.0.0.1"}`);
751
+ if (method === "GET" && url.pathname === "/") {
752
+ if (!validateTokenQuery(url, sessionToken, res))
753
+ return;
754
+ touchHeartbeat();
755
+ let html = buildHostHtmlTemplate({
756
+ sessionToken,
757
+ serverName: options.serverName,
758
+ toolName: options.toolName,
759
+ toolArgs: options.toolArgs,
760
+ resource: options.resource,
761
+ allowAttribute: AZ(options.resource.meta.permissions),
762
+ requireToolConsent: options.consentManager.requiresPrompt(options.serverName),
763
+ cacheToolConsent: options.consentManager.shouldCacheConsent(),
764
+ hostContext
765
+ });
766
+ res.writeHead(200, {
767
+ "Content-Type": "text/html; charset=utf-8",
768
+ "Cache-Control": "no-store"
769
+ }), res.end(html);
770
+ return;
771
+ }
772
+ if (method === "GET" && url.pathname === "/events") {
773
+ if (!validateTokenQuery(url, sessionToken, res))
774
+ return;
775
+ touchHeartbeat(), log.debug("SSE client connected", { clientCount: sseClients.size + 1 }), res.writeHead(200, {
776
+ "Content-Type": "text/event-stream",
777
+ "Cache-Control": "no-cache, no-transform",
778
+ Connection: "keep-alive",
779
+ "X-Accel-Buffering": "no"
780
+ }), res.write(`: connected
781
+
782
+ `), sseClients.add(res), replayEvents(res, req.headers["last-event-id"] ? String(req.headers["last-event-id"]) : null), req.on("close", () => {
783
+ sseClients.delete(res);
784
+ });
785
+ return;
786
+ }
787
+ if (method === "GET" && url.pathname === "/health") {
788
+ if (!validateTokenQuery(url, sessionToken, res))
789
+ return;
790
+ sendJson(res, 200, { ok: !0, result: { healthy: !0 } });
791
+ return;
792
+ }
793
+ if (method === "GET" && url.pathname === "/ui-app") {
794
+ if (!validateTokenQuery(url, sessionToken, res))
795
+ return;
796
+ touchHeartbeat();
797
+ let cspContent = buildCspMetaContent(options.resource.meta.csp), appHtml = applyCspMeta(options.resource.html, cspContent);
798
+ res.writeHead(200, {
799
+ "Content-Type": "text/html; charset=utf-8",
800
+ "Cache-Control": "no-store"
801
+ }), res.end(appHtml);
802
+ return;
803
+ }
804
+ if (method === "GET" && url.pathname === "/app-bridge.bundle.js") {
805
+ let bundlePath = path.join(import.meta.dirname, "app-bridge.bundle.js");
806
+ try {
807
+ let content = await fs.readFile(bundlePath, "utf-8");
808
+ res.writeHead(200, {
809
+ "Content-Type": "application/javascript",
810
+ "Cache-Control": "public, max-age=31536000"
811
+ }), res.end(content);
812
+ } catch {
813
+ sendJson(res, 500, { ok: !1, error: "Bundle not found" });
814
+ }
815
+ return;
816
+ }
817
+ if (method !== "POST") {
818
+ sendJson(res, 404, { ok: !1, error: "Not found" });
819
+ return;
820
+ }
821
+ let body = await parseBody(req, res);
822
+ if (!body || !validateTokenBody(body, sessionToken, res))
823
+ return;
824
+ let params = body.params ?? {};
825
+ if (touchHeartbeat(), url.pathname === "/proxy/tools/call") {
826
+ options.consentManager.ensureApproved(options.serverName);
827
+ let callParams = params;
828
+ if (!callParams || typeof callParams.name != "string" || !callParams.name.trim()) {
829
+ sendJson(res, 400, { ok: !1, error: "Invalid tools/call params" });
830
+ return;
831
+ }
832
+ let connection = options.manager.getConnection(options.serverName);
833
+ if (!connection || connection.status !== "connected") {
834
+ sendJson(res, 503, { ok: !1, error: `Server "${options.serverName}" is not connected` });
835
+ return;
836
+ }
837
+ try {
838
+ options.manager.touch(options.serverName), options.manager.incrementInFlight(options.serverName);
839
+ let result = await connection.client.callTool({
840
+ name: callParams.name,
841
+ arguments: callParams.arguments && typeof callParams.arguments == "object" && !Array.isArray(callParams.arguments) ? callParams.arguments : {}
842
+ }, void 0, options.manager.getRequestOptions?.(options.serverName));
843
+ sendJson(res, 200, { ok: !0, result });
844
+ } finally {
845
+ options.manager.decrementInFlight(options.serverName), options.manager.touch(options.serverName);
846
+ }
847
+ return;
848
+ }
849
+ if (url.pathname === "/proxy/ui/consent") {
850
+ let approved = !!params.approved;
851
+ options.consentManager.registerDecision(options.serverName, approved), sendJson(res, 200, { ok: !0, result: { approved } });
852
+ return;
853
+ }
854
+ if (url.pathname === "/proxy/ui/message") {
855
+ let msgParams = params, promptText = extractUiPromptText(msgParams);
856
+ if (promptText)
857
+ sessionMessages.prompts.push(promptText), log.debug("UI prompt received", { prompt: promptText.slice(0, 100) });
858
+ else if (msgParams.type === "intent" || msgParams.intent) {
859
+ let intentName = msgParams.intent ?? "";
860
+ intentName && (sessionMessages.intents.push({
861
+ intent: intentName,
862
+ params: msgParams.params
863
+ }), log.debug("UI intent received", { intent: intentName }));
864
+ } else if (msgParams.type === "notify" || msgParams.message) {
865
+ let notifyText = msgParams.message ?? "";
866
+ notifyText && (sessionMessages.notifications.push(notifyText), log.debug("UI notification", { message: notifyText.slice(0, 100) }));
867
+ }
868
+ await options.onMessage?.(msgParams), sendJson(res, 200, { ok: !0, result: {} });
869
+ return;
870
+ }
871
+ if (url.pathname === "/proxy/ui/context") {
872
+ let ctxParams = params;
873
+ log.debug("UI context update", { hasContent: !!ctxParams.content }), await options.onContextUpdate?.(ctxParams), sendJson(res, 200, { ok: !0, result: {} });
874
+ return;
875
+ }
876
+ if (url.pathname === "/proxy/ui/open-link") {
877
+ let openParams = params;
878
+ if (!openParams?.url || typeof openParams.url != "string") {
879
+ sendJson(res, 400, { ok: !1, error: "Invalid open-link params" });
880
+ return;
881
+ }
882
+ let result = {};
883
+ try {
884
+ new URL(openParams.url);
885
+ } catch {
886
+ result = { isError: !0 };
887
+ }
888
+ sendJson(res, 200, { ok: !0, result });
889
+ return;
890
+ }
891
+ if (url.pathname === "/proxy/ui/download-file") {
892
+ sendJson(res, 200, { ok: !0, result: { isError: !0 } });
893
+ return;
894
+ }
895
+ if (url.pathname === "/proxy/ui/request-display-mode") {
896
+ let requested = params?.mode, available = hostContext.availableDisplayModes ?? ["inline"];
897
+ requested && available.includes(requested) && (currentDisplayMode = requested), hostContext.displayMode = currentDisplayMode, pushEvent("host-context", { displayMode: currentDisplayMode }), sendJson(res, 200, { ok: !0, result: { mode: currentDisplayMode } });
898
+ return;
899
+ }
900
+ if (url.pathname === "/proxy/ui/heartbeat") {
901
+ sendJson(res, 200, { ok: !0, result: {} });
902
+ return;
903
+ }
904
+ if (url.pathname === "/proxy/ui/complete") {
905
+ let reason = typeof params.reason == "string" ? params.reason : "done";
906
+ markCompleted(reason), sendJson(res, 200, { ok: !0, result: {} }), setTimeout(() => {
907
+ try {
908
+ server.close();
909
+ } catch {
910
+ }
911
+ closeSse();
912
+ }, 20).unref();
913
+ return;
914
+ }
915
+ sendJson(res, 404, { ok: !1, error: "Not found" });
916
+ } catch (error) {
917
+ let wrapped = wrapError(error, { server: options.serverName, tool: options.toolName }), status = /approval required|denied/i.test(wrapped.message) ? 403 : 500;
918
+ status === 500 && log.error("Request handler error", error instanceof Error ? error : void 0), sendJson(res, status, { ok: !1, error: wrapped.message });
919
+ }
920
+ });
921
+ return options.initialResultPromise && options.initialResultPromise.then((result) => pushEvent("tool-result", result), (error) => {
922
+ let reason = error instanceof Error ? error.message : String(error);
923
+ pushEvent("tool-cancelled", { reason });
924
+ }), watchdog = setInterval(() => {
925
+ if (!completed && !(Date.now() - lastHeartbeatAt <= ABANDONED_GRACE_MS)) {
926
+ markCompleted("stale");
927
+ try {
928
+ server.close();
929
+ } catch {
930
+ }
931
+ closeSse();
932
+ }
933
+ }, WATCHDOG_INTERVAL_MS), watchdog.unref(), new Promise((resolve, reject) => {
934
+ let onError = (error) => {
935
+ log.error("Failed to start server", error), reject(new ServerError(error.message, { port: options.port, cause: error }));
936
+ };
937
+ server.once("error", onError), server.listen(options.port ?? 0, "127.0.0.1", () => {
938
+ server.off("error", onError);
939
+ let address = server.address();
940
+ if (!address || typeof address == "string") {
941
+ let err = new ServerError("invalid address");
942
+ log.error("Invalid server address", err), reject(err);
943
+ return;
944
+ }
945
+ log.debug("Server started", { port: address.port });
946
+ let handle = {
947
+ url: `http://localhost:${address.port}/?session=${sessionToken}`,
948
+ port: address.port,
949
+ sessionToken,
950
+ serverName: options.serverName,
951
+ toolName: options.toolName,
952
+ close: (reason) => {
953
+ markCompleted(reason ?? "closed");
954
+ try {
955
+ server.close();
956
+ } catch {
957
+ }
958
+ closeSse();
959
+ },
960
+ sendToolInput: (args) => {
961
+ pushEvent("tool-input", { arguments: args });
962
+ },
963
+ sendToolResult: (result) => {
964
+ pushEvent("tool-result", result);
965
+ },
966
+ sendResultPatch: (result) => {
967
+ pushEvent("result-patch", result);
968
+ },
969
+ sendToolCancelled: (reason) => {
970
+ pushEvent("tool-cancelled", { reason });
971
+ },
972
+ sendHostContext: (context) => {
973
+ Object.assign(hostContext, context), pushEvent("host-context", context);
974
+ },
975
+ getSessionMessages: () => ({ ...sessionMessages }),
976
+ getStreamSummary: () => streamSummary ? { ...streamSummary, phases: [...streamSummary.phases] } : void 0
977
+ };
978
+ resolve(handle);
979
+ });
980
+ });
981
+ }
982
+ async function parseBody(req, res) {
983
+ try {
984
+ let body = await readBody(req);
985
+ return !body || typeof body != "object" ? (sendJson(res, 400, { ok: !1, error: "Invalid request body" }), null) : body;
986
+ } catch (error) {
987
+ return sendJson(res, 400, { ok: !1, error: error instanceof Error ? error.message : "Invalid body" }), null;
988
+ }
989
+ }
990
+ function readBody(req) {
991
+ return new Promise((resolve, reject) => {
992
+ let size = 0, chunks = [];
993
+ req.on("data", (chunk) => {
994
+ if (size += chunk.length, size > MAX_BODY_SIZE) {
995
+ req.destroy(), reject(new Error("Request body too large"));
996
+ return;
997
+ }
998
+ chunks.push(chunk);
999
+ }), req.on("end", () => {
1000
+ try {
1001
+ resolve(JSON.parse(Buffer.concat(chunks).toString("utf-8")));
1002
+ } catch (error) {
1003
+ reject(error);
1004
+ }
1005
+ }), req.on("error", reject);
1006
+ });
1007
+ }
1008
+ function validateTokenQuery(url, expected, res) {
1009
+ return url.searchParams.get("session") !== expected ? (sendJson(res, 403, { ok: !1, error: "Invalid session" }), !1) : !0;
1010
+ }
1011
+ function validateTokenBody(body, expected, res) {
1012
+ return body.token !== expected ? (sendJson(res, 403, { ok: !1, error: "Invalid session" }), !1) : !0;
1013
+ }
1014
+ function sendJson(res, status, payload) {
1015
+ res.writeHead(status, {
1016
+ "Content-Type": "application/json; charset=utf-8",
1017
+ "Cache-Control": "no-store"
1018
+ }), res.end(JSON.stringify(payload));
1019
+ }
1020
+
1021
+ // packages/coding-agent/dist/builtin-extensions/pi-mcp-adapter/glimpse-ui.js
1022
+ import { existsSync } from "node:fs";
1023
+ import { execFileSync } from "node:child_process";
1024
+ import { join as join2, dirname } from "node:path";
1025
+ import { platform } from "node:os";
1026
+ import { createRequire } from "node:module";
1027
+ var __rewriteRelativeImportExtension = function(path2, preserveJsx) {
1028
+ return typeof path2 == "string" && /^\.\.?\//.test(path2) ? path2.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
1029
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : d + ext + "." + cm.toLowerCase() + "js";
1030
+ }) : path2;
1031
+ }, glimpseAvailable = null, resolvedBinaryPath = null;
1032
+ function isGlimpseAvailable() {
1033
+ return glimpseAvailable !== null ? glimpseAvailable : platform() !== "darwin" ? (glimpseAvailable = !1, !1) : (resolvedBinaryPath = getGlimpseBinaryPath(), glimpseAvailable = resolvedBinaryPath !== null, glimpseAvailable);
1034
+ }
1035
+ function getGlimpseBinaryPath() {
1036
+ if (process.env.GLIMPSE_BINARY && existsSync(process.env.GLIMPSE_BINARY))
1037
+ return process.env.GLIMPSE_BINARY;
1038
+ try {
1039
+ let glimpseuiPath = createRequire(new URL("../builtin-extensions/pi-mcp-adapter/glimpse-ui.js", import.meta.url).href).resolve("glimpseui"), binaryPath = join2(dirname(glimpseuiPath), "glimpse");
1040
+ if (existsSync(binaryPath))
1041
+ return binaryPath;
1042
+ } catch {
1043
+ }
1044
+ try {
1045
+ let globalRoot = execFileSync("npm", ["root", "-g"], { encoding: "utf-8" }).trim(), binaryPath = join2(globalRoot, "glimpseui", "src", "glimpse");
1046
+ if (existsSync(binaryPath))
1047
+ return binaryPath;
1048
+ } catch {
1049
+ }
1050
+ return null;
1051
+ }
1052
+ async function openGlimpseWindow(html, options) {
1053
+ let modulePath = resolvedBinaryPath ? join2(dirname(resolvedBinaryPath), "glimpse.mjs") : "glimpseui", glimpse = await import(__rewriteRelativeImportExtension(modulePath)), active = !0, win = glimpse.open(html, {
1054
+ width: options.width ?? 900,
1055
+ height: options.height ?? 700,
1056
+ title: options.title
1057
+ });
1058
+ return win.on("closed", () => {
1059
+ active && (active = !1, options.onClosed());
1060
+ }), {
1061
+ close: () => {
1062
+ active && (active = !1, win.close());
1063
+ }
1064
+ };
1065
+ }
1066
+
1067
+ // packages/coding-agent/dist/builtin-extensions/pi-mcp-adapter/ui-session.js
1068
+ var activeGlimpseWindow = null, MAX_COMPLETED_SESSIONS = 10;
1069
+ function withStreamEnvelope(result, streamId, sequence) {
1070
+ if (!streamId)
1071
+ return result;
1072
+ let structuredContent = result.structuredContent && typeof result.structuredContent == "object" && !Array.isArray(result.structuredContent) ? { ...result.structuredContent } : {}, rawEnvelope = structuredContent[UI_STREAM_STRUCTURED_CONTENT_KEY], envelope = rawEnvelope && typeof rawEnvelope == "object" && !Array.isArray(rawEnvelope) ? { ...rawEnvelope } : {
1073
+ frameType: "final",
1074
+ phase: "settled",
1075
+ status: result.isError ? "error" : "ok"
1076
+ };
1077
+ return structuredContent[UI_STREAM_STRUCTURED_CONTENT_KEY] = {
1078
+ ...envelope,
1079
+ streamId,
1080
+ sequence
1081
+ }, {
1082
+ ...result,
1083
+ structuredContent
1084
+ };
1085
+ }
1086
+ async function openInBrowser(state, url) {
1087
+ try {
1088
+ await state.openBrowser(url);
1089
+ } catch (error) {
1090
+ let message = error instanceof Error ? error.message : String(error);
1091
+ state.ui?.notify(`MCP UI browser open failed: ${message}`, "warning"), state.ui?.notify(`Open manually: ${url}`, "info");
1092
+ }
1093
+ }
1094
+ async function maybeStartUiSession(state, request) {
1095
+ let log = logger.child({
1096
+ component: "UiSession",
1097
+ server: request.serverName,
1098
+ tool: request.toolName
1099
+ });
1100
+ try {
1101
+ if (state.uiServer && state.uiServer.serverName === request.serverName && state.uiServer.toolName === request.toolName) {
1102
+ let existingHandle = state.uiServer, streamMode2 = request.streamMode, streamId2 = streamMode2 ? randomUUID2() : void 0, streamToken2 = streamMode2 ? randomUUID2() : void 0, active2 = !0, nextStreamSequence2 = 0, cleanupStreamListener2 = () => {
1103
+ streamToken2 && state.manager.removeUiStreamListener(streamToken2);
1104
+ };
1105
+ return existingHandle.sendToolInput(request.toolArgs), streamToken2 && state.manager.registerUiStreamListener(streamToken2, (serverName, notification) => {
1106
+ !active2 || state.uiServer !== existingHandle || serverName === request.serverName && (nextStreamSequence2 += 1, existingHandle.sendResultPatch(withStreamEnvelope(notification.result, streamId2, nextStreamSequence2)));
1107
+ }), {
1108
+ serverName: request.serverName,
1109
+ toolName: request.toolName,
1110
+ reused: !0,
1111
+ streamId: streamId2,
1112
+ streamToken: streamToken2,
1113
+ streamMode: streamMode2,
1114
+ requestMeta: streamToken2 ? { [UI_STREAM_REQUEST_META_KEY]: streamToken2 } : void 0,
1115
+ url: existingHandle.url,
1116
+ isActive: () => active2 && state.uiServer === existingHandle,
1117
+ sendToolResult: (result) => {
1118
+ !active2 || state.uiServer !== existingHandle || (nextStreamSequence2 += 1, existingHandle.sendToolResult(withStreamEnvelope(result, streamId2, nextStreamSequence2)));
1119
+ },
1120
+ sendResultPatch: (result) => {
1121
+ !active2 || state.uiServer !== existingHandle || (nextStreamSequence2 += 1, existingHandle.sendResultPatch(withStreamEnvelope(result, streamId2, nextStreamSequence2)));
1122
+ },
1123
+ sendToolCancelled: (reason) => {
1124
+ !active2 || state.uiServer !== existingHandle || (nextStreamSequence2 += 1, existingHandle.sendToolResult(withStreamEnvelope({
1125
+ isError: !0,
1126
+ content: [{ type: "text", text: reason }]
1127
+ }, streamId2, nextStreamSequence2)));
1128
+ },
1129
+ close: () => {
1130
+ active2 = !1, cleanupStreamListener2();
1131
+ }
1132
+ };
1133
+ }
1134
+ let resource = await state.uiResourceHandler.readUiResource(request.serverName, request.uiResourceUri);
1135
+ state.uiServer && (state.uiServer.close("replaced"), state.uiServer = null), activeGlimpseWindow && (activeGlimpseWindow.close(), activeGlimpseWindow = null);
1136
+ let streamMode = request.streamMode, streamId = streamMode ? randomUUID2() : void 0, streamToken = streamMode ? randomUUID2() : void 0, hostContext = streamMode && streamId ? {
1137
+ [UI_STREAM_HOST_CONTEXT_KEY]: {
1138
+ mode: streamMode,
1139
+ streamId,
1140
+ intermediateResultPatches: streamMode === "stream-first",
1141
+ partialInput: !1
1142
+ }
1143
+ } : void 0, active = !0, nextStreamSequence = 0, handle = null, cleanupStreamListener = () => {
1144
+ streamToken && state.manager.removeUiStreamListener(streamToken);
1145
+ };
1146
+ handle = await startUiServer({
1147
+ serverName: request.serverName,
1148
+ toolName: request.toolName,
1149
+ toolArgs: streamMode === "stream-first" ? {} : request.toolArgs,
1150
+ resource,
1151
+ manager: state.manager,
1152
+ consentManager: state.consentManager,
1153
+ hostContext,
1154
+ onMessage: (params) => {
1155
+ let prompt = extractUiPromptText(params);
1156
+ if (prompt)
1157
+ state.sendMessage && (state.sendMessage({
1158
+ customType: "mcp-ui-prompt",
1159
+ content: [{ type: "text", text: `User sent prompt from ${request.serverName} UI: "${prompt}"` }],
1160
+ display: `\u{1F4AC} UI Prompt: ${prompt}`,
1161
+ details: { server: request.serverName, tool: request.toolName, prompt }
1162
+ }, { triggerTurn: !0 }), log.debug("Triggered agent turn for UI prompt", { prompt: prompt.slice(0, 50) }));
1163
+ else if (params.type === "intent" || params.intent) {
1164
+ let intent = params.intent ?? "", intentParams = params.params;
1165
+ if (intent && state.sendMessage) {
1166
+ let paramsStr = intentParams ? ` ${JSON.stringify(intentParams)}` : "";
1167
+ state.sendMessage({
1168
+ customType: "mcp-ui-intent",
1169
+ content: [{ type: "text", text: `User triggered intent from ${request.serverName} UI: ${intent}${paramsStr}` }],
1170
+ display: `\u{1F3AF} UI Intent: ${intent}`,
1171
+ details: { server: request.serverName, tool: request.toolName, intent, params: intentParams }
1172
+ }, { triggerTurn: !0 }), log.debug("Triggered agent turn for UI intent", { intent });
1173
+ }
1174
+ } else if (params.type === "notify" || params.message) {
1175
+ let text = params.message ?? "";
1176
+ text && state.ui && state.ui.notify(`[${request.serverName}] ${text}`, "info");
1177
+ }
1178
+ },
1179
+ onContextUpdate: (params) => {
1180
+ log.debug("Model context update from UI", {
1181
+ hasContent: !!params.content,
1182
+ hasStructured: !!params.structuredContent
1183
+ });
1184
+ },
1185
+ onComplete: (reason) => {
1186
+ if (active = !1, cleanupStreamListener(), state.uiServer === handle) {
1187
+ let messages = handle.getSessionMessages(), stream = handle.getStreamSummary();
1188
+ if (messages.prompts.length > 0 || messages.intents.length > 0 || messages.notifications.length > 0 || !!stream) {
1189
+ for (state.completedUiSessions.push({
1190
+ serverName: handle.serverName,
1191
+ toolName: handle.toolName,
1192
+ completedAt: /* @__PURE__ */ new Date(),
1193
+ reason,
1194
+ messages,
1195
+ stream
1196
+ }); state.completedUiSessions.length > MAX_COMPLETED_SESSIONS; )
1197
+ state.completedUiSessions.shift();
1198
+ log.debug("Session completed", {
1199
+ reason,
1200
+ prompts: messages.prompts.length,
1201
+ intents: messages.intents.length,
1202
+ notifications: messages.notifications.length,
1203
+ streamFrames: stream?.frames ?? 0
1204
+ });
1205
+ }
1206
+ state.uiServer = null, activeGlimpseWindow && (activeGlimpseWindow.close(), activeGlimpseWindow = null);
1207
+ }
1208
+ }
1209
+ }), streamToken && state.manager.registerUiStreamListener(streamToken, (serverName, notification) => {
1210
+ !active || state.uiServer !== handle || serverName === request.serverName && (nextStreamSequence += 1, handle.sendResultPatch(withStreamEnvelope(notification.result, streamId, nextStreamSequence)));
1211
+ }), state.uiServer = handle;
1212
+ let glimpseDetected = isGlimpseAvailable(), viewerPref = process.env.MCP_UI_VIEWER?.toLowerCase();
1213
+ if (viewerPref === "glimpse" || viewerPref !== "browser" && glimpseDetected)
1214
+ try {
1215
+ let glimpseHtml = `<!DOCTYPE html><html><head><meta charset="utf-8"><style>body{margin:0;padding:0;width:100vw;height:100vh;overflow:hidden}iframe{width:100%;height:100%;border:none}</style></head><body><iframe src="${handle.url}"></iframe></body></html>`;
1216
+ activeGlimpseWindow = await openGlimpseWindow(glimpseHtml, {
1217
+ title: `MCP \xB7 ${request.serverName} \xB7 ${request.toolName}`,
1218
+ width: 1e3,
1219
+ height: 800,
1220
+ onClosed: () => {
1221
+ active && handle.close("glimpse-closed");
1222
+ }
1223
+ });
1224
+ } catch (error) {
1225
+ log.debug("Glimpse unavailable, using browser", {
1226
+ error: error instanceof Error ? error.message : String(error)
1227
+ }), await openInBrowser(state, handle.url);
1228
+ }
1229
+ else
1230
+ await openInBrowser(state, handle.url);
1231
+ return {
1232
+ serverName: request.serverName,
1233
+ toolName: request.toolName,
1234
+ reused: !1,
1235
+ streamId,
1236
+ streamToken,
1237
+ streamMode,
1238
+ requestMeta: streamToken ? { [UI_STREAM_REQUEST_META_KEY]: streamToken } : void 0,
1239
+ url: handle.url,
1240
+ isActive: () => active && state.uiServer === handle,
1241
+ sendToolResult: (result) => {
1242
+ !active || state.uiServer !== handle || (nextStreamSequence += 1, handle.sendToolResult(withStreamEnvelope(result, streamId, nextStreamSequence)));
1243
+ },
1244
+ sendResultPatch: (result) => {
1245
+ !active || state.uiServer !== handle || (nextStreamSequence += 1, handle.sendResultPatch(withStreamEnvelope(result, streamId, nextStreamSequence)));
1246
+ },
1247
+ sendToolCancelled: (reason) => {
1248
+ !active || state.uiServer !== handle || handle.sendToolCancelled(reason);
1249
+ },
1250
+ close: (reason) => {
1251
+ active = !1, cleanupStreamListener(), handle.close(reason);
1252
+ }
1253
+ };
1254
+ } catch (error) {
1255
+ if (error instanceof UrlElicitationRequiredError)
1256
+ throw error;
1257
+ let message = error instanceof Error ? error.message : String(error);
1258
+ return log.error("Failed to start UI session", error instanceof Error ? error : void 0), state.ui?.notify(`MCP UI unavailable for ${request.toolName} (${request.serverName}): ${message}`, "warning"), null;
1259
+ }
1260
+ }
1261
+
1262
+ export {
1263
+ transformMcpContent,
1264
+ resolveMcpResultContent,
1265
+ resolveMcpOutputGuardOptions,
1266
+ guardedMcpDetails,
1267
+ guardMcpOutput,
1268
+ maybeStartUiSession
1269
+ };