@tequila99/githuman 0.11.2 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (325) hide show
  1. package/README.md +74 -2
  2. package/dist/cli/commands/mcp.js +112 -0
  3. package/dist/cli/commands/pi-acp.js +21 -0
  4. package/dist/cli/config.js +10 -1
  5. package/dist/cli/index.js +19 -8
  6. package/dist/cli/server-runtime.js +5 -0
  7. package/dist/server/adapters/agents/artifact-permission.js +88 -0
  8. package/dist/server/adapters/pi-acp/agent.js +98 -0
  9. package/dist/server/adapters/pi-acp/compatibility.js +57 -0
  10. package/dist/server/adapters/pi-acp/control.js +76 -0
  11. package/dist/server/adapters/pi-acp/errors.js +17 -0
  12. package/dist/server/adapters/pi-acp/extension.js +255 -0
  13. package/dist/server/adapters/pi-acp/launch.js +16 -0
  14. package/dist/server/adapters/pi-acp/mcp.js +153 -0
  15. package/dist/server/adapters/pi-acp/process.js +199 -0
  16. package/dist/server/adapters/pi-acp/session.js +409 -0
  17. package/dist/server/adapters/pi-acp/vendor/LICENSE +21 -0
  18. package/dist/server/adapters/pi-acp/vendor/README.md +29 -0
  19. package/dist/server/adapters/pi-acp/vendor/prompt.js +56 -0
  20. package/dist/server/app.js +95 -5
  21. package/dist/server/config/agents.js +4 -6
  22. package/dist/server/db/artifact-graph-migrations.js +56 -0
  23. package/dist/server/db/artifact-migrations.js +70 -0
  24. package/dist/server/db/artifact-review-migrations.js +24 -0
  25. package/dist/server/db/artifact-search-migrations.js +31 -0
  26. package/dist/server/db/artifact-validation-migrations.js +70 -0
  27. package/dist/server/db/index.js +3 -0
  28. package/dist/server/db/migrations.js +10 -0
  29. package/dist/server/db/sqlite-error.js +15 -0
  30. package/dist/server/db/transaction.js +40 -0
  31. package/dist/server/errors/artifacts.js +28 -0
  32. package/dist/server/errors/database.js +2 -0
  33. package/dist/server/hooks/access/local-request.js +5 -0
  34. package/dist/server/hooks/access/require-access.js +13 -2
  35. package/dist/server/repositories/artifact-catalog.repo.js +283 -0
  36. package/dist/server/repositories/artifact-files.repo.js +181 -0
  37. package/dist/server/repositories/artifact-graph.repo.js +50 -0
  38. package/dist/server/repositories/artifact-search.repo.js +192 -0
  39. package/dist/server/repositories/artifact-transition.repo.js +85 -0
  40. package/dist/server/repositories/artifact-validation.repo.js +157 -0
  41. package/dist/server/repositories/notes-catalog.repo.js +2 -10
  42. package/dist/server/repositories/task.repo.js +114 -0
  43. package/dist/server/routes/agent.js +8 -1
  44. package/dist/server/routes/artifact-actions.js +129 -0
  45. package/dist/server/routes/artifact-agent.js +199 -0
  46. package/dist/server/routes/artifact-definitions.js +163 -0
  47. package/dist/server/routes/artifact-transitions.js +80 -0
  48. package/dist/server/routes/artifacts.js +111 -0
  49. package/dist/server/routes/events.js +5 -1
  50. package/dist/server/services/agent/agent-session.js +180 -10
  51. package/dist/server/services/agent/context-builder.js +30 -2
  52. package/dist/server/services/agent/session-registry.js +136 -10
  53. package/dist/server/services/agent/turn-task-context.js +1 -0
  54. package/dist/server/services/artifact-authorization.service.js +199 -0
  55. package/dist/server/services/artifact-definition.service.js +96 -0
  56. package/dist/server/services/artifact-export.service.js +44 -0
  57. package/dist/server/services/artifact-graph-validation.js +541 -0
  58. package/dist/server/services/artifact-graph.service.js +81 -0
  59. package/dist/server/services/artifact-lifecycle.service.js +431 -0
  60. package/dist/server/services/artifact-maintenance.service.js +55 -0
  61. package/dist/server/services/artifact-search.service.js +331 -0
  62. package/dist/server/services/artifact-storage.service.js +646 -0
  63. package/dist/server/services/artifact-transition.service.js +608 -0
  64. package/dist/server/services/artifact-type.service.js +74 -0
  65. package/dist/server/services/artifact-validation-jobs.service.js +848 -0
  66. package/dist/server/services/device-connections.js +9 -1
  67. package/dist/server/services/review.service.js +6 -5
  68. package/dist/server/services/task.service.js +225 -0
  69. package/dist/server/utils/artifact-actor.js +13 -0
  70. package/dist/server/utils/artifact-page.js +42 -0
  71. package/dist/server/utils/take-within-bytes.js +16 -0
  72. package/dist/server/utils/text.js +7 -0
  73. package/dist/shared/agents/schemas.js +30 -0
  74. package/dist/shared/app/storage-constants.js +2 -0
  75. package/dist/shared/artifact-tools/descriptions.js +17 -0
  76. package/dist/shared/artifact-tools/instructions.js +14 -0
  77. package/dist/shared/artifact-tools/schemas.js +124 -0
  78. package/dist/shared/artifact-transitions/constants.js +21 -0
  79. package/dist/shared/artifact-transitions/schemas.js +111 -0
  80. package/dist/shared/artifact-transitions/transitions.js +61 -0
  81. package/dist/shared/artifact-transitions/types.js +1 -0
  82. package/dist/shared/artifacts/constants.js +34 -0
  83. package/dist/shared/artifacts/mcp-constants.js +24 -0
  84. package/dist/shared/artifacts/normalize.js +9 -0
  85. package/dist/shared/artifacts/schemas.js +874 -0
  86. package/dist/shared/artifacts/search.js +101 -0
  87. package/dist/shared/artifacts/types.js +1 -0
  88. package/dist/shared/events/schemas.js +1 -1
  89. package/dist/shared/events/types.js +1 -0
  90. package/dist/shared/tasks/schemas.js +261 -0
  91. package/dist/shared/tasks/types.js +1 -0
  92. package/dist/shared/utils/artifact-body.js +10 -0
  93. package/dist/shared/utils/canonical-json.js +22 -0
  94. package/dist/shared/utils/is-safe-prefixed-filename.js +10 -0
  95. package/dist/shared/utils/is-uuid.js +4 -2
  96. package/dist/shared/utils/is-valid-artifact-type-id.js +9 -0
  97. package/dist/shared/utils/is-valid-filename-prefix.js +13 -0
  98. package/dist/web/assets/AccessPage-D9xfFUBC.js +1 -0
  99. package/dist/web/assets/AddButton-DKNKmS1i.js +4 -0
  100. package/dist/web/assets/AddToAgentButton-wC1dzbDE.js +1 -0
  101. package/dist/web/assets/AppPage-Cozv2vqG.js +1 -0
  102. package/dist/web/assets/ArtifactsPage-IHUO7SbH.js +2 -0
  103. package/dist/web/assets/ArtifactsPage-nRD9XiRm.css +1 -0
  104. package/dist/web/assets/CancelButton-mkxRHwoZ.js +1 -0
  105. package/dist/web/assets/ClosePopup-Bd5a-Lu_.js +1 -0
  106. package/dist/web/assets/CreateButton-zCmb7snC.js +1 -0
  107. package/dist/web/assets/CreateReviewFabButton-D58IHr36.js +1 -0
  108. package/dist/web/assets/DialogHeader-BVrtb0Ri.js +1 -0
  109. package/dist/web/assets/DialogHeader-CPL9OtDV.css +1 -0
  110. package/dist/web/assets/{ErrorNotFound-DucDzOUJ.js → ErrorNotFound-fXS367lZ.js} +1 -1
  111. package/dist/web/assets/{IndexPage-D5PvyGrX.css → IndexPage-5V5GLtgi.css} +1 -1
  112. package/dist/web/assets/IndexPage-BJ1EQdlT.js +1 -0
  113. package/dist/web/assets/MainLayout-C3Ie5yOo.css +1 -0
  114. package/dist/web/assets/MainLayout-CeogGMHH.js +7 -0
  115. package/dist/web/assets/{NoteVisualEditor-CawpxEFB.css → NoteVisualEditor-DE4ACTRJ.css} +1 -1
  116. package/dist/web/assets/NoteVisualEditor-DqAZZig1.js +1054 -0
  117. package/dist/web/assets/NotesPage-C_eoCUl7.css +1 -0
  118. package/dist/web/assets/NotesPage-DXgI-kwN.js +4 -0
  119. package/dist/web/assets/{PdfPreview-rlkcqoMF.js → PdfPreview-ByeBjQMQ.js} +2 -2
  120. package/dist/web/assets/ProjectFilePage-DV1anYfN.js +1 -0
  121. package/dist/web/assets/QBtn-V3VXtJXi.js +1 -0
  122. package/dist/web/assets/QFab-DJhLqo9i.js +1 -0
  123. package/dist/web/assets/{QForm-Be8-ucuJ.js → QForm-ClpSneeD.js} +1 -1
  124. package/dist/web/assets/QInput-BnqLJGXl.js +1 -0
  125. package/dist/web/assets/QScrollArea-qf2G1s2r.js +1 -0
  126. package/dist/web/assets/QSeparator-B8uLaDiI.js +1 -0
  127. package/dist/web/assets/QSpace-CVp0CPR_.js +1 -0
  128. package/dist/web/assets/QSplitter-K2LjbupZ.js +1 -0
  129. package/dist/web/assets/QTabs-Bl_rIz4_.js +1 -0
  130. package/dist/web/assets/QVirtualScroll-BeEkuL6x.js +1 -0
  131. package/dist/web/assets/ReviewDetailPage-BgxcsTqY.css +1 -0
  132. package/dist/web/assets/ReviewDetailPage-CL4Dmz0L.js +1 -0
  133. package/dist/web/assets/ReviewsPage-BPJFTulG.js +1 -0
  134. package/dist/web/assets/SaveButton-D1q2suzR.js +3 -0
  135. package/dist/web/assets/SaveButton-Vtjvcbt0.css +1 -0
  136. package/dist/web/assets/SearchInput-DapVXrFj.js +1 -0
  137. package/dist/web/assets/StatusSwitcher-BtbSIr5q.js +1 -0
  138. package/dist/web/assets/{StatusSwitcher-D6i8_OfR.css → StatusSwitcher-DaE1ufAA.css} +1 -1
  139. package/dist/web/assets/TagFilterField-CPl-BxtL.js +1 -0
  140. package/dist/web/assets/TagFilterField-DjUH0m3_.css +1 -0
  141. package/dist/web/assets/{TerminalView-D4elkzN4.js → TerminalView-B56cEx8g.js} +12 -12
  142. package/dist/web/assets/{TerminalView-617DZuPt.css → TerminalView-BCeke4xd.css} +1 -1
  143. package/dist/web/assets/{abnfDiagram-O67JEVCF-Cugru96L.js → abnfDiagram-O67JEVCF-D_6l0gCA.js} +1 -1
  144. package/dist/web/assets/{access-store-Cdg8oRAM.js → access-store-CwkOl71l.js} +1 -1
  145. package/dist/web/assets/{agent-store-D_W7iD_B.js → agent-store-Cs-hu1v1.js} +5 -5
  146. package/dist/web/assets/architecture-7GRP2DOG-KT2-_RA5.js +1 -0
  147. package/dist/web/assets/{architectureDiagram-NJMV4G6O-7rMsE4Wt.js → architectureDiagram-NJMV4G6O-BFgjp9nL.js} +1 -1
  148. package/dist/web/assets/{blockDiagram-BEXU5L5S-BvSnwUrI.js → blockDiagram-BEXU5L5S-BWfbJk26.js} +1 -1
  149. package/dist/web/assets/{c4Diagram-YGBWAQC7-CgmQlCVx.js → c4Diagram-YGBWAQC7-oIqgOwQa.js} +1 -1
  150. package/dist/web/assets/channel-CAhty-fl.js +1 -0
  151. package/dist/web/assets/{chunk-3FUC2YCW-_i8udThz.js → chunk-3FUC2YCW-WI2pliXT.js} +1 -1
  152. package/dist/web/assets/{chunk-5DYCD2WN-Mhk2LlLk.js → chunk-5DYCD2WN-DYvaF8o2.js} +1 -1
  153. package/dist/web/assets/{chunk-742MDFTN-CDVcwgEp.js → chunk-742MDFTN-xd7B3x5h.js} +1 -1
  154. package/dist/web/assets/{chunk-7INBJB4K-C2c1fi9s.js → chunk-7INBJB4K-nsyx3RGB.js} +1 -1
  155. package/dist/web/assets/{chunk-7M6MHVWA-BeGkoIBL.js → chunk-7M6MHVWA-BxPQ9AEv.js} +1 -1
  156. package/dist/web/assets/{chunk-7PRAP22T-BVWTh9sT.js → chunk-7PRAP22T-CvHw2y-F.js} +1 -1
  157. package/dist/web/assets/{chunk-GTNCS2PH-gVhX7NZP.js → chunk-GTNCS2PH-DIfN1SOI.js} +1 -1
  158. package/dist/web/assets/{chunk-GWA4HPMP-BPdnIcQH.js → chunk-GWA4HPMP-2WZX1fG-.js} +1 -1
  159. package/dist/web/assets/{chunk-MBY4JIJT-B2VfO_06.js → chunk-MBY4JIJT-BL7akw7q.js} +1 -1
  160. package/dist/web/assets/{chunk-NETBCI7D-DZF_gITO.js → chunk-NETBCI7D-CQX1tY3W.js} +1 -1
  161. package/dist/web/assets/{chunk-O7XYJQB3-CDpBWiLq.js → chunk-O7XYJQB3-CtGXf4J6.js} +1 -1
  162. package/dist/web/assets/{chunk-UA2S7LBM-Iv7TSRE_.js → chunk-UA2S7LBM-C_3M_IIp.js} +1 -1
  163. package/dist/web/assets/{chunk-WEXAMYUT-Ce6goZ2Y.js → chunk-WEXAMYUT-6MO559WJ.js} +1 -1
  164. package/dist/web/assets/{chunk-Z7XXMR3K-CY6E6_Ux.js → chunk-Z7XXMR3K-CHJ55IlF.js} +1 -1
  165. package/dist/web/assets/{chunk-ZIGJFQKS-BLzsXZBc.js → chunk-ZIGJFQKS-533qcfPb.js} +1 -1
  166. package/dist/web/assets/{classDiagram-v2-NBCMYWYE-Dz0kD9P6.js → classDiagram-v2-NBCMYWYE-CFySVswx.js} +1 -1
  167. package/dist/web/assets/copy-code-XoEu_Yh6.js +1 -0
  168. package/dist/web/assets/create-DedXY-KP.js +1 -0
  169. package/dist/web/assets/{cynefin-OW5HDTMX-DWIx3wRm.js → cynefin-OW5HDTMX-Dfg_2VTu.js} +1 -1
  170. package/dist/web/assets/{cynefinDiagram-VND7K2PF-2D80uocv.js → cynefinDiagram-VND7K2PF-DaSXiPph.js} +1 -1
  171. package/dist/web/assets/{dagre-6A5THRUB-BLBhukn-.js → dagre-6A5THRUB-D7d1gbRO.js} +1 -1
  172. package/dist/web/assets/date-snFAXn1W.js +1 -0
  173. package/dist/web/assets/{devices-store-BfZKPOhg.js → devices-store-DB_tWC1Q.js} +1 -1
  174. package/dist/web/assets/{diagram-22UHCM2B-DY8dMLZ3.js → diagram-22UHCM2B-CNuTss_x.js} +1 -1
  175. package/dist/web/assets/{diagram-3UASUU5V-Bf6Od1NH.js → diagram-3UASUU5V--Rt3-ARV.js} +1 -1
  176. package/dist/web/assets/{diagram-ATOU4E4O-CjLGcYD5.js → diagram-ATOU4E4O-BP79L-gP.js} +1 -1
  177. package/dist/web/assets/{diagram-CDSNMT55-gIvaVNvs.js → diagram-CDSNMT55-CRO5cocs.js} +1 -1
  178. package/dist/web/assets/{diagram-MLGK6HIB-VR5kiCi5.js → diagram-MLGK6HIB-Difu0Zmh.js} +1 -1
  179. package/dist/web/assets/{diagram-MPIPVDR6-CdAdj25I.js → diagram-MPIPVDR6-grQ3ie17.js} +1 -1
  180. package/dist/web/assets/diff-store-D4XiTkfi.js +93 -0
  181. package/dist/web/assets/{dist-CBGyhCYv.js → dist-75uxNoTf.js} +1 -1
  182. package/dist/web/assets/{dist-CIMEaJAX.js → dist-9rzCziV2.js} +1 -1
  183. package/dist/web/assets/{dist-CEl-Ko94.js → dist-B9i6cUYu.js} +1 -1
  184. package/dist/web/assets/{dist-yzAhvE-V.js → dist-BU-fZfEv.js} +1 -1
  185. package/dist/web/assets/{dist-CTd7Kuqx.js → dist-BeUB43Ur.js} +1 -1
  186. package/dist/web/assets/{dist-C85t5q3z.js → dist-BxIdk5Al.js} +1 -1
  187. package/dist/web/assets/{dist-joQDFmfy.js → dist-By534Syk.js} +1 -1
  188. package/dist/web/assets/{dist-C54FrSb8.js → dist-DFjLCq-0.js} +1 -1
  189. package/dist/web/assets/{dist-lgw4kcVA.js → dist-DNrP7O-J.js} +1 -1
  190. package/dist/web/assets/{dist-BU8erXQF.js → dist-Du5VPTAq.js} +1 -1
  191. package/dist/web/assets/{dist-DLuI1PxH.js → dist-DyBqP777.js} +1 -1
  192. package/dist/web/assets/{ebnfDiagram-ZINNZB2B-irTAlMFO.js → ebnfDiagram-ZINNZB2B-DX2rcvMK.js} +1 -1
  193. package/dist/web/assets/{elk-276RUBZZ-Dj5ligvC.js → elk-276RUBZZ-DSHIl9hv.js} +1 -1
  194. package/dist/web/assets/{erDiagram-OPXOYQCR-Bvn6rbL1.js → erDiagram-OPXOYQCR-BIZVJO8N.js} +1 -1
  195. package/dist/web/assets/eventmodeling-NTZA5JFV-Bh_xDKx6.js +1 -0
  196. package/dist/web/assets/flowDiagram-KWPJA3E3-DXkIxaXL.js +1 -0
  197. package/dist/web/assets/{ganttDiagram-FUAMR5RP-BNGAUF5H.js → ganttDiagram-FUAMR5RP-D4kPfh4X.js} +1 -1
  198. package/dist/web/assets/{gitGraph-4MIJSDKK-DYSHOl72.js → gitGraph-4MIJSDKK-B41R-oAb.js} +1 -1
  199. package/dist/web/assets/{gitGraphDiagram-X574FWY7-BGwRHrPq.js → gitGraphDiagram-X574FWY7-xXrZiSJI.js} +1 -1
  200. package/dist/web/assets/i18n-Cfw_OfRR.js +1 -0
  201. package/dist/web/assets/icons-BIOTvmdT.js +1 -0
  202. package/dist/web/assets/index-B1Bugudn.js +2 -0
  203. package/dist/web/assets/index-BQU3KK1E.css +1 -0
  204. package/dist/web/assets/{info-A6RAGUB7-DNWR20pW.js → info-A6RAGUB7-CgSmK-La.js} +1 -1
  205. package/dist/web/assets/{infoDiagram-VRGFBTTK-BhNwJLY5.js → infoDiagram-VRGFBTTK-CDNEJ_R-.js} +1 -1
  206. package/dist/web/assets/{init-app-cg-B_TFN.js → init-app-C3tD3faT.js} +1 -1
  207. package/dist/web/assets/{is-D0waCELe.js → is-B1kBQ5Va.js} +1 -1
  208. package/dist/web/assets/{ishikawaDiagram-OU5B5YK6-CSkDpn64.js → ishikawaDiagram-OU5B5YK6-ZcU1IxFn.js} +1 -1
  209. package/dist/web/assets/{journeyDiagram-ZHPQQLJL-D2CEecC3.js → journeyDiagram-ZHPQQLJL-g-8ZRhJj.js} +1 -1
  210. package/dist/web/assets/{kanban-definition-PNTS6WVX-CQHlo4Hh.js → kanban-definition-PNTS6WVX-nfsfxVOE.js} +1 -1
  211. package/dist/web/assets/{line-C-izH1ks.js → line-BpuX_ban.js} +1 -1
  212. package/dist/web/assets/markdown-ogvtoQzt.js +16 -0
  213. package/dist/web/assets/mdi-Du7sIqtH.js +1 -0
  214. package/dist/web/assets/{mermaid-parser.core-CAGwq6D-.js → mermaid-parser.core-BBj_ep7Z.js} +3 -3
  215. package/dist/web/assets/{mermaid.core--xlI_0tK.js → mermaid.core-DP4USVSM.js} +4 -4
  216. package/dist/web/assets/{mindmap-definition-NLK3R4M7-BuCxhlwy.js → mindmap-definition-NLK3R4M7-C5GhUvi3.js} +1 -1
  217. package/dist/web/assets/{packet-AYTQ26CC-Bi7x5lJK.js → packet-AYTQ26CC-BIdb-vfg.js} +1 -1
  218. package/dist/web/assets/{pegDiagram-GJSIUBJH-qWzBPkCQ.js → pegDiagram-GJSIUBJH-DH-SdKj6.js} +1 -1
  219. package/dist/web/assets/{pie-WAS4IAKB-Di0wC4XB.js → pie-WAS4IAKB-Du3-jRjK.js} +1 -1
  220. package/dist/web/assets/{pieDiagram-5QR66LMP-BCDVY9q2.js → pieDiagram-5QR66LMP-CJh2ngqY.js} +1 -1
  221. package/dist/web/assets/pinia-BfqEuvsi.js +1 -0
  222. package/dist/web/assets/pinia-mdReENsc.js +1 -0
  223. package/dist/web/assets/preview-store-DOnSmm_C.js +2 -0
  224. package/dist/web/assets/{project-files-store-byqyG2ts.js → project-files-store-CHP6RYFI.js} +1 -1
  225. package/dist/web/assets/{quadrantDiagram-O4NWA36T-CpFObUjT.js → quadrantDiagram-O4NWA36T-DYsSScxc.js} +1 -1
  226. package/dist/web/assets/{radar-RG4KPBEZ-Br8yH8rq.js → radar-RG4KPBEZ-BBjvaVVB.js} +1 -1
  227. package/dist/web/assets/{railroad-74A4TZTK-CACSqhA-.js → railroad-74A4TZTK-B-CRncBU.js} +1 -1
  228. package/dist/web/assets/railroad-abnf-HS5TGJTU-D37zpoYN.js +1 -0
  229. package/dist/web/assets/railroad-ebnf-LZEXJU2U-ZnMxH6Ym.js +1 -0
  230. package/dist/web/assets/railroad-peg-WCYAUIDC-Dg3g-VsM.js +1 -0
  231. package/dist/web/assets/{railroadDiagram-XR7U4H2S-sYXRKGK1.js → railroadDiagram-XR7U4H2S-hqp-2UHb.js} +1 -1
  232. package/dist/web/assets/{render-C7fu7uYY.js → render-Brao9Nj2.js} +1 -1
  233. package/dist/web/assets/repository-store-DZgQ5H7J.js +1 -0
  234. package/dist/web/assets/{requirementDiagram-PLB6GJNP-C9I1JbQc.js → requirementDiagram-PLB6GJNP-Dhuw5jcQ.js} +1 -1
  235. package/dist/web/assets/runtime-core.esm-bundler-DDnHUoIy.js +1 -0
  236. package/dist/web/assets/{safe-storage-C76bPypO.js → safe-storage-BchoYSbq.js} +1 -1
  237. package/dist/web/assets/{sankeyDiagram-IPEJSGJF-CuvFQhPh.js → sankeyDiagram-IPEJSGJF-D5rCIxGR.js} +1 -1
  238. package/dist/web/assets/{sequenceDiagram-PO4LG4MO-CaVb9Y6e.js → sequenceDiagram-PO4LG4MO-YEHR4Mp-.js} +1 -1
  239. package/dist/web/assets/single-flight-CyDZB3rb.js +1 -0
  240. package/dist/web/assets/{stateDiagram-v2-GCMORJYK-Dp_APryr.js → stateDiagram-v2-GCMORJYK-9iWmz6Xf.js} +1 -1
  241. package/dist/web/assets/{swimlanes-2SLR337P-FclUI-k0.js → swimlanes-2SLR337P-Cjwvgt_n.js} +1 -1
  242. package/dist/web/assets/swimlanesDiagram-TC7HE7FX-gJwxhWoO.js +8 -0
  243. package/dist/web/assets/{terminal-store-BnEkXuBj.js → terminal-store-i7HHlWzR.js} +1 -1
  244. package/dist/web/assets/theme-CQ9InaWa.js +1 -0
  245. package/dist/web/assets/{timeline-definition-EJHVYXUP-BAqwqj3c.js → timeline-definition-EJHVYXUP-Cd5n2-Py.js} +1 -1
  246. package/dist/web/assets/{treeView-Q6P3EWNA-D87jJbUQ.js → treeView-Q6P3EWNA-C_QH9vtR.js} +1 -1
  247. package/dist/web/assets/{treemap-WGGIJYW6-B6nhGhRc.js → treemap-WGGIJYW6-CVnU7TVz.js} +1 -1
  248. package/dist/web/assets/use-add-agent-context-D5VqMr0p.js +1 -0
  249. package/dist/web/assets/use-app-theme-DgC4ivPF.js +1 -0
  250. package/dist/web/assets/use-countdown-D6_qSOZJ.js +1 -0
  251. package/dist/web/assets/use-notify-error-Dx2D9IEP.js +1 -0
  252. package/dist/web/assets/use-router-link-D7geCGQI.js +1 -0
  253. package/dist/web/assets/use-row-height-BgHg4-J-.js +1 -0
  254. package/dist/web/assets/use-server-events-CvcbsbIf.js +1 -0
  255. package/dist/web/assets/use-virtual-scroll-DixIsJk4.js +1 -0
  256. package/dist/web/assets/{use-workspace-navigation-CnebLvBV.js → use-workspace-navigation-Dq-Aw8Xq.js} +1 -1
  257. package/dist/web/assets/{usecaseDiagram-POWQR4AR-7YcIKxAb.js → usecaseDiagram-POWQR4AR-Cbj2Pvab.js} +1 -1
  258. package/dist/web/assets/{vennDiagram-UO4OBE2U-BZq5cFC4.js → vennDiagram-UO4OBE2U-2j79YqCN.js} +1 -1
  259. package/dist/web/assets/viewport-store-NqQS7itT.js +1 -0
  260. package/dist/web/assets/{vue-i18n.runtime-CEtihHHL.js → vue-i18n.runtime-JOo8b7-t.js} +2 -2
  261. package/dist/web/assets/{wardley-WFR3VGLG-BT8YO9H4.js → wardley-WFR3VGLG-wsMK7zm3.js} +1 -1
  262. package/dist/web/assets/{wardleyDiagram-VNRHLVJA-rDpXFf6D.js → wardleyDiagram-VNRHLVJA-D6PKTQIJ.js} +1 -1
  263. package/dist/web/assets/weighted-lru-BFtZKA_y.js +1 -0
  264. package/dist/web/assets/workspace-navigation-CoXKJJpP.js +1 -0
  265. package/dist/web/assets/{xychartDiagram-PMCCYNJV-ClniUuZc.js → xychartDiagram-PMCCYNJV-D1fQN7KG.js} +1 -1
  266. package/dist/web/index.html +10 -9
  267. package/package.json +5 -3
  268. package/dist/web/assets/AccessPage-CX3w30zw.js +0 -1
  269. package/dist/web/assets/AppPage-PFJG281y.js +0 -1
  270. package/dist/web/assets/CreateButton-Ch0b7juj.js +0 -1
  271. package/dist/web/assets/CreateReviewFabButton-DTuJzw3q.js +0 -1
  272. package/dist/web/assets/IndexPage-tgW07Qvs.js +0 -1
  273. package/dist/web/assets/MainLayout-C6yBhQnf.css +0 -1
  274. package/dist/web/assets/MainLayout-Cw4jpB1x.js +0 -8
  275. package/dist/web/assets/NoteVisualEditor-DiGhLhQg.js +0 -1054
  276. package/dist/web/assets/NotesPage-CVyVr9tl.js +0 -4
  277. package/dist/web/assets/NotesPage-CxGnZuVQ.css +0 -1
  278. package/dist/web/assets/PanelResize-B6FP9ZVB.js +0 -1
  279. package/dist/web/assets/ProjectFilePage-CkxfX9b1.js +0 -1
  280. package/dist/web/assets/QBtn-CyyV1Bx_.js +0 -1
  281. package/dist/web/assets/QExpansionItem-Dp9lbdVb.js +0 -4
  282. package/dist/web/assets/QFab-LOmZ9rev.js +0 -1
  283. package/dist/web/assets/QInput-Dq6131uz.js +0 -1
  284. package/dist/web/assets/QSelect-B34OqtIH.js +0 -1
  285. package/dist/web/assets/QSpace-BhOVGpQh.js +0 -1
  286. package/dist/web/assets/QVirtualScroll-BYgJ1Kh2.js +0 -1
  287. package/dist/web/assets/ReviewDetailPage-CkCilMNW.css +0 -1
  288. package/dist/web/assets/ReviewDetailPage-GNjBa4X0.js +0 -1
  289. package/dist/web/assets/ReviewsPage-An5fRS92.js +0 -1
  290. package/dist/web/assets/StatusSwitcher-DrFHHwGm.js +0 -1
  291. package/dist/web/assets/architecture-7GRP2DOG-BPCNj4lR.js +0 -1
  292. package/dist/web/assets/channel-CzRYxuLe.js +0 -1
  293. package/dist/web/assets/create-B9Tn5Xvi.js +0 -1
  294. package/dist/web/assets/diff-store-B4adGxC2.js +0 -93
  295. package/dist/web/assets/eventmodeling-NTZA5JFV-BJsTZ_nG.js +0 -1
  296. package/dist/web/assets/flUhRq6tzZclQEJ-Vdg-IuiaDsNa-Dr0goTwe.woff +0 -0
  297. package/dist/web/assets/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ-D-x-0Q06.woff2 +0 -0
  298. package/dist/web/assets/flowDiagram-KWPJA3E3-CvXh1Df7.js +0 -1
  299. package/dist/web/assets/i18n-DnlAcIbT.js +0 -1
  300. package/dist/web/assets/index-Cw7GJi3K.js +0 -2
  301. package/dist/web/assets/index-wsOPzloa.css +0 -1
  302. package/dist/web/assets/markdown-CvtLTiBZ.js +0 -16
  303. package/dist/web/assets/pinia-DO0AdKGg.js +0 -1
  304. package/dist/web/assets/pinia-uOZCmBi-.js +0 -1
  305. package/dist/web/assets/preview-store-DyO8G-ox.js +0 -1
  306. package/dist/web/assets/railroad-abnf-HS5TGJTU-DTBsRB1c.js +0 -1
  307. package/dist/web/assets/railroad-ebnf-LZEXJU2U-D3mrY4ar.js +0 -1
  308. package/dist/web/assets/railroad-peg-WCYAUIDC-33ZjWX0u.js +0 -1
  309. package/dist/web/assets/repository-store-DtRDth1L.js +0 -1
  310. package/dist/web/assets/runtime-core.esm-bundler-CAvPiMpd.js +0 -1
  311. package/dist/web/assets/single-flight-fPyIy7h5.js +0 -1
  312. package/dist/web/assets/swimlanesDiagram-TC7HE7FX-CuUvsn0e.js +0 -8
  313. package/dist/web/assets/theme-CnbaLamF.js +0 -1
  314. package/dist/web/assets/use-add-agent-context-xHAjjOf1.js +0 -1
  315. package/dist/web/assets/use-app-theme-DEowpWRR.js +0 -1
  316. package/dist/web/assets/use-countdown-DlcwwJrs.js +0 -1
  317. package/dist/web/assets/use-panel-width-CjSWCFr4.js +0 -1
  318. package/dist/web/assets/use-router-link-CUoYaYUw.js +0 -1
  319. package/dist/web/assets/use-row-height-BsE9-rO2.js +0 -1
  320. package/dist/web/assets/use-server-events-C2X4Xz00.js +0 -1
  321. package/dist/web/assets/use-virtual-scroll-BAZGswHv.js +0 -1
  322. package/dist/web/assets/viewport-store-CCHiY2QG.js +0 -1
  323. package/dist/web/assets/weighted-lru-BGovtJ2a.js +0 -1
  324. package/dist/web/assets/workspace-navigation-DdW0rSGz.js +0 -1
  325. /package/dist/web/assets/{PanelResize-XjrbOj2S.css → AddToAgentButton-XjrbOj2S.css} +0 -0
@@ -0,0 +1,76 @@
1
+ import { isRecord } from "../../../shared/utils/guards.js";
2
+ // Large artifact pages can expand when escaped as JSON.
3
+ export const MAX_CONTROL_BYTES = 16 * 1024 * 1024;
4
+ // Bound permissions and outstanding RPC calls for one session.
5
+ export const MAX_PENDING_CALLS = 64;
6
+ // Startup must not leave a partial context alive indefinitely.
7
+ export const BRIDGE_TIMEOUT_MS = 30000;
8
+ // Version both peers together when the control contract changes.
9
+ export const CONTROL_VERSION = 1;
10
+ export class JsonChannel {
11
+ #buffer = Buffer.alloc(0);
12
+ #closed = false;
13
+ input;
14
+ output;
15
+ failed;
16
+ constructor(input, output, receive, failed) {
17
+ this.input = input;
18
+ this.output = output;
19
+ this.failed = failed;
20
+ input.on('data', (chunk) => {
21
+ if (this.#closed)
22
+ return;
23
+ if (this.#buffer.length + chunk.length > MAX_CONTROL_BYTES) {
24
+ return this.close(true);
25
+ }
26
+ this.#buffer = Buffer.concat([this.#buffer, chunk]);
27
+ let index;
28
+ while ((index = this.#buffer.indexOf(10)) >= 0) {
29
+ const line = this.#buffer.subarray(0, index);
30
+ this.#buffer = this.#buffer.subarray(index + 1);
31
+ try {
32
+ const frame = JSON.parse(line.toString());
33
+ if (!isRecord(frame) ||
34
+ typeof frame.type !== 'string' ||
35
+ typeof frame.nonce !== 'string' ||
36
+ frame.version !== CONTROL_VERSION) {
37
+ throw new Error('Invalid control frame');
38
+ }
39
+ receive({
40
+ ...frame,
41
+ type: frame.type,
42
+ nonce: frame.nonce,
43
+ version: CONTROL_VERSION
44
+ });
45
+ }
46
+ catch {
47
+ this.close(true);
48
+ return;
49
+ }
50
+ }
51
+ });
52
+ input.on('end', () => this.close(true));
53
+ input.on('error', () => this.close(true));
54
+ output.on('error', () => this.close(true));
55
+ }
56
+ send(frame) {
57
+ if (this.#closed)
58
+ throw new Error('Pi control channel is closed');
59
+ const line = JSON.stringify(frame) + '\n';
60
+ if (Buffer.byteLength(line) > MAX_CONTROL_BYTES ||
61
+ this.output.writableLength > MAX_CONTROL_BYTES) {
62
+ throw new Error('Pi control output exceeds the limit');
63
+ }
64
+ this.output.write(line);
65
+ }
66
+ close(failure = false) {
67
+ if (this.#closed)
68
+ return;
69
+ this.#closed = true;
70
+ this.#buffer = Buffer.alloc(0);
71
+ this.input.destroy();
72
+ this.output.destroy();
73
+ if (failure)
74
+ this.failed();
75
+ }
76
+ }
@@ -0,0 +1,17 @@
1
+ export function piFailureReason(message) {
2
+ if (typeof message !== 'string')
3
+ return 'Pi model request failed.';
4
+ if (/api.?key|unauthori[sz]ed|authenticat|\b40[13]\b/i.test(message)) {
5
+ return 'Pi model authorization failed. Check the installed pi configuration.';
6
+ }
7
+ if (/no model|model.*not found|model.*not available/i.test(message)) {
8
+ return 'Pi has no usable configured model. Check the installed pi configuration.';
9
+ }
10
+ if (/fetch|connect|ECONN|ENOTFOUND|network/i.test(message)) {
11
+ return 'Pi model connection failed. Check the installed pi endpoint.';
12
+ }
13
+ if (/rate.?limit|quota|\b429\b/i.test(message)) {
14
+ return 'Pi model provider limit was reached.';
15
+ }
16
+ return 'Pi model request failed. Check the installed pi configuration.';
17
+ }
@@ -0,0 +1,255 @@
1
+ /// <reference lib="es2024.promise" />
2
+ import { Socket } from 'node:net';
3
+ import { addAbortListener } from 'node:events';
4
+ import { JsonChannel, CONTROL_VERSION, BRIDGE_TIMEOUT_MS, MAX_PENDING_CALLS } from "./control.js";
5
+ import { isRecord } from "../../../shared/utils/guards.js";
6
+ // Bound late-result tracking without retaining call arguments or results.
7
+ const MAX_RETIRED_CALLS = 10000;
8
+ export default async function extension(pi) {
9
+ const nonce = process.env.GITHUMAN_PI_NONCE ?? '';
10
+ delete process.env.GITHUMAN_PI_NONCE;
11
+ if (!nonce ||
12
+ typeof pi.registerTool !== 'function' ||
13
+ typeof pi.getAllTools !== 'function') {
14
+ throw new Error('Pi bridge extension capabilities are unavailable');
15
+ }
16
+ await initializePiExtension(pi, {
17
+ nonce,
18
+ input: new Socket({ fd: 4, readable: true, writable: false }),
19
+ output: new Socket({ fd: 3, readable: false, writable: true }),
20
+ exit: () => process.exit(1)
21
+ });
22
+ }
23
+ export async function initializePiExtension(pi, options) {
24
+ const { nonce } = options;
25
+ const pending = new Map();
26
+ const retired = new Set();
27
+ let generation = 0;
28
+ let configured = false;
29
+ let profile = '';
30
+ let instructions = '';
31
+ let names = new Set();
32
+ let registerTools;
33
+ let ready = false;
34
+ const configuration = Promise.withResolvers();
35
+ const shutdown = () => {
36
+ for (const request of pending.values()) {
37
+ request.reject(new Error('Pi bridge control channel closed'));
38
+ }
39
+ pending.clear();
40
+ return options.exit();
41
+ };
42
+ const channel = new JsonChannel(options.input, options.output, frame => {
43
+ if (frame.nonce !== nonce)
44
+ shutdown();
45
+ if (frame.type === 'configure') {
46
+ if (configured ||
47
+ !Array.isArray(frame.tools) ||
48
+ !['validator', 'chat'].includes(String(frame.profile)) ||
49
+ typeof frame.instructions !== 'string') {
50
+ shutdown();
51
+ }
52
+ configured = true;
53
+ profile = String(frame.profile);
54
+ instructions = frame.instructions;
55
+ const tools = frame.tools.filter(isRegistryTool);
56
+ if (tools.some(tool => !isRecord(tool) ||
57
+ typeof tool.name !== 'string' ||
58
+ typeof tool.description !== 'string' ||
59
+ !isRecord(tool.inputSchema))) {
60
+ shutdown();
61
+ }
62
+ names = new Set(tools.map(tool => tool.name));
63
+ if (names.size !== tools.length)
64
+ shutdown();
65
+ registerTools = () => {
66
+ for (const tool of tools) {
67
+ pi.registerTool({
68
+ name: tool.name,
69
+ label: tool.name,
70
+ description: tool.description,
71
+ parameters: tool.inputSchema,
72
+ execute: async (id, toolInput, signal) => {
73
+ if (!generation ||
74
+ pending.size >= MAX_PENDING_CALLS ||
75
+ signal?.aborted) {
76
+ throw new Error('Pi bridge call is not active');
77
+ }
78
+ const callGeneration = generation;
79
+ const key = `${callGeneration}:${id}`;
80
+ if (pending.has(key) || retired.has(key)) {
81
+ throw new Error('Duplicate pi bridge call ID');
82
+ }
83
+ const response = Promise.withResolvers();
84
+ let abortListener;
85
+ let settled = false;
86
+ const timer = setTimeout(() => reject(new Error('Pi bridge tool deadline exceeded')), BRIDGE_TIMEOUT_MS);
87
+ const cleanup = () => {
88
+ clearTimeout(timer);
89
+ abortListener?.[Symbol.dispose]();
90
+ pending.delete(key);
91
+ };
92
+ function reject(error) {
93
+ if (settled)
94
+ return;
95
+ settled = true;
96
+ // A timed-out or cancelled call can still receive one backend response.
97
+ retired.add(key);
98
+ if (retired.size > MAX_RETIRED_CALLS) {
99
+ retired.delete(retired.values().next().value);
100
+ }
101
+ cleanup();
102
+ response.reject(error);
103
+ }
104
+ pending.set(key, {
105
+ resolve: value => {
106
+ if (settled)
107
+ return;
108
+ settled = true;
109
+ cleanup();
110
+ response.resolve(value);
111
+ },
112
+ reject
113
+ });
114
+ let result;
115
+ try {
116
+ try {
117
+ if (signal) {
118
+ abortListener = addAbortListener(signal, () => reject(new Error('Pi bridge call cancelled')));
119
+ }
120
+ send('call', {
121
+ id,
122
+ generation: callGeneration,
123
+ name: tool.name,
124
+ arguments: toolInput
125
+ });
126
+ }
127
+ catch (error) {
128
+ settled = true;
129
+ cleanup();
130
+ response.reject(error);
131
+ }
132
+ result = await response.promise;
133
+ }
134
+ finally {
135
+ cleanup();
136
+ }
137
+ if (generation !== callGeneration ||
138
+ signal?.aborted ||
139
+ !isRecord(result) ||
140
+ !Array.isArray(result.content)) {
141
+ throw new Error('Pi bridge returned a stale or malformed result');
142
+ }
143
+ if (result.isError === true) {
144
+ throw new Error(result.content
145
+ .filter(isRecord)
146
+ .map(block => block.type === 'text' ? String(block.text) : '')
147
+ .join('\n') || 'MCP tool failed');
148
+ }
149
+ const content = result.content.filter(isRecord).map(block => {
150
+ if (block.type === 'text' || block.type === 'image') {
151
+ return block;
152
+ }
153
+ if (block.type === 'resource' &&
154
+ isRecord(block.resource) &&
155
+ typeof block.resource.text === 'string') {
156
+ return { type: 'text', text: block.resource.text };
157
+ }
158
+ return { type: 'text', text: JSON.stringify(block) };
159
+ });
160
+ return {
161
+ content,
162
+ details: { structuredContent: result.structuredContent }
163
+ };
164
+ }
165
+ });
166
+ }
167
+ };
168
+ configuration.resolve();
169
+ }
170
+ else if (frame.type === 'begin') {
171
+ if (!configured ||
172
+ !Number.isSafeInteger(frame.generation) ||
173
+ Number(frame.generation) <= generation) {
174
+ shutdown();
175
+ }
176
+ generation = Number(frame.generation);
177
+ send('begun', { generation });
178
+ }
179
+ else if (frame.type === 'cancel') {
180
+ generation = 0;
181
+ for (const request of pending.values()) {
182
+ request.reject(new Error('Pi bridge call cancelled'));
183
+ }
184
+ pending.clear();
185
+ }
186
+ else if (frame.type === 'result') {
187
+ if (typeof frame.id !== 'string' ||
188
+ !Number.isSafeInteger(frame.generation)) {
189
+ shutdown();
190
+ }
191
+ const key = `${String(frame.generation)}:${frame.id}`;
192
+ // Only calls already rejected locally may have a harmless late result.
193
+ if (retired.delete(key))
194
+ return;
195
+ if (frame.generation !== generation)
196
+ shutdown();
197
+ const request = pending.get(key);
198
+ if (!request)
199
+ shutdown();
200
+ request.resolve(frame.result);
201
+ }
202
+ else {
203
+ shutdown();
204
+ }
205
+ }, shutdown);
206
+ function send(type, fields = {}) {
207
+ channel.send({ ...fields, type, nonce, version: CONTROL_VERSION });
208
+ }
209
+ const timer = setTimeout(shutdown, BRIDGE_TIMEOUT_MS);
210
+ try {
211
+ send('hello');
212
+ await configuration.promise;
213
+ }
214
+ finally {
215
+ clearTimeout(timer);
216
+ }
217
+ pi.on('session_start', () => {
218
+ if (ready) {
219
+ send('fatal', { reason: 'reload' });
220
+ shutdown();
221
+ }
222
+ ready = true;
223
+ const all = pi.getAllTools().map(tool => tool.name);
224
+ if ([...names].some(name => all.includes(name))) {
225
+ send('fatal', { reason: 'tool_name_collision' });
226
+ shutdown();
227
+ }
228
+ registerTools?.();
229
+ if (profile === 'validator')
230
+ pi.setActiveTools([...names]);
231
+ send('ready', { profile, registryGeneration: 1 });
232
+ });
233
+ // Only validator installs a native/custom tool guard. MCP approval lives in execute.
234
+ if (profile === 'validator') {
235
+ pi.on('tool_call', event => names.has(String(event.toolName))
236
+ ? undefined
237
+ : {
238
+ block: true,
239
+ reason: 'Validator denies tools outside its immutable MCP registry.'
240
+ });
241
+ }
242
+ pi.on('before_agent_start', event => ({
243
+ systemPrompt: `${String(event.systemPrompt)}\n\n${instructions}`
244
+ }));
245
+ pi.on('session_shutdown', shutdown);
246
+ }
247
+ function isRegistryTool(value) {
248
+ return (isRecord(value) &&
249
+ typeof value.name === 'string' &&
250
+ typeof value.description === 'string' &&
251
+ typeof value.server === 'string' &&
252
+ typeof value.originalName === 'string' &&
253
+ isRecord(value.inputSchema) &&
254
+ value.inputSchema.type === 'object');
255
+ }
@@ -0,0 +1,16 @@
1
+ import { fileURLToPath } from 'node:url';
2
+ export function localPiLaunch() {
3
+ const entry = import.meta.url.endsWith('.ts')
4
+ ? '../../../cli/index.ts'
5
+ : '../../../cli/index.js';
6
+ return {
7
+ command: process.execPath,
8
+ args: [fileURLToPath(new URL(entry, import.meta.url)), 'pi-acp', '--stdio']
9
+ };
10
+ }
11
+ export function isLocalPiLaunch(preset) {
12
+ const trusted = localPiLaunch();
13
+ return (preset.command === trusted.command &&
14
+ preset.args.length === trusted.args.length &&
15
+ preset.args.every((arg, index) => arg === trusted.args[index]));
16
+ }
@@ -0,0 +1,153 @@
1
+ import { terminateProcesses } from "../../services/terminal/processes.js";
2
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
3
+ import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
4
+ import { AjvJsonSchemaValidator } from '@modelcontextprotocol/sdk/validation/ajv-provider.js';
5
+ import { isRecord } from "../../../shared/utils/guards.js";
6
+ import { BRIDGE_TIMEOUT_MS } from "./control.js";
7
+ // Bound discovery across pages and servers before exposing any tools.
8
+ const MAX_TOOLS = 512;
9
+ // Repeated or excessive cursors cannot keep session/new pending.
10
+ const MAX_PAGES = 32;
11
+ // pi's built-in tool names must never resolve to MCP backends.
12
+ const BUILTIN_NAMES = new Set([
13
+ 'read',
14
+ 'write',
15
+ 'edit',
16
+ 'bash',
17
+ 'powershell',
18
+ 'grep',
19
+ 'find',
20
+ 'ls',
21
+ 'tool_search',
22
+ 'codemode'
23
+ ]);
24
+ function isValidMcpName(name) {
25
+ return /^[a-zA-Z0-9_-]+$/.test(name);
26
+ }
27
+ export class McpRegistry {
28
+ #entries = new Map();
29
+ #clients = [];
30
+ #transports = [];
31
+ #instructions = [];
32
+ #closed = false;
33
+ onFailure = () => { };
34
+ get tools() {
35
+ return structuredClone([...this.#entries.values()].map(entry => entry.descriptor));
36
+ }
37
+ get instructions() {
38
+ return this.#instructions.join('\n\n');
39
+ }
40
+ async connect(servers) {
41
+ if (servers.length > 8)
42
+ throw new Error('Too many pi MCP servers');
43
+ const names = new Set();
44
+ const schemas = new AjvJsonSchemaValidator();
45
+ try {
46
+ for (const server of servers) {
47
+ if ('type' in server ||
48
+ !isValidMcpName(server.name) ||
49
+ names.has(server.name)) {
50
+ throw new Error('Pi bridge requires unique server-owned stdio MCP descriptors');
51
+ }
52
+ names.add(server.name);
53
+ const env = {};
54
+ for (const entry of server.env) {
55
+ if (Object.hasOwn(env, entry.name)) {
56
+ throw new Error('Duplicate MCP environment variable');
57
+ }
58
+ env[entry.name] = entry.value;
59
+ }
60
+ const transport = new StdioClientTransport({
61
+ command: server.command,
62
+ args: [...server.args],
63
+ env,
64
+ maxBufferSize: 16 * 1024 * 1024,
65
+ stderr: 'pipe'
66
+ });
67
+ this.#transports.push(transport);
68
+ const client = new Client({ name: 'githuman-pi-bridge', version: '1' });
69
+ this.#clients.push(client);
70
+ // oxlint-disable-next-line unicorn/prefer-add-event-listener -- MCP Client exposes onclose as a callback property.
71
+ client.onclose = () => {
72
+ if (!this.#closed)
73
+ this.onFailure();
74
+ };
75
+ transport.stderr?.on('data', () => { });
76
+ await client.connect(transport, { timeout: BRIDGE_TIMEOUT_MS });
77
+ const instructions = client.getInstructions();
78
+ if (instructions)
79
+ this.#instructions.push(instructions);
80
+ const cursors = new Set();
81
+ let cursor;
82
+ for (let page = 0;; page++) {
83
+ if (page >= MAX_PAGES) {
84
+ throw new Error('MCP tools/list page limit exceeded');
85
+ }
86
+ const response = await client.listTools(cursor ? { cursor } : {}, {
87
+ timeout: BRIDGE_TIMEOUT_MS
88
+ });
89
+ for (const tool of response.tools) {
90
+ const name = `mcp__${server.name}__${tool.name}`;
91
+ if (!isValidMcpName(tool.name) ||
92
+ name.length > 128 ||
93
+ BUILTIN_NAMES.has(tool.name) ||
94
+ this.#entries.has(name) ||
95
+ this.#entries.size >= MAX_TOOLS) {
96
+ throw new Error('MCP tool name collision or registry limit exceeded');
97
+ }
98
+ const descriptor = structuredClone({
99
+ name,
100
+ description: tool.description ?? tool.name,
101
+ inputSchema: tool.inputSchema,
102
+ server: server.name,
103
+ originalName: tool.name
104
+ });
105
+ this.#entries.set(name, {
106
+ descriptor,
107
+ client,
108
+ validate: schemas.getValidator(descriptor.inputSchema)
109
+ });
110
+ }
111
+ cursor = response.nextCursor;
112
+ if (!cursor)
113
+ break;
114
+ if (cursors.has(cursor)) {
115
+ throw new Error('MCP tools/list repeated a cursor');
116
+ }
117
+ cursors.add(cursor);
118
+ }
119
+ }
120
+ }
121
+ catch (error) {
122
+ await this.close();
123
+ throw error;
124
+ }
125
+ }
126
+ snapshot(name, input) {
127
+ const entry = this.#entries.get(name);
128
+ if (!entry || !isRecord(input)) {
129
+ throw new Error('Unknown MCP tool or invalid arguments');
130
+ }
131
+ const args = JSON.parse(JSON.stringify(input));
132
+ if (!isRecord(args) || !entry.validate(args).valid) {
133
+ throw new Error('MCP arguments do not match the registered schema');
134
+ }
135
+ return { descriptor: structuredClone(entry.descriptor), arguments: args };
136
+ }
137
+ async call(name, args, signal) {
138
+ const entry = this.#entries.get(name);
139
+ if (!entry || this.#closed || signal.aborted) {
140
+ throw new Error('MCP call is no longer active');
141
+ }
142
+ return entry.client.callTool({ name: entry.descriptor.originalName, arguments: args }, undefined, { signal, timeout: BRIDGE_TIMEOUT_MS });
143
+ }
144
+ async close() {
145
+ if (this.#closed)
146
+ return;
147
+ this.#closed = true;
148
+ await Promise.allSettled(this.#transports.map(transport => transport.pid ? terminateProcesses(transport.pid) : Promise.resolve()));
149
+ await Promise.allSettled(this.#clients.map(client => client.close()));
150
+ await Promise.allSettled(this.#transports.map(transport => transport.close()));
151
+ this.#entries.clear();
152
+ }
153
+ }